Поведение очистки памяти 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;
}