Skip to content

Commit cb4447c

Browse files
npomfretZack Story
authored andcommitted
add fixOrientation option (react-native-camera#682)
* optional fix orientation * comments * docs
1 parent 8878954 commit cb4447c

File tree

5 files changed

+45
-25
lines changed

5 files changed

+45
-25
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@ If set to `true`, the device will not sleep while the camera preview is visible.
294294

295295
If set to `true`, the image returned will be mirrored.
296296

297+
#### `fixOrientation` (_deprecated_)
298+
299+
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.
300+
301+
(_If you find that you need to use this option because your images are incorrectly oriented by default,
302+
could please submit a PR and include the make model of the device. We believe that it's not
303+
required functionality any more and would like to remove it._)
304+
297305
## Component instance methods
298306

299307
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.

android/src/main/java/com/lwansbrough/RCTCamera/MutableImage.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,22 @@ public void fixOrientation() throws ImageMutationFailedException {
6666
return;
6767
} else if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
6868
int exifOrientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
69-
rotate(exifOrientation);
69+
if(exifOrientation != 1) {
70+
rotate(exifOrientation);
71+
exifIFD0Directory.setInt(ExifIFD0Directory.TAG_ORIENTATION, 1);
72+
}
7073
}
7174
} catch (ImageProcessingException | IOException | MetadataException e) {
7275
throw new ImageMutationFailedException("failed to fix orientation", e);
7376
}
7477
}
7578

79+
//see http://www.impulseadventure.com/photo/exif-orientation.html
7680
private void rotate(int exifOrientation) throws ImageMutationFailedException {
7781
final Matrix bitmapMatrix = new Matrix();
7882
switch (exifOrientation) {
7983
case 1:
80-
break;
84+
return;//no rotation required
8185
case 2:
8286
bitmapMatrix.postScale(-1, 1);
8387
break;

android/src/main/java/com/lwansbrough/RCTCamera/RCTCameraModule.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,6 @@ private void captureWithOrientation(final ReadableMap options, final Promise pro
524524
RCTCamera.getInstance().setCaptureQuality(options.getInt("type"), options.getString("quality"));
525525
}
526526

527-
final Boolean shouldMirror = options.hasKey("mirrorImage") && options.getBoolean("mirrorImage");
528-
529527
RCTCamera.getInstance().adjustCameraRotationToDeviceOrientation(options.getInt("type"), deviceOrientation);
530528
camera.setPreviewCallback(null);
531529

@@ -538,7 +536,7 @@ public void onPictureTaken(final byte[] data, Camera camera) {
538536
AsyncTask.execute(new Runnable() {
539537
@Override
540538
public void run() {
541-
processImage(new MutableImage(data), shouldMirror, options, promise);
539+
processImage(new MutableImage(data), options, promise);
542540
}
543541
});
544542

@@ -560,13 +558,17 @@ public void run() {
560558
* synchronized in order to prevent the user crashing the app by taking many photos and them all being processed
561559
* concurrently which would blow the memory (esp on smaller devices), and slow things down.
562560
*/
563-
private synchronized void processImage(MutableImage mutableImage, Boolean shouldMirror, ReadableMap options, Promise promise) {
564-
try {
565-
mutableImage.fixOrientation();
566-
} catch (MutableImage.ImageMutationFailedException e) {
567-
promise.reject("Error mirroring image", e);
561+
private synchronized void processImage(MutableImage mutableImage, ReadableMap options, Promise promise) {
562+
boolean shouldFixOrientation = options.hasKey("fixOrientation") && options.getBoolean("fixOrientation");
563+
if(shouldFixOrientation) {
564+
try {
565+
mutableImage.fixOrientation();
566+
} catch (MutableImage.ImageMutationFailedException e) {
567+
promise.reject("Error fixing orientation image", e);
568+
}
568569
}
569-
570+
571+
boolean shouldMirror = options.hasKey("mirrorImage") && options.getBoolean("mirrorImage");
570572
if (shouldMirror) {
571573
try {
572574
mutableImage.mirrorImage();

index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export default class Camera extends Component {
100100
onFocusChanged: PropTypes.func,
101101
onZoomChanged: PropTypes.func,
102102
mirrorImage: PropTypes.bool,
103+
fixOrientation: PropTypes.bool,
103104
barCodeTypes: PropTypes.array,
104105
orientation: PropTypes.oneOfType([
105106
PropTypes.string,
@@ -120,6 +121,7 @@ export default class Camera extends Component {
120121
aspect: CameraManager.Aspect.fill,
121122
type: CameraManager.Type.back,
122123
orientation: CameraManager.Orientation.auto,
124+
fixOrientation: false,
123125
captureAudio: false,
124126
captureMode: CameraManager.CaptureMode.still,
125127
captureTarget: CameraManager.CaptureTarget.cameraRoll,
@@ -219,6 +221,7 @@ export default class Camera extends Component {
219221
title: '',
220222
description: '',
221223
mirrorImage: props.mirrorImage,
224+
fixOrientation: props.fixOrientation,
222225
...options
223226
};
224227

ios/RCTCameraManager.m

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -595,32 +595,35 @@ - (void)captureStill:(NSInteger)target options:(NSDictionary *)options orientati
595595
NSMutableDictionary *imageMetadata = [(NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source, 0, NULL)) mutableCopy];
596596

597597
// create cgimage
598-
CGImageRef CGImage;
599-
CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
598+
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
600599

601600
// Rotate it
602601
CGImageRef rotatedCGImage;
603602
if ([options objectForKey:@"rotation"]) {
604603
float rotation = [[options objectForKey:@"rotation"] floatValue];
605-
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:rotation];
606-
} else {
604+
rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:rotation];
605+
} else if ([options objectForKey:@"fixOrientation"]){
607606
// Get metadata orientation
608607
int metadataOrientation = [[imageMetadata objectForKey:(NSString *)kCGImagePropertyOrientation] intValue];
609-
608+
609+
bool rotated = false;
610+
//see http://www.impulseadventure.com/photo/exif-orientation.html
610611
if (metadataOrientation == 6) {
611-
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:270];
612-
} else if (metadataOrientation == 1) {
613-
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:0];
612+
rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:270];
613+
rotated = true;
614614
} else if (metadataOrientation == 3) {
615-
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:180];
616-
} else {
617-
rotatedCGImage = [self newCGImageRotatedByAngle:CGImage angle:0];
615+
rotatedCGImage = [self newCGImageRotatedByAngle:cgImage angle:180];
616+
rotated = true;
618617
}
618+
619+
if(rotated) {
620+
[imageMetadata setObject:[NSNumber numberWithInteger:1] forKey:(NSString *)kCGImagePropertyOrientation];
621+
CGImageRelease(cgImage);
622+
}
623+
} else {
624+
rotatedCGImage = cgImage;
619625
}
620-
CGImageRelease(CGImage);
621626

622-
// Erase metadata orientation
623-
[imageMetadata removeObjectForKey:(NSString *)kCGImagePropertyOrientation];
624627
// Erase stupid TIFF stuff
625628
[imageMetadata removeObjectForKey:(NSString *)kCGImagePropertyTIFFDictionary];
626629

0 commit comments

Comments
 (0)