Fix the bug that SDImageCoderDecodeScaleDownLimitBytes still use the AnimatedImageRep and beyond the byte limit
Also, expose the limit bytes calculation utils method
This commit is contained in:
parent
c51ba84499
commit
47fd1c9a10
|
@ -83,6 +83,7 @@ FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeUseLazyDec
|
|||
3. If the `framePixelSize < originalImagePixelSize`, then do thumbnail decoding (see `SDImageCoderDecodeThumbnailPixelSize`) use the `framePixelSize` and `preseveAspectRatio = YES`
|
||||
4. Else, use the full pixel decoding (small than limit bytes)
|
||||
5. Whatever result, this does not effect the animated/static behavior of image. So even if you set `limitBytes = 1 && frameCount = 100`, we will stll create animated image with each frame `1x1` pixel size.
|
||||
@note You can use the logic from `+[SDImageCoder scaledSizeWithImageSize:limitBytes:bytesPerPixel:frameCount:]`
|
||||
@note This option has higher priority than `.decodeThumbnailPixelSize`
|
||||
*/
|
||||
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeScaleDownLimitBytes;
|
||||
|
|
|
@ -104,6 +104,12 @@ typedef NS_ENUM(NSUInteger, SDImageCoderDecodeSolution) {
|
|||
*/
|
||||
+ (CGSize)scaledSizeWithImageSize:(CGSize)imageSize scaleSize:(CGSize)scaleSize preserveAspectRatio:(BOOL)preserveAspectRatio shouldScaleUp:(BOOL)shouldScaleUp;
|
||||
|
||||
/// Calculate the limited image size with the bytes, when using `SDImageCoderDecodeScaleDownLimitBytes`. This preserve aspect ratio and never scale up
|
||||
/// @param imageSize The image size (in pixel or point defined by caller)
|
||||
/// @param limitBytes The limit bytes
|
||||
/// @param bytesPerPixel The bytes per pixel
|
||||
/// @param frameCount The image frame count, 0 means 1 frame as well
|
||||
+ (CGSize)scaledSizeWithImageSize:(CGSize)imageSize limitBytes:(NSUInteger)limitBytes bytesPerPixel:(NSUInteger)bytesPerPixel frameCount:(NSUInteger)frameCount;
|
||||
/**
|
||||
Return the decoded image by the provided image. This one unlike `CGImageCreateDecoded:`, will not decode the image which contains alpha channel or animated image. On iOS 15+, this may use `UIImage.preparingForDisplay()` to use CMPhoto for better performance than the old solution.
|
||||
@param image The image to be decoded
|
||||
|
|
|
@ -428,6 +428,19 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
return CGSizeMake(resultWidth, resultHeight);
|
||||
}
|
||||
|
||||
+ (CGSize)scaledSizeWithImageSize:(CGSize)imageSize limitBytes:(NSUInteger)limitBytes bytesPerPixel:(NSUInteger)bytesPerPixel frameCount:(NSUInteger)frameCount {
|
||||
if (CGSizeEqualToSize(imageSize, CGSizeZero)) return CGSizeMake(1, 1);
|
||||
NSUInteger totalFramePixelSize = limitBytes / bytesPerPixel / (frameCount ?: 1);
|
||||
CGFloat ratio = imageSize.height / imageSize.width;
|
||||
CGFloat width = sqrt(totalFramePixelSize / ratio);
|
||||
CGFloat height = width * ratio;
|
||||
width = MAX(1, floor(width));
|
||||
height = MAX(1, floor(height));
|
||||
CGSize size = CGSizeMake(width, height);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
|
||||
if (![self shouldDecodeImage:image]) {
|
||||
return image;
|
||||
|
|
|
@ -47,19 +47,6 @@ static CGImageRef __nullable SDCGImageCreateCopy(CGImageRef cg_nullable image) {
|
|||
return newImage;
|
||||
}
|
||||
|
||||
static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize originalSize, NSUInteger frameCount, NSUInteger bytesPerPixel) {
|
||||
if (CGSizeEqualToSize(originalSize, CGSizeZero)) return CGSizeMake(1, 1);
|
||||
NSUInteger totalFramePixelSize = limitBytes / bytesPerPixel / (frameCount ?: 1);
|
||||
CGFloat ratio = originalSize.height / originalSize.width;
|
||||
CGFloat width = sqrt(totalFramePixelSize / ratio);
|
||||
CGFloat height = width * ratio;
|
||||
width = MAX(1, floor(width));
|
||||
height = MAX(1, floor(height));
|
||||
CGSize size = CGSizeMake(width, height);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@interface SDImageIOCoderFrame : NSObject
|
||||
|
||||
@property (nonatomic, assign) NSUInteger index; // Frame index (zero based)
|
||||
|
@ -384,10 +371,16 @@ static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize
|
|||
lazyDecode = lazyDecodeValue.boolValue;
|
||||
}
|
||||
|
||||
NSUInteger limitBytes = 0;
|
||||
NSNumber *limitBytesValue = options[SDImageCoderDecodeScaleDownLimitBytes];
|
||||
if (limitBytesValue != nil) {
|
||||
limitBytes = limitBytesValue.unsignedIntegerValue;
|
||||
}
|
||||
|
||||
#if SD_MAC
|
||||
// If don't use thumbnail, prefers the built-in generation of frames (GIF/APNG)
|
||||
// Which decode frames in time and reduce memory usage
|
||||
if (thumbnailSize.width == 0 || thumbnailSize.height == 0) {
|
||||
if (limitBytes == 0 && (thumbnailSize.width == 0 || thumbnailSize.height == 0)) {
|
||||
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:data];
|
||||
if (imageRep) {
|
||||
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
|
||||
|
@ -432,11 +425,6 @@ static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize
|
|||
size_t frameCount = CGImageSourceGetCount(source);
|
||||
UIImage *animatedImage;
|
||||
|
||||
NSUInteger limitBytes = 0;
|
||||
NSNumber *limitBytesValue = options[SDImageCoderDecodeScaleDownLimitBytes];
|
||||
if (limitBytesValue != nil) {
|
||||
limitBytes = limitBytesValue.unsignedIntegerValue;
|
||||
}
|
||||
// Parse the image properties
|
||||
NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
|
||||
size_t width = [properties[(__bridge NSString *)kCGImagePropertyPixelWidth] doubleValue];
|
||||
|
@ -445,7 +433,7 @@ static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize
|
|||
if (limitBytes > 0) {
|
||||
// Hack since ImageIO public API (not CGImageDecompressor/CMPhoto) always return back RGBA8888 CGImage
|
||||
CGSize imageSize = CGSizeMake(width, height);
|
||||
CGSize framePixelSize = SDCalculateScaleDownPixelSize(limitBytes, imageSize, frameCount, 4);
|
||||
CGSize framePixelSize = [SDImageCoderHelper scaledSizeWithImageSize:imageSize limitBytes:limitBytes bytesPerPixel:4 frameCount:frameCount];
|
||||
// Override thumbnail size
|
||||
thumbnailSize = framePixelSize;
|
||||
preserveAspectRatio = YES;
|
||||
|
@ -568,7 +556,7 @@ static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize
|
|||
if (_limitBytes > 0) {
|
||||
// Hack since ImageIO public API (not CGImageDecompressor/CMPhoto) always return back RGBA8888 CGImage
|
||||
CGSize imageSize = CGSizeMake(_width, _height);
|
||||
CGSize framePixelSize = SDCalculateScaleDownPixelSize(_limitBytes, imageSize, _frameCount, 4);
|
||||
CGSize framePixelSize = [SDImageCoderHelper scaledSizeWithImageSize:imageSize limitBytes:_limitBytes bytesPerPixel:4 frameCount:_frameCount];
|
||||
// Override thumbnail size
|
||||
_thumbnailSize = framePixelSize;
|
||||
_preserveAspectRatio = YES;
|
||||
|
@ -773,7 +761,7 @@ static inline CGSize SDCalculateScaleDownPixelSize(NSUInteger limitBytes, CGSize
|
|||
if (_limitBytes > 0) {
|
||||
// Hack since ImageIO public API (not CGImageDecompressor/CMPhoto) always return back RGBA8888 CGImage
|
||||
CGSize imageSize = CGSizeMake(_width, _height);
|
||||
CGSize framePixelSize = SDCalculateScaleDownPixelSize(_limitBytes, imageSize, _frameCount, 4);
|
||||
CGSize framePixelSize = [SDImageCoderHelper scaledSizeWithImageSize:imageSize limitBytes:_limitBytes bytesPerPixel:4 frameCount:_frameCount];
|
||||
// Override thumbnail size
|
||||
_thumbnailSize = framePixelSize;
|
||||
_preserveAspectRatio = YES;
|
||||
|
|
Loading…
Reference in New Issue