diff --git a/packages/react-native/Libraries/Image/RCTImageUtils.mm b/packages/react-native/Libraries/Image/RCTImageUtils.mm index bac55d05c68e6d..11a5175f990a4d 100644 --- a/packages/react-native/Libraries/Image/RCTImageUtils.mm +++ b/packages/react-native/Libraries/Image/RCTImageUtils.mm @@ -293,18 +293,28 @@ BOOL RCTUpscalingRequired( // Calculate target size CGSize targetSize = RCTTargetSize(sourceSize, 1, destSize, destScale, resizeMode, NO); 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); + CGImageRef imageRef; + BOOL createFullImage = targetPixelSize.width == 0 || targetPixelSize.height == 0 || (sourceSize.width <= targetPixelSize.width && sourceSize.height <= targetPixelSize.height); + + if (createFullImage) { + // Get an image in full size. This is faster than `CGImageSourceCreateThumbnailAtIndex` + // and consumes less memory if only the target size doesn't require downscaling. + imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)@{ + (id)kCGImageSourceShouldAllowFloat : @YES, + }); + } else { + CGFloat maxPixelSize = fmax(targetPixelSize.width, targetPixelSize.height); + + // Get a thumbnail of the source image. This is usually slower than creating a full-sized image, + // but takes up less memory once it's done. + imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)@{ + (id)kCGImageSourceShouldAllowFloat : @YES, + (id)kCGImageSourceCreateThumbnailWithTransform : @YES, + (id)kCGImageSourceCreateThumbnailFromImageAlways : @YES, + (id)kCGImageSourceThumbnailMaxPixelSize : @(maxPixelSize), + }); + } + CFRelease(sourceRef); if (!imageRef) { return nil;