【问题标题】:CGImageRef gets corrupted after returned from a method从方法返回后 CGImageRef 损坏
【发布时间】:2020-05-13 06:47:06
【问题描述】:

我的代码创建了一个图像的 TIFFRepresentation,我想将它重新编码为不同的东西。这没有问题。

我的 ImgUtils 函数是:

+ (CGImageRef) processImageData:(NSData*)rep {

    NSBitmapImageRep *bitmapRep = [NSBitmapImageRep imageRepWithData:rep];

    int width = bitmapRep.size.width;
    int height = bitmapRep.size.height;
    size_t pixels_size = width * height;
    Byte raw_bytes[pixels_size * 3];

    //
    //  processing, creates and stores raw byte stream
    //

    int bitsPerComponent = 8;
    int bytesPerPixel = 3;
    int bitsPerPixel = bytesPerPixel * bitsPerComponent;
    int bytesPerRow = bytesPerPixel * width;

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                              raw_bytes,
                                                              pixels_size * bytesPerPixel,
                                                              NULL);

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;

    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    CGImageRef imageRef = CGImageCreate(width,
                                        height,
                                        bitsPerComponent,
                                        bitsPerPixel,
                                        bytesPerRow,
                                        colorSpaceRef,
                                        bitmapInfo,
                                        provider,
                                        NULL,
                                        NO,
                                        renderingIntent);


    [ImgUtils saveToPng:imageRef withSuffix:@"-ok"];

    CGColorSpaceRelease(colorSpaceRef);
    CGDataProviderRelease(provider);

    return imageRef;
}

还有另一种方法,将 CGImageRef 保存到文件系统。

+ (BOOL) saveToPng:(CGImageRef)imageRef withSuffix:(NSString*)suffix {
    CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:[NSString stringWithFormat:@"~/Downloads/pic%@.png", suffix]];
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
    CGImageDestinationAddImage(destination, imageRef, nil);
    CGImageDestinationFinalize(destination);
    CFRelease(destination);
    return YES;
}

如您所见,处理完图像后,我立即将其保存在磁盘上,为pic-ok.png

这是调用处理函数的代码:

 CGImageRef cgImage = [ImgUtils processImageData:imageRep];
 [ImgUtils saveToPng:cgImage withSuffix:@"-bad"];

问题是,这两个图像不同。第二个,带有-bad 后缀的已损坏。 请参阅下面的示例。似乎 CGImageRef 指针指向的内存区域在从方法返回后立即被释放和覆盖。

我也试过return CGImageCreateCopy(imageRef);,但没有任何改变。

我错过了什么?

【问题讨论】:

    标签: objective-c xcode macos core-graphics


    【解决方案1】:

    CGDataProviderCreateWithData() 不会复制您提供的缓冲区。其目的是允许创建直接访问该缓冲区的数据提供者。

    您的缓冲区是在堆栈上创建的。在+processImageData: 返回后它就失效了。但是,CGImage 仍然引用了提供者,并且提供者仍然引用了现在无效的缓冲区。

    一种解决方案是在堆上创建缓冲区并通过释放它的releaseData 参数提供回调。另一种方法是从缓冲区(复制它)创建一个CFData,然后使用CGDataProviderCreateWithCFData() 创建数据提供者。最好的方法可能是创建一个具有所需容量的CFMutableData,将其长度设置为匹配,并从一开始就使用其存储空间 (CFDataGetMutableBytePtr()) 作为缓冲区。这是堆分配的、内存管理的,并且不需要任何复制。

    【讨论】:

    • 太好了,谢谢,错过了这一部分。还用完成块包装了所有内容并管理释放自己。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 2020-01-01
    相关资源
    最近更新 更多