本篇文章主要写的是转换过程中遇到的几个令人头疼的问题并解决,转换的和显示的主要代码参考了SDWebImage/Web和# iOS-WebP;
使用的库:'libwebp','~> 1.0.0'
1.遇到的问题及解决
出问题的图片主要是iphone6及以上手机截频的图片,这种图片有一个共同特性:包含Alpha通道;以及少部分不包含Alpha通道且从网络下载的图片。
1> 图片转换后无法显示
这个问题出现在iOS11及以上系统机型。
主要原因:
如下方法中代码:
+ (UIImage *)imageWithWebPData:(NSData *)imgData error:(NSError **)error;
有误代码:
CGDataProviderRef provider = CGDataProviderCreateWithData(config, data, config->options.scaled_width * config->options.scaled_height * 4, free_image_data);
config->options.scaled_width和config->options.scaled_height的值都为0;
解决:
CGDataProviderRef provider = CGDataProviderCreateWithData(&config, data,width * height * 4 , free_image_data);
2> 转换成webP直接在google浏览器显示或者再转换成png显示后的样式
解决:
方法:
+ (NSData *)convertToWebP:(UIImage *)image
compressionQuality:(CGFloat)quality
alpha:(CGFloat)alpha
preset:(WebPPreset)preset
configBlock:(void (^)(WebPConfig *))configBlock
error:(NSError **)error;
旧代码:
if (alpha < 1) {
image = [self webPImage:image withAlpha:alpha];
}
新代码:
image = [self webPImage:image withAlpha:alpha];
修改代码转换后的样式:
依旧有问题。
3> 最后一步
经过测试发现只有将从相册或者拍照获取的图片按照宽 = 320的整倍数,高 = 320 /(原始图片宽/原始图片高)的方式转换后,才能完整的将图片转换为webP并展示。
方法:
+ (NSData *)convertToWebP:(UIImage *)image
compressionQuality:(CGFloat)quality
alpha:(CGFloat)alpha
preset:(WebPPreset)preset
configBlock:(void (^)(WebPConfig *))configBlock
error:(NSError **)error;
加入新的代码:
CGFloat scale = image.size.width / image.size.height;
CGFloat imageWidth = 320 * 2;
if (image.size.width > 1000){
imageWidth = 320 * 3;
}
UIImage *resizeImage = [self imageResize:image size:CGSizeMake(imageWidth,imageWidth/scale)];
resizeImage = [self webPImage:resizeImage withAlpha:alpha];
CGImageRef webPImageRef = resizeImage.CGImage;
新代码转换后的效果:
如果不按这种比列去转换则会出现如下样式:
UIImage *resizeImage = [self imageResize:image size:CGSizeMake(414,736)];
- (UIImage)imageResize:(UIImage)image size:(CGSize)size ;方法实现的代码
+ (UIImage*)imageResize:(UIImage*)image size:(CGSize)size {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
4> 最最最后一步
经过以上散步发现直拖入到项目内部的图片可以正常转换和展示了,但是经过photos框架从相册中获取的图片仍然无法正常转换。
解决办法如下:
UIImage *convertImage = [UIImage imageWithData:UIImageJPEGRepresentation(image, 1.0)];
将从相册中的获取的图片通过UIImageJPEGRepresentation装换成data再转换为UIImage,将现在在的image执行上诉的1,2,3步即可获。
完整代码如下:
+ (NSData *)convertToWebP:(UIImage *)image
compressionQuality:(CGFloat)quality
alpha:(CGFloat)alpha
preset:(WebPPreset)preset
configBlock:(void (^)(WebPConfig *))configBlock
error:(NSError **)error
{
UIImage *convertImage = [UIImage imageWithData:UIImageJPEGRepresentation(image, 1.0)];
CGFloat scale = convertImage.size.width / convertImage.size.height;
CGFloat imageWidth = 320 * 2;
if (convertImage.size.width > 1000){
imageWidth = 320 * 3;
}
UIImage *resizeImage = [self imageResize:convertImage size:CGSizeMake(imageWidth,imageWidth/scale)];
resizeImage = [self webPImage:resizeImage withAlpha:alpha];
CGImageRef webPImageRef = resizeImage.CGImage;
size_t webPBytesPerRow = CGImageGetBytesPerRow(webPImageRef);
size_t webPImageWidth = CGImageGetWidth(webPImageRef);
size_t webPImageHeight = CGImageGetHeight(webPImageRef);
... ...
2.其它
我们服务器为了减小服务器存储图片空间的大小,经过调研选用webP格式图片为最佳的方案。但是同事在调研时未能测试出以上问题。我接手这个问题开始以为是相册框架的问题,经过测试排除。前后总共花了两天时间测试才解决了这个几个坑,以下是demo地址:https://github.com/moreFine/WWWebPConvert。