CGBitmapInfo 在Mac与iOS平台需要区分初始化,不然会解码失败。
+ (nullable UIImage *)sd_rawWebpImageWithData:(WebPData)webpData {
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config)) {
return nil;
}
if (WebPGetFeatures(webpData.bytes, webpData.size, &config.input) != VP8_STATUS_OK) {
return nil;
}
if ([[UIDevice currentDevice].systemVersion floatValue] >=12.0) {
//ios 12中系统api不再兼容24bpp,8bpc的组合,这里让webp无论是否存在alpha通道都输出4个components
config.output.colorspace = MODE_rgbA;
} else {
config.output.colorspace = config.input.has_alpha ? MODE_rgbA : MODE_RGB;
}
config.options.use_threads = 1;
// Decode the WebP image data into a RGBA value array.
if (WebPDecode(webpData.bytes, webpData.size, &config) != VP8_STATUS_OK) {
return nil;
}
int width = config.input.width;
int height = config.input.height;
if (config.options.use_scaling) {
width = config.options.scaled_width;
height = config.options.scaled_height;
}
// Construct a UIImage from the decoded RGBA value array.
CGDataProviderRef provider =
CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
// 这里需要注意,Mac与iOS端 CGBitmapInfo 需要分别处理
#if TARGET_OS_MACCATALYST
CGBitmapInfo bitmapInfo;
// `CGBitmapContextCreate` does not support RGB888 on iOS. Where `CGImageCreate` supports.
if (!config.input.has_alpha) {
// RGB888
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNone;
} else {
// RGBA8888
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
}
#else
CGBitmapInfo bitmapInfo = config.input.has_alpha ? kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast : kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast;
#endif
size_t components = config.input.has_alpha ? 4 : 3;
if ([[UIDevice currentDevice].systemVersion floatValue] >=12.0) {
//同上修改,ios 12中使用MODE_rgbA, components数量与has_alpha无关,均为4
components = 4;
}
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(width, height, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
UIImage *image = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return image;
}
网友评论