@@ -88,6 +88,20 @@ static inline CGContextRef _Nullable CreateWebPCanvas(BOOL hasAlpha, CGSize canv
8888 return canvas;
8989}
9090
91+ // TODO, share this logic for multiple coders, or do refactory in v6.0 (The coder plugin should provide image information back to Core, like `CGImageSourceCopyPropertiesAtIndex`)
92+ static inline CGSize SDCalculateScaleDownPixelSize (NSUInteger limitBytes, CGSize originalSize, NSUInteger frameCount, NSUInteger bytesPerPixel) {
93+ if (CGSizeEqualToSize (originalSize, CGSizeZero)) return CGSizeMake (1 , 1 );
94+ NSUInteger totalFramePixelSize = limitBytes / bytesPerPixel / (frameCount ?: 1 );
95+ CGFloat ratio = originalSize.height / originalSize.width ;
96+ CGFloat width = sqrt (totalFramePixelSize / ratio);
97+ CGFloat height = width * ratio;
98+ width = MAX (1 , floor (width));
99+ height = MAX (1 , floor (height));
100+ CGSize size = CGSizeMake (width, height);
101+
102+ return size;
103+ }
104+
91105@interface SDWebPCoderFrame : NSObject
92106
93107@property (nonatomic , assign ) NSUInteger index; // Frame index (zero based)
@@ -126,6 +140,7 @@ @implementation SDImageWebPCoder {
126140 NSUInteger _currentBlendIndex;
127141 BOOL _preserveAspectRatio;
128142 CGSize _thumbnailSize;
143+ BOOL _limitBytes;
129144}
130145
131146- (void )dealloc {
@@ -218,6 +233,24 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
218233 CGColorSpaceRef colorSpace = [self sd_createColorSpaceWithDemuxer: demuxer];
219234 int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
220235 int canvasHeight = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_HEIGHT);
236+ uint32_t frameCount = WebPDemuxGetI (demuxer, WEBP_FF_FRAME_COUNT);
237+ int loopCount = WebPDemuxGetI (demuxer, WEBP_FF_LOOP_COUNT);
238+
239+ NSUInteger limitBytes = 0 ;
240+ NSNumber *limitBytesValue = options[SDImageCoderDecodeScaleDownLimitBytes];
241+ if (limitBytesValue != nil ) {
242+ limitBytes = limitBytesValue.unsignedIntegerValue ;
243+ }
244+ // Scale down to limit bytes if need
245+ if (limitBytes > 0 ) {
246+ // Hack 32 BitsPerPixel
247+ CGSize imageSize = CGSizeMake (canvasWidth, canvasHeight);
248+ CGSize framePixelSize = SDCalculateScaleDownPixelSize (limitBytes, imageSize, frameCount, 4 );
249+ // Override thumbnail size
250+ thumbnailSize = framePixelSize;
251+ preserveAspectRatio = YES ;
252+ }
253+
221254 // Check whether we need to use thumbnail
222255 CGSize scaledSize = [SDImageCoderHelper scaledSizeWithImageSize: CGSizeMake (canvasWidth, canvasHeight) scaleSize: thumbnailSize preserveAspectRatio: preserveAspectRatio shouldScaleUp: NO ];
223256
@@ -245,7 +278,6 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
245278 return nil ;
246279 }
247280
248- int loopCount = WebPDemuxGetI (demuxer, WEBP_FF_LOOP_COUNT);
249281 NSMutableArray <SDImageFrame *> *frames = [NSMutableArray array ];
250282
251283 do {
@@ -312,6 +344,12 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
312344 preserveAspectRatio = preserveAspectRatioValue.boolValue ;
313345 }
314346 _preserveAspectRatio = preserveAspectRatio;
347+ NSUInteger limitBytes = 0 ;
348+ NSNumber *limitBytesValue = options[SDImageCoderDecodeScaleDownLimitBytes];
349+ if (limitBytesValue != nil ) {
350+ limitBytes = limitBytesValue.unsignedIntegerValue ;
351+ }
352+ _limitBytes = limitBytes;
315353 _currentBlendIndex = NSNotFound ;
316354 SD_LOCK_INIT (_lock);
317355 }
@@ -352,6 +390,15 @@ - (void)updateIncrementalData:(NSData *)data finished:(BOOL)finished {
352390 [self scanAndCheckFramesValidWithDemuxer: _demux];
353391 }
354392 SD_UNLOCK (_lock);
393+ // Scale down to limit bytes if need
394+ if (_limitBytes > 0 ) {
395+ // Hack 32 BitsPerPixel
396+ CGSize imageSize = CGSizeMake (_canvasWidth, _canvasHeight);
397+ CGSize framePixelSize = SDCalculateScaleDownPixelSize (_limitBytes, imageSize, _frameCount, 4 );
398+ // Override thumbnail size
399+ _thumbnailSize = framePixelSize;
400+ _preserveAspectRatio = YES ;
401+ }
355402}
356403
357404- (UIImage *)incrementalDecodedImageWithOptions : (SDImageCoderOptions *)options {
@@ -911,6 +958,21 @@ - (instancetype)initWithAnimatedImageData:(NSData *)data options:(nullable SDIma
911958 preserveAspectRatio = preserveAspectRatioValue.boolValue ;
912959 }
913960 _preserveAspectRatio = preserveAspectRatio;
961+ NSUInteger limitBytes = 0 ;
962+ NSNumber *limitBytesValue = options[SDImageCoderDecodeScaleDownLimitBytes];
963+ if (limitBytesValue != nil ) {
964+ limitBytes = limitBytesValue.unsignedIntegerValue ;
965+ }
966+ _limitBytes = limitBytes;
967+ // Scale down to limit bytes if need
968+ if (_limitBytes > 0 ) {
969+ // Hack 32 BitsPerPixel
970+ CGSize imageSize = CGSizeMake (_canvasWidth, _canvasHeight);
971+ CGSize framePixelSize = SDCalculateScaleDownPixelSize (_limitBytes, imageSize, _frameCount, 4 );
972+ // Override thumbnail size
973+ _thumbnailSize = framePixelSize;
974+ _preserveAspectRatio = YES ;
975+ }
914976 _scale = scale;
915977 _demux = demuxer;
916978 _imageData = data;
0 commit comments