add animated webP support
This commit is contained in:
parent
6a623cd58f
commit
c2173c1e75
|
@ -173,6 +173,7 @@
|
|||
5D5B9145188EE8DD006D06BD /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D5B9141188EE8DD006D06BD /* NSData+ImageContentType.m */; };
|
||||
5D5B9146188EE8DD006D06BD /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D5B9141188EE8DD006D06BD /* NSData+ImageContentType.m */; };
|
||||
5D5B9147188EE8DD006D06BD /* NSData+ImageContentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D5B9141188EE8DD006D06BD /* NSData+ImageContentType.m */; };
|
||||
750C1B8E1C494AB000DC00B9 /* demux.c in Sources */ = {isa = PBXBuildFile; fileRef = 750C1B8A1C49491900DC00B9 /* demux.c */; };
|
||||
A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = A18A6CC5172DC28500419892 /* UIImage+GIF.h */; };
|
||||
A18A6CC8172DC28500419892 /* UIImage+GIF.h in Headers */ = {isa = PBXBuildFile; fileRef = A18A6CC5172DC28500419892 /* UIImage+GIF.h */; };
|
||||
A18A6CC9172DC28500419892 /* UIImage+GIF.m in Sources */ = {isa = PBXBuildFile; fileRef = A18A6CC6172DC28500419892 /* UIImage+GIF.m */; };
|
||||
|
@ -316,6 +317,7 @@
|
|||
53FB894814D35E9E0020B787 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
5D5B9140188EE8DD006D06BD /* NSData+ImageContentType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+ImageContentType.h"; sourceTree = "<group>"; };
|
||||
5D5B9141188EE8DD006D06BD /* NSData+ImageContentType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+ImageContentType.m"; sourceTree = "<group>"; };
|
||||
750C1B8A1C49491900DC00B9 /* demux.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = demux.c; sourceTree = "<group>"; };
|
||||
A18A6CC5172DC28500419892 /* UIImage+GIF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+GIF.h"; sourceTree = "<group>"; };
|
||||
A18A6CC6172DC28500419892 /* UIImage+GIF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+GIF.m"; sourceTree = "<group>"; };
|
||||
AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+WebCacheOperation.h"; sourceTree = "<group>"; };
|
||||
|
@ -571,6 +573,14 @@
|
|||
name = Utils;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
750C1B891C49491900DC00B9 /* demux */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
750C1B8A1C49491900DC00B9 /* demux.c */,
|
||||
);
|
||||
path = demux;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA577C121998E60B007367ED /* libwebp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -583,6 +593,7 @@
|
|||
DA577C4F1998E60B007367ED /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
750C1B891C49491900DC00B9 /* demux */,
|
||||
DA577D5A1998E6B2007367ED /* dec */,
|
||||
DA577C651998E60B007367ED /* dsp */,
|
||||
DA577CA71998E60B007367ED /* utils */,
|
||||
|
@ -1134,6 +1145,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
750C1B8E1C494AB000DC00B9 /* demux.c in Sources */,
|
||||
DA577D101998E60B007367ED /* upsampling_neon.c in Sources */,
|
||||
DA577D151998E60B007367ED /* yuv_sse2.c in Sources */,
|
||||
DA577D111998E60B007367ED /* upsampling_sse2.c in Sources */,
|
||||
|
|
|
@ -11,8 +11,12 @@
|
|||
|
||||
#if !COCOAPODS
|
||||
#import "webp/decode.h"
|
||||
#import "webp/mux_types.h"
|
||||
#import "webp/demux.h"
|
||||
#else
|
||||
#import "libwebp/webp/decode.h"
|
||||
#import "libwebp/webpc/mux_types.h"
|
||||
#import "libwebp/webp/demux.h"
|
||||
#endif
|
||||
|
||||
// Callback for CGDataProviderRelease
|
||||
|
@ -24,12 +28,101 @@ static void FreeImageData(void *info, const void *data, size_t size)
|
|||
@implementation UIImage (WebP)
|
||||
|
||||
+ (UIImage *)sd_imageWithWebPData:(NSData *)data {
|
||||
if (!data) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
WebPData webpData;
|
||||
WebPDataInit(&webpData);
|
||||
webpData.bytes = data.bytes;
|
||||
webpData.size = data.length;
|
||||
WebPDemuxer *demuxer = WebPDemux(&webpData);
|
||||
if (!demuxer) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
uint32_t flags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
|
||||
if (!(flags & ANIMATION_FLAG)) {
|
||||
// for static single webp image
|
||||
UIImage *staticImage = [self sd_rawWepImageWithData:webpData];
|
||||
WebPDemuxDelete(demuxer);
|
||||
return staticImage;
|
||||
}
|
||||
|
||||
WebPIterator iter;
|
||||
if (!WebPDemuxGetFrame(demuxer, 1, &iter)) {
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
WebPDemuxDelete(demuxer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableArray *images = [NSMutableArray array];
|
||||
NSTimeInterval duration = 0;
|
||||
|
||||
do {
|
||||
UIImage *image;
|
||||
if (iter.blend_method == WEBP_MUX_BLEND) {
|
||||
image = [self sd_blendWebpImageWithOriginImage:[images lastObject] iterator:iter];
|
||||
} else {
|
||||
image = [self sd_rawWepImageWithData:iter.fragment];
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[images addObject:image];
|
||||
duration += iter.duration / 1000.0f;
|
||||
|
||||
} while (WebPDemuxNextFrame(&iter));
|
||||
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
WebPDemuxDelete(demuxer);
|
||||
UIImage *animateImage = [UIImage animatedImageWithImages:images duration:duration];
|
||||
return animateImage;
|
||||
}
|
||||
|
||||
|
||||
+ (UIImage *)sd_blendWebpImageWithOriginImage:(UIImage *)originImage iterator:(WebPIterator)iter
|
||||
{
|
||||
if (!originImage) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGSize size = originImage.size;
|
||||
CGFloat tmpX = iter.x_offset;
|
||||
CGFloat tmpY = size.height - iter.height - iter.y_offset;
|
||||
CGRect imageRect = CGRectMake(tmpX, tmpY, iter.width, iter.height);
|
||||
|
||||
UIImage *image = [self sd_rawWepImageWithData:iter.fragment];
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
|
||||
uint32_t bitmapInfo = iter.has_alpha ? kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast : 0;
|
||||
CGContextRef blendCanvas = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, colorSpaceRef, bitmapInfo);
|
||||
CGContextDrawImage(blendCanvas, CGRectMake(0, 0, size.width, size.height), originImage.CGImage);
|
||||
CGContextDrawImage(blendCanvas, imageRect, image.CGImage);
|
||||
CGImageRef newImageRef = CGBitmapContextCreateImage(blendCanvas);
|
||||
|
||||
image = [UIImage imageWithCGImage:newImageRef];
|
||||
|
||||
CGImageRelease(newImageRef);
|
||||
CGContextRelease(blendCanvas);
|
||||
CGColorSpaceRelease(colorSpaceRef);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
+ (UIImage *)sd_rawWepImageWithData:(WebPData)webpData
|
||||
{
|
||||
WebPDecoderConfig config;
|
||||
if (!WebPInitDecoderConfig(&config)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (WebPGetFeatures(data.bytes, data.length, &config.input) != VP8_STATUS_OK) {
|
||||
if (WebPGetFeatures(webpData.bytes, webpData.size, &config.input) != VP8_STATUS_OK) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -37,7 +130,7 @@ static void FreeImageData(void *info, const void *data, size_t size)
|
|||
config.options.use_threads = 1;
|
||||
|
||||
// Decode the WebP image data into a RGBA value array.
|
||||
if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK) {
|
||||
if (WebPDecode(webpData.bytes, webpData.size, &config) != VP8_STATUS_OK) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue