@@ -96,6 +96,8 @@ @implementation SDImageWebPCoder {
96
96
BOOL _hasAnimation;
97
97
BOOL _hasAlpha;
98
98
BOOL _finished;
99
+ CGFloat _canvasWidth; // Full Size without thumbnail scale
100
+ CGFloat _canvasHeight; // Full Size without thumbnail scale
99
101
dispatch_semaphore_t _lock;
100
102
NSUInteger _currentBlendIndex;
101
103
BOOL _preserveAspectRatio;
@@ -207,7 +209,15 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
207
209
return firstFrameImage;
208
210
}
209
211
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);
211
221
if (!canvas) {
212
222
WebPDemuxDelete (demuxer);
213
223
CGColorSpaceRelease (colorSpace);
@@ -219,7 +229,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
219
229
220
230
do {
221
231
@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 ];
223
233
if (!imageRef) {
224
234
continue ;
225
235
}
@@ -330,7 +340,7 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
330
340
return nil ;
331
341
}
332
342
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) ;
334
344
if (!canvas) {
335
345
CGImageRelease (imageRef);
336
346
return nil ;
@@ -367,11 +377,17 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
367
377
return image;
368
378
}
369
379
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);
371
382
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);
375
391
376
392
if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
377
393
CGContextClearRect (canvas, imageRect);
@@ -390,16 +406,22 @@ - (void)sd_blendWebpImageWithCanvas:(CGContextRef)canvas iterator:(WebPIterator)
390
406
}
391
407
}
392
408
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 {
394
410
CGImageRef imageRef = [self sd_createWebpImageWithData: iter.fragment colorSpace: colorSpaceRef preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize];
395
411
if (!imageRef) {
396
412
return nil ;
397
413
}
398
414
415
+ size_t canvasWidth = CGBitmapContextGetWidth (canvas);
399
416
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);
403
425
BOOL shouldBlend = iter.blend_method == WEBP_MUX_BLEND;
404
426
405
427
// If not blend, cover the target image rect. (firstly clear then draw)
@@ -520,20 +542,6 @@ - (nonnull CGColorSpaceRef)sd_createColorSpaceWithDemuxer:(nonnull WebPDemuxer *
520
542
return colorSpaceRef;
521
543
}
522
544
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
-
537
545
#pragma mark - Encode
538
546
- (BOOL )canEncodeToFormat : (SDImageFormat)format {
539
547
return (format == SDImageFormatWebP);
@@ -810,6 +818,8 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
810
818
811
819
_hasAnimation = hasAnimation;
812
820
_hasAlpha = hasAlpha;
821
+ _canvasWidth = canvasWidth;
822
+ _canvasHeight = canvasHeight;
813
823
_frameCount = frameCount;
814
824
_loopCount = loopCount;
815
825
@@ -925,8 +935,12 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
925
935
if (!_colorSpace) {
926
936
_colorSpace = [self sd_createColorSpaceWithDemuxer: _demux];
927
937
}
938
+ CGSize canvasFullSize = CGSizeMake (_canvasWidth, _canvasHeight);
928
939
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);
930
944
if (!canvas) {
931
945
return nil ;
932
946
}
@@ -967,7 +981,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
967
981
if (endIndex > startIndex) {
968
982
do {
969
983
@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 ];
971
985
}
972
986
} while ((size_t )iter.frame_num < endIndex && WebPDemuxNextFrame (&iter));
973
987
}
@@ -980,7 +994,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
980
994
_currentBlendIndex = index;
981
995
982
996
// 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 ];
984
998
if (!imageRef) {
985
999
return nil ;
986
1000
}
0 commit comments