Leak in OpenCV NSImage To IplImage converter proce

2019-07-17 05:19发布

问题:

I have a leak in the code which I put below. When I used cvCreateImage instead of cvCreateImageHeader it was 304Kb and 107b leak but when I changed it became to be 107 bites only. Could You help me to find leak.

+ (IplImage *) nsImageToIplImage:(NSImage *)image {
    // NSImage to IplImage

    NSBitmapImageRep *orig = [[image representations] objectAtIndex: 0];
    // a copy or else the color-channel shift that we do later on will affect the original NSImage!

    NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:[orig representationUsingType:NSTIFFFileType properties:NULL]];
    int depth       = [rep bitsPerSample];
    int channels    = [rep samplesPerPixel];
    int height      = [rep size].height;
    int width       = [rep size].width;

    // note- channels had better be "3", or else the loop down below will act pretty funky...
    // NSTIFFFileType seems to always give three-channel images, so I think it's okay...


    IplImage *to_return = cvCreateImageHeader(cvSize(width, height), depth, channels);
    cvSetImageData(to_return, [rep bitmapData], [rep bytesPerRow]);



    // Reorder BGR to RGB
    // no, I don't know why it's in BGR after cvSetData
    for (int i = 0; i < to_return->imageSize; i += 3) {
        uchar tempR, tempG, tempB;
        tempR = to_return->imageData[i];
        tempG = to_return->imageData[i+1];
        tempB = to_return->imageData[i+2];

        to_return->imageData[i] = tempR;
        to_return->imageData[i+1] =tempG;
        to_return->imageData[i+2] = tempB;

    }




    return to_return;
}

回答1:

It's your call to cvSetImageData. When you call cvCreateImage, it allocates both the header and the image data. cvCreateImageHeader only allocates the image header.

When you call off to cvSetImageData, it does NOT copy the data into the structure. Rather it simply sets the pointer to point at whatever data you've supplied. So if you call cvCreateImage and then cvSetImageData, the image data allocated by cvCreateImage is lost.

A rather nasty side-effect of the way you're doing this, is that the user could potentially call off to cvReleaseImage, which would in fact try to free the data in [rep bitmapData]. A much better way would be to simply call cvCreateImage, and then copy all the data from [rep bitmapData] into it.

Hope this helps.