add fixOrientation option (#682)
* optional fix orientation * comments * docs
This commit is contained in:
parent
8878954e08
commit
cb4447c60e
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
3
index.js
3
index.js
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
Loading…
Reference in New Issue