mrousavy / react-native-vision-camera

📸 A powerful, high-performance React Native Camera library.
https://react-native-vision-camera.com
MIT License
7.35k stars 1.07k forks source link

💭 What is the equivalence of V2's `preset="photo"` in V3? #2675

Closed jackylu0124 closed 5 months ago

jackylu0124 commented 6 months ago

Question

I am currently upgrading the library version from "^2.15.4" to "^3.9.1", and previously I have the prop preset="photo" in my Camera component, but I see that the preset prop is no longer available in V3. I have spent a lot of time on trying out different camera formats in V3 with the goal of reproducing the image quality (e.g. exposure, image sharpness, image noise level, etc.) of setting preset="photo" in V2, but with no luck. Does anyone by chance know what is the equivalent configuration/setting/camera format in V3 that maps to preset="photo" in V2? Thanks a lot in advance!

For reference, my code in V2 looks like the following:

const devices = useCameraDevices();
const { back } = devices;
<Camera
  style={styles.camera}
  device={back}
  isActive={true}
  photo={true}
  ref={cameraRef}
  preset="photo"
  enableZoomGesture={true}
  zoom={back.neutralZoom}
/>

What I tried

I have a React Native CLI project and I am testing my app on iPhone 11, and I have tried various different camera formats in V3, such as the one in the code below: the video I see in the "preview" before taking the picture and also the taken picture itself have noticeably more noise, and higher exposure then using preset="photo" in V2, the color also appears less saturated than what I had with preset="photo" in V2. My goal is to reproduce the same image quality (both in "preview" and in the image taken) as the one from using preset="photo" in V2. Any help would be greatly apprciated!

My V3 Code:

const backDevice = useCameraDevice('back', {
  physicalDevices: [
    'ultra-wide-angle-camera',
    'wide-angle-camera'
  ]
});

const backDeviceFormat = useCameraFormat(backDevice, [
  { photoResolution: 'max' },
  { videoResolution: 'max' },
]);

<Camera
  style={styles.camera}
  device={backDevice}
  isActive={true}
  photo={true}
  ref={cameraRef}
  enableZoomGesture={true}
  zoom={backDevice.neutralZoom}
  format={backDeviceFormat}
/>

My V2 Code:

const devices = useCameraDevices();
const { back } = devices;
<Camera
  style={styles.camera}
  device={back}
  isActive={true}
  photo={true}
  ref={cameraRef}
  preset="photo"
  enableZoomGesture={true}
  zoom={back.neutralZoom}
/>

VisionCamera Version

3.9.1

Additional information

Dingenis commented 5 months ago

Hey @jackylu0124, maybe you could see what kind of device and format you get on V2 and compare that to the ones you get on V3 (just by logging them). The format filter you use on V3 only maximises the resolution of the photo and video (preview). That is not the best format necessarily, it depends on your use case.

Futhermore, I think enabling HDR and setting qualityPrioritization for taking photos to quality could also help boost the results you see.

jackylu0124 commented 5 months ago

Hi @Dingenis, thank you for your reply and insight! Would you mind sharing how I can log/print out the device format when I am using preset="photo"? I have tried logging out the various props of the ref object that's passed into <Camera>, but I could not find the ones that are currently being used for the preset="photo" setting. Thanks for your help in advance!

Dingenis commented 5 months ago

Hi @jackylu0124, good point, it's hard to log that way. It seems that preset only does something on iOS and is determined by Apple, so it's a bit hard to see what it actually does. What you could try is to alter the source code to log the format that is being used.

After this line, you could add something like this:

guard let f = device.activeFormat else { return }
let formatDict = f.toDictionary()

do {
  let jsonData = try JSONSerialization.data(withJSONObject: formatDict, options: .prettyPrinted)
  let jsonText = String(data: jsonData, encoding: .ascii)
  ReactLogger.log(level: .info, message: "Format: \(jsonText)")
} catch { 
  ReactLogger.log(level: .error, message: "Error occured while serializing format to JSON")
}

I didn't test this code so there could be error in it, but I think it points you to the right direction. You could just add something like this in your node_modules/react-native-vision-camera/ios/CameraView+AVCaptureSession.swift

mrousavy commented 5 months ago

Hey - you could try to use useCameraFormat(device, Templates.Photo) for example. But by default, photo is already high quality.