CGImageRef 从方法返回后损坏
CGImageRef gets corrupted after returned from a method
我的代码创建了一个图像的 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);
但没有任何改变。
我错过了什么?
CGDataProviderCreateWithData()
不会复制您提供的缓冲区。其目的是允许创建直接访问该缓冲区的数据提供程序。
您的缓冲区是在堆栈上创建的。 +processImageData:
returns 后失效。但是,CGImage 仍然引用提供者,并且提供者仍然引用现在无效的缓冲区。
一种解决方案是在堆上创建缓冲区并通过 releaseData
参数提供回调以释放它。另一种方法是从缓冲区(复制它)创建一个 CFData
,然后使用 CGDataProviderCreateWithCFData()
创建数据提供者。最好的方法可能是创建所需容量的 CFMutableData
,将其长度设置为匹配,并从一开始就将其存储 (CFDataGetMutableBytePtr()
) 用作缓冲区。这是堆分配的、内存管理的,不需要任何复制。
我的代码创建了一个图像的 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);
但没有任何改变。
我错过了什么?
CGDataProviderCreateWithData()
不会复制您提供的缓冲区。其目的是允许创建直接访问该缓冲区的数据提供程序。
您的缓冲区是在堆栈上创建的。 +processImageData:
returns 后失效。但是,CGImage 仍然引用提供者,并且提供者仍然引用现在无效的缓冲区。
一种解决方案是在堆上创建缓冲区并通过 releaseData
参数提供回调以释放它。另一种方法是从缓冲区(复制它)创建一个 CFData
,然后使用 CGDataProviderCreateWithCFData()
创建数据提供者。最好的方法可能是创建所需容量的 CFMutableData
,将其长度设置为匹配,并从一开始就将其存储 (CFDataGetMutableBytePtr()
) 用作缓冲区。这是堆分配的、内存管理的,不需要任何复制。