iOS上传图片颜色失真问题

app上传前的原图与上传后CDN上压缩图对比颜色有失真
具体描述可见:拒绝黯淡!教你还原iPhone 7照片本色

问题的原因与文中一致, 我们CDN压缩图片是用的sRGB色域, iPhone 7以后用的是Display P3色域
解决方案: 上传前对图片色域进行转换
具体步骤:

  1. 先获取图片源的色域(colorspace)与目标色域(iOS9以上为kCGColorSpaceSRGB, iOS9以下为CGColorSpaceCreateDeviceRGB(), 两者色域相同不处理)
  2. 初始化源图buffer和目标图buffer
  3. 初始化输入色域格式与输出色域格式并构造转换器
  4. 利用转换器和转换函数vImageConvert_AnyToAny生成目标图buffer
  5. 最后通过目标图buffer生成目标图片
    代码如下:
#import <Accelerate/Accelerate.h>

@implementation UIImage (sRGB)

- (UIImage *)mz_convertToSRGBColorSpace
{
    UIImage *newImage = self;
    do {
        CGImageRef CGImage = self.CGImage;
        CGColorSpaceRef srcSpace = CGImageGetColorSpace(CGImage);
        CGColorSpaceRef dstSpace = [UIDevice currentDevice].systemVersion.floatValue >= 9.0 ? CGColorSpaceCreateWithName(kCGColorSpaceSRGB) : CGColorSpaceCreateDeviceRGB();
        
        // 颜色空间一样直接返回 self
        if (CFEqual(srcSpace, CFAutorelease(CGColorSpaceCreateDeviceRGB())) ||
            CFEqual(srcSpace, dstSpace)) {
            CGColorSpaceRelease(dstSpace);
            break;
        }
        
        vImage_Buffer srcBuffer;
        vImage_Buffer dstBuffer;
        
        vImage_CGImageFormat srcFormat = {
            .bitsPerComponent       = (uint32_t)CGImageGetBitsPerComponent(CGImage),
            .bitsPerPixel           = (uint32_t)CGImageGetBitsPerPixel(CGImage),
            .colorSpace             = srcSpace,
            .bitmapInfo             = CGImageGetBitmapInfo(CGImage)
        };
        vImage_CGImageFormat dstFormat = {
            .bitsPerComponent       = (uint32_t)CGImageGetBitsPerComponent(CGImage),
            .bitsPerPixel           = (uint32_t)CGImageGetBitsPerPixel(CGImage),
            .colorSpace             = dstSpace,
            .bitmapInfo             = CGImageGetBitmapInfo(CGImage)
        };
        
        vImage_Error error = kvImageNoError;
        
        error = vImageBuffer_InitWithCGImage(&srcBuffer, &srcFormat, NULL, CGImage, kvImageNoFlags);
        if (error != kvImageNoError) {
            CGColorSpaceRelease(dstSpace);
            break;
        }
        
        vImageConverterRef convertRef = vImageConverter_CreateWithCGImageFormat(&srcFormat, &dstFormat, NULL, kvImageNoFlags, &error);
        if (error != kvImageNoError) {
            free(srcBuffer.data);
            CGColorSpaceRelease(dstSpace);
            break;
        }
        
        error = vImageBuffer_Init(&dstBuffer, srcBuffer.height, srcBuffer.width, dstFormat.bitsPerPixel, kvImageNoFlags);
        if (error != kvImageNoError) {
            free(srcBuffer.data);
            CGColorSpaceRelease(dstSpace);
            vImageConverter_Release(convertRef);
            break;
        }
        
        error = vImageConvert_AnyToAny(convertRef, &srcBuffer, &dstBuffer, NULL, kvImageNoFlags);
        if (error != kvImageNoError) {
            free(srcBuffer.data);
            free(dstBuffer.data);
            CGColorSpaceRelease(dstSpace);
            vImageConverter_Release(convertRef);
            break;
        }
        
        CGImageRef newCGImage = vImageCreateCGImageFromBuffer(&dstBuffer, &dstFormat, NULL, NULL, kvImageNoFlags, &error);
        if (error != kvImageNoError) {
            if (newCGImage) {
                CGImageRelease(newCGImage);
            }
            free(srcBuffer.data);
            free(dstBuffer.data);
            CGColorSpaceRelease(dstSpace);
            vImageConverter_Release(convertRef);
            break;
        }
        newImage = [UIImage imageWithCGImage:newCGImage];
        
        free(srcBuffer.data);
        free(dstBuffer.data);
        CGImageRelease(newCGImage);
        CGColorSpaceRelease(dstSpace);
        vImageConverter_Release(convertRef);
        
    } while(0);
    return newImage;
}

@end

依赖苹果原生图片bitmap处理库Accelerate库, 经测试单张1080px图的处理需要大概10ms左右
源码来源

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 月22日以来湖南遭受了近年来历时最长、范围最广、强度最大的降雨过程,造成全省14个市州120个县市区受灾。据初步统...
    秦嘉卉阅读 444评论 0 0
  • 好歹是读过书的,自然是不信本命年红带趋吉避邪之说。可诸如高晓松之类,常年也红带缠身,或只是笑谈,此不追究。 忆此去...
    1璐有你阅读 348评论 0 1
  • 今日体验,今天一天活很少,总结了一下明天要讲的内容,去其它店学习学习步骤,只为明天能有一个完美的会议。核心,在发展...
    任武科阅读 155评论 0 0

友情链接更多精彩内容