Improved and generalized image thumbnail decoding logic

Reviewed By: jspahrsummers

Differential Revision: D2631934

fb-gh-sync-id: 3ddea328dcb0fc84b9d7b20708324f0b515f1b7f
This commit is contained in:
Nick Lockwood
2015-11-10 05:03:07 -08:00
committed by facebook-github-bot-2
parent 4b78ed2123
commit 2eb8068cf1
3 changed files with 104 additions and 48 deletions

View File

@@ -9,6 +9,9 @@
#import "RCTImageUtils.h"
#import <ImageIO/ImageIO.h>
#import <tgmath.h>
#import "RCTLog.h"
static CGFloat RCTCeilValue(CGFloat value, CGFloat scale)
@@ -193,3 +196,69 @@ BOOL RCTUpscalingRequired(CGSize sourceSize, CGFloat sourceScale,
return NO;
}
}
RCT_EXTERN CGSize RCTSizeInPixels(CGSize pointSize, CGFloat scale)
{
return (CGSize){
ceil(pointSize.width * scale),
ceil(pointSize.height * scale),
};
}
RCT_EXTERN UIImage *RCTDecodeImageWithData(NSData *data,
CGSize destSize,
CGFloat destScale,
UIViewContentMode resizeMode)
{
CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
if (!sourceRef) {
return nil;
}
// get original image size
CGSize sourceSize;
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(sourceRef, 0, NULL);
if (!imageProperties) {
CFRelease(sourceRef);
return nil;
}
NSNumber *width = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
NSNumber *height = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
sourceSize = (CGSize){width.doubleValue, height.doubleValue};
CFRelease(imageProperties);
if (CGSizeEqualToSize(destSize, CGSizeZero)) {
destSize = sourceSize;
}
// calculate target size
CGSize targetSize = RCTTargetSize(sourceSize, 1, destSize, destScale, resizeMode, YES);
CGSize targetPixelSize = RCTSizeInPixels(targetSize, destScale);
CGFloat maxPixelSize = fmax(fmin(sourceSize.width, targetPixelSize.width),
fmin(sourceSize.height, targetPixelSize.height));
NSDictionary *options = @{
(id)kCGImageSourceShouldAllowFloat: @YES,
(id)kCGImageSourceCreateThumbnailWithTransform: @YES,
(id)kCGImageSourceCreateThumbnailFromImageAlways: @YES,
(id)kCGImageSourceThumbnailMaxPixelSize: @(maxPixelSize),
};
// get thumbnail
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
CFRelease(sourceRef);
if (!imageRef) {
return nil;
}
//adjust scale
size_t actualWidth = CGImageGetWidth(imageRef);
CGFloat scale = actualWidth / targetSize.width;
// return image
UIImage *image = [UIImage imageWithCGImage:imageRef
scale:scale
orientation:UIImageOrientationUp];
CGImageRelease(imageRef);
return image;
}