I'm trying to use freeimage library to decode images, do some processing in opencv and encode it back. For now I trying to parse GIF files. Pixels data looks ok, I'm able to convert palette to rgb24, create IplImage and show it in highgui window.
The problem is with metatada. GIF files contains some info about how animation should run. Here I got disposal method for every frame, and stored it in array to compile resulting GIF later, on encode stage:
FITAG* tag;
int res = FreeImage_GetMetadata(FIMD_ANIMATION, frame, "DisposalMethod", &tag);
int* dispose = FreeImage_GetTagValue(tag);
// dispose[frameid] = *dispose; // <- problem with this line
Code runs ok, if commented line remains commented, but if uncomment it, I'll get error
freeimg(15745,0x7fff73f61300) malloc: * error for object 0x100c6e9c0: incorrect checksum for freed object - object was probably modified after being freed. * set a breakpoint in malloc_error_break to debug Program ended with exit code: 9
on 4th (!) frame. In other files current frame number can be 5, 7 etc. I don't even use dispose
array yet, it's just stores some ints. How this can affect memory management? Below is complete app code:
#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;
}