7
7
*/
8
8
9
9
#import " SDImageWebPCoder.h"
10
+ #import " SDWebImageWebPCoderDefine.h"
11
+ #import < Accelerate/Accelerate.h>
12
+ #import < os/lock.h>
13
+ #import < libkern/OSAtomic.h>
10
14
11
15
#if __has_include("webp/decode.h") && __has_include("webp/encode.h") && __has_include("webp/demux.h") && __has_include("webp/mux.h")
12
16
#import " webp/decode.h"
22
26
@import libwebp;
23
27
#endif
24
28
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
26
70
27
71
// / Calculate the actual thumnail pixel size
28
72
static CGSize SDCalculateThumbnailSize (CGSize fullSize, BOOL preserveAspectRatio, CGSize thumbnailSize) {
@@ -98,7 +142,7 @@ @implementation SDImageWebPCoder {
98
142
BOOL _finished;
99
143
CGFloat _canvasWidth;
100
144
CGFloat _canvasHeight;
101
- dispatch_semaphore_t _lock;
145
+ SD_LOCK_DECLARE ( _lock) ;
102
146
NSUInteger _currentBlendIndex;
103
147
BOOL _preserveAspectRatio;
104
148
CGSize _thumbnailSize;
@@ -291,7 +335,7 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
291
335
}
292
336
_preserveAspectRatio = preserveAspectRatio;
293
337
_currentBlendIndex = NSNotFound ;
294
- _lock = dispatch_semaphore_create ( 1 );
338
+ SD_LOCK_INIT (_lock );
295
339
}
296
340
return self;
297
341
}
@@ -617,7 +661,11 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
617
661
BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue ];
618
662
if (encodeFirstFrame || frames.count == 0 ) {
619
663
// 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];
621
669
} else {
622
670
// for animated webp image
623
671
WebPMux *mux = WebPMuxNew ();
@@ -626,7 +674,11 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
626
674
}
627
675
for (size_t i = 0 ; i < frames.count ; i++) {
628
676
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];
630
682
int duration = currentFrame.duration * 1000 ;
631
683
WebPMuxFrameInfo frame = { .bitstream .bytes = webpData.bytes ,
632
684
.bitstream .size = webpData.length ,
@@ -663,7 +715,12 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
663
715
return data;
664
716
}
665
717
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
+ {
667
724
NSData *webpData;
668
725
if (!imageRef) {
669
726
return nil ;
@@ -779,10 +836,7 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
779
836
return nil ;
780
837
}
781
838
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];
786
840
picture.use_argb = 0 ; // Lossy encoding use YUV for internel bitstream
787
841
picture.width = (int )width;
788
842
picture.height = (int )height;
@@ -830,6 +884,89 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
830
884
return webpData;
831
885
}
832
886
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
+
833
970
static void FreeImageData (void *info, const void *data, size_t size) {
834
971
free ((void *)data);
835
972
}
@@ -881,7 +1018,7 @@ - (instancetype)initWithAnimatedImageData:(NSData *)data options:(nullable SDIma
881
1018
_demux = demuxer;
882
1019
_imageData = data;
883
1020
_currentBlendIndex = NSNotFound ;
884
- _lock = dispatch_semaphore_create ( 1 );
1021
+ SD_LOCK_INIT (_lock );
885
1022
}
886
1023
return self;
887
1024
}
0 commit comments