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);
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(), ^{
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.");
__block NSString *imageTag;
dispatch_sync(_methodQueue, ^{
imageTag = [self _storeImageData:RCTGetImageData(image.CGImage, 0.75)];
imageTag = [self _storeImageData:RCTGetImageData(image, 0.75)];
});
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
* 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,

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,
CGFloat destScale, RCTResizeMode resizeMode)
{
@ -314,20 +330,23 @@ NSDictionary<NSString *, id> *__nullable RCTGetImageMetadata(NSData *data)
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;
CFMutableDataRef imageData = CFDataCreateMutable(NULL, 0);
if (RCTImageHasAlpha(image)) {
CGImageRef cgImage = image.CGImage;
if (RCTImageHasAlpha(cgImage)) {
// get png data
destination = CGImageDestinationCreateWithData(imageData, kUTTypePNG, 1, NULL);
} else {
// get jpeg data
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))
{
CFRelease(imageData);