iOS UIImage的解码时机

来源:互联网 发布:电脑桌面 知乎 编辑:程序博客网 时间:2024/06/07 21:41

     在看博客 UITableView优化技巧 时想到列表的优化主要还是对图片的优化处理。 博文中介绍了按需加载、快速滑动时不加载、异步刷新等等技巧。

      这里有个问题, 当我们实例化一个UIImage对象并为UIImageView的image赋值时, 到底有没有将jpg/png转换为bitmap格式呢?  答案是否定的, 默认情况下CPU不会对图像进行解码; 当CPU将图像数据传送给GPU时, GPU会判断数据格式并转换为Bitmap格式。

       PS: GPU只能显示Bitmap格式的图像,而且GPU的解码操作运行在主线程,绕不过去的;所以UI要显示大量的png/jpg/gif时, 可能会卡顿!

       为什么我们在日常开发中没发现这个问题呢? 其实是三方图像库帮我们做过优化了。  下面看看主流的SDWebImage是怎么做的, 缓存中可以存储未解码图片, 当需要显示到界面时一定会执行解码函数decodedImageWithImage。

+ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image {    if (![UIImage shouldDecodeImage:image]) {        return image;    }        // autorelease the bitmap context and all vars to help system to free memory when there are memory warning.    // on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];    @autoreleasepool{                CGImageRef imageRef = image.CGImage;        CGColorSpaceRef colorspaceRef = [UIImage colorSpaceForImageRef:imageRef];                size_t width = CGImageGetWidth(imageRef);        size_t height = CGImageGetHeight(imageRef);        size_t bytesPerRow = kBytesPerPixel * width;        // kCGImageAlphaNone is not supported in CGBitmapContextCreate.        // Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast        // to create bitmap graphics contexts without alpha info.        CGContextRef context = CGBitmapContextCreate(NULL,                                                     width,                                                     height,                                                     kBitsPerComponent,                                                     bytesPerRow,                                                     colorspaceRef,                                                     kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);        if (context == NULL) {            return image;        }                // Draw the image into the context and retrieve the new bitmap image without alpha        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);        CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);        UIImage *imageWithoutAlpha = [UIImage imageWithCGImage:imageRefWithoutAlpha                                                         scale:image.scale                                                   orientation:image.imageOrientation];                CGContextRelease(context);        CGImageRelease(imageRefWithoutAlpha);                return imageWithoutAlpha;    }}

      即在子线程中将图片格式转换为Bitmap, 然后赋值给UIImageView的image参数显示到界面。


      对比一下喵神写的Kingfisher, 并没有这个转码操作,相信以后的版本可能会加上这个Feature。