Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 从方法返回后,CGImageRef损坏_Objective C_Xcode_Macos_Core Graphics - Fatal编程技术网

Objective c 从方法返回后,CGImageRef损坏

Objective c 从方法返回后,CGImageRef损坏,objective-c,xcode,macos,core-graphics,Objective C,Xcode,Macos,Core Graphics,我的代码创建了一个图像的TIFF表示,我希望将其重新编码为其他内容。这没有问题 我的ImgUtils功能是: + (CGImageRef) processImageData:(NSData*)rep { NSBitmapImageRep *bitmapRep = [NSBitmapImageRep imageRepWithData:rep]; int width = bitmapRep.size.width; int height = bitmapRep.size.h

我的代码创建了一个图像的TIFF表示,我希望将其重新编码为其他内容。这没有问题

我的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指针指向的内存区域在从方法返回后立即被释放和覆盖

我还尝试了
返回CGImageCreateCopy(imageRef)但它没有改变什么


我缺少什么?

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

缓冲区是在堆栈上创建的。在
+processImageData:
返回后,它将无效。但是,CGImage仍然引用提供程序,提供程序仍然引用现在无效的缓冲区


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

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

缓冲区是在堆栈上创建的。在
+processImageData:
返回后,它将无效。但是,CGImage仍然引用提供程序,提供程序仍然引用现在无效的缓冲区


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

太好了,谢谢,错过了这一部分。还用一个完成块包装了所有东西,并设法释放了我自己。太好了,谢谢,错过了这一部分。还用一个完成块包装了所有东西,并设法释放了我自己。