Skip to content

Commit 5317375

Browse files
authored
Merge pull request #49 from AaaK00/webp-options
Added new encoding options to WebP encoding
2 parents 779dd7d + de7ba8d commit 5317375

File tree

6 files changed

+352
-7
lines changed

6 files changed

+352
-7
lines changed

SDWebImageWebPCoder.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
220A623A257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; };
11+
220A623B257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; };
12+
220A623C257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; };
13+
220A623D257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; };
14+
220A623E257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; };
15+
220A623F257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; };
16+
220A6240257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; };
17+
228EA36125825A52005903D9 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; };
1018
806E77B32136A2E900A316D2 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 806E77AA2136A2E900A316D2 /* UIImage+WebP.m */; };
1119
806E77B42136A2E900A316D2 /* SDImageWebPCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 806E77AB2136A2E900A316D2 /* SDImageWebPCoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
1220
806E77B62136A2E900A316D2 /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 806E77AD2136A2E900A316D2 /* UIImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -38,6 +46,8 @@
3846
/* End PBXBuildFile section */
3947

4048
/* Begin PBXFileReference section */
49+
220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageWebPCoderDefine.m; sourceTree = "<group>"; };
50+
220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageWebPCoderDefine.h; sourceTree = "<group>"; };
4151
28D8AA3D3015E075692FD3E3 /* Pods-SDWebImageWebPCoderTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageWebPCoderTests.debug.xcconfig"; path = "Tests/Pods/Target Support Files/Pods-SDWebImageWebPCoderTests/Pods-SDWebImageWebPCoderTests.debug.xcconfig"; sourceTree = "<group>"; };
4252
3217BE7B220547EB003D0310 /* SDWebImageWebPCoder.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = SDWebImageWebPCoder.modulemap; sourceTree = "<group>"; };
4353
46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageWebPCoderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -146,6 +156,8 @@
146156
806E77A92136A2E900A316D2 /* Classes */ = {
147157
isa = PBXGroup;
148158
children = (
159+
220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */,
160+
220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */,
149161
806E77AB2136A2E900A316D2 /* SDImageWebPCoder.h */,
150162
806E77AE2136A2E900A316D2 /* SDImageWebPCoder.m */,
151163
806E77AD2136A2E900A316D2 /* UIImage+WebP.h */,
@@ -228,6 +240,7 @@
228240
files = (
229241
806E77C72136A7AD00A316D2 /* SDWebImageWebPCoder.h in Headers */,
230242
806E77B62136A2E900A316D2 /* UIImage+WebP.h in Headers */,
243+
220A623D257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */,
231244
806E77B42136A2E900A316D2 /* SDImageWebPCoder.h in Headers */,
232245
);
233246
runOnlyForDeploymentPostprocessing = 0;
@@ -238,6 +251,7 @@
238251
files = (
239252
80BFF2502136BC1500B95470 /* UIImage+WebP.h in Headers */,
240253
80BFF24D2136BC0600B95470 /* SDWebImageWebPCoder.h in Headers */,
254+
220A623E257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */,
241255
80BFF24E2136BC1000B95470 /* SDImageWebPCoder.h in Headers */,
242256
);
243257
runOnlyForDeploymentPostprocessing = 0;
@@ -248,6 +262,7 @@
248262
files = (
249263
80BFF2632136BE2200B95470 /* SDWebImageWebPCoder.h in Headers */,
250264
80BFF2612136BE1C00B95470 /* UIImage+WebP.h in Headers */,
265+
220A623F257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */,
251266
80BFF25F2136BE1700B95470 /* SDImageWebPCoder.h in Headers */,
252267
);
253268
runOnlyForDeploymentPostprocessing = 0;
@@ -258,6 +273,7 @@
258273
files = (
259274
80BFF27F2136BEF200B95470 /* SDWebImageWebPCoder.h in Headers */,
260275
80BFF27D2136BEED00B95470 /* UIImage+WebP.h in Headers */,
276+
220A6240257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */,
261277
80BFF27B2136BEE700B95470 /* SDImageWebPCoder.h in Headers */,
262278
);
263279
runOnlyForDeploymentPostprocessing = 0;
@@ -416,6 +432,7 @@
416432
isa = PBXSourcesBuildPhase;
417433
buildActionMask = 2147483647;
418434
files = (
435+
228EA36125825A52005903D9 /* SDWebImageWebPCoderDefine.m in Sources */,
419436
806E77B72136A2E900A316D2 /* SDImageWebPCoder.m in Sources */,
420437
806E77B32136A2E900A316D2 /* UIImage+WebP.m in Sources */,
421438
);
@@ -425,6 +442,7 @@
425442
isa = PBXSourcesBuildPhase;
426443
buildActionMask = 2147483647;
427444
files = (
445+
220A623A257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */,
428446
80BFF24F2136BC1300B95470 /* SDImageWebPCoder.m in Sources */,
429447
80BFF2512136BC1800B95470 /* UIImage+WebP.m in Sources */,
430448
);
@@ -434,6 +452,7 @@
434452
isa = PBXSourcesBuildPhase;
435453
buildActionMask = 2147483647;
436454
files = (
455+
220A623B257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */,
437456
80BFF2602136BE1A00B95470 /* SDImageWebPCoder.m in Sources */,
438457
80BFF2622136BE1F00B95470 /* UIImage+WebP.m in Sources */,
439458
);
@@ -443,6 +462,7 @@
443462
isa = PBXSourcesBuildPhase;
444463
buildActionMask = 2147483647;
445464
files = (
465+
220A623C257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */,
446466
80BFF27C2136BEEB00B95470 /* SDImageWebPCoder.m in Sources */,
447467
80BFF27E2136BEF000B95470 /* UIImage+WebP.m in Sources */,
448468
);

SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#endif
2424

2525
#import <Accelerate/Accelerate.h>
26+
#import "SDWebImageWebPCoderDefine.h"
2627

2728
/// Calculate the actual thumnail pixel size
2829
static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio, CGSize thumbnailSize) {
@@ -617,7 +618,11 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
617618
BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue];
618619
if (encodeFirstFrame || frames.count == 0) {
619620
// for static single webp image
620-
data = [self sd_encodedWebpDataWithImage:image.CGImage quality:compressionQuality maxPixelSize:maxPixelSize maxFileSize:maxFileSize];
621+
data = [self sd_encodedWebpDataWithImage:image.CGImage
622+
quality:compressionQuality
623+
maxPixelSize:maxPixelSize
624+
maxFileSize:maxFileSize
625+
options:options];
621626
} else {
622627
// for animated webp image
623628
WebPMux *mux = WebPMuxNew();
@@ -626,7 +631,11 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
626631
}
627632
for (size_t i = 0; i < frames.count; i++) {
628633
SDImageFrame *currentFrame = frames[i];
629-
NSData *webpData = [self sd_encodedWebpDataWithImage:currentFrame.image.CGImage quality:compressionQuality maxPixelSize:maxPixelSize maxFileSize:maxFileSize];
634+
NSData *webpData = [self sd_encodedWebpDataWithImage:currentFrame.image.CGImage
635+
quality:compressionQuality
636+
maxPixelSize:maxPixelSize
637+
maxFileSize:maxFileSize
638+
options:options];
630639
int duration = currentFrame.duration * 1000;
631640
WebPMuxFrameInfo frame = { .bitstream.bytes = webpData.bytes,
632641
.bitstream.size = webpData.length,
@@ -663,7 +672,12 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
663672
return data;
664673
}
665674

666-
- (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef quality:(double)quality maxPixelSize:(CGSize)maxPixelSize maxFileSize:(NSUInteger)maxFileSize {
675+
- (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef
676+
quality:(double)quality
677+
maxPixelSize:(CGSize)maxPixelSize
678+
maxFileSize:(NSUInteger)maxFileSize
679+
options:(nullable SDImageCoderOptions *)options
680+
{
667681
NSData *webpData;
668682
if (!imageRef) {
669683
return nil;
@@ -779,10 +793,7 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
779793
return nil;
780794
}
781795

782-
config.target_size = (int)maxFileSize; // Max filesize for output, 0 means use quality instead
783-
config.pass = maxFileSize > 0 ? 6 : 1; // Use 6 passes for file size limited encoding, which is the default value of `cwebp` command line
784-
config.thread_level = 1; // Thread encoding for fast
785-
config.lossless = 0; // Disable lossless encoding (If we need, can add new Encoding Options in future version)
796+
[self updateWebPOptionsToConfig:&config maxFileSize:maxFileSize options:options];
786797
picture.use_argb = 0; // Lossy encoding use YUV for internel bitstream
787798
picture.width = (int)width;
788799
picture.height = (int)height;
@@ -830,6 +841,89 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
830841
return webpData;
831842
}
832843

844+
- (void) updateWebPOptionsToConfig:(WebPConfig * _Nonnull)config
845+
maxFileSize:(NSUInteger)maxFileSize
846+
options:(nullable SDImageCoderOptions *)options {
847+
848+
config->target_size = (int)maxFileSize; // Max filesize for output, 0 means use quality instead
849+
config->pass = maxFileSize > 0 ? 6 : 1; // Use 6 passes for file size limited encoding, which is the default value of `cwebp` command line
850+
config->lossless = 0; // Disable lossless encoding (If we need, can add new Encoding Options in future version)
851+
852+
if ([options[SDImageCoderEncodeWebPMethod] intValue]) {
853+
config->method = [options[SDImageCoderEncodeWebPMethod] intValue];
854+
}
855+
if ([options[SDImageCoderEncodeWebPPass] intValue]) {
856+
config->pass = [options[SDImageCoderEncodeWebPPass] intValue];
857+
}
858+
if ([options[SDImageCoderEncodeWebPPreprocessing] intValue]) {
859+
config->preprocessing = [options[SDImageCoderEncodeWebPPreprocessing] intValue];
860+
}
861+
if ([options[SDImageCoderEncodeWebPThreadLevel] intValue]) {
862+
config->thread_level = [options[SDImageCoderEncodeWebPThreadLevel] intValue];
863+
} else {
864+
config->thread_level = 1;
865+
}
866+
if ([options[SDImageCoderEncodeWebPLowMemory] intValue]) {
867+
config->low_memory = [options[SDImageCoderEncodeWebPLowMemory] intValue];
868+
}
869+
870+
if ([options[SDImageCoderEncodeWebPTargetPSNR] floatValue]) {
871+
config->target_PSNR = [options[SDImageCoderEncodeWebPTargetPSNR] floatValue];
872+
}
873+
874+
if ([options[SDImageCoderEncodeWebPSegments] intValue]) {
875+
config->segments = [options[SDImageCoderEncodeWebPSegments] intValue];
876+
}
877+
878+
if ([options[SDImageCoderEncodeWebPSnsStrength] intValue]) {
879+
config->sns_strength = [options[SDImageCoderEncodeWebPSnsStrength] intValue];
880+
}
881+
882+
if ([options[SDImageCoderEncodeWebPFilterStrength] intValue]) {
883+
config->filter_strength = [options[SDImageCoderEncodeWebPFilterStrength] intValue];
884+
}
885+
886+
if ([options[SDImageCoderEncodeWebPFilterSharpness] intValue]) {
887+
config->filter_sharpness = [options[SDImageCoderEncodeWebPFilterSharpness] intValue];
888+
}
889+
890+
if ([options[SDImageCoderEncodeWebPFilterType] intValue]) {
891+
config->filter_type = [options[SDImageCoderEncodeWebPFilterType] intValue];
892+
}
893+
894+
if ([options[SDImageCoderEncodeWebPAutofilter] intValue]) {
895+
config->autofilter = [options[SDImageCoderEncodeWebPAutofilter] intValue];
896+
}
897+
898+
if ([options[SDImageCoderEncodeWebPAlphaCompression] intValue]) {
899+
config->alpha_compression = [options[SDImageCoderEncodeWebPAlphaCompression] intValue];
900+
}
901+
902+
if ([options[SDImageCoderEncodeWebPAlphaFiltering] intValue]) {
903+
config->alpha_filtering = [options[SDImageCoderEncodeWebPAlphaFiltering] intValue];
904+
}
905+
906+
if ([options[SDImageCoderEncodeWebPAlphaQuality] intValue]) {
907+
config->alpha_quality = [options[SDImageCoderEncodeWebPAlphaQuality] intValue];
908+
}
909+
910+
if ([options[SDImageCoderEncodeWebPShowCompressed] intValue]) {
911+
config->show_compressed = [options[SDImageCoderEncodeWebPShowCompressed] intValue];
912+
}
913+
914+
if ([options[SDImageCoderEncodeWebPPartitions] intValue]) {
915+
config->partitions = [options[SDImageCoderEncodeWebPPartitions] intValue];
916+
}
917+
918+
if ([options[SDImageCoderEncodeWebPPartitionLimit] intValue]) {
919+
config->partition_limit = [options[SDImageCoderEncodeWebPPartitionLimit] intValue];
920+
}
921+
922+
if ([options[SDImageCoderEncodeWebPUseSharpYuv] intValue]) {
923+
config->use_sharp_yuv = [options[SDImageCoderEncodeWebPUseSharpYuv] intValue];
924+
}
925+
}
926+
833927
static void FreeImageData(void *info, const void *data, size_t size) {
834928
free((void *)data);
835929
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//
2+
// SDWebImageWebPCoderDefine.h
3+
// SDWebImageWebPCoderDefine
4+
//
5+
// Created by Antti Kortetmaa on 2020/12/06.
6+
//
7+
8+
#if __has_include(<SDWebImage/SDWebImage.h>)
9+
#import <SDWebImage/SDWebImage.h>
10+
#else
11+
@import SDWebImage;
12+
#endif
13+
14+
NS_ASSUME_NONNULL_BEGIN
15+
16+
/**
17+
Integer value
18+
Quality/speed trade-off (0=fast, 6=slower-better)
19+
*/
20+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPMethod;
21+
22+
/**
23+
Integer value
24+
Number of entropy-analysis passes (in [1..10])
25+
*/
26+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPass;
27+
28+
/**
29+
Integer value
30+
Preprocessing filter (0=none, 1=segment-smooth)
31+
*/
32+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPreprocessing;
33+
34+
/**
35+
Float value
36+
if non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size.
37+
*/
38+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPTargetPSNR;
39+
40+
/**
41+
Integer value
42+
If non-zero, try and use multi-threaded encoding.
43+
*/
44+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPThreadLevel;
45+
46+
/**
47+
Integer value
48+
If set, reduce memory usage (but increase CPU use).
49+
*/
50+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPLowMemory;
51+
52+
/**
53+
Integer value
54+
if non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size.
55+
*/
56+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPSegments;
57+
58+
/**
59+
Integer value
60+
Spatial Noise Shaping. 0=off, 100=maximum.
61+
*/
62+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPSnsStrength;
63+
64+
/**
65+
Integer value
66+
Range: [0 = off .. 100 = strongest]
67+
*/
68+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterStrength;
69+
70+
/**
71+
Integer value
72+
range: [0 = off .. 7 = least sharp]
73+
*/
74+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterSharpness;
75+
76+
/**
77+
Integer value
78+
Filtering type: 0 = simple, 1 = strong (only used If filter_strength > 0 or autofilter > 0)
79+
*/
80+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterType;
81+
82+
/**
83+
Integer value
84+
Auto adjust filter's strength [0 = off, 1 = on]
85+
*/
86+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAutofilter;
87+
88+
/**
89+
Integer value
90+
Algorithm for encoding the alpha plane (0 = none, 1 = compressed with WebP lossless). Default is 1.
91+
*/
92+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaCompression;
93+
94+
/**
95+
Integer value
96+
Predictive filtering method for alpha plane. 0: none, 1: fast, 2: best. Default if 1.
97+
*/
98+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaFiltering;
99+
100+
/**
101+
Integer value
102+
Between 0 (smallest size) and 100 (lossless).
103+
Default is 100.
104+
*/
105+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaQuality;
106+
107+
/**
108+
Integer value
109+
If true, export the compressed picture back.
110+
In-loop filtering is not applied.
111+
*/
112+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPShowCompressed;
113+
114+
/**
115+
Integer
116+
Log2(number of token partitions) in [0..3]
117+
Default is set to 0 for easier progressive decoding.
118+
*/
119+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPartitions;
120+
121+
/**
122+
Integer value
123+
Quality degradation allowed to fit the 512k limit on
124+
Prediction modes coding (0: no degradation, 100: maximum possible degradation).
125+
*/
126+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPartitionLimit;
127+
128+
/**
129+
Integer value
130+
if needed, use sharp (and slow) RGB->YUV conversion
131+
*/
132+
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPUseSharpYuv;
133+
134+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)