feat: Flash with AE Pre-capture trigger for Android (#2558)

### Flash (`flash`)

Adds `flash` functionality with a fully custom pre-capture AE/AF/AWB trigger sequence for Android. 🎉 

```ts
camera.current.takePhoto({
  flash: 'on' // or 'auto'
})
```

### Better photos (`qualityPrioritization`)

We now also run the AE/AF/AWB precapture sequence on every photo (unless `qualityPrioritization` is `speed`), meaning photos are now less blurry, properly exposed, and properly white-balanced - so in short: **photo quality is now better!**.

The fast path still exists when using `qualityPrioritization: speed`, as that will skip the precapture sequence and metering actions and just grab an Image from the Camera as quickly as possible.

Additionally, `qualityPrioritization` now controls these options:

- [COLOR_CORRECTION_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#COLOR_CORRECTION_MODE)
- [EDGE_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#EDGE_MODE)
- [COLOR_CORRECTION_ABERRATION_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE)
- [HOT_PIXEL_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#HOT_PIXEL_MODE)
- [DISTORTION_CORRECTION_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#DISTORTION_CORRECTION_MODE)
- [NOISE_REDUCTION_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#NOISE_REDUCTION_MODE)
- [SHADING_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#SHADING_MODE)
- [TONEMAP_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#TONEMAP_MODE)

..by setting them to `_FAST` or `_HIGH_QUALITY`, which was previously left untouched. 

This now means:
- `takePhoto({ qualityPrioritization: 'speed' })` got FASTER 🚀 
- `takePhoto({ qualityPrioritization: 'quality' })` got BETTER QUALITY 📸 
- `takePhoto({ qualityPrioritization: 'balanced' })` is left unchanged 
This commit is contained in:
Marc Rousavy
2024-02-14 16:43:30 +01:00
committed by GitHub
parent 61b2f7dd4a
commit 37398cc909
11 changed files with 448 additions and 131 deletions

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useRef } from 'react'
import React, { useCallback, useRef } from 'react'
import { StyleSheet, View, ViewProps } from 'react-native'
import {
PanGestureHandler,
@@ -19,7 +19,7 @@ import Reanimated, {
useSharedValue,
withRepeat,
} from 'react-native-reanimated'
import type { Camera, PhotoFile, TakePhotoOptions, VideoFile } from 'react-native-vision-camera'
import type { Camera, PhotoFile, VideoFile } from 'react-native-vision-camera'
import { CAPTURE_BUTTON_SIZE, SCREEN_HEIGHT, SCREEN_WIDTH } from './../Constants'
const PAN_GESTURE_HANDLER_FAIL_X = [-SCREEN_WIDTH, SCREEN_WIDTH]
@@ -58,15 +58,6 @@ const _CaptureButton: React.FC<Props> = ({
const pressDownDate = useRef<Date | undefined>(undefined)
const isRecording = useRef(false)
const recordingProgress = useSharedValue(0)
const takePhotoOptions = useMemo<TakePhotoOptions>(
() => ({
qualityPrioritization: 'speed',
flash: flash,
quality: 90,
enableShutterSound: false,
}),
[flash],
)
const isPressingButton = useSharedValue(false)
//#region Camera Capture
@@ -75,12 +66,16 @@ const _CaptureButton: React.FC<Props> = ({
if (camera.current == null) throw new Error('Camera ref is null!')
console.log('Taking photo...')
const photo = await camera.current.takePhoto(takePhotoOptions)
const photo = await camera.current.takePhoto({
qualityPrioritization: 'quality',
flash: flash,
enableShutterSound: false,
})
onMediaCaptured(photo, 'photo')
} catch (e) {
console.error('Failed to take photo!', e)
}
}, [camera, onMediaCaptured, takePhotoOptions])
}, [camera, flash, onMediaCaptured])
const onStoppedRecording = useCallback(() => {
isRecording.current = false