Objective-c UIImage 到 Greyscale Bitmap 转换函数中的内存泄漏

Memory leak in Objective-c UIImage to Greyscale Bitmap conversion function

提问人:Cosworth66 提问时间:7/29/2020 最后编辑:Cosworth66 更新时间:7/29/2020 访问量:64

问:

我正在尝试解决 iOS 应用程序的内存泄漏问题,我已将其缩小到将 UIImage 转换为灰度位图的函数。代码工作正常,但每次运行会占用大约 500kb。

我有一种感觉,这是由 CGImageRef 和 CGDataRef 未释放引起的,但是如果我在函数结束时使用 CGImageRelease(sourceImage) 或 CGDataRelease(theData) 释放它们中的任何一个,那么返回的图像 grayBitmapImage 是空的。

谁能帮助我理解为什么我不能在不丢失最终图像的情况下发布这些 Refs 中的任何一个?

当我返回由 bytes[] 缓冲区创建的 grayBitmapImage 时,它们不应该已经用完并完成吗?

有谁看到此功能还有什么地方可能导致内存泄漏?

+ (NSData*) convertJpegToBmpGray: (UIImage *)houghSourceImage :(NSString *)destImgPath :(NSString *)fileName  :(int)width : (int)height
{
    RGBQUAD Palette[0x100];
    
    int totalbytesinbitmap = (int)(width * height) + 54 + (0x100 * sizeof(RGBQUAD) + 2);  //THE SIZE OF THE IMAGE WE WANT WITH NULL TERM
    
    //OUTPUT IMAGE BUFFER
    unsigned char *bytes = new unsigned char[totalbytesinbitmap];
    
    [self writeBitmapHeaderGray:bytes :width :height];
    
    UIImage *sourceImage1 = houghSourceImage;
    if(sourceImage1==nil)
        return nil;
    
    CGImageRef sourceImage = sourceImage1.CGImage;
    CFDataRef theData;
    theData = CGDataProviderCopyData(CGImageGetDataProvider(sourceImage));
    
    UInt8 *pixelDataS = (UInt8 *) CFDataGetBytePtr(theData);
    int dataLength = (int)CFDataGetLength(theData);  //LENGTH OF THE WHOLE BITMAP BUFFER
    
    int row = (int)height -1;                        //NUMBER OF ROWS IS THE HEIGHT MINUS 1
    
    int col = 0;

    int totalbytesinrow = (int) width;
    
    for(int i=0; i<dataLength;){
        
        int red     =   pixelDataS[i++];    //GET RED PIXEL
        int green   =   pixelDataS[i++];    //GET GREEN PIXEL
        int blue    =   pixelDataS[i++];    //GET BLUE PIXEL
                            i++;            //ADD A BYTE FOR RESERVED
        
        if(col == totalbytesinrow){
            col = 0;                       //RESET COLUMN COUNT TO ZERO AT END OF ROW
            row--;                         //FIGURE OUT THE ROW AND COLUMN COUNTS
        }
        
        //STARTS THE LOCATION FROM THE END OF THE BUFFER AND WORKS BACKWARDS IN ROWS
        int location = (row * totalbytesinrow) + col + 54 + (0x100 * sizeof(RGBQUAD));
        
                                            //CONVERT ALL PIXELS TO GRAY
        int gray = (red + green + blue) / 3;
        
        bytes[location]   = gray;
        col++;
         
    }
    
    for(int i=0; i<0x100; i++)              //CREATE THE PALETTE ARRAY FOR USE WITH GREYSCALE BITMAPS
    {
        Palette[i].rgbRed = i;
        Palette[i].rgbGreen = i;
        Palette[i].rgbBlue = i;
        Palette[i].rgbReserved = 0;
    }
    
    int paletteLocation = 54;               //START THE PALETTE RIGHT AFTER THE INFOHEADER
    for(int i=0; i < 0x100; i++)            //COPY THE PALETTE ARRAY INTO THE BYTE ARRAY AFTER INFOHEADER
    {
        bytes[paletteLocation] = Palette[i].rgbRed;
        paletteLocation++;
        bytes[paletteLocation] = Palette[i].rgbGreen;
        paletteLocation++;
        bytes[paletteLocation] = Palette[i].rgbBlue;
        paletteLocation++;
        bytes[paletteLocation] = Palette[i].rgbReserved;
        paletteLocation++;
        
    }
    
    //ADD NULL TERMINATORS TO BITMAP BUFFER
    bytes[totalbytesinbitmap+1] = 0x00;
    bytes[totalbytesinbitmap+2] = 0x00;

    NSData *grayBitmapImage = [NSData dataWithBytes:bytes length:totalbytesinbitmap];
    

    CFAutorelease(theData);  //EDIT-MEMORY LEAK FIXED BY ADDING THIS
    delete[] bytes;
    return grayBitmapImage;

}

该函数是这样调用的。


UIImage *image = [ImageUtils UIImageFromCVMat:small];
int width = image.size.width;
int height = image.size.height;

NSData *raw2dmiImage = [ImageUtils convertJpegToBmpGray :image :savedFilePath :@"raw2dmiImage.BMP" :width :height];


ios objective-c 管理内存 泄漏 cgimage

评论

1赞 matt 7/29/2020
它。你通过说.你读过文档吗?你看到“复制”这个词了吗?您必须释放该对象。如果要返回的结果涉及该缓冲区的内容,则使用 .theDataCGDataProviderCopyDataCFAutorelease
0赞 matt 7/29/2020
顺便问一下,你运行了静态分析器吗?它应该告诉你的。
1赞 Rob 7/29/2020
静态分析器不会对创建规则发出警告。但是,它会在代码中报告一个不同的、不相关的问题,即他有一条执行路径,如果是,他将返回而不删除他的 .但失败是关键问题。sourceImage1nilbytesCFReleasetheData
0赞 Rob 7/29/2020
完全无关,但平均红色、绿色和蓝色通常不会产生非常好的灰度图像。通常,您会使用亮度计算,例如 0.2126 * 红色 + 0.7152 * 绿色 + 0.0722 * 蓝色。
0赞 Cosworth66 7/29/2020
@Rob 感谢您的反馈,3 种颜色的平均值对于接收图像的图像识别代码来说已经绰绰有余了。还要感谢 CFRelease 的其他选项,我会试一试,看看会发生什么。

答: 暂无答案