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 

@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左右
源码来源

你可能感兴趣的:(iOS上传图片颜色失真问题)