Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ee7665e

Browse files
authoredApr 7, 2020
Merge pull request #35 from SDWebImage/project_encoding_max_file_size_advanced_api
Upgrade the dependency to SDWebImage 5.7, supports the maxFileSize encoding options, as well as enabling the thread-encoding for speedup
2 parents eb6e84f + a62950d commit ee7665e

File tree

5 files changed

+53
-25
lines changed

5 files changed

+53
-25
lines changed
 

‎Cartfile

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

‎Cartfile.resolved

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github "SDWebImage/SDWebImage" "5.5.0"
1+
github "SDWebImage/SDWebImage" "5.7.0"
22
github "SDWebImage/libwebp-Xcode" "1.1.0"

‎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.5.0"),
20+
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.7.0"),
2121
.package(url: "https://github.com/SDWebImage/libwebp-Xcode.git", from: "1.1.0")
2222
],
2323
targets: [

‎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.5'
30+
s.dependency 'SDWebImage/Core', '~> 5.7'
3131
s.dependency 'libwebp', '~> 1.0'
3232

3333
end

‎SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -609,12 +609,16 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
609609
if (options[SDImageCoderEncodeCompressionQuality]) {
610610
compressionQuality = [options[SDImageCoderEncodeCompressionQuality] doubleValue];
611611
}
612+
NSUInteger maxFileSize = 0;
613+
if (options[SDImageCoderEncodeMaxFileSize]) {
614+
maxFileSize = [options[SDImageCoderEncodeMaxFileSize] unsignedIntegerValue];
615+
}
612616
NSArray<SDImageFrame *> *frames = [SDImageCoderHelper framesFromAnimatedImage:image];
613617

614618
BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue];
615619
if (encodeFirstFrame || frames.count == 0) {
616620
// for static single webp image
617-
data = [self sd_encodedWebpDataWithImage:image.CGImage quality:compressionQuality];
621+
data = [self sd_encodedWebpDataWithImage:image.CGImage quality:compressionQuality fileSize:maxFileSize];
618622
} else {
619623
// for animated webp image
620624
WebPMux *mux = WebPMuxNew();
@@ -623,7 +627,7 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
623627
}
624628
for (size_t i = 0; i < frames.count; i++) {
625629
SDImageFrame *currentFrame = frames[i];
626-
NSData *webpData = [self sd_encodedWebpDataWithImage:currentFrame.image.CGImage quality:compressionQuality];
630+
NSData *webpData = [self sd_encodedWebpDataWithImage:currentFrame.image.CGImage quality:compressionQuality fileSize:maxFileSize];
627631
int duration = currentFrame.duration * 1000;
628632
WebPMuxFrameInfo frame = { .bitstream.bytes = webpData.bytes,
629633
.bitstream.size = webpData.length,
@@ -660,7 +664,7 @@ - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format o
660664
return data;
661665
}
662666

663-
- (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef quality:(double)quality {
667+
- (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef quality:(double)quality fileSize:(NSUInteger)fileSize {
664668
NSData *webpData;
665669
if (!imageRef) {
666670
return nil;
@@ -704,7 +708,7 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
704708
return nil;
705709
}
706710

707-
uint8_t *rgba = NULL;
711+
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
708712
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
709713
if (byteOrderNormal && ((alphaInfo == kCGImageAlphaNone) || (alphaInfo == kCGImageAlphaLast))) {
710714
// If the input CGImage is already RGB888/RGBA8888
@@ -758,34 +762,58 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef q
758762

759763
rgba = dest.data; // Converted buffer
760764
bytesPerRow = dest.rowBytes; // Converted bytePerRow
761-
CFRelease(dataRef);
762-
dataRef = NULL;
765+
CFRelease(dataRef); // Use CFData to manage bytes for free, the same code path for error handling
766+
dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, rgba, bytesPerRow * height, kCFAllocatorDefault);
763767
}
764768

765-
uint8_t *data = NULL; // Output WebP data
766769
float qualityFactor = quality * 100; // WebP quality is 0-100
767770
// Encode RGB888/RGBA8888 buffer to WebP data
768-
size_t size;
771+
// Using the libwebp advanced API: https://developers.google.com/speed/webp/docs/api#advanced_encoding_api
772+
WebPConfig config;
773+
WebPPicture picture;
774+
WebPMemoryWriter writer;
775+
776+
if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, qualityFactor) ||
777+
!WebPPictureInit(&picture)) {
778+
// shouldn't happen, except if system installation is broken
779+
CFRelease(dataRef);
780+
return nil;
781+
}
782+
783+
config.target_size = (int)fileSize; // Max filesize for output, 0 means use quality instead
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)
786+
picture.use_argb = config.lossless; // Lossy encoding use YUV for internel bitstream
787+
picture.width = (int)width;
788+
picture.height = (int)height;
789+
picture.writer = WebPMemoryWrite; // Output in memory data buffer
790+
picture.custom_ptr = &writer;
791+
WebPMemoryWriterInit(&writer);
792+
793+
int result;
769794
if (hasAlpha) {
770-
size = WebPEncodeRGBA(rgba, (int)width, (int)height, (int)bytesPerRow, qualityFactor, &data);
795+
result = WebPPictureImportRGBA(&picture, rgba, (int)bytesPerRow);
771796
} else {
772-
size = WebPEncodeRGB(rgba, (int)width, (int)height, (int)bytesPerRow, qualityFactor, &data);
797+
result = WebPPictureImportRGB(&picture, rgba, (int)bytesPerRow);
773798
}
774-
if (dataRef) {
775-
CFRelease(dataRef); // free non-converted rgba buffer
776-
dataRef = NULL;
777-
} else {
778-
free(rgba); // free converted rgba buffer
779-
rgba = NULL;
799+
if (!result) {
800+
WebPMemoryWriterClear(&writer);
801+
CFRelease(dataRef);
802+
return nil;
780803
}
781804

782-
if (size) {
805+
result = WebPEncode(&config, &picture);
806+
CFRelease(dataRef); // Free bitmap buffer
807+
WebPPictureFree(&picture);
808+
809+
if (result) {
783810
// success
784-
webpData = [NSData dataWithBytes:data length:size];
785-
}
786-
if (data) {
787-
WebPFree(data);
811+
webpData = [NSData dataWithBytes:writer.mem length:writer.size];
812+
} else {
813+
// failed
814+
webpData = nil;
788815
}
816+
WebPMemoryWriterClear(&writer);
789817

790818
return webpData;
791819
}

0 commit comments

Comments
 (0)
Please sign in to comment.