77 */
88
99#import " SDImageWebPCoder.h"
10+ #import " SDWebImageWebPCoderDefine.h"
11+ #import < Accelerate/Accelerate.h>
12+ #import < os/lock.h>
13+ #import < libkern/OSAtomic.h>
1014
1115#if __has_include("webp/decode.h") && __has_include("webp/encode.h") && __has_include("webp/demux.h") && __has_include("webp/mux.h")
1216#import " webp/decode.h"
2226@import libwebp;
2327#endif
2428
25- #import < Accelerate/Accelerate.h>
29+ #define SD_USE_OS_UNFAIR_LOCK TARGET_OS_MACCATALYST ||\
30+ (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_10_0) ||\
31+ (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_12) ||\
32+ (__TV_OS_VERSION_MIN_REQUIRED >= __TVOS_10_0) ||\
33+ (__WATCH_OS_VERSION_MIN_REQUIRED >= __WATCHOS_3_0)
34+
35+ #ifndef SD_LOCK_DECLARE
36+ #if SD_USE_OS_UNFAIR_LOCK
37+ #define SD_LOCK_DECLARE (lock ) os_unfair_lock lock
38+ #else
39+ #define SD_LOCK_DECLARE (lock ) os_unfair_lock lock API_AVAILABLE (ios(10.0 ), tvos(10 ), watchos(3 ), macos(10.12 )); \
40+ OSSpinLock lock##_deprecated;
41+ #endif
42+ #endif
43+
44+ #ifndef SD_LOCK_INIT
45+ #if SD_USE_OS_UNFAIR_LOCK
46+ #define SD_LOCK_INIT (lock ) lock = OS_UNFAIR_LOCK_INIT
47+ #else
48+ #define SD_LOCK_INIT (lock ) if (@available(iOS 10 , tvOS 10 , watchOS 3 , macOS 10.12 , *)) lock = OS_UNFAIR_LOCK_INIT; \
49+ else lock##_deprecated = OS_SPINLOCK_INIT;
50+ #endif
51+ #endif
52+
53+ #ifndef SD_LOCK
54+ #if SD_USE_OS_UNFAIR_LOCK
55+ #define SD_LOCK (lock ) os_unfair_lock_lock(&lock)
56+ #else
57+ #define SD_LOCK (lock ) if (@available(iOS 10 , tvOS 10 , watchOS 3 , macOS 10.12 , *)) os_unfair_lock_lock(&lock); \
58+ else OSSpinLockLock(&lock##_deprecated);
59+ #endif
60+ #endif
61+
62+ #ifndef SD_UNLOCK
63+ #if SD_USE_OS_UNFAIR_LOCK
64+ #define SD_UNLOCK (lock ) os_unfair_lock_unlock(&lock)
65+ #else
66+ #define SD_UNLOCK (lock ) if (@available(iOS 10 , tvOS 10 , watchOS 3 , macOS 10.12 , *)) os_unfair_lock_unlock(&lock); \
67+ else OSSpinLockUnlock(&lock##_deprecated);
68+ #endif
69+ #endif
2670
2771// / Calculate the actual thumnail pixel size
2872static CGSize SDCalculateThumbnailSize (CGSize fullSize, BOOL preserveAspectRatio, CGSize thumbnailSize) {
@@ -98,7 +142,7 @@ @implementation SDImageWebPCoder {
98142 BOOL _finished;
99143 CGFloat _canvasWidth;
100144 CGFloat _canvasHeight;
101- dispatch_semaphore_t _lock;
145+ SD_LOCK_DECLARE ( _lock) ;
102146 NSUInteger _currentBlendIndex;
103147 BOOL _preserveAspectRatio;
104148 CGSize _thumbnailSize;
@@ -291,7 +335,7 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
291335 }
292336 _preserveAspectRatio = preserveAspectRatio;
293337 _currentBlendIndex = NSNotFound ;
294- _lock = dispatch_semaphore_create ( 1 );
338+ SD_LOCK_INIT (_lock );
295339 }
296340 return self;
297341}
@@ -617,7 +661,11 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
617661 BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue ];
618662 if (encodeFirstFrame || frames.count == 0 ) {
619663 // for static single webp image
620- data = [self sd_encodedWebpDataWithImage: image.CGImage quality: compressionQuality maxPixelSize: maxPixelSize maxFileSize: maxFileSize];
664+ data = [self sd_encodedWebpDataWithImage: image.CGImage
665+ quality: compressionQuality
666+ maxPixelSize: maxPixelSize
667+ maxFileSize: maxFileSize
668+ options: options];
621669 } else {
622670 // for animated webp image
623671 WebPMux *mux = WebPMuxNew ();
@@ -626,7 +674,11 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
626674 }
627675 for (size_t i = 0 ; i < frames.count ; i++) {
628676 SDImageFrame *currentFrame = frames[i];
629- NSData *webpData = [self sd_encodedWebpDataWithImage: currentFrame.image.CGImage quality: compressionQuality maxPixelSize: maxPixelSize maxFileSize: maxFileSize];
677+ NSData *webpData = [self sd_encodedWebpDataWithImage: currentFrame.image.CGImage
678+ quality: compressionQuality
679+ maxPixelSize: maxPixelSize
680+ maxFileSize: maxFileSize
681+ options: options];
630682 int duration = currentFrame.duration * 1000 ;
631683 WebPMuxFrameInfo frame = { .bitstream .bytes = webpData.bytes ,
632684 .bitstream .size = webpData.length ,
@@ -663,7 +715,12 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
663715 return data;
664716}
665717
666- - (nullable NSData *)sd_encodedWebpDataWithImage : (nullable CGImageRef)imageRef quality : (double )quality maxPixelSize : (CGSize)maxPixelSize maxFileSize : (NSUInteger )maxFileSize {
718+ - (nullable NSData *)sd_encodedWebpDataWithImage : (nullable CGImageRef)imageRef
719+ quality : (double )quality
720+ maxPixelSize : (CGSize)maxPixelSize
721+ maxFileSize : (NSUInteger )maxFileSize
722+ options : (nullable SDImageCoderOptions *)options
723+ {
667724 NSData *webpData;
668725 if (!imageRef) {
669726 return nil ;
@@ -779,10 +836,7 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
779836 return nil ;
780837 }
781838
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)
839+ [self updateWebPOptionsToConfig: &config maxFileSize: maxFileSize options: options];
786840 picture.use_argb = 0 ; // Lossy encoding use YUV for internel bitstream
787841 picture.width = (int )width;
788842 picture.height = (int )height;
@@ -830,6 +884,89 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
830884 return webpData;
831885}
832886
887+ - (void ) updateWebPOptionsToConfig : (WebPConfig * _Nonnull)config
888+ maxFileSize : (NSUInteger )maxFileSize
889+ options : (nullable SDImageCoderOptions *)options {
890+
891+ config->target_size = (int )maxFileSize; // Max filesize for output, 0 means use quality instead
892+ config->pass = maxFileSize > 0 ? 6 : 1 ; // Use 6 passes for file size limited encoding, which is the default value of `cwebp` command line
893+ config->lossless = 0 ; // Disable lossless encoding (If we need, can add new Encoding Options in future version)
894+
895+ if ([options[SDImageCoderEncodeWebPMethod] intValue ]) {
896+ config->method = [options[SDImageCoderEncodeWebPMethod] intValue ];
897+ }
898+ if ([options[SDImageCoderEncodeWebPPass] intValue ]) {
899+ config->pass = [options[SDImageCoderEncodeWebPPass] intValue ];
900+ }
901+ if ([options[SDImageCoderEncodeWebPPreprocessing] intValue ]) {
902+ config->preprocessing = [options[SDImageCoderEncodeWebPPreprocessing] intValue ];
903+ }
904+ if ([options[SDImageCoderEncodeWebPThreadLevel] intValue ]) {
905+ config->thread_level = [options[SDImageCoderEncodeWebPThreadLevel] intValue ];
906+ } else {
907+ config->thread_level = 1 ;
908+ }
909+ if ([options[SDImageCoderEncodeWebPLowMemory] intValue ]) {
910+ config->low_memory = [options[SDImageCoderEncodeWebPLowMemory] intValue ];
911+ }
912+
913+ if ([options[SDImageCoderEncodeWebPTargetPSNR] floatValue ]) {
914+ config->target_PSNR = [options[SDImageCoderEncodeWebPTargetPSNR] floatValue ];
915+ }
916+
917+ if ([options[SDImageCoderEncodeWebPSegments] intValue ]) {
918+ config->segments = [options[SDImageCoderEncodeWebPSegments] intValue ];
919+ }
920+
921+ if ([options[SDImageCoderEncodeWebPSnsStrength] intValue ]) {
922+ config->sns_strength = [options[SDImageCoderEncodeWebPSnsStrength] intValue ];
923+ }
924+
925+ if ([options[SDImageCoderEncodeWebPFilterStrength] intValue ]) {
926+ config->filter_strength = [options[SDImageCoderEncodeWebPFilterStrength] intValue ];
927+ }
928+
929+ if ([options[SDImageCoderEncodeWebPFilterSharpness] intValue ]) {
930+ config->filter_sharpness = [options[SDImageCoderEncodeWebPFilterSharpness] intValue ];
931+ }
932+
933+ if ([options[SDImageCoderEncodeWebPFilterType] intValue ]) {
934+ config->filter_type = [options[SDImageCoderEncodeWebPFilterType] intValue ];
935+ }
936+
937+ if ([options[SDImageCoderEncodeWebPAutofilter] intValue ]) {
938+ config->autofilter = [options[SDImageCoderEncodeWebPAutofilter] intValue ];
939+ }
940+
941+ if ([options[SDImageCoderEncodeWebPAlphaCompression] intValue ]) {
942+ config->alpha_compression = [options[SDImageCoderEncodeWebPAlphaCompression] intValue ];
943+ }
944+
945+ if ([options[SDImageCoderEncodeWebPAlphaFiltering] intValue ]) {
946+ config->alpha_filtering = [options[SDImageCoderEncodeWebPAlphaFiltering] intValue ];
947+ }
948+
949+ if ([options[SDImageCoderEncodeWebPAlphaQuality] intValue ]) {
950+ config->alpha_quality = [options[SDImageCoderEncodeWebPAlphaQuality] intValue ];
951+ }
952+
953+ if ([options[SDImageCoderEncodeWebPShowCompressed] intValue ]) {
954+ config->show_compressed = [options[SDImageCoderEncodeWebPShowCompressed] intValue ];
955+ }
956+
957+ if ([options[SDImageCoderEncodeWebPPartitions] intValue ]) {
958+ config->partitions = [options[SDImageCoderEncodeWebPPartitions] intValue ];
959+ }
960+
961+ if ([options[SDImageCoderEncodeWebPPartitionLimit] intValue ]) {
962+ config->partition_limit = [options[SDImageCoderEncodeWebPPartitionLimit] intValue ];
963+ }
964+
965+ if ([options[SDImageCoderEncodeWebPUseSharpYuv] intValue ]) {
966+ config->use_sharp_yuv = [options[SDImageCoderEncodeWebPUseSharpYuv] intValue ];
967+ }
968+ }
969+
833970static void FreeImageData (void *info, const void *data, size_t size) {
834971 free ((void *)data);
835972}
@@ -881,7 +1018,7 @@ - (instancetype)initWithAnimatedImageData:(NSData *)data options:(nullable SDIma
8811018 _demux = demuxer;
8821019 _imageData = data;
8831020 _currentBlendIndex = NSNotFound ;
884- _lock = dispatch_semaphore_create ( 1 );
1021+ SD_LOCK_INIT (_lock );
8851022 }
8861023 return self;
8871024}
0 commit comments