我的应用程序读取并调整从互联网加载的图像;不幸的是,我无法控制这些图像的创建。
最近我发生了一次撞车事故,我不知道如何才能最好地处理。在这种情况下,图像是一个损坏的GIF文件。它没有严重损坏,但它报告的分辨率大小(高度x宽度)不准确。该图像应该是400x600图像,但报告的内容类似于1111x999。
崩溃的代码段是:
- (void) saveRawImageRefToDisk:(CGImageRef)image withUUID:(NSString *)uuid andType:(NSString *)type {
if (!uuid || !type) {
return;
}
NSDictionary *imageDestinationWriteOptions = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], (id)kCGImagePropertyOrientation,
(id)kCFBooleanFalse, (id)kCGImagePropertyHasAlpha,
[NSNumber numberWithInt:1.0], kCGImageDestinationLossyCompressionQuality,
nil];
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:[self getRawImagePathForUUID:uuid]], (CFStringRef)type, 1, nil);
if (imageDestination) {
CGImageDestinationAddImage(imageDestination, image, (CFDictionaryRef)imageDestinationWriteOptions);
CGImageDestinationFinalize(imageDestination); //<--- EXC_BAD_ACCESS in here
CFRelease(imageDestination);
}
}
崩溃日志的片段是:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x06980000
Crashed Thread: 8
Thread 8 name: Dispatch queue: com.apple.root.default-priority
Thread 8 Crashed:
0 libsystem_c.dylib 0x348cf6a4 memcpy$VARIANT$CortexA9 + 212
1 CoreGraphics 0x366de30c CGAccessSessionGetBytes + 112
2 ImageIO 0x32941b04 GenerateFromRGBImageWu + 256
3 ImageIO 0x329432aa _CGImagePluginWriteGIF + 3390
4 ImageIO 0x32932b3a CGImageDestinationFinalize + 118
有问题的图片是GIF,所以我的方法中的类型设置为 @“com.compuserve.gif”。据我所知,CGImageDestinationRef imageDestination是一个有效的对象。
我的应用程序的部分逻辑是保持图像的格式与读取的格式相同。所以在这种情况下,我正在调整大小并写回GIF。
我试图强制将 CGImageRef 写成PNG,有趣的是应用程序没有崩溃。它写出了PNG(这是无效的 - 只是一个空白的黑色图像),但它没有崩溃。但是我不知道在正常的执行过程中知道我应该把GIF写成PNG。
任何人都对我如何处理或陷入这种情况有任何想法?我非常感谢任何建议,因为这让我很担心:应用程序的稳定性。或者这只是一个直接的“报告作为对苹果的雷达”?
编辑&amp;补充代码:
所有这些处理都发生在NSOperationQueue内而不是主线程上
有问题的图片可在http://dribbble.com/system/users/1409/screenshots/182540/htg-logo-tiny.gif?1306878218
找到这是我创建CGImageRef的函数:
- (CGImageRef) createIpadSizedImageRefFromImageSource:(CGImageSourceRef)imageSource withSourceSizeOf(CGSize)imageSourceSize {
NSDictionary *imageCreationOptions = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent,
[NSNumber numberWithInt:1024], kCGImageSourceThumbnailMaxPixelSize,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways,
nil];
CGImageRef image = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (CFDictionaryRef)imageCreationOptions);
if (!image) {
return nil;
} else {
[(id) image autorelease];
return image;
}
}
并且CGImageSourceRef是从文件路径创建的,如:
- (CGImageSourceRef) createImageSourceFromURL:(NSURL *)imageLocationOnDisk {
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageLocationOnDisk, NULL);
if (!imageSource) {
DebugLog(@"Issue creating image source for image at: %@", imageLocationOnDisk);
return nil;
} else {
[(id) imageSource autorelease];
return imageSource;
}
}
答案 0 :(得分:2)
我根据您的描述创建了一个测试项目,该项目从提供的URL加载并保存图像。它在模拟器和iPhone 4(iOS 4.3.2)上运行没有问题。
您是否可以尝试在项目/环境中运行以下方法:
- (void)checkImage
{
NSURL *imageLocationOnDisk = [[NSBundle mainBundle] URLForResource:@"htg-logo-tiny"
withExtension:@"gif"];
assert(imageLocationOnDisk);
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageLocationOnDisk, NULL);
assert(imageSource);
id options = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent,
[NSNumber numberWithInt:1024], kCGImageSourceThumbnailMaxPixelSize,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways,
nil];
CGImageRef image = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (CFDictionaryRef)options);
assert(image);
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* file = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"foo.png"];
options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], (id)kCGImagePropertyOrientation,
(id)kCFBooleanFalse, (id)kCGImagePropertyHasAlpha,
[NSNumber numberWithInt:1.0], kCGImageDestinationLossyCompressionQuality,
nil];
CGImageDestinationRef dest = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:file],
kUTTypePNG,
1,
NULL);
assert(dest);
CGImageDestinationAddImage(dest, image, (CFDictionaryRef)options);
CGImageDestinationFinalize(dest);
}
要运行测试,您必须将图像复制到项目的资源中。
正如我上面所说,代码在我的机器上工作正常。我也用CGImageSourceCreateImageAtIndex
成功地尝试了它。
您的应用中发生错误的事实可能与其他类型的错误有关。您的线程使用ImageIO API可能存在问题。
我注意到的一件事是你在CGImageDestinationCreateWithURL
电话中传递的选项参数。根据文档,它应该是NULL
。
修改:相关图片的大小为792×1111(由PhotoShop和Preview.app报告),大部分为黑色。
答案 1 :(得分:0)
您可以做的是将图像存储在UIImage
对象中,在新的上下文中绘制(使用size
属性),然后创建一个CGImageRef
对象。这将解决腐败问题。虽然您需要为您收到的每张图片执行此操作,但这将是一个很小的性能损失。
请注意,您必须从主线程向UIImage
发送消息。
答案 2 :(得分:-1)
我要发布一小段调试后发现的类似崩溃的消息,也许对某人有用...... 原因是如此愚蠢的事情。 我在NSLog中有两个占位符,只有一个实变量。
NSLog(@"lastItemDate = %@ unixtime = %@", lastItemDate);