[iOS]系统升级后应用无法展示WebP格式图片问题

[iOS]系统升级后应用无法展示WebP格式图片问题
资源:

备份:SDWebImage、YYImage

比较惭愧,虽然问题解决了,但并未找到为什么系统升级会导致WebP解析失败的原因,希望知道的朋友分享一下。

情况介绍:
前段时间新供职公司所有线上APP出了一个问题,苹果手机升级11.2后应用中解析WebP格式图片全部失败。
这套APP核心功能是用户DIY家装场景,由于需要网络请求并快速展示大量图片,设计之初就决定使用现在比较流行的WebP格式来提高功能的流畅性。
实话说之前对 WebP不怎么了解,只知道是谷歌(google)开发的一种加快图片加载速度的图片格式,然而苹果并不支持,若一定需要使用 WebP则需要在本地通过代码或工具将之转换为jpg或png。
我的前任公司上个程序员是使用第三方SDWebImage来加载webp,如图一SDWebImage有个WebP.framework框架,在加载网络图片时已经支持 WebP格式。但是SDWebImage对 WebP格式支持得不完美,当然也可能是我们使用的版本有问题。据我向同事了解,以前系统升级时加载 WebP也曾出现过无法解析的问题,那么如今再次出现同样的问题就感觉有点危险。

查看UIImage+WebP.m中解析源码发现,iOS11.1这方法能正常解析Data为image,但iOS11.2这个方法就无法解析Data了。
+ (UIImage *)imageWithWebPData:(NSData *)imgData error:(NSError **)error
{
    // `WebPGetInfo` weill return image width and height
    int width = 0, height = 0;
    if(!WebPGetInfo([imgData bytes], [imgData length], &width, &height)) {
        NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
        [errorDetail setValue:@"Header formatting error." forKey:NSLocalizedDescriptionKey];
        if(error != NULL)
            *error = [NSError errorWithDomain:[NSString stringWithFormat:@"%@.errorDomain",  [[NSBundle mainBundle] bundleIdentifier]] code:-101 userInfo:errorDetail];
        return nil;
    }
    
    WebPDecoderConfig config;
    if(!WebPInitDecoderConfig(&config)) {
        NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
        [errorDetail setValue:@"Failed to initialize structure. Version mismatch." forKey:NSLocalizedDescriptionKey];
        if(error != NULL)
            *error = [NSError errorWithDomain:[NSString stringWithFormat:@"%@.errorDomain",  [[NSBundle mainBundle] bundleIdentifier]] code:-101 userInfo:errorDetail];
        return nil;
    }
    config.options.no_fancy_upsampling = 1;
    config.options.bypass_filtering = 1;
    config.options.use_threads = 1;
    config.output.colorspace = MODE_RGBA;
    
    // Decode the WebP image data into a RGBA value array
    VP8StatusCode decodeStatus = WebPDecode([imgData bytes], [imgData length], &config);
    if (decodeStatus != VP8_STATUS_OK) {
        NSString *errorString = [self statusForVP8Code:decodeStatus];
        NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
        [errorDetail setValue:errorString forKey:NSLocalizedDescriptionKey];
        if(error != NULL)
            *error = [NSError errorWithDomain:[NSString stringWithFormat:@"%@.errorDomain",  [[NSBundle mainBundle] bundleIdentifier]] code:-101 userInfo:errorDetail];
        return nil;
    }
    
    // Construct UIImage from the decoded RGBA value array
    uint8_t *data = WebPDecodeRGBA([imgData bytes], [imgData length], &width, &height);
    CGDataProviderRef provider = CGDataProviderCreateWithData(&config, data, config.options.scaled_width  * config.options.scaled_height * 4, free_image_data);
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault |kCGImageAlphaLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    
    CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, provider, NULL, YES, renderingIntent);
    UIImage *result = [UIImage imageWithCGImage:imageRef];
 
    // Free resources to avoid memory leaks
    CGImageRelease(imageRef);
    CGColorSpaceRelease(colorSpaceRef);
    CGDataProviderRelease(provider);
    WebPFreeDecBuffer(&config.output);
    
    return result;
}
一开始确定是解析失败导致 WebP无法展示时,个人觉得实力不够搞定不了这个问题,感觉很无力。还好当时手上有更重要的项目在限期开发,这问题被压下暂时搁置了几天。经常开玩笑说,这问题要升级最新iOS系统才会发生,“手贱”点升级系统的人活该!

解决方案:
前两天重新思考解决这个问题时,发现很简单并没有想象中复杂。我们已经获取到了 WebP的data,要最小代价的修复问题,只需要重写上面那个解析方法将 WebP的data转换成UIImage并返回就行了,下面主要是按照这个思路。
百度 WebP如何转换成jpg时,发现有人推荐 YYImage支持WebP、APNG、GIF格式动画图像的播放/编码/解码。苹果不是不支持webp格式么,那么这个YYImage的demo中就一定也存在 WebP的data转换Image的方法,只要这个方法与SDWebImage中的方法不一样那么之前的问题就解决了。
如图二发现WebP.framework框架更丰富,查看YYImage.h有方法“+ (nullable YYImage *)imageWithData:(NSData *)data;”。那么导入项目重写方法WebP无法展示的问题就得到了解决。
+ (UIImage *)imageWithWebPData:(NSData *)imgData error:(NSError **)error
{
    UIImage *webpImage = [YYImage imageWithData:imgData];
    return webpImage;
}

[图一]

[图二]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值