2010-10-11 34 views
10

Tôi có một chuỗi nền tải hình ảnh và hiển thị chúng trong chuỗi chính. Tôi nhận thấy rằng các chủ đề nền hầu như không có gì để làm, bởi vì hình ảnh giải mã thực tế dường như được thực hiện trong các chủ đề chính:Giải mã hình ảnh trong chuỗi nền?

alt text

Cho đến nay tôi đã cố gắng gọi [UIImage imageNamed:], [UIImage imageWithData:]CGImageCreateWithJPEGDataProvider ở chế độ nền chủ đề không có sự khác biệt. Có cách nào để buộc các giải mã được thực hiện trên các chủ đề nền?

Đã có a similar question tại đây nhưng không hiệu quả. Như tôi đã viết ở đó, tôi đã cố gắng lừa sau:

@implementation UIImage (Loading) 

- (void) forceLoad 
{ 
    const CGImageRef cgImage = [self CGImage]; 

    const int width = CGImageGetWidth(cgImage); 
    const int height = CGImageGetHeight(cgImage); 

    const CGColorSpaceRef colorspace = CGImageGetColorSpace(cgImage); 
    const CGContextRef context = CGBitmapContextCreate(
     NULL, /* Where to store the data. NULL = don’t care */ 
     width, height, /* width & height */ 
     8, width * 4, /* bits per component, bytes per row */ 
     colorspace, kCGImageAlphaNoneSkipFirst); 

    NSParameterAssert(context); 
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage); 
    CGContextRelease(context); 
} 

@end 

đó làm việc (buộc hình ảnh để giải mã), nhưng nó cũng gây nên một cuộc gọi rõ ràng tốn kém để ImageIO_BGR_A_TO_RGB_A_8Bit.

Trả lời

7

Nói chính thức, UIKit không phải là chủ đề an toàn (mặc dù nó đã trở nên an toàn hơn một chút trong iOS 4), vì vậy bạn không nên gọi một trong hai phương thức UIImage trên một chuỗi nền. Trong thực tế tôi nghĩ bạn có xu hướng không gặp vấn đề nếu bạn không làm bất cứ điều gì gây ra một đối tượng UIKit muốn vẽ lại, nhưng đó là quy tắc của những thứ mà bạn không bao giờ nên dựa vào trong mã vận chuyển - tôi đề cập đến nó chỉ để giải thích tại sao có thể bạn không gặp vấn đề gì.

Như bạn đã phát hiện, CGImageRefs (bao gồm cả khi được bao bọc trong UIImage) tiếp tục tham chiếu đến hình ảnh nguồn ở dạng mã hóa của chúng trừ khi và cho đến khi ai đó cần chúng giải mã. 'Bí quyết' bạn trích dẫn có hiệu quả để kích hoạt giải mã; một giải pháp tốt hơn là tránh hoàn toàn UIImage cho đến khi bạn an toàn trở lại luồng chính, bắt đầu bằng CGImageCreateWithJPEGDataProvider, tạo một ngữ cảnh riêng biệt như bạn làm ở trên, CGContextDrawImage từ JPEGDataProvider đến ngữ cảnh mới và sau đó chuyển ngữ cảnh mới vào làm hình ảnh, phát hành nhà cung cấp dữ liệu JPEG.

Đối với ImageIO_BGR_A_TO_RGB_A_8Bit, có thể đáng giá cho CGColorSpaceCreateDeviceRGB() thay cho CGImageGetColorSpace (cgImage), để lấy bối cảnh với không gian màu không phụ thuộc vào tệp hình ảnh nguồn bên dưới.

10

Tôi gặp sự cố tương tự với hình ảnh có độ phân giải cao trên iPad retina mới. Hình ảnh lớn hơn kích thước màn hình (gần) sẽ gây ra các vấn đề lớn với giao diện người dùng. Đây là những hình ảnh JPG, do đó, để chúng giải mã trên nền có vẻ là điều đúng đắn để làm. Tôi vẫn đang làm việc để thắt chặt tất cả những điều này, nhưng giải pháp của Tommy đã làm việc rất tốt cho tôi. Tôi chỉ muốn đóng góp một số mã để giúp người tiếp theo cùng khi họ đang cố gắng xác định lý do tại sao giao diện người dùng của họ đang nói lắp với hình ảnh lớn. Đây là những gì tôi đã làm (mã này chạy trong NSOperation trên một hàng đợi nền). Ví dụ này là sự pha trộn mã của tôi và mã ở trên:

CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((CFDataRef)self.data); 
    CGImageRef newImage = CGImageCreateWithJPEGDataProvider(dataProvider, 
            NULL, NO, 
            kCGRenderingIntentDefault); 


    ////////// 
    // force DECODE 

    const int width = CGImageGetWidth(newImage); 
    const int height = CGImageGetHeight(newImage); 

    const CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 
    const CGContextRef context = CGBitmapContextCreate(
                NULL, /* Where to store the data. NULL = don’t care */ 
                width, height, /* width & height */ 
                8, width * 4, /* bits per component, bytes per row */ 
                colorspace, kCGImageAlphaNoneSkipFirst); 

    NSParameterAssert(context); 
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), newImage); 
    CGImageRef drawnImage = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorspace); 

    ////////// 

    self.downloadedImage = [UIImage imageWithCGImage:drawnImage]; 

    CGDataProviderRelease(dataProvider); 
    CGImageRelease(newImage); 
    CGImageRelease(drawnImage); 

Tôi vẫn đang tối ưu hóa điều này. Nhưng nó có vẻ khá tốt cho đến nay.

+0

cảm ơn bạn, hoạt động tốt. – Morrowless

Các vấn đề liên quan