@@ -96,6 +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
99101 dispatch_semaphore_t _lock;
100102 NSUInteger _currentBlendIndex;
101103 BOOL _preserveAspectRatio;
@@ -207,7 +209,15 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
207209 return firstFrameImage;
208210 }
209211
210- CGContextRef canvas = [self sd_createCanvasWithDemuxer: demuxer colorSpace: colorSpace preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize];
212+ int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
213+ int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
214+ BOOL hasAlpha = flags & ALPHA_FLAG;
215+ CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
216+ 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);
211221 if (!canvas) {
212222 WebPDemuxDelete (demuxer);
213223 CGColorSpaceRelease (colorSpace);
@@ -219,7 +229,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
219229
220230 do {
221231 @autoreleasepool {
222- CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: canvas iterator: iter colorSpace: colorSpace preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize];
232+ CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: canvas iterator: iter colorSpace: colorSpace preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize canvasFullSize: canvasFullSize ];
223233 if (!imageRef) {
224234 continue ;
225235 }
@@ -330,7 +340,7 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
330340 return nil ;
331341 }
332342
333- CGContextRef canvas = [ self sd_createCanvasWithDemuxer: _demux colorSpace: colorSpaceRef preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize] ;
343+ CGContextRef canvas = CGBitmapContextCreate ( NULL , width, height, 8 , 0 , [SDImageCoderHelper colorSpaceGetDeviceRGB ], bitmapInfo) ;
334344 if (!canvas) {
335345 CGImageRelease (imageRef);
336346 return nil ;
@@ -367,11 +377,17 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
367377 return image;
368378}
369379
370- - (void )sd_blendWebpImageWithCanvas : (CGContextRef)canvas iterator : (WebPIterator)iter colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef preserveAspectRatio : (BOOL )preserveAspectRatio thumbnailSize : (CGSize)thumbnailSize {
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);
371382 size_t canvasHeight = CGBitmapContextGetHeight (canvas);
372- CGFloat tmpX = iter.x_offset ;
373- CGFloat tmpY = canvasHeight - iter.height - iter.y_offset ;
374- CGRect imageRect = CGRectMake (tmpX, tmpY, iter.width , iter.height );
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);
375391
376392 if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
377393 CGContextClearRect (canvas, imageRect);
@@ -390,16 +406,22 @@ - (void)sd_blendWebpImageWithCanvas:(CGContextRef)canvas iterator:(WebPIterator)
390406 }
391407}
392408
393- - (nullable CGImageRef)sd_drawnWebpImageWithCanvas : (CGContextRef)canvas iterator : (WebPIterator)iter colorSpace : (nonnull CGColorSpaceRef)colorSpaceRef preserveAspectRatio : (BOOL )preserveAspectRatio thumbnailSize : (CGSize)thumbnailSize CF_RETURNS_RETAINED {
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 {
394410 CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpaceRef preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize];
395411 if (!imageRef) {
396412 return nil ;
397413 }
398414
415+ size_t canvasWidth = CGBitmapContextGetWidth (canvas);
399416 size_t canvasHeight = CGBitmapContextGetHeight (canvas);
400- CGFloat tmpX = iter.x_offset ;
401- CGFloat tmpY = canvasHeight - iter.height - iter.y_offset ;
402- CGRect imageRect = CGRectMake (tmpX, tmpY, iter.width , iter.height );
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);
403425 BOOL shouldBlend = iter.blend_method == WEBP_MUX_BLEND;
404426
405427 // If not blend, cover the target image rect. (firstly clear then draw)
@@ -520,20 +542,6 @@ - (nonnull CGColorSpaceRef)sd_createColorSpaceWithDemuxer:(nonnull WebPDemuxer *
520542 return colorSpaceRef;
521543}
522544
523- - (CGContextRef)sd_createCanvasWithDemuxer : (nonnull WebPDemuxer *)demuxer colorSpace : (nonnull CGColorSpaceRef)colorSpace preserveAspectRatio : (BOOL )preserveAspectRatio thumbnailSize : (CGSize)thumbnailSize CF_RETURNS_RETAINED {
524- uint32_t flags = WebPDemuxGetI (demuxer, WEBP_FF_FORMAT_FLAGS);
525- int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
526- int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
527- BOOL hasAlpha = flags & ALPHA_FLAG;
528- CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
529- bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst ;
530-
531- CGSize canvasSize = SDCalculateThumbnailSize (CGSizeMake (canvasWidth, canvasHeight), preserveAspectRatio, thumbnailSize);
532- CGContextRef canvas = CGBitmapContextCreate (NULL , canvasSize.width , canvasSize.height , 8 , 0 , colorSpace, bitmapInfo);
533-
534- return canvas;
535- }
536-
537545#pragma mark - Encode
538546- (BOOL )canEncodeToFormat : (SDImageFormat)format {
539547 return (format == SDImageFormatWebP);
@@ -810,6 +818,8 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
810818
811819 _hasAnimation = hasAnimation;
812820 _hasAlpha = hasAlpha;
821+ _canvasWidth = canvasWidth;
822+ _canvasHeight = canvasHeight;
813823 _frameCount = frameCount;
814824 _loopCount = loopCount;
815825
@@ -925,8 +935,12 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
925935 if (!_colorSpace) {
926936 _colorSpace = [self sd_createColorSpaceWithDemuxer: _demux];
927937 }
938+ CGSize canvasFullSize = CGSizeMake (_canvasWidth, _canvasHeight);
928939 if (!_canvas) {
929- CGContextRef canvas = [self sd_createCanvasWithDemuxer: _demux colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize];
940+ CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
941+ 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);
930944 if (!canvas) {
931945 return nil ;
932946 }
@@ -967,7 +981,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
967981 if (endIndex > startIndex) {
968982 do {
969983 @autoreleasepool {
970- [self sd_blendWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize];
984+ [self sd_blendWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize canvasFullSize: canvasFullSize ];
971985 }
972986 } while ((size_t )iter.frame_num < endIndex && WebPDemuxNextFrame (&iter));
973987 }
@@ -980,7 +994,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
980994 _currentBlendIndex = index;
981995
982996 // Now the canvas is ready, which respects of dispose method behavior. Just do normal decoding and produce image.
983- CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize];
997+ CGImageRef imageRef = [self sd_drawnWebpImageWithCanvas: _canvas iterator: iter colorSpace: _colorSpace preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize canvasFullSize: canvasFullSize ];
984998 if (!imageRef) {
985999 return nil ;
9861000 }
0 commit comments