@@ -96,8 +96,8 @@ @implementation SDImageWebPCoder {
9696 BOOL _hasAnimation;
9797 BOOL _hasAlpha;
9898 BOOL _finished;
99- CGFloat _canvasWidth; // Full Size without thumbnail scale
100- CGFloat _canvasHeight; // Full Size without thumbnail scale
99+ CGFloat _canvasWidth;
100+ CGFloat _canvasHeight;
101101 dispatch_semaphore_t _lock;
102102 NSUInteger _currentBlendIndex;
103103 BOOL _preserveAspectRatio;
@@ -192,10 +192,14 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
192192 return nil ;
193193 }
194194 CGColorSpaceRef colorSpace = [self sd_createColorSpaceWithDemuxer: demuxer];
195+ int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
196+ int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
195197
196198 if (!hasAnimation || decodeFirstFrame) {
197199 // first frame for animated webp image
198- CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpace preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize];
200+ CGSize scaledSize = SDCalculateThumbnailSize (CGSizeMake (canvasWidth, canvasHeight), preserveAspectRatio, thumbnailSize);
201+ // Create thumbnail if need
202+ CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpace scaledSize: scaledSize];
199203 CGColorSpaceRelease (colorSpace);
200204#if SD_UIKIT || SD_WATCH
201205 UIImage *firstFrameImage = [[UIImage alloc ] initWithCGImage: imageRef scale: scale orientation: UIImageOrientationUp];
@@ -209,15 +213,10 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
209213 return firstFrameImage;
210214 }
211215
212- int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
213- int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
214216 BOOL hasAlpha = flags & ALPHA_FLAG;
215217 CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
216218 bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst ;
217-
218- CGSize canvasFullSize = CGSizeMake (canvasWidth, canvasHeight);
219- CGSize canvasSize = SDCalculateThumbnailSize (canvasFullSize, preserveAspectRatio, thumbnailSize);
220- CGContextRef canvas = CGBitmapContextCreate (NULL , canvasSize.width , canvasSize.height , 8 , 0 , [SDImageCoderHelper colorSpaceGetDeviceRGB ], bitmapInfo);
219+ CGContextRef canvas = CGBitmapContextCreate (NULL , canvasWidth, canvasHeight, 8 , 0 , [SDImageCoderHelper colorSpaceGetDeviceRGB ], bitmapInfo);
221220 if (!canvas) {
222221 WebPDemuxDelete (demuxer);
223222 CGColorSpaceRelease (colorSpace);
@@ -229,7 +228,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
229228
230229 do {
231230 @autoreleasepool {
232- CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: canvas iterator: iter colorSpace: colorSpace preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize canvasFullSize: canvasFullSize ];
231+ CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: canvas iterator: iter colorSpace: colorSpace];
233232 if (!imageRef) {
234233 continue ;
235234 }
@@ -377,22 +376,16 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
377376 return image;
378377}
379378
380- - (void )sd_blendWebpImageWithCanvas : (CGContextRef)canvas iterator : (WebPIterator)iter colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef preserveAspectRatio : (BOOL )preserveAspectRatio thumbnailSize : (CGSize)thumbnailSize canvasFullSize : (CGSize)canvasFullSize {
381- size_t canvasWidth = CGBitmapContextGetWidth (canvas);
379+ - (void )sd_blendWebpImageWithCanvas : (CGContextRef)canvas iterator : (WebPIterator)iter colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef {
382380 size_t canvasHeight = CGBitmapContextGetHeight (canvas);
383- CGFloat xScale = canvasWidth / canvasFullSize.width ;
384- CGFloat yScale = canvasHeight / canvasFullSize.height ;
385-
386- CGFloat tmpX = iter.x_offset * xScale;
387- CGFloat tmpY = (canvasFullSize.height - iter.height - iter.y_offset ) * yScale;
388- CGFloat tmpWidth = iter.width * xScale;
389- CGFloat tmpHeight = iter.height * yScale;
390- CGRect imageRect = CGRectMake (tmpX, tmpY, tmpWidth, tmpHeight);
381+ CGFloat tmpX = iter.x_offset ;
382+ CGFloat tmpY = canvasHeight - iter.height - iter.y_offset ;
383+ CGRect imageRect = CGRectMake (tmpX, tmpY, iter.width , iter.height );
391384
392385 if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
393386 CGContextClearRect (canvas, imageRect);
394387 } else {
395- CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpaceRef preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize ];
388+ CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpaceRef scaledSize: CGSizeZero ];
396389 if (!imageRef) {
397390 return ;
398391 }
@@ -406,22 +399,17 @@ - (void)sd_blendWebpImageWithCanvas:(CGContextRef)canvas iterator:(WebPIterator)
406399 }
407400}
408401
409- - (nullable CGImageRef)sd_drawnWebpImageWithCanvas : (CGContextRef)canvas iterator : (WebPIterator)iter colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef preserveAspectRatio : ( BOOL ) preserveAspectRatio thumbnailSize : (CGSize) thumbnailSize canvasFullSize : (CGSize) canvasFullSize CF_RETURNS_RETAINED {
410- CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpaceRef preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize ];
402+ - (nullable CGImageRef)sd_drawnWebpImageWithCanvas : (CGContextRef)canvas iterator : (WebPIterator)iter colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef CF_RETURNS_RETAINED {
403+ CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpaceRef scaledSize: CGSizeZero ];
411404 if (!imageRef) {
412405 return nil ;
413406 }
414407
415- size_t canvasWidth = CGBitmapContextGetWidth (canvas);
416408 size_t canvasHeight = CGBitmapContextGetHeight (canvas);
417- CGFloat xScale = canvasWidth / canvasFullSize.width ;
418- CGFloat yScale = canvasHeight / canvasFullSize.height ;
419-
420- CGFloat tmpX = iter.x_offset * xScale;
421- CGFloat tmpY = (canvasFullSize.height - iter.height - iter.y_offset ) * yScale;
422- CGFloat tmpWidth = iter.width * xScale;
423- CGFloat tmpHeight = iter.height * yScale;
424- CGRect imageRect = CGRectMake (tmpX, tmpY, tmpWidth, tmpHeight);
409+ CGFloat tmpX = iter.x_offset ;
410+ CGFloat tmpY = canvasHeight - iter.height - iter.y_offset ;
411+ CGRect imageRect = CGRectMake (tmpX, tmpY, iter.width , iter.height );
412+
425413 BOOL shouldBlend = iter.blend_method == WEBP_MUX_BLEND;
426414
427415 // If not blend, cover the target image rect. (firstly clear then draw)
@@ -432,15 +420,15 @@ - (nullable CGImageRef)sd_drawnWebpImageWithCanvas:(CGContextRef)canvas iterator
432420 CGImageRef newImageRef = CGBitmapContextCreateImage (canvas);
433421
434422 CGImageRelease (imageRef);
435-
423+
436424 if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
437425 CGContextClearRect (canvas, imageRect);
438426 }
439427
440428 return newImageRef;
441429}
442430
443- - (nullable CGImageRef)sd_createWebpImageWithData : (WebPData)webpData colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef preserveAspectRatio : ( BOOL ) preserveAspectRatio thumbnailSize : ( CGSize)thumbnailSize CF_RETURNS_RETAINED {
431+ - (nullable CGImageRef)sd_createWebpImageWithData : (WebPData)webpData colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef scaledSize : ( CGSize)scaledSize CF_RETURNS_RETAINED {
444432 WebPDecoderConfig config;
445433 if (!WebPInitDecoderConfig (&config)) {
446434 return nil ;
@@ -458,34 +446,28 @@ - (nullable CGImageRef)sd_createWebpImageWithData:(WebPData)webpData colorSpace:
458446 config.options .use_threads = 1 ;
459447 config.output .colorspace = MODE_bgrA;
460448
461- int width = config.input .width ;
462- int height = config.input .height ;
463- CGSize resultSize = SDCalculateThumbnailSize (CGSizeMake (width, height), preserveAspectRatio, thumbnailSize);
464- if (resultSize.width != width || resultSize.height != height) {
465- // Use scaling
449+ // Use scaling for thumbnail
450+ if (scaledSize.width != 0 && scaledSize.height != 0 ) {
466451 config.options .use_scaling = 1 ;
467- config.options .scaled_width = resultSize .width ;
468- config.options .scaled_height = resultSize .height ;
452+ config.options .scaled_width = scaledSize .width ;
453+ config.options .scaled_height = scaledSize .height ;
469454 }
470455
471456 // Decode the WebP image data into a RGBA value array
472457 if (WebPDecode (webpData.bytes , webpData.size , &config) != VP8_STATUS_OK) {
473458 return nil ;
474459 }
475460
476- if (config.options .use_scaling ) {
477- width = config.options .scaled_width ;
478- height = config.options .scaled_height ;
479- }
480-
481461 // Construct a UIImage from the decoded RGBA value array
482462 CGDataProviderRef provider =
483463 CGDataProviderCreateWithData (NULL , config.output .u .RGBA .rgba , config.output .u .RGBA .size , FreeImageData);
484464 size_t bitsPerComponent = 8 ;
485465 size_t bitsPerPixel = 32 ;
486466 size_t bytesPerRow = config.output .u .RGBA .stride ;
467+ size_t width = config.output .width ;
468+ size_t height = config.output .height ;
487469 CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault ;
488- CGImageRef imageRef = CGImageCreate (resultSize. width , resultSize. height , bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL , NO , renderingIntent);
470+ CGImageRef imageRef = CGImageCreate (width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL , NO , renderingIntent);
489471
490472 CGDataProviderRelease (provider);
491473
@@ -917,7 +899,8 @@ - (UIImage *)safeStaticImageFrame {
917899 WebPDemuxReleaseIterator (&iter);
918900 return nil ;
919901 }
920- CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize];
902+ CGSize scaledSize = SDCalculateThumbnailSize (CGSizeMake (_canvasWidth, _canvasHeight), _preserveAspectRatio, _thumbnailSize);
903+ CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: _colorSpace scaledSize: scaledSize];
921904 if (!imageRef) {
922905 return nil ;
923906 }
@@ -935,12 +918,10 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
935918 if (!_colorSpace) {
936919 _colorSpace = [self sd_createColorSpaceWithDemuxer: _demux];
937920 }
938- CGSize canvasFullSize = CGSizeMake (_canvasWidth, _canvasHeight);
939921 if (!_canvas) {
940922 CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
941923 bitmapInfo |= _hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst ;
942- CGSize canvasSize = SDCalculateThumbnailSize (canvasFullSize, _preserveAspectRatio, _thumbnailSize);
943- CGContextRef canvas = CGBitmapContextCreate (NULL , canvasSize.width , canvasSize.height , 8 , 0 , [SDImageCoderHelper colorSpaceGetDeviceRGB ], bitmapInfo);
924+ CGContextRef canvas = CGBitmapContextCreate (NULL , _canvasWidth, _canvasHeight, 8 , 0 , [SDImageCoderHelper colorSpaceGetDeviceRGB ], bitmapInfo);
944925 if (!canvas) {
945926 return nil ;
946927 }
@@ -981,7 +962,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
981962 if (endIndex > startIndex) {
982963 do {
983964 @autoreleasepool {
984- [self sd_blendWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize canvasFullSize: canvasFullSize ];
965+ [self sd_blendWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace];
985966 }
986967 } while ((size_t )iter.frame_num < endIndex && WebPDemuxNextFrame (&iter));
987968 }
@@ -994,7 +975,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
994975 _currentBlendIndex = index;
995976
996977 // Now the canvas is ready, which respects of dispose method behavior. Just do normal decoding and produce image.
997- CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize canvasFullSize: canvasFullSize ];
978+ CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace];
998979 if (!imageRef) {
999980 return nil ;
1000981 }
0 commit comments