Ios 为什么这段代码解压UIImage要比原始方法好得多?
在我的应用程序中,我需要加载大型JPEG图像并以滚动视图显示它们。为了保持UI的响应性,我决定在后台加载图像,然后在主线程上显示它们。为了在背景中完全加载它们,我强制对每个图像进行解压缩。我用这段代码解压了一个图像(注意我的应用程序只有iOS 7,所以我知道在后台线程上使用这些方法是可以的): 然而,我仍然有很长的加载时间、UI口吃和很大的内存压力。我刚刚发现: 这段代码好几个数量级。图像几乎是立即加载的,没有用户界面结巴,内存使用率也大大降低了 所以我的问题有两个:Ios 为什么这段代码解压UIImage要比原始方法好得多?,ios,objective-c,performance,uiimage,Ios,Objective C,Performance,Uiimage,在我的应用程序中,我需要加载大型JPEG图像并以滚动视图显示它们。为了保持UI的响应性,我决定在后台加载图像,然后在主线程上显示它们。为了在背景中完全加载它们,我强制对每个图像进行解压缩。我用这段代码解压了一个图像(注意我的应用程序只有iOS 7,所以我知道在后台线程上使用这些方法是可以的): 然而,我仍然有很长的加载时间、UI口吃和很大的内存压力。我刚刚发现: 这段代码好几个数量级。图像几乎是立即加载的,没有用户界面结巴,内存使用率也大大降低了 所以我的问题有两个: 为什么第二种方法比第一种好
我想你是在视网膜设备上运行的。在
UIGraphicsBeginImageContextWithOptions
中,您询问了默认比例,即主屏幕的比例,即2。这意味着它正在生成一个4倍大的位图。在第二个函数中,以1x比例绘制
尝试将1的刻度传递到
UIGraphicsBeginImageContextWithOptions
,看看您的性能是否相似。。是的,我在视网膜设备上运行,是的,设置scale=1可以提供类似的性能和内存使用。现在我将使用第一种方法,因为我认为无论设备的特性如何,它都会做正确的事情。为了实现这两个方面的最佳效果(速度和美观,以牺牲更多代码为代价),您可能需要显示一个快速1x渲染(甚至是0.5x渲染)如果图像仍在屏幕上,请稍后返回并填充视网膜渲染。例如,请参见(这是iOS 6编程《突破极限》第13章中的内容;今年晚些时候发布时,它将成为iOS 7 PTL中的第9章。)将UIGraphicsBeginImageContextWithOptions更改为scale=1会使图像渲染在放大时质量非常差。使用CGImage的代码以高质量渲染,就像没有使用强制解压缩一样。此外,UIGraphicsBeginImageContextWithOptions指定为不透明,不适用于透明度
+ (UIImage *)decompressedImageFromImage:(UIImage *)image {
UIGraphicsBeginImageContextWithOptions(image.size, YES, 0);
[image drawAtPoint:CGPointZero];
UIImage *decompressedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return decompressedImage;
}
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
CGImageRef imageRef = image.CGImage;
// System only supports RGB, set explicitly and prevent context error
// if the downloaded image is not the supported format
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,
CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef),
8,
// width * 4 will be enough because are in ARGB format, don't read from the image
CGImageGetWidth(imageRef) * 4,
colorSpace,
// kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
// makes system don't need to do extra conversion when displayed.
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpace);
if ( ! context) {
return nil;
}
CGRect rect = (CGRect){CGPointZero, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)};
CGContextDrawImage(context, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [[UIImage alloc] initWithCGImage:decompressedImageRef];
CGImageRelease(decompressedImageRef);
return decompressedImage;
}