Added new API for custom coder better handling the thumbnail size

The current WebP/HEIF/AVIF coder both copy paste the same code multiple times and have to fix one by one
This commit is contained in:
DreamPiggy 2022-06-22 16:53:40 +08:00
parent 19b4b47c60
commit 1f3ee8e9d5
3 changed files with 72 additions and 0 deletions

View File

@ -76,6 +76,7 @@
/**
Create a scaled CGImage by the provided CGImage and size. This follows The Create Rule and you are response to call release after usage.
It will detect whether the image size matching the scale size, if not, stretch the image to the target size.
@note If you need to keep aspect ratio, you can calculate the scale size by using `scaledSizeWithImageSize` first.
@param cgImage The CGImage
@param size The scale size in pixel.
@ -83,6 +84,16 @@
*/
+ (CGImageRef _Nullable)CGImageCreateScaled:(_Nonnull CGImageRef)cgImage size:(CGSize)size CF_RETURNS_RETAINED;
/** Scale the image size based on provided scale size, whether or not to preserve aspect ratio, whether or not to scale up.
@note For example, if you implements thumnail decoding, pass `shouldScaleUp` to NO to avoid the calculated size larger than image size.
@param imageSize The image size (in pixel or point defined by caller)
@param scaleSize The scale size (in pixel or point defined by caller)
@param preserveAspectRatio Whether or not to preserve aspect ratio
@param shouldScaleUp Whether or not to scale up (or scale down only)
*/
+ (CGSize)scaledSizeWithImageSize:(CGSize)imageSize scaleSize:(CGSize)scaleSize preserveAspectRatio:(BOOL)preserveAspectRatio shouldScaleUp:(BOOL)shouldScaleUp;
/**
Return the decoded image by the provided image. This one unlike `CGImageCreateDecoded:`, will not decode the image which contains alpha channel or animated image
@param image The image to be decoded

View File

@ -325,6 +325,43 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return outputImage;
}
+ (CGSize)scaledSizeWithImageSize:(CGSize)imageSize scaleSize:(CGSize)scaleSize preserveAspectRatio:(BOOL)preserveAspectRatio shouldScaleUp:(BOOL)shouldScaleUp {
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat resultWidth;
CGFloat resultHeight;
if (width <= 0 || height <= 0 || scaleSize.width <= 0 || scaleSize.height <= 0) {
// Protect
resultWidth = width;
resultHeight = height;
} else {
// Scale to fit
if (preserveAspectRatio) {
CGFloat pixelRatio = width / height;
CGFloat scaleRatio = scaleSize.width / scaleSize.height;
if (pixelRatio > scaleRatio) {
resultWidth = scaleSize.width;
resultHeight = ceil(scaleSize.width / pixelRatio);
} else {
resultHeight = scaleSize.height;
resultWidth = ceil(scaleSize.height * pixelRatio);
}
} else {
// Stretch
resultWidth = scaleSize.width;
resultHeight = scaleSize.height;
}
if (!shouldScaleUp) {
// Scale down only
resultWidth = MIN(width, resultWidth);
resultHeight = MIN(height, resultHeight);
}
}
return CGSizeMake(resultWidth, resultHeight);
}
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
if (![self shouldDecodeImage:image]) {
return image;

View File

@ -366,6 +366,30 @@
expect(encodedImage.size).equal(CGSizeMake(4000, 2629));
}
- (void)test24ThatScaleSizeCalculation {
// preserveAspectRatio true
CGSize size1 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(100, 200) scaleSize:CGSizeMake(150, 150) preserveAspectRatio:YES shouldScaleUp:NO];
expect(size1).equal(CGSizeMake(75, 150));
CGSize size2 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(100, 200) scaleSize:CGSizeMake(150, 150) preserveAspectRatio:YES shouldScaleUp:YES];
expect(size2).equal(CGSizeMake(75, 150));
CGSize size3 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(100, 200) scaleSize:CGSizeMake(300, 300) preserveAspectRatio:YES shouldScaleUp:NO];
expect(size3).equal(CGSizeMake(100, 200));
CGSize size4 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(100, 200) scaleSize:CGSizeMake(300, 300) preserveAspectRatio:YES shouldScaleUp:YES];
expect(size4).equal(CGSizeMake(150, 300));
// preserveAspectRatio false
CGSize size5 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(100, 200) scaleSize:CGSizeMake(150, 150) preserveAspectRatio:NO shouldScaleUp:NO];
expect(size5).equal(CGSizeMake(100, 150));
CGSize size6 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(100, 200) scaleSize:CGSizeMake(150, 150) preserveAspectRatio:NO shouldScaleUp:YES];
expect(size6).equal(CGSizeMake(150, 150));
// 0 value
CGSize size7 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(0, 0) scaleSize:CGSizeMake(999, 999) preserveAspectRatio:NO shouldScaleUp:NO];
expect(size7).equal(CGSizeMake(0, 0));
CGSize size8 = [SDImageCoderHelper scaledSizeWithImageSize:CGSizeMake(999, 999) scaleSize:CGSizeMake(0, 0) preserveAspectRatio:NO shouldScaleUp:NO];
expect(size8).equal(CGSizeMake(999, 999));
}
#pragma mark - Utils
- (void)verifyCoder:(id<SDImageCoder>)coder