freeimage内存清理行为

时间:2014-11-20 11:48:31

标签: c memory-management freeimage

我正在尝试使用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;
}

0 个答案:

没有答案