2011-06-01 29 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); 
相關問題