Поведение очистки памяти freeimage

Я пытаюсь использовать библиотеку freeimage для декодирования изображений, сделать некоторую обработку в opencv и закодировать его обратно. Сейчас я пытаюсь разобрать GIF-файлы. Пиксельные данные выглядят нормально, я могу конвертировать палитру в rgb24, создать IplImage и показать его в окне высокого уровня.

Проблема с метатой. GIF-файлы содержат некоторую информацию о том, как должна работать анимация. Здесь я получил метод удаления для каждого кадра и сохранил его в массиве, чтобы скомпилировать полученный GIF позже, на этапе кодирования:

FITAG* tag;
int res = FreeImage_GetMetadata(FIMD_ANIMATION, frame, "DisposalMethod", &tag);
int* dispose = FreeImage_GetTagValue(tag);
// dispose[frameid] = *dispose; // <- problem with this line

Код работает нормально, если закомментированная строка остается закомментированной, но если раскомментировать ее, я получу ошибку

freeimg (15745,0x7fff73f61300) malloc: * ошибка для объекта 0x100c6e9c0: неверная контрольная сумма для освобожденного объекта - объект, вероятно, был изменен после освобождения. * установить точку останова в malloc_error_break для отладки. Программа завершилась с кодом выхода: 9

на 4-м (!) кадре. В других файлах текущий номер кадра может быть 5, 7 и т. Д. Я даже не использую dispose Массива пока нет, он просто хранит некоторые целые. Как это может повлиять на управление памятью? Ниже приведен полный код приложения:

#include <stdlib.h>
#include <stdio.h>
#include <FreeImage.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>

#define cvPxAddr(src, x, y, c) (src->widthStep * y + x * src->nChannels + c)
#define cvSetComponent(src, x, y, c, val) (src->imageData[cvPxAddr(src, x, y, c)] = val)
#define cvGetRawComponent(src, x, y, c) (src->imageData[cvPxAddr(src, x, y, c)])
#define cvGetComponent(src, x, y, c) ((u_char)cvGetRawComponent(src, x, y, c))

int main(int argc, const char * argv[]) {
    FIMULTIBITMAP* container = FreeImage_OpenMultiBitmap(FIF_GIF, "file.gif", 0, 1, 1, 0);

    int framecount = FreeImage_GetPageCount(container);

    char* winname = "Result";
    cvNamedWindow(winname, CV_WINDOW_AUTOSIZE);

    int* dispose = malloc(framecount * sizeof(int));

    for (int frameid = 0; frameid < framecount; frameid++) {
        FIBITMAP* frame = FreeImage_LockPage(container, frameid);

        int w = FreeImage_GetWidth(frame);
        int h = FreeImage_GetHeight(frame);
        int scan_width = FreeImage_GetPitch(frame);

        FITAG* tag;
        int res = FreeImage_GetMetadata(FIMD_ANIMATION, frame, "DisposalMethod", &tag);
        int* dispose = FreeImage_GetTagValue(tag);
        dispose[frameid] = *dispose; // <- commenting this line solves problem

        RGBQUAD* palette = FreeImage_GetPalette(frame);
        int transparencykey = FreeImage_GetTransparentIndex(frame);

        IplImage* image = cvCreateImageHeader(cvSize(w, h), IPL_DEPTH_8U, 4);
        image->imageData = malloc(w * h * 4);

        for (int y = 0; y < h; y++) {
            unsigned char* row = FreeImage_GetScanLine(frame, h - y);
            for (int x = 0; x < w; x++) {
                int coloridx = row[x];
                RGBQUAD color = palette[coloridx];
                cvSetComponent(image, x, y, 0, color.rgbBlue);
                cvSetComponent(image, x, y, 1, color.rgbGreen);
                cvSetComponent(image, x, y, 2, color.rgbRed);
                cvSetComponent(image, x, y, 3, coloridx == transparencykey ? 0 : 255);
            }
        }

        cvShowImage(winname, image);
        cvWaitKey(120);

        free(image->imageData);
        cvReleaseImageHeader(&image);

        FreeImage_UnlockPage(container, frame, 0); // <- here I got exception on nth frame
    }

    free(dispose);

    cvDestroyAllWindows();
    FreeImage_CloseMultiBitmap(container, 0);
    return 0;
}

0 ответов

Другие вопросы по тегам