图片解码

有两种方式

1、通过获取绘图上下文,将图片绘制到上下文中,然后从上下文中取出这个图片(优点就是,绘图过程会对图片做优化处理)

2、通过CGDataProviderCopyData( CGDataProviderRef cg_nullable provider)进行解码

说明:[UIImage imageNamed:@"name"]得到的图片是已经解码的图片,并且将这个解码好的图片缓存了起来。

第一种实现方式如下:

//将要解码的图片
UIImage *img = [[UIImage alloc] initWithContentsOfFile:@"..."];
CGImageRef imageRef = img.CGImage;
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
        BOOL hasAlpha = NO;
        if (alphaInfo == kCGImageAlphaPremultipliedLast ||
            alphaInfo == kCGImageAlphaPremultipliedFirst ||
            alphaInfo == kCGImageAlphaLast ||
            alphaInfo == kCGImageAlphaFirst) {
            hasAlpha = YES;
        }
        // BGRA8888 (premultiplied) or BGRX8888
        // same as UIGraphicsBeginImageContext() and -[UIView drawRect:]
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
        bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, YYCGColorSpaceGetDeviceRGB(), bitmapInfo);
        if (!context) return NULL;
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); // 图片解码
        CGImageRef newImage = CGBitmapContextCreateImage(context);
        CFRelease(context);
UIImage *decodedImg = [UIImage imageWithCGImage:newImage]; // 解码后的图片

 

第二种方式如下:

//将要解码的图片
UIImage *img = [[UIImage alloc] initWithContentsOfFile:@"..."];
CGImageRef imageRef = img.CGImage;
CGColorSpaceRef space = CGImageGetColorSpace(imageRef);
        size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
        size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
        size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
        CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
        if (bytesPerRow == 0 || width == 0 || height == 0) return NULL;
        
        CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef);
        if (!dataProvider) return NULL;
        CFDataRef data = CGDataProviderCopyData(dataProvider); // 对图片解码
        if (!data) return NULL;
        
        CGDataProviderRef newProvider = CGDataProviderCreateWithCFData(data);
        CFRelease(data);
        if (!newProvider) return NULL;
        
        CGImageRef newImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, newProvider, NULL, false, kCGRenderingIntentDefault);
        CFRelease(newProvider);
UIImage *decodedImg = [UIImage imageWithCGImage:newImage]; // 解码后的图片

 

以上就是手动解码的过程,解码的目的就是为了让图像渲染引擎将图片绘制到屏幕上

如果我们不手动解码,并且图片不是通过[UIImage imageNamed:@"name"]创建的,UIImage是不会对图片进行解码的

那系统是在什么时候解码的呢?

其实显示到屏幕上的图层的绘制是由一个独立与app的渲染引擎操作的,这个引擎只接收解码好的图片,然后只接绘制到屏幕上(可能是出于效率考虑)。那么图片的解码操作也就是在这个图片将要让渲染引擎绘制的时候进行的,这个操作是在app内部完成的。

为什么需要手动解码?

目的只有一个,那就是提高显示过程的效率。如果一个图片已经提前解码好了,那么在显示的过程中,就不需要再次解码了,解码的过程是很消耗性能的,从而提高了图片的加载速度。

 

posted @ 2020-04-21 17:07  zbblogs  阅读(4453)  评论(0编辑  收藏  举报