react-native-vision-camera: 🐛 takePhoto always returns asset with landscape orientation on iOS

What were you trying to do?

I am trying to capture a photo with portrait orientation. The orientation prop is set to “portrait”.

Reproduceable Code

<ReanimatedCamera
                      ref={camera}
                      style={StyleSheet.absoluteFill}
                      device={device}
                      format={format}
                      fps={fps}
                      hdr={enableHdr}
                      lowLightBoost={device.supportsLowLightBoost && enableNightMode}
                      isActive={isActive}
                      onInitialized={onInitialized}
                      onError={onError}
                      enableZoomGesture={true}
                      animatedProps={cameraAnimatedProps}
                      photo={true}
                      audio={true}
                      orientation="portrait"
                    />

const takePhotoOptions = useMemo<TakePhotoOptions & TakeSnapshotOptions>(
    () => ({
      photoCodec: 'jpeg',
      enableAutoStabilization: true,
      qualityPrioritization: 'balanced',
      flash: flash,
      skipMetadata: true,
    }),
    [flash],
  );

  const takePicture = useCallback(async () => {
    if (camera.current) {
      try {
        if (camera.current == null) throw new Error('Camera ref is null!');

        console.log('Taking photo...');
        const photo = await camera.current.takePhoto(takePhotoOptions);
        onPhotoCaptured(photo)
      } catch (e) {
        console.error('Failed to take photo!', e);
      }
    }
  }, [onPhotoCaptured, takePhotoOptions])

Also confirmed that the device is locked to portrait.

What happened instead?

Media asset returned is in landscape mode

Relevant log output

Xcode logs show everything is clear. This is the returned media (PhotoFile) obj:

{"height":2160,"metadata":{"{MakerApple}":{"1":14,"2":null,"3":{"timescale":1000000000,"epoch":0,"value":159656062542708,"flags":1},"4":1,"5":173,"6":176,"7":1,"8":[0.14260585606098175,-0.9722282290458679,-0.2048303186893463],"12":[0.1796875,0.2578125],"13":15,"14":0,"15":3,"16":1,"20":1,"23":0,"25":0,"31":0,"32":"BAB2A4BE-9E24-4F46-AC0D-DFF33150EA17","35":[362,268435524],"37":8,"38":1,"39":17.76178741455078,"43":"BEAAC845-CF70-4BB5-860A-DE9779A1477A","45":3896,"46":1,"47":58,"51":0,"52":1,"53":0,"54":90,"55":8,"58":0,"59":0,"60":4,"63":0,"65":false,"74":2},"{TIFF}":{"ResolutionUnit":2,"Software":"15.3","Make":"Apple","DateTime":"2022:02:09 18:48:01","XResolution":72,"HostComputer":"iPhone 12 Pro","Model":"iPhone 12 Pro","YResolution":72},"DPIWidth":72,"Orientation":6,"{Exif}":{"DateTimeOriginal":"2022:02:09 18:48:01","ExposureTime":0.016129032258064516,"FNumber":1.6,"LensSpecification":[4.2,4.2,1.6,1.6],"ExposureBiasValue":0,"ColorSpace":1,"FocalLenIn35mmFilm":29,"BrightnessValue":0.20465028074923952,"ExposureMode":0,"LensModel":"iPhone 12 Pro back camera 4.2mm f/1.6","SceneType":1,"PixelXDimension":3840,"ShutterSpeedValue":5.965603959052092,"SensingMethod":2,"SubjectArea":[1920,1077,2112,946],"ApertureValue":1.3561438102252754,"SubsecTimeDigitized":"492","FocalLength":4.2,"LensMake":"Apple","SubsecTimeOriginal":"492","OffsetTimeDigitized":"-05:00","PixelYDimension":2160,"ISOSpeedRatings":[640],"WhiteBalance":0,"DateTimeDigitized":"2022:02:09 18:48:01","OffsetTimeOriginal":"-05:00","ExifVersion":"0232","OffsetTime":"-05:00","Flash":16,"ExposureProgram":2,"MeteringMode":5},"DPIHeight":72},"isRawPhoto":false,"thumbnail":null,"path":"/private/var/mobile/Containers/Data/Application/FA4B93BB-2AD8-4CA0-96BE-94C2E83FE1F6/tmp/ReactNative/2E5F7B8A-9233-428E-8FB2-6B2358E08460.jpeg","width":3840}

Device

iPhone 12 Pro

VisionCamera Version

2.12.0

Additional information

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 3
  • Comments: 17 (5 by maintainers)

Commits related to this issue

Most upvoted comments

+1 Facing the same issue.

@tedi @ethul @mrousavy

In the Apple Document there is talk about this issue.

For example, an iOS device camera always encodes pixel data in the camera sensor's native landscape orientation, along with metadata indicating the camera orientation. When UIImage loads a photo shot in portrait orientation, it automatically applies a 90° rotation before displaying the image data, and the image's [imageOrientation](https://developer.apple.com/documentation/uikit/uiimage/1624141-imageorientation) value of [UIImage.Orientation.right](https://developer.apple.com/documentation/uikit/uiimage/orientation/right) indicates that this rotation has been applied.

And this is how we get height and width of the image.

I think we need change logic in here, look like this:

Screen Shot 2022-03-31 at 13 40 11

@mrousavy We’re also only using portrait.

@wego-deluxe @akshay8033 we’re doing a hacky workaround. We’re cropping in the exact center of the returned image, with the size of the viewport, which essentially returns whatever is in the preview. We started working on a possible PR, but we’re in the middle of a launch. I hope to return to this in 2-3 weeks.

Regardless, this library is way ahead of anything else out there. Thank you @mrousavy for all your work.

Guys, android has this problem also. It gives the height and width reverse if you use takePhoto function. It is giving the correct results with takeSnaphot function . Do you have any solution for that ?