Fix photo orientation from ImagePickerIOS

Summary:
Original PR: https://github.com/facebook/react-native/pull/12249

ImagePickerIOS saves photos to ImageStoreManager without meta information. So photo has wrong orientation.

**Test plan**
1. Take the 2 photos (in landspape and portrait orientation) with this code:
```
ImagePickerIOS.openCameraDialog(
  {},
  (uri) => CameraRoll.saveToCameraRoll(uri),
  () => {}
);
```
2. Ensure that photos in Photos app have right orientation.
Closes https://github.com/facebook/react-native/pull/15060

Differential Revision: D5487595

Pulled By: shergin

fbshipit-source-id: ce1a47f4d5ba33e03070f318f3d6a8dd0df5ab88
This commit is contained in:
Aleksei Androsov 2017-07-24 21:39:02 -07:00 committed by Facebook Github Bot
parent eec58237ce
commit 6555f9bee8
3 changed files with 27 additions and 8 deletions

View File

@ -76,7 +76,7 @@ RCT_EXPORT_MODULE()
{ {
RCTAssertParam(block); RCTAssertParam(block);
dispatch_async(_methodQueue, ^{ dispatch_async(_methodQueue, ^{
NSString *imageTag = [self _storeImageData:RCTGetImageData(image.CGImage, 0.75)]; NSString *imageTag = [self _storeImageData:RCTGetImageData(image, 0.75)];
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
block(imageTag); block(imageTag);
}); });
@ -197,7 +197,7 @@ RCT_EXPORT_METHOD(addImageFromBase64:(NSString *)base64String
RCTLogWarn(@"RCTImageStoreManager.storeImage() is deprecated and has poor performance. Use an alternative method instead."); RCTLogWarn(@"RCTImageStoreManager.storeImage() is deprecated and has poor performance. Use an alternative method instead.");
__block NSString *imageTag; __block NSString *imageTag;
dispatch_sync(_methodQueue, ^{ dispatch_sync(_methodQueue, ^{
imageTag = [self _storeImageData:RCTGetImageData(image.CGImage, 0.75)]; imageTag = [self _storeImageData:RCTGetImageData(image, 0.75)];
}); });
return imageTag; return imageTag;
} }

View File

@ -76,7 +76,7 @@ RCT_EXTERN NSDictionary<NSString *, id> *__nullable RCTGetImageMetadata(NSData *
* conversion, with 1.0 being maximum quality. It has no effect for images * conversion, with 1.0 being maximum quality. It has no effect for images
* using PNG compression. * using PNG compression.
*/ */
RCT_EXTERN NSData *__nullable RCTGetImageData(CGImageRef image, float quality); RCT_EXTERN NSData *__nullable RCTGetImageData(UIImage *image, float quality);
/** /**
* This function transforms an image. `destSize` is the size of the final image, * This function transforms an image. `destSize` is the size of the final image,

View File

@ -35,6 +35,22 @@ static CGSize RCTCeilSize(CGSize size, CGFloat scale)
}; };
} }
static CGImagePropertyOrientation CGImagePropertyOrientationFromUIImageOrientation(UIImageOrientation imageOrientation)
{
// see https://stackoverflow.com/a/6699649/496389
switch (imageOrientation) {
case UIImageOrientationUp: return kCGImagePropertyOrientationUp;
case UIImageOrientationDown: return kCGImagePropertyOrientationDown;
case UIImageOrientationLeft: return kCGImagePropertyOrientationLeft;
case UIImageOrientationRight: return kCGImagePropertyOrientationRight;
case UIImageOrientationUpMirrored: return kCGImagePropertyOrientationUpMirrored;
case UIImageOrientationDownMirrored: return kCGImagePropertyOrientationDownMirrored;
case UIImageOrientationLeftMirrored: return kCGImagePropertyOrientationLeftMirrored;
case UIImageOrientationRightMirrored: return kCGImagePropertyOrientationRightMirrored;
default: return kCGImagePropertyOrientationUp;
}
}
CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize, CGRect RCTTargetRect(CGSize sourceSize, CGSize destSize,
CGFloat destScale, RCTResizeMode resizeMode) CGFloat destScale, RCTResizeMode resizeMode)
{ {
@ -314,20 +330,23 @@ NSDictionary<NSString *, id> *__nullable RCTGetImageMetadata(NSData *data)
return (__bridge_transfer id)imageProperties; return (__bridge_transfer id)imageProperties;
} }
NSData *__nullable RCTGetImageData(CGImageRef image, float quality) NSData *__nullable RCTGetImageData(UIImage *image, float quality)
{ {
NSDictionary *properties; NSMutableDictionary *properties = [[NSMutableDictionary alloc] initWithDictionary:@{
(id)kCGImagePropertyOrientation : @(CGImagePropertyOrientationFromUIImageOrientation(image.imageOrientation))
}];
CGImageDestinationRef destination; CGImageDestinationRef destination;
CFMutableDataRef imageData = CFDataCreateMutable(NULL, 0); CFMutableDataRef imageData = CFDataCreateMutable(NULL, 0);
if (RCTImageHasAlpha(image)) { CGImageRef cgImage = image.CGImage;
if (RCTImageHasAlpha(cgImage)) {
// get png data // get png data
destination = CGImageDestinationCreateWithData(imageData, kUTTypePNG, 1, NULL); destination = CGImageDestinationCreateWithData(imageData, kUTTypePNG, 1, NULL);
} else { } else {
// get jpeg data // get jpeg data
destination = CGImageDestinationCreateWithData(imageData, kUTTypeJPEG, 1, NULL); destination = CGImageDestinationCreateWithData(imageData, kUTTypeJPEG, 1, NULL);
properties = @{(NSString *)kCGImageDestinationLossyCompressionQuality: @(quality)}; [properties setValue:@(quality) forKey:(id)kCGImageDestinationLossyCompressionQuality];
} }
CGImageDestinationAddImage(destination, image, (__bridge CFDictionaryRef)properties); CGImageDestinationAddImage(destination, cgImage, (__bridge CFDictionaryRef)properties);
if (!CGImageDestinationFinalize(destination)) if (!CGImageDestinationFinalize(destination))
{ {
CFRelease(imageData); CFRelease(imageData);