Skip to content

Commit 99064f9

Browse files
committed
Added the support for 5.15.0+ limit bytes feature from SDWebImage Coder Plugin API
1 parent 7087a82 commit 99064f9

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

Example/SDWebImageWebPCoderExample/ViewController.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ - (void)viewDidLoad {
3737
NSURL *staticWebPURL = [NSURL URLWithString:@"https://www.gstatic.com/webp/gallery/2.webp"];
3838
NSURL *animatedWebPURL = [NSURL URLWithString:@"http://littlesvr.ca/apng/images/world-cup-2014-42.webp"];
3939

40-
[self.imageView1 sd_setImageWithURL:staticWebPURL placeholderImage:nil options:0 context:@{SDWebImageContextImageThumbnailPixelSize : @(CGSizeMake(300, 300))} progress:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
40+
[self.imageView1 sd_setImageWithURL:staticWebPURL placeholderImage:nil options:0 context:@{SDWebImageContextImageScaleDownLimitBytes : @(1024 * 100)} progress:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
41+
NSCAssert(image.size.width < 200, @"Limit Bytes should limit image size to 186");
4142
if (image) {
4243
NSLog(@"%@", @"Static WebP load success");
4344
}

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)