From 66cfc23f1c16359899650f5d49687b0a2e95dc1d Mon Sep 17 00:00:00 2001 From: Antti Kortetmaa Date: Thu, 10 Dec 2020 14:31:08 +0200 Subject: [PATCH 1/3] Added new encoding options to WebP encoding --- SDWebImageWebPCoder.xcodeproj/project.pbxproj | 20 +++ .../Classes/SDImageWebPCoder.m | 108 +++++++++++++- .../Classes/SDWebImageWebPCoderDefine.h | 134 ++++++++++++++++++ .../Classes/SDWebImageWebPCoderDefine.m | 28 ++++ .../Module/SDWebImageWebPCoder.h | 1 + 5 files changed, 284 insertions(+), 7 deletions(-) create mode 100644 SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.h create mode 100644 SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.m diff --git a/SDWebImageWebPCoder.xcodeproj/project.pbxproj b/SDWebImageWebPCoder.xcodeproj/project.pbxproj index d4a8813..6023d9e 100644 --- a/SDWebImageWebPCoder.xcodeproj/project.pbxproj +++ b/SDWebImageWebPCoder.xcodeproj/project.pbxproj @@ -7,6 +7,14 @@ objects = { /* Begin PBXBuildFile section */ + 220A6239257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; + 220A623A257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; + 220A623B257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; + 220A623C257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; + 220A623D257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; + 220A623E257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; + 220A623F257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; + 220A6240257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; 806E77B32136A2E900A316D2 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 806E77AA2136A2E900A316D2 /* UIImage+WebP.m */; }; 806E77B42136A2E900A316D2 /* SDImageWebPCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 806E77AB2136A2E900A316D2 /* SDImageWebPCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 806E77B62136A2E900A316D2 /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 806E77AD2136A2E900A316D2 /* UIImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -38,6 +46,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageWebPCoderDefine.m; sourceTree = ""; }; + 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageWebPCoderDefine.h; sourceTree = ""; }; 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 = ""; }; 3217BE7B220547EB003D0310 /* SDWebImageWebPCoder.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = SDWebImageWebPCoder.modulemap; sourceTree = ""; }; 46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageWebPCoderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -146,6 +156,8 @@ 806E77A92136A2E900A316D2 /* Classes */ = { isa = PBXGroup; children = ( + 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */, + 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */, 806E77AB2136A2E900A316D2 /* SDImageWebPCoder.h */, 806E77AE2136A2E900A316D2 /* SDImageWebPCoder.m */, 806E77AD2136A2E900A316D2 /* UIImage+WebP.h */, @@ -228,6 +240,7 @@ files = ( 806E77C72136A7AD00A316D2 /* SDWebImageWebPCoder.h in Headers */, 806E77B62136A2E900A316D2 /* UIImage+WebP.h in Headers */, + 220A623D257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */, 806E77B42136A2E900A316D2 /* SDImageWebPCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -238,6 +251,7 @@ files = ( 80BFF2502136BC1500B95470 /* UIImage+WebP.h in Headers */, 80BFF24D2136BC0600B95470 /* SDWebImageWebPCoder.h in Headers */, + 220A623E257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */, 80BFF24E2136BC1000B95470 /* SDImageWebPCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -248,6 +262,7 @@ files = ( 80BFF2632136BE2200B95470 /* SDWebImageWebPCoder.h in Headers */, 80BFF2612136BE1C00B95470 /* UIImage+WebP.h in Headers */, + 220A623F257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */, 80BFF25F2136BE1700B95470 /* SDImageWebPCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -258,6 +273,7 @@ files = ( 80BFF27F2136BEF200B95470 /* SDWebImageWebPCoder.h in Headers */, 80BFF27D2136BEED00B95470 /* UIImage+WebP.h in Headers */, + 220A6240257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */, 80BFF27B2136BEE700B95470 /* SDImageWebPCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -416,6 +432,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 220A6239257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */, 806E77B72136A2E900A316D2 /* SDImageWebPCoder.m in Sources */, 806E77B32136A2E900A316D2 /* UIImage+WebP.m in Sources */, ); @@ -425,6 +442,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 220A623A257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */, 80BFF24F2136BC1300B95470 /* SDImageWebPCoder.m in Sources */, 80BFF2512136BC1800B95470 /* UIImage+WebP.m in Sources */, ); @@ -434,6 +452,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 220A623B257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */, 80BFF2602136BE1A00B95470 /* SDImageWebPCoder.m in Sources */, 80BFF2622136BE1F00B95470 /* UIImage+WebP.m in Sources */, ); @@ -443,6 +462,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 220A623C257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */, 80BFF27C2136BEEB00B95470 /* SDImageWebPCoder.m in Sources */, 80BFF27E2136BEF000B95470 /* UIImage+WebP.m in Sources */, ); diff --git a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m index 9aaa45a..1759fd3 100644 --- a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m +++ b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m @@ -23,6 +23,7 @@ #endif #import +#import "SDWebImageWebPCoderDefine.h" /// Calculate the actual thumnail pixel size static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio, CGSize thumbnailSize) { @@ -617,7 +618,11 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue]; if (encodeFirstFrame || frames.count == 0) { // for static single webp image - data = [self sd_encodedWebpDataWithImage:image.CGImage quality:compressionQuality maxPixelSize:maxPixelSize maxFileSize:maxFileSize]; + data = [self sd_encodedWebpDataWithImage:image.CGImage + quality:compressionQuality + maxPixelSize:maxPixelSize + maxFileSize:maxFileSize + options:options]; } else { // for animated webp image WebPMux *mux = WebPMuxNew(); @@ -626,7 +631,11 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio } for (size_t i = 0; i < frames.count; i++) { SDImageFrame *currentFrame = frames[i]; - NSData *webpData = [self sd_encodedWebpDataWithImage:currentFrame.image.CGImage quality:compressionQuality maxPixelSize:maxPixelSize maxFileSize:maxFileSize]; + NSData *webpData = [self sd_encodedWebpDataWithImage:currentFrame.image.CGImage + quality:compressionQuality + maxPixelSize:maxPixelSize + maxFileSize:maxFileSize + options:options]; int duration = currentFrame.duration * 1000; WebPMuxFrameInfo frame = { .bitstream.bytes = webpData.bytes, .bitstream.size = webpData.length, @@ -663,7 +672,12 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio return data; } -- (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef quality:(double)quality maxPixelSize:(CGSize)maxPixelSize maxFileSize:(NSUInteger)maxFileSize { +- (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef + quality:(double)quality + maxPixelSize:(CGSize)maxPixelSize + maxFileSize:(NSUInteger)maxFileSize + options:(nullable SDImageCoderOptions *)options +{ NSData *webpData; if (!imageRef) { return nil; @@ -779,10 +793,7 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio return nil; } - config.target_size = (int)maxFileSize; // Max filesize for output, 0 means use quality instead - config.pass = maxFileSize > 0 ? 6 : 1; // Use 6 passes for file size limited encoding, which is the default value of `cwebp` command line - config.thread_level = 1; // Thread encoding for fast - config.lossless = 0; // Disable lossless encoding (If we need, can add new Encoding Options in future version) + [self updateWebPOptionsToConfig:&config maxFileSize:maxFileSize options:options]; picture.use_argb = 0; // Lossy encoding use YUV for internel bitstream picture.width = (int)width; picture.height = (int)height; @@ -830,6 +841,89 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio return webpData; } +- (void) updateWebPOptionsToConfig:(WebPConfig*)config + maxFileSize:(NSUInteger)maxFileSize + options:(nullable SDImageCoderOptions *)options { + + config->target_size = (int)maxFileSize; // Max filesize for output, 0 means use quality instead + config->pass = maxFileSize > 0 ? 6 : 1; // Use 6 passes for file size limited encoding, which is the default value of `cwebp` command line + config->lossless = 0; // Disable lossless encoding (If we need, can add new Encoding Options in future version) + + if ([options[SDImageCoderEncodeWebPMethod] intValue]) { + config->method = [options[SDImageCoderEncodeWebPMethod] intValue]; + } + if ([options[SDImageCoderEncodeWebPPass] intValue]) { + config->pass = [options[SDImageCoderEncodeWebPPass] intValue]; + } + if ([options[SDImageCoderEncodeWebPPreprocessing] intValue]) { + config->preprocessing = [options[SDImageCoderEncodeWebPPreprocessing] intValue]; + } + if ([options[SDImageCoderEncodeWebPThreadLevel] intValue]) { + config->thread_level = [options[SDImageCoderEncodeWebPThreadLevel] intValue]; + } else { + config->thread_level = 1; + } + if ([options[SDImageCoderEncodeWebPLowMemory] intValue]) { + config->low_memory = [options[SDImageCoderEncodeWebPLowMemory] intValue]; + } + + if ([options[SDImageCoderEncodeWebPTargetPSNR] floatValue]) { + config->target_PSNR = [options[SDImageCoderEncodeWebPTargetPSNR] floatValue]; + } + + if ([options[SDImageCoderEncodeWebPSegments] intValue]) { + config->segments = [options[SDImageCoderEncodeWebPSegments] intValue]; + } + + if ([options[SDImageCoderEncodeWebPSnsStrength] intValue]) { + config->sns_strength = [options[SDImageCoderEncodeWebPSnsStrength] intValue]; + } + + if ([options[SDImageCoderEncodeWebPFilterStrength] intValue]) { + config->filter_strength = [options[SDImageCoderEncodeWebPFilterStrength] intValue]; + } + + if ([options[SDImageCoderEncodeWebPFilterSharpness] intValue]) { + config->filter_sharpness = [options[SDImageCoderEncodeWebPFilterSharpness] intValue]; + } + + if ([options[SDImageCoderEncodeWebPFilterType] intValue]) { + config->filter_type = [options[SDImageCoderEncodeWebPFilterType] intValue]; + } + + if ([options[SDImageCoderEncodeWebPAutofilter] intValue]) { + config->autofilter = [options[SDImageCoderEncodeWebPAutofilter] intValue]; + } + + if ([options[SDImageCoderEncodeWebPAlphaCompression] intValue]) { + config->alpha_compression = [options[SDImageCoderEncodeWebPAlphaCompression] intValue]; + } + + if ([options[SDImageCoderEncodeWebPAlphaFiltering] intValue]) { + config->alpha_filtering = [options[SDImageCoderEncodeWebPAlphaFiltering] intValue]; + } + + if ([options[SDImageCoderEncodeWebPAlphaQuality] intValue]) { + config->alpha_quality = [options[SDImageCoderEncodeWebPAlphaQuality] intValue]; + } + + if ([options[SDImageCoderEncodeWebPShowCompressed] intValue]) { + config->show_compressed = [options[SDImageCoderEncodeWebPShowCompressed] intValue]; + } + + if ([options[SDImageCoderEncodeWebPPartitions] intValue]) { + config->partitions = [options[SDImageCoderEncodeWebPPartitions] intValue]; + } + + if ([options[SDImageCoderEncodeWebPPartitionLimit] intValue]) { + config->partition_limit = [options[SDImageCoderEncodeWebPPartitionLimit] intValue]; + } + + if ([options[SDImageCoderEncodeWebPUseSharpYuv] intValue]) { + config->use_sharp_yuv = [options[SDImageCoderEncodeWebPUseSharpYuv] intValue]; + } +} + static void FreeImageData(void *info, const void *data, size_t size) { free((void *)data); } diff --git a/SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.h b/SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.h new file mode 100644 index 0000000..e04a536 --- /dev/null +++ b/SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.h @@ -0,0 +1,134 @@ +// +// SDWebImageWebPCoderDefine.h +// SDWebImageWebPCoderDefine +// +// Created by Antti Kortetmaa on 2020/12/06. +// + +#if __has_include() +#import +#else +@import SDWebImage; +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** +Integer value +Quality/speed trade-off (0=fast, 6=slower-better) + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPMethod; + +/** +Integer value +Number of entropy-analysis passes (in [1..10]) + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPass; + +/** + Integer value + Preprocessing filter (0=none, 1=segment-smooth) + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPreprocessing; + +/** + Float value + if non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPTargetPSNR; + +/** + Integer value + If non-zero, try and use multi-threaded encoding. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPThreadLevel; + +/** + Integer value + If set, reduce memory usage (but increase CPU use). + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPLowMemory; + +/** + Integer value + if non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPSegments; + +/** + Integer value + Spatial Noise Shaping. 0=off, 100=maximum. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPSnsStrength; + +/** + Integer value + Range: [0 = off .. 100 = strongest] + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterStrength; + +/** + Integer value + range: [0 = off .. 7 = least sharp] + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterSharpness; + +/** + Integer value + Filtering type: 0 = simple, 1 = strong (only used If filter_strength > 0 or autofilter > 0) + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterType; + +/** + Integer value + Auto adjust filter's strength [0 = off, 1 = on] + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAutofilter; + +/** + Integer value + Algorithm for encoding the alpha plane (0 = none, 1 = compressed with WebP lossless). Default is 1. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaCompression; + +/** + Integer value + Predictive filtering method for alpha plane. 0: none, 1: fast, 2: best. Default if 1. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaFiltering; + +/** + Integer value + Between 0 (smallest size) and 100 (lossless). + Default is 100. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaQuality; + +/** + Integer value + If true, export the compressed picture back. + In-loop filtering is not applied. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPShowCompressed; + +/** + Integer + Log2(number of token partitions) in [0..3] + Default is set to 0 for easier progressive decoding. + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPartitions; + +/** + Integer value + Quality degradation allowed to fit the 512k limit on + Prediction modes coding (0: no degradation, 100: maximum possible degradation). + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPartitionLimit; + +/** + Integer value + if needed, use sharp (and slow) RGB->YUV conversion + */ +FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPUseSharpYuv; + +NS_ASSUME_NONNULL_END diff --git a/SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.m b/SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.m new file mode 100644 index 0000000..ff333de --- /dev/null +++ b/SDWebImageWebPCoder/Classes/SDWebImageWebPCoderDefine.m @@ -0,0 +1,28 @@ +// +// SDWebImageWebPCoderDefine.m +// SDWebImageWebPCoder +// +// Created by Antti Kortetmaa on 2020/12/06. +// + +#import "SDWebImageWebPCoderDefine.h" + +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPMethod = @"webPMethod"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPass = @"webPPass"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPreprocessing = @"webPPreprocessing"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPThreadLevel = @"webPThreadLevel"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPLowMemory = @"webPLowMemory"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPTargetPSNR = @"webPTargetPSNR"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPSegments = @"webPSegments"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPSnsStrength = @"webPSnsStrength"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterStrength = @"webPFilterStrength"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterSharpness = @"webPFilterSharpness"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPFilterType = @"webPFilterType"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAutofilter = @"webPAutofilter"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaCompression = @"webPAlphaCompression"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaFiltering = @"webPAlphaFiltering"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPAlphaQuality = @"webPAlphaQuality"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPShowCompressed = @"webPShowCompressed"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPartitions = @"webPPartitions"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPPartitionLimit = @"webPPartitionLimit"; +SDImageCoderOption _Nonnull const SDImageCoderEncodeWebPUseSharpYuv = @"webPUseSharpYuv"; diff --git a/SDWebImageWebPCoder/Module/SDWebImageWebPCoder.h b/SDWebImageWebPCoder/Module/SDWebImageWebPCoder.h index d0c0797..69e8947 100644 --- a/SDWebImageWebPCoder/Module/SDWebImageWebPCoder.h +++ b/SDWebImageWebPCoder/Module/SDWebImageWebPCoder.h @@ -12,4 +12,5 @@ FOUNDATION_EXPORT double SDWebImageWebPCoderVersionNumber; FOUNDATION_EXPORT const unsigned char SDWebImageWebPCoderVersionString[]; #import +#import #import From e330f22573720b70b658c80319012619185896d2 Mon Sep 17 00:00:00 2001 From: Antti Kortetmaa Date: Thu, 10 Dec 2020 21:07:37 +0200 Subject: [PATCH 2/3] Added unit tests for WebP settings. --- SDWebImageWebPCoder.xcodeproj/project.pbxproj | 4 +- .../Classes/SDImageWebPCoder.h | 18 +++++++ .../Classes/SDImageWebPCoder.m | 6 +-- Tests/SDWebImageWebPCoderTests.m | 49 +++++++++++++++++++ 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/SDWebImageWebPCoder.xcodeproj/project.pbxproj b/SDWebImageWebPCoder.xcodeproj/project.pbxproj index 6023d9e..86d8a32 100644 --- a/SDWebImageWebPCoder.xcodeproj/project.pbxproj +++ b/SDWebImageWebPCoder.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 220A6239257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; 220A623A257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; 220A623B257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; 220A623C257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; @@ -15,6 +14,7 @@ 220A623E257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; 220A623F257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; 220A6240257EAFB300262720 /* SDWebImageWebPCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 220A6238257EAFB300262720 /* SDWebImageWebPCoderDefine.h */; }; + 228EA36125825A52005903D9 /* SDWebImageWebPCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 220A6237257EAFB300262720 /* SDWebImageWebPCoderDefine.m */; }; 806E77B32136A2E900A316D2 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 806E77AA2136A2E900A316D2 /* UIImage+WebP.m */; }; 806E77B42136A2E900A316D2 /* SDImageWebPCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 806E77AB2136A2E900A316D2 /* SDImageWebPCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 806E77B62136A2E900A316D2 /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 806E77AD2136A2E900A316D2 /* UIImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -432,7 +432,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 220A6239257EAFB300262720 /* SDWebImageWebPCoderDefine.m in Sources */, + 228EA36125825A52005903D9 /* SDWebImageWebPCoderDefine.m in Sources */, 806E77B72136A2E900A316D2 /* SDImageWebPCoder.m in Sources */, 806E77B32136A2E900A316D2 /* UIImage+WebP.m in Sources */, ); diff --git a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h index 7629ded..849259f 100644 --- a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h +++ b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h @@ -12,6 +12,20 @@ @import SDWebImage; #endif +#if __has_include("webp/decode.h") && __has_include("webp/encode.h") && __has_include("webp/demux.h") && __has_include("webp/mux.h") +#import "webp/decode.h" +#import "webp/encode.h" +#import "webp/demux.h" +#import "webp/mux.h" +#elif __has_include() && __has_include() && __has_include() && __has_include() +#import +#import +#import +#import +#else +@import libwebp; +#endif + /** Built in coder that supports WebP and animated WebP */ @@ -19,4 +33,8 @@ @property (nonatomic, class, readonly, nonnull) SDImageWebPCoder *sharedCoder; +- (void) updateWebPOptionsToConfig:(WebPConfig * _Nonnull)config + maxFileSize:(NSUInteger)maxFileSize + options:(nullable SDImageCoderOptions *)options; + @end diff --git a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m index 1759fd3..612ed91 100644 --- a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m +++ b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.m @@ -841,9 +841,9 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio return webpData; } -- (void) updateWebPOptionsToConfig:(WebPConfig*)config - maxFileSize:(NSUInteger)maxFileSize - options:(nullable SDImageCoderOptions *)options { +- (void) updateWebPOptionsToConfig:(WebPConfig * _Nonnull)config + maxFileSize:(NSUInteger)maxFileSize + options:(nullable SDImageCoderOptions *)options { config->target_size = (int)maxFileSize; // Max filesize for output, 0 means use quality instead config->pass = maxFileSize > 0 ? 6 : 1; // Use 6 passes for file size limited encoding, which is the default value of `cwebp` command line diff --git a/Tests/SDWebImageWebPCoderTests.m b/Tests/SDWebImageWebPCoderTests.m index f2deee5..7583d13 100644 --- a/Tests/SDWebImageWebPCoderTests.m +++ b/Tests/SDWebImageWebPCoderTests.m @@ -10,6 +10,7 @@ @import XCTest; #import #import +#import #import #import @@ -196,6 +197,54 @@ const int64_t kAsyncTestTimeout = 5; XCTAssertLessThanOrEqual(dataWithLimit.length, maxFileSize); } +- (void)testEncodingSettings { + WebPConfig config; + WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, 0.2); + + SDImageCoderOptions *options = @{ SDImageCoderEncodeWebPMethod: @1, + SDImageCoderEncodeWebPPass: @2, + SDImageCoderEncodeWebPPreprocessing: @3, + SDImageCoderEncodeWebPThreadLevel: @4, + SDImageCoderEncodeWebPLowMemory: @5, + SDImageCoderEncodeWebPTargetPSNR: @6, + SDImageCoderEncodeWebPSegments: @7, + SDImageCoderEncodeWebPSnsStrength: @8, + SDImageCoderEncodeWebPFilterStrength: @9, + SDImageCoderEncodeWebPFilterSharpness: @10, + SDImageCoderEncodeWebPFilterType: @11, + SDImageCoderEncodeWebPAutofilter: @12, + SDImageCoderEncodeWebPAlphaCompression: @13, + SDImageCoderEncodeWebPAlphaFiltering: @14, + SDImageCoderEncodeWebPAlphaQuality: @15, + SDImageCoderEncodeWebPShowCompressed: @16, + SDImageCoderEncodeWebPPartitions: @17, + SDImageCoderEncodeWebPPartitionLimit: @18, + SDImageCoderEncodeWebPUseSharpYuv: @19 }; + + [SDImageWebPCoder.sharedCoder updateWebPOptionsToConfig:&config maxFileSize:1200 options:options]; + + expect(config.method).to.equal(1); + expect(config.pass).to.equal(2); + expect(config.preprocessing).to.equal(3); + expect(config.thread_level).to.equal(4); + expect(config.low_memory).to.equal(5); + expect(config.target_PSNR).to.equal(6); + expect(config.segments).to.equal(7); + expect(config.sns_strength).to.equal(8); + expect(config.filter_strength).to.equal(9); + expect(config.filter_sharpness).to.equal(10); + expect(config.filter_type).to.equal(11); + expect(config.autofilter).to.equal(12); + expect(config.alpha_compression).to.equal(13); + expect(config.alpha_filtering).to.equal(14); + expect(config.alpha_quality).to.equal(15); + expect(config.show_compressed).to.equal(16); + expect(config.partitions).to.equal(17); + expect(config.partition_limit).to.equal(18); + expect(config.use_sharp_yuv).to.equal(19); + +} + @end @implementation SDWebImageWebPCoderTests (Helpers) From de7ba8d08e2ba9b76b5c9707113f9be0f1046c58 Mon Sep 17 00:00:00 2001 From: Antti Kortetmaa Date: Fri, 11 Dec 2020 12:09:26 +0200 Subject: [PATCH 3/3] Removed updateWebPOptionsToConfig from the public API of SDImageWebPCoder --- .../Classes/SDImageWebPCoder.h | 18 ------------------ Tests/SDWebImageWebPCoderTests.m | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h index 849259f..7629ded 100644 --- a/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h +++ b/SDWebImageWebPCoder/Classes/SDImageWebPCoder.h @@ -12,20 +12,6 @@ @import SDWebImage; #endif -#if __has_include("webp/decode.h") && __has_include("webp/encode.h") && __has_include("webp/demux.h") && __has_include("webp/mux.h") -#import "webp/decode.h" -#import "webp/encode.h" -#import "webp/demux.h" -#import "webp/mux.h" -#elif __has_include() && __has_include() && __has_include() && __has_include() -#import -#import -#import -#import -#else -@import libwebp; -#endif - /** Built in coder that supports WebP and animated WebP */ @@ -33,8 +19,4 @@ @property (nonatomic, class, readonly, nonnull) SDImageWebPCoder *sharedCoder; -- (void) updateWebPOptionsToConfig:(WebPConfig * _Nonnull)config - maxFileSize:(NSUInteger)maxFileSize - options:(nullable SDImageCoderOptions *)options; - @end diff --git a/Tests/SDWebImageWebPCoderTests.m b/Tests/SDWebImageWebPCoderTests.m index 7583d13..43ee412 100644 --- a/Tests/SDWebImageWebPCoderTests.m +++ b/Tests/SDWebImageWebPCoderTests.m @@ -13,6 +13,19 @@ #import #import #import +#if __has_include("webp/decode.h") && __has_include("webp/encode.h") && __has_include("webp/demux.h") && __has_include("webp/mux.h") +#import "webp/decode.h" +#import "webp/encode.h" +#import "webp/demux.h" +#import "webp/mux.h" +#elif __has_include() && __has_include() && __has_include() && __has_include() +#import +#import +#import +#import +#else +@import libwebp; +#endif const int64_t kAsyncTestTimeout = 5; @@ -31,6 +44,12 @@ const int64_t kAsyncTestTimeout = 5; @property (nonatomic, assign) NSUInteger blendFromIndex; // The nearest previous frame index which blend mode is WEBP_MUX_BLEND @end +@interface SDImageWebPCoder () +- (void) updateWebPOptionsToConfig:(WebPConfig * _Nonnull)config + maxFileSize:(NSUInteger)maxFileSize + options:(nullable SDImageCoderOptions *)options; +@end + @implementation SDWebImageWebPCoderTests + (void)setUp {