add fixOrientation option (#682)

* optional fix orientation

* comments

* docs
This commit is contained in:
Nick Pomfret 2017-05-17 18:32:53 +01:00 committed by Zack Story
parent 8878954e08
commit cb4447c60e
5 changed files with 45 additions and 25 deletions

View File

@ -294,6 +294,14 @@ If set to `true`, the device will not sleep while the camera preview is visible.
If set to `true`, the image returned will be mirrored.
#### `fixOrientation` (_deprecated_)
If set to `true`, the image returned will be rotated to the _right way up_. WARNING: It uses a significant amount of memory and my cause your application to crash if the device cannot provide enough RAM to perform the rotation.
(_If you find that you need to use this option because your images are incorrectly oriented by default,
could please submit a PR and include the make model of the device. We believe that it's not
required functionality any more and would like to remove it._)
## Component instance methods
You can access component methods by adding a `ref` (ie. `ref="camera"`) prop to your `<Camera>` element, then you can use `this.refs.camera.capture(cb)`, etc. inside your component.

View File

@ -66,18 +66,22 @@ public class MutableImage {
return;
} else if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
int exifOrientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
rotate(exifOrientation);
if(exifOrientation != 1) {
rotate(exifOrientation);
exifIFD0Directory.setInt(ExifIFD0Directory.TAG_ORIENTATION, 1);
}
}
} catch (ImageProcessingException | IOException | MetadataException e) {
throw new ImageMutationFailedException("failed to fix orientation", e);
}
}
//see http://www.impulseadventure.com/photo/exif-orientation.html
private void rotate(int exifOrientation) throws ImageMutationFailedException {
final Matrix bitmapMatrix = new Matrix();
switch (exifOrientation) {
case 1:
break;
return;//no rotation required
case 2:
bitmapMatrix.postScale(-1, 1);
break;

View File

@ -524,8 +524,6 @@ public class RCTCameraModule extends ReactContextBaseJavaModule
RCTCamera.getInstance().setCaptureQuality(options.getInt("type"), options.getString("quality"));
}
final Boolean shouldMirror = options.hasKey("mirrorImage") && options.getBoolean("mirrorImage");
RCTCamera.getInstance().adjustCameraRotationToDeviceOrientation(options.getInt("type"), deviceOrientation);
camera.setPreviewCallback(null);
@ -538,7 +536,7 @@ public class RCTCameraModule extends ReactContextBaseJavaModule
AsyncTask.execute(new Runnable() {
@Override
public void run() {
processImage(new MutableImage(data), shouldMirror, options, promise);
processImage(new MutableImage(data), options, promise);
}
});
@ -560,13 +558,17 @@ public class RCTCameraModule extends ReactContextBaseJavaModule
* synchronized in order to prevent the user crashing the app by taking many photos and them all being processed
* concurrently which would blow the memory (esp on smaller devices), and slow things down.
*/
private synchronized void processImage(MutableImage mutableImage, Boolean shouldMirror, ReadableMap options, Promise promise) {
try {
mutableImage.fixOrientation();
} catch (MutableImage.ImageMutationFailedException e) {
promise.reject("Error mirroring image", e);
private synchronized void processImage(MutableImage mutableImage, ReadableMap options, Promise promise) {
boolean shouldFixOrientation = options.hasKey("fixOrientation") && options.getBoolean("fixOrientation");
if(shouldFixOrientation) {
try {
mutableImage.fixOrientation();
} catch (MutableImage.ImageMutationFailedException e) {
promise.reject("Error fixing orientation image", e);
}
}
boolean shouldMirror = options.hasKey("mirrorImage") && options.getBoolean("mirrorImage");
if (shouldMirror) {
try {
mutableImage.mirrorImage();

View File

@ -100,6 +100,7 @@ export default class Camera extends Component {
onFocusChanged: PropTypes.func,
onZoomChanged: PropTypes.func,
mirrorImage: PropTypes.bool,
fixOrientation: PropTypes.bool,
barCodeTypes: PropTypes.array,
orientation: PropTypes.oneOfType([
PropTypes.string,
@ -120,6 +121,7 @@ export default class Camera extends Component {
aspect: CameraManager.Aspect.fill,
type: CameraManager.Type.back,
orientation: CameraManager.Orientation.auto,
fixOrientation: false,
captureAudio: false,
captureMode: CameraManager.CaptureMode.still,
captureTarget: CameraManager.CaptureTarget.cameraRoll,
@ -219,6 +221,7 @@ export default class Camera extends Component {
title: '',
description: '',
mirrorImage: props.mirrorImage,
fixOrientation: props.fixOrientation,
...options
};

View File

@ -595,32 +595,35 @@ RCT_EXPORT_METHOD(hasFlash:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRej
NSMutableDictionary *imageMetadata = [(NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL)) mutableCopy];
// create cgimage
CGImageRef CGImage;
CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
// Rotate it
CGImageRef rotatedCGImage;
if ([options objectForKey:@"rotation"]) {
float rotation = [[options objectForKey:@"rotation"] floatValue];
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:rotation];
} else {
rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:rotation];
} else if ([options objectForKey:@"fixOrientation"]){
// Get metadata orientation
int metadataOrientation = [[imageMetadata objectForKey:(NSString *)kCGImagePropertyOrientation] intValue];
bool rotated = false;
//see http://www.impulseadventure.com/photo/exif-orientation.html
if (metadataOrientation == 6) {
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:270];
} else if (metadataOrientation == 1) {
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:0];
rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:270];
rotated = true;
} else if (metadataOrientation == 3) {
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:180];
} else {
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:0];
rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:180];
rotated = true;
}
if(rotated) {
[imageMetadata setObject:[NSNumber numberWithInteger:1] forKey:(NSString *)kCGImagePropertyOrientation];
CGImageRelease(cgImage);
}
} else {
rotatedCGImage = cgImage;
}
CGImageRelease(CGImage);
// Erase metadata orientation
[imageMetadata removeObjectForKey:(NSString *)kCGImagePropertyOrientation];
// Erase stupid TIFF stuff
[imageMetadata removeObjectForKey:(NSString *)kCGImagePropertyTIFFDictionary];