2011-06-01 48 views
0

我的应用程序读取并调整从互联网加载的图像;不幸的是我无法控制这些图像的创作。关于如何在CGImageDestinationFinalize中处理这个崩溃的任何建议?

最近我有一个崩溃,我不知道如何能够最好地处理。在这种情况下,图像是一个损坏的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。

任何人有任何想法,我如何处理或陷入这种情况?我会大大appreaciate任何建议,因为这是我的一个担心:应用程序的稳定性。或者这只是一个直接的“作为苹果雷达报告”?

编辑&补充代码:

所有该处理的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

“CGImageRef图像”参数来自哪里?你自己创造它吗?怎么样?你能发布损坏的图像吗?你有没有尝试在你的应用中绘制它? – 2011-06-01 10:31:15

+0

@Nikolai Ruhe:感谢您的评论。我更新了更多信息的问题。我没有尝试绘制图像,因为在这种情况下,场景仅仅是下载,调整大小和存储在磁盘上。 – Damien 2011-06-01 10:43:10

+0

通常,在测试10,000张图像时,这是我们遇到的唯一问题! – Damien 2011-06-01 10:45:52

回答

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报告),并且大部分是黑色的。

+0

对不起,延迟回复你。 WWDC的活动使我比预期忙。感谢您为此付出的所有帮助和工作。我还没有机会尝试你的建议(我会在这个周末)。 – Damien 2011-06-09 09:40:39

0

你可以做的是存储图像中的UIImage对象,在新的上下文(使用size属性)绘制,然后作出CGImageRef它的对象。这将解决腐败问题。虽然你需要为你收到的每一张图片都做到这一点,这将是一个小的性能损失。

请注意,您必须从主线程发送消息到UIImage

+0

非常感谢您的回答/评论。我的错我应该在我的问题中表明,所有这些处理都发生在NSOperationsQueue内。我想我可以在理论上使用performSelectorOnMainThread,如果它不会堵塞运行循环太多。 – Damien 2011-06-06 09:19:47

+0

关于如何知道正确尺寸的任何想法,因为我目前依靠ImageIO lib来告诉我,在这种情况下它的值不正确。我不希望能够处理图像,只需检测条件并防止崩溃。 – Damien 2011-06-06 09:22:16

+0

@Damien您是否尝试过'CGImageSourceCreateImageAtIndex'而不是'CGImageSourceCreateThumbnailAtIndex'? – 2011-06-06 12:25:03

-1

我要发布调试小时后发现的类似崩溃的情况,可能对某人有用... 原因是在这么愚蠢的事情。 我在NSLog中有两个占位符,只有一个实数变量。

NSLog(@"lastItemDate = %@ unixtime = %@", lastItemDate);