Skip to content

Commit f4c0907

Browse files
authored
Merge pull request #75 from SDWebImage/feat/limit_bytes
Added the support for 5.16.0+ limit bytes feature from SDWebImage Coder Plugin API
2 parents 7087a82 + 1d982f6 commit f4c0907

File tree

10 files changed

+78
-28
lines changed

10 files changed

+78
-28
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,27 +74,13 @@ jobs:
7474
- name: Test - ${{ matrix.iosDestination }}
7575
run: |
7676
set -o pipefail
77-
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "Tests iOS" -destination "${{ matrix.iosDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO
77+
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "SDWebImageWebPCoderTests" -destination "${{ matrix.iosDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO
7878
mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/iOS
7979
80-
- name: Test - ${{ matrix.macOSDestination }}
81-
run: |
82-
set -o pipefail
83-
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "Tests Mac" -destination "${{ matrix.macOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO
84-
mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/macOS
85-
86-
- name: Test - ${{ matrix.tvOSDestination }}
87-
run: |
88-
set -o pipefail
89-
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "Tests TV" -destination "${{ matrix.tvOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO
90-
mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/tvOS
91-
9280
- name: Code Coverage
9381
run: |
9482
set -o pipefail
9583
export PATH="/usr/local/opt/curl/bin:$PATH"
9684
curl --version
97-
bash <(curl -s https://codecov.io/bash) -v -D './DerivedData/macOS' -J '^SDWebImageWebPCoder$' -c -X gcov -F macos
9885
bash <(curl -s https://codecov.io/bash) -v -D './DerivedData/iOS' -J '^SDWebImageWebPCoder$' -c -X gcov -F ios
99-
bash <(curl -s https://codecov.io/bash) -v -D './DerivedData/tvOS' -J '^SDWebImageWebPCoder$' -c -X gcov -F tvos
10086

Cartfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github "SDWebImage/SDWebImage" ~> 5.15
1+
github "SDWebImage/SDWebImage" ~> 5.16
22
github "SDWebImage/libwebp-Xcode" ~> 1.0

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.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let package = Package(
1717
dependencies: [
1818
// Dependencies declare other packages that this package depends on.
1919
// .package(url: /* package url */, from: "1.0.0"),
20-
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.15.0"),
20+
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.16.0"),
2121
.package(url: "https://github.com/SDWebImage/libwebp-Xcode.git", from: "1.1.0")
2222
],
2323
targets: [

Podfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ target 'SDWebImageWebPCoderExample' do
88
platform :ios, '9.0'
99
project example_project_path
1010
pod 'SDWebImageWebPCoder', :path => './'
11-
pod 'SDWebImage', :path => '../SDWebImage'
1211
end
1312

1413
target 'SDWebImageWebPCoderTests' do
1514
platform :ios, '9.0'
1615
project test_project_path
1716
pod 'Expecta'
1817
pod 'SDWebImageWebPCoder', :path => './'
19-
pod 'SDWebImage', :path => '../SDWebImage'
2018
end

SDWebImageWebPCoder.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ This is a SDWebImage coder plugin to support WebP image.
2727
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SD_WEBP=1 WEBP_USE_INTRINSICS=1',
2828
'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src'
2929
}
30-
s.dependency 'SDWebImage/Core', '~> 5.15'
30+
s.dependency 'SDWebImage/Core', '~> 5.16'
3131
s.dependency 'libwebp', '~> 1.0'
3232

3333
end

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;

Tests/SDWebImageWebPCoderTests.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ - (void)test32AnimatedImageViewCategoryProgressive {
129129
XCTestExpectation *expectation = [self expectationWithDescription:@"test SDAnimatedImageView view category"];
130130
SDAnimatedImageView *imageView = [SDAnimatedImageView new];
131131
NSURL *testURL = [NSURL URLWithString:@"http://littlesvr.ca/apng/images/SteamEngine.webp"];
132+
NSString *key = [SDWebImageManager.sharedManager cacheKeyForURL:testURL];
133+
[SDImageCache.sharedImageCache removeImageFromMemoryForKey:key];
134+
[SDImageCache.sharedImageCache removeImageFromDiskForKey:key];
132135
[imageView sd_setImageWithURL:testURL placeholderImage:nil options:SDWebImageProgressiveLoad progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
133136
dispatch_async(dispatch_get_main_queue(), ^{
134137
UIImage *image = imageView.image;

Tests/SDWebImageWebPCoderTests.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@
284284
PRODUCT_NAME = SDWebImageWebPCoder;
285285
SDKROOT = iphoneos;
286286
SKIP_INSTALL = YES;
287-
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
288-
TARGETED_DEVICE_FAMILY = "1,2";
287+
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos";
288+
TARGETED_DEVICE_FAMILY = "1,2,3,4";
289289
TVOS_DEPLOYMENT_TARGET = 9.0;
290290
VERSIONING_SYSTEM = "apple-generic";
291291
VERSION_INFO_PREFIX = "";
@@ -358,8 +358,8 @@
358358
PRODUCT_NAME = SDWebImageWebPCoder;
359359
SDKROOT = iphoneos;
360360
SKIP_INSTALL = YES;
361-
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
362-
TARGETED_DEVICE_FAMILY = "1,2";
361+
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvsimulator appletvos";
362+
TARGETED_DEVICE_FAMILY = "1,2,3,4";
363363
TVOS_DEPLOYMENT_TARGET = 9.0;
364364
VALIDATE_PRODUCT = YES;
365365
VERSIONING_SYSTEM = "apple-generic";

0 commit comments

Comments
 (0)