我正在尝试使用freeimage库来解码图像,在opencv中进行一些处理并对其进行编码。现在我试图解析GIF文件。像素数据看起来不错,我可以将调色板转换为rgb24,创建IplImage并在highgui窗口中显示它。
问题在于metatada。 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;
}