@@ -96,8 +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
+ CGFloat _canvasWidth;
100
+ CGFloat _canvasHeight;
101
101
dispatch_semaphore_t _lock;
102
102
NSUInteger _currentBlendIndex;
103
103
BOOL _preserveAspectRatio;
@@ -192,10 +192,14 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
192
192
return nil ;
193
193
}
194
194
CGColorSpaceRef colorSpace = [self sd_createColorSpaceWithDemuxer: demuxer];
195
+ int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
196
+ int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
195
197
196
198
if (!hasAnimation || decodeFirstFrame) {
197
199
// 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];
199
203
CGColorSpaceRelease (colorSpace);
200
204
#if SD_UIKIT || SD_WATCH
201
205
UIImage *firstFrameImage = [[UIImage alloc ] initWithCGImage: imageRef scale: scale orientation: UIImageOrientationUp];
@@ -209,15 +213,10 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
209
213
return firstFrameImage;
210
214
}
211
215
212
- int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
213
- int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
214
216
BOOL hasAlpha = flags & ALPHA_FLAG;
215
217
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
216
218
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);
221
220
if (!canvas) {
222
221
WebPDemuxDelete (demuxer);
223
222
CGColorSpaceRelease (colorSpace);
@@ -229,7 +228,7 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
229
228
230
229
do {
231
230
@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];
233
232
if (!imageRef) {
234
233
continue ;
235
234
}
@@ -377,22 +376,16 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
377
376
return image;
378
377
}
379
378
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 {
382
380
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 );
391
384
392
385
if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
393
386
CGContextClearRect (canvas, imageRect);
394
387
} 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 ];
396
389
if (!imageRef) {
397
390
return ;
398
391
}
@@ -406,22 +399,17 @@ - (void)sd_blendWebpImageWithCanvas:(CGContextRef)canvas iterator:(WebPIterator)
406
399
}
407
400
}
408
401
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 ];
411
404
if (!imageRef) {
412
405
return nil ;
413
406
}
414
407
415
- size_t canvasWidth = CGBitmapContextGetWidth (canvas);
416
408
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
+
425
413
BOOL shouldBlend = iter.blend_method == WEBP_MUX_BLEND;
426
414
427
415
// If not blend, cover the target image rect. (firstly clear then draw)
@@ -432,15 +420,15 @@ - (nullable CGImageRef)sd_drawnWebpImageWithCanvas:(CGContextRef)canvas iterator
432
420
CGImageRef newImageRef = CGBitmapContextCreateImage (canvas);
433
421
434
422
CGImageRelease (imageRef);
435
-
423
+
436
424
if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
437
425
CGContextClearRect (canvas, imageRect);
438
426
}
439
427
440
428
return newImageRef;
441
429
}
442
430
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 {
444
432
WebPDecoderConfig config;
445
433
if (!WebPInitDecoderConfig (&config)) {
446
434
return nil ;
@@ -458,34 +446,28 @@ - (nullable CGImageRef)sd_createWebpImageWithData:(WebPData)webpData colorSpace:
458
446
config.options .use_threads = 1 ;
459
447
config.output .colorspace = MODE_bgrA;
460
448
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 ) {
466
451
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 ;
469
454
}
470
455
471
456
// Decode the WebP image data into a RGBA value array
472
457
if (WebPDecode (webpData.bytes , webpData.size , &config) != VP8_STATUS_OK) {
473
458
return nil ;
474
459
}
475
460
476
- if (config.options .use_scaling ) {
477
- width = config.options .scaled_width ;
478
- height = config.options .scaled_height ;
479
- }
480
-
481
461
// Construct a UIImage from the decoded RGBA value array
482
462
CGDataProviderRef provider =
483
463
CGDataProviderCreateWithData (NULL , config.output .u .RGBA .rgba , config.output .u .RGBA .size , FreeImageData);
484
464
size_t bitsPerComponent = 8 ;
485
465
size_t bitsPerPixel = 32 ;
486
466
size_t bytesPerRow = config.output .u .RGBA .stride ;
467
+ size_t width = config.output .width ;
468
+ size_t height = config.output .height ;
487
469
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);
489
471
490
472
CGDataProviderRelease (provider);
491
473
@@ -917,7 +899,8 @@ - (UIImage *)safeStaticImageFrame {
917
899
WebPDemuxReleaseIterator (&iter);
918
900
return nil ;
919
901
}
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];
921
904
if (!imageRef) {
922
905
return nil ;
923
906
}
@@ -935,12 +918,10 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
935
918
if (!_colorSpace) {
936
919
_colorSpace = [self sd_createColorSpaceWithDemuxer: _demux];
937
920
}
938
- CGSize canvasFullSize = CGSizeMake (_canvasWidth, _canvasHeight);
939
921
if (!_canvas) {
940
922
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host ;
941
923
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);
944
925
if (!canvas) {
945
926
return nil ;
946
927
}
@@ -981,7 +962,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
981
962
if (endIndex > startIndex) {
982
963
do {
983
964
@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];
985
966
}
986
967
} while ((size_t )iter.frame_num < endIndex && WebPDemuxNextFrame (&iter));
987
968
}
@@ -994,7 +975,7 @@ - (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
994
975
_currentBlendIndex = index;
995
976
996
977
// 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];
998
979
if (!imageRef) {
999
980
return nil ;
1000
981
}
0 commit comments