Fix the maxPixelSize for animated images, update the readme

This commit is contained in:
DreamPiggy 2020-04-03 23:59:17 +08:00
parent e71bbf239c
commit f798b89fc2
3 changed files with 32 additions and 4 deletions

View File

@ -37,6 +37,7 @@ FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodePreserveAs
/**
A CGSize value indicating whether or not to generate the thumbnail images (or bitmap images from vector format). When this value is provided, the decoder will generate a thumbnail image which pixel size is smaller than or equal to (depends the `.preserveAspectRatio`) the value size.
Defaults to CGSizeZero, which means no thumbnail generation at all.
@note Supports for animated image as well.
@note When you pass `.preserveAspectRatio == NO`, the thumbnail image is stretched to match each dimension. When `.preserveAspectRatio == YES`, the thumbnail image's width is limited to pixel size's width, the thumbnail image's height is limited to pixel size's height. For common cases, you can just pass a square size to limit both.
@note works for `SDImageCoder`, `SDProgressiveImageCoder`, `SDAnimatedImageCoder`.
*/
@ -62,8 +63,10 @@ FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeCompressio
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeBackgroundColor;
/**
A CGSize value indicating the max image resolution in pixels during encoding. For vector image, this also effect the output vector data information about width and height. The encoder will not generate the encoded image larger than this limit. Note it always use the aspect ratio of input image.
A CGSize value indicating the max image resolution in pixels during encoding. For vector image, this also effect the output vector data information about width and height. The encoder will not generate the encoded image larger than this limit. Note it always use the aspect ratio of input image..
Defaults to CGSizeZero, which means no max size limit at all.
@note Supports for animated image as well.
@note The ouput image's width is limited to pixel size's width, the output image's height is limited to pixel size's height. For common cases, you can just pass a square size to limit both.
@note works for `SDImageCoder`
*/
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeMaxPixelSize;

View File

@ -452,21 +452,23 @@ static NSString * kSDCGImageSourceRasterizationDPI = @"kCGImageSourceRasterizati
}
NSUInteger pixelWidth = CGImageGetWidth(imageRef);
NSUInteger pixelHeight = CGImageGetHeight(imageRef);
CGFloat finalPixelSize = 0;
if (maxPixelSize.width > 0 && maxPixelSize.height > 0 && pixelWidth > 0 && pixelHeight > 0) {
CGFloat pixelRatio = pixelWidth / pixelHeight;
CGFloat maxPixelSizeRatio = maxPixelSize.width / maxPixelSize.height;
CGFloat finalPixelSize;
if (pixelRatio > maxPixelSizeRatio) {
finalPixelSize = maxPixelSize.width;
} else {
finalPixelSize = maxPixelSize.height;
}
properties[(__bridge NSString *)kCGImageDestinationImageMaxPixelSize] = @(finalPixelSize);
}
BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue];
if (encodeFirstFrame || frames.count == 0) {
// for static single images
if (finalPixelSize > 0) {
properties[(__bridge NSString *)kCGImageDestinationImageMaxPixelSize] = @(finalPixelSize);
}
CGImageDestinationAddImage(imageDestination, imageRef, (__bridge CFDictionaryRef)properties);
} else {
// for animated images
@ -479,7 +481,11 @@ static NSString * kSDCGImageSourceRasterizationDPI = @"kCGImageSourceRasterizati
SDImageFrame *frame = frames[i];
NSTimeInterval frameDuration = frame.duration;
CGImageRef frameImageRef = frame.image.CGImage;
NSDictionary *frameProperties = @{self.class.dictionaryProperty : @{self.class.delayTimeProperty : @(frameDuration)}};
NSMutableDictionary *frameProperties = [NSMutableDictionary dictionary];
frameProperties[self.class.dictionaryProperty] = @{self.class.delayTimeProperty : @(frameDuration)};
if (finalPixelSize > 0) {
frameProperties[(__bridge NSString *)kCGImageDestinationImageMaxPixelSize] = @(finalPixelSize);
}
CGImageDestinationAddImage(imageDestination, frameImageRef, (__bridge CFDictionaryRef)frameProperties);
}
}

View File

@ -271,6 +271,25 @@ withLocalImageURL:(NSURL *)imageUrl
#if SD_UIKIT
expect(outputImage.images.count).to.equal(inputImage.images.count);
#endif
// check max pixel size encoding with scratch
CGFloat maxWidth = 50;
CGFloat maxHeight = 50;
CGFloat maxRatio = maxWidth / maxHeight;
CGSize maxPixelSize;
if (ratio > maxRatio) {
maxPixelSize = CGSizeMake(maxWidth, round(maxWidth / ratio));
} else {
maxPixelSize = CGSizeMake(round(maxHeight * ratio), maxHeight);
}
NSData *outputMaxImageData = [coder encodedDataWithImage:inputImage format:encodingFormat options:@{SDImageCoderEncodeMaxPixelSize : @(CGSizeMake(maxWidth, maxHeight))}];
UIImage *outputMaxImage = [coder decodedImageWithData:outputMaxImageData options:nil];
// Image/IO's thumbnail API does not always use round to preserve precision, we check ABS <= 1
expect(ABS(outputMaxImage.size.width - maxPixelSize.width) <= 1);
expect(ABS(outputMaxImage.size.height - maxPixelSize.height) <= 1);
#if SD_UIKIT
expect(outputMaxImage.images.count).to.equal(inputImage.images.count);
#endif
}
}