在上面的步骤中,我们提到了图片的解压缩是一个非常耗时的 CPU 操作,并且它默认是在主线程中执行的。那么当需要加载的图片比较多时,就会对我们应用的响应性造成严重的影响,尤其是在快速滑动的列表上,这个问题会表现得更加突出。
为什么需要解压缩
既然图片的解压缩需要消耗大量的 CPU 时间,那么我们为什么还要对图片进行解压缩呢?是否可以不经过解压缩,而直接将图片显示到屏幕上呢?答案是否定的。要想弄明白这个问题,我们首先需要知道什么是位图:
A bitmap image (or sampled image) is an array of pixels (or samples). Each pixel represents a single point in the image. JPEG, TIFF, and PNG graphics files are examples of bitmap images.
// return image as PNG. May return nil if image has no CGImageRef or invalid bitmap formatUIKIT_EXTERNNSData*__nullableUIImagePNGRepresentation(UIImage*__nonnullimage);// return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least) UIKIT_EXTERNNSData*__nullableUIImageJPEGRepresentation(UIImage*__nonnullimage,CGFloatcompressionQuality);
/* Create a bitmap context. The context draws into a bitmap which is `width' pixels wide and `height' pixels high. The number of components for each pixel is specified by `space', which may also specify a destination color profile. The number of bits for each component of a pixel is specified by `bitsPerComponent'. The number of bytes per pixel is equal to `(bitsPerComponent * number of components + 7)/8'. Each row of the bitmap consists of `bytesPerRow' bytes, which must be at least `width * bytes per pixel' bytes; in addition, `bytesPerRow' must be an integer multiple of the number of bytes per pixel. `data', if non-NULL, points to a block of memory at least `bytesPerRow * height' bytes. If `data' is NULL, the data for context is allocated automatically and freed when the context is deallocated. `bitmapInfo' specifies whether the bitmap should contain an alpha channel and how it's to be generated, along with whether the components are floating-point or integer. */CG_EXTERNCGContextRef__nullableCGBitmapContextCreate(void*__nullabledata,size_twidth,size_theight,size_tbitsPerComponent,size_tbytesPerRow,CGColorSpaceRefcg_nullablespace,uint32_tbitmapInfo)CG_AVAILABLE_STARTING(__MAC_10_0,__IPHONE_2_0);
typedefCF_ENUM(uint32_t,CGImageAlphaInfo){kCGImageAlphaNone,/* For example, RGB. */kCGImageAlphaPremultipliedLast,/* For example, premultiplied RGBA */kCGImageAlphaPremultipliedFirst,/* For example, premultiplied ARGB */kCGImageAlphaLast,/* For example, non-premultiplied RGBA */kCGImageAlphaFirst,/* For example, non-premultiplied ARGB */kCGImageAlphaNoneSkipLast,/* For example, RBGX. */kCGImageAlphaNoneSkipFirst,/* For example, XRGB. */kCGImageAlphaOnly/* No color data, alpha data only */};
You use this function to configure the drawing environment for rendering into a bitmap. The format for the bitmap is a ARGB 32-bit integer pixel format using host-byte order. If the opaque parameter is YES, the alpha channel is ignored and the bitmap is treated as fully opaque (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host). Otherwise, each pixel uses a premultipled ARGB format (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host).
CGImageRefYYCGImageCreateDecodedCopy(CGImageRefimageRef,BOOLdecodeForDisplay){...if(decodeForDisplay){// decode with redraw (may lose some precision)CGImageAlphaInfoalphaInfo=CGImageGetAlphaInfo(imageRef)&kCGBitmapAlphaInfoMask;BOOLhasAlpha=NO;if(alphaInfo==kCGImageAlphaPremultipliedLast||alphaInfo==kCGImageAlphaPremultipliedFirst||alphaInfo==kCGImageAlphaLast||alphaInfo==kCGImageAlphaFirst){hasAlpha=YES;}// BGRA8888 (premultiplied) or BGRX8888// same as UIGraphicsBeginImageContext() and -[UIView drawRect:]CGBitmapInfobitmapInfo=kCGBitmapByteOrder32Host;bitmapInfo|=hasAlpha?kCGImageAlphaPremultipliedFirst:kCGImageAlphaNoneSkipFirst;CGContextRefcontext=CGBitmapContextCreate(NULL,width,height,8,0,YYCGColorSpaceGetDeviceRGB(),bitmapInfo);if(!context)returnNULL;CGContextDrawImage(context,CGRectMake(0,0,width,height),imageRef);// decodeCGImageRefnewImage=CGBitmapContextCreateImage(context);CFRelease(context);returnnewImage;}else{...}}