@@ -88,6 +88,20 @@ static inline CGContextRef _Nullable CreateWebPCanvas(BOOL hasAlpha, CGSize canv
88
88
return canvas;
89
89
}
90
90
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
+
91
105
@interface SDWebPCoderFrame : NSObject
92
106
93
107
@property (nonatomic , assign ) NSUInteger index; // Frame index (zero based)
@@ -126,6 +140,7 @@ @implementation SDImageWebPCoder {
126
140
NSUInteger _currentBlendIndex;
127
141
BOOL _preserveAspectRatio;
128
142
CGSize _thumbnailSize;
143
+ BOOL _limitBytes;
129
144
}
130
145
131
146
- (void )dealloc {
@@ -218,6 +233,24 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
218
233
CGColorSpaceRef colorSpace = [self sd_createColorSpaceWithDemuxer: demuxer];
219
234
int canvasWidth = WebPDemuxGetI (demuxer, WEBP_FF_CANVAS_WIDTH);
220
235
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
+
221
254
// Check whether we need to use thumbnail
222
255
CGSize scaledSize = [SDImageCoderHelper scaledSizeWithImageSize: CGSizeMake (canvasWidth, canvasHeight) scaleSize: thumbnailSize preserveAspectRatio: preserveAspectRatio shouldScaleUp: NO ];
223
256
@@ -245,7 +278,6 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
245
278
return nil ;
246
279
}
247
280
248
- int loopCount = WebPDemuxGetI (demuxer, WEBP_FF_LOOP_COUNT);
249
281
NSMutableArray <SDImageFrame *> *frames = [NSMutableArray array ];
250
282
251
283
do {
@@ -312,6 +344,12 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
312
344
preserveAspectRatio = preserveAspectRatioValue.boolValue ;
313
345
}
314
346
_preserveAspectRatio = preserveAspectRatio;
347
+ NSUInteger limitBytes = 0 ;
348
+ NSNumber *limitBytesValue = options[SDImageCoderDecodeScaleDownLimitBytes];
349
+ if (limitBytesValue != nil ) {
350
+ limitBytes = limitBytesValue.unsignedIntegerValue ;
351
+ }
352
+ _limitBytes = limitBytes;
315
353
_currentBlendIndex = NSNotFound ;
316
354
SD_LOCK_INIT (_lock);
317
355
}
@@ -352,6 +390,15 @@ - (void)updateIncrementalData:(NSData *)data finished:(BOOL)finished {
352
390
[self scanAndCheckFramesValidWithDemuxer: _demux];
353
391
}
354
392
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
+ }
355
402
}
356
403
357
404
- (UIImage *)incrementalDecodedImageWithOptions : (SDImageCoderOptions *)options {
@@ -911,6 +958,21 @@ - (instancetype)initWithAnimatedImageData:(NSData *)data options:(nullable SDIma
911
958
preserveAspectRatio = preserveAspectRatioValue.boolValue ;
912
959
}
913
960
_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
+ }
914
976
_scale = scale;
915
977
_demux = demuxer;
916
978
_imageData = data;
0 commit comments