import { type CanvasProps, type SkImage } from '@shopify/react-native-skia'; import React from 'react'; import { type CameraController, type CameraProps, type FocusOptions, type Frame, type Point, type TargetVideoPixelFormat } from 'react-native-vision-camera'; import { type SkiaOnFrameState } from '../render'; /** * A reference to a {@linkcode SkiaCamera}. * * You can obtain a `SkiaCameraRef` via `useRef(...)`: * @example * ```tsx * function App() { * const camera = useRef(null) * * const onPress = async () => { * const snapshot = await camera.current.takeSnapshot() * console.log('Captured Skia snapshot!', snapshot.getImageInfo()) * } * * return ( * { * 'worklet' * render(({ canvas, frameTexture }) => { * canvas.drawImage(frameTexture, 0, 0) * }) * frame.dispose() * }} * /> * ) * } * ``` */ export interface SkiaCameraRef extends Pick { /** * Focuses the Camera pipeline to the specified {@linkcode viewPoint} * relative to the Camera Skia view's coordiante system, * using the specified {@linkcode MeteringMode}s. * @param viewPoint The point in the view coordinate system to focus to. * @param options Options for the focus operation. * @example * ```tsx * // Focus center * await camera.current.focusTo({ x: width / 2, y: height / 2 }) * ``` */ focusTo(viewPoint: Point, options?: FocusOptions): Promise; /** * Takes a snapshot of the currently rendered * content, or `undefined` if none are available. * @example * ```ts * const snapshot = await camera.current.takeSnapshot() * console.log('Captured Skia snapshot!', snapshot.getImageInfo()) * ``` */ takeSnapshot(): SkImage | undefined; /** * Converts the given {@linkcode viewPoint} to * a normalized {@linkcode Point} with values ranging from `0...1`. */ convertViewPointToNormalizedPoint(viewPoint: Point): Point; } /** * Represents props for a {@linkcode SkiaCamera}. */ export interface SkiaCameraProps extends CameraProps, Pick { /** * A reference to a {@linkcode SkiaCamera}. * @see {@linkcode SkiaCameraRef} */ ref?: React.Ref; /** * Called on every Frame with the current state. * * @note You must render the Frame to the Canvas yourself * via {@linkcode render}, otherwise it'll just be a black screen. * @worklet * @example * ```ts * onFrame(frame, render) { * 'worklet' * render(({ frameTexture, canvas }) => { * canvas.drawImage(frameTexture, 0, 0) * }) * frame.dispose() * } * ``` */ onFrame: (frame: Frame, render: (onDraw: (state: SkiaOnFrameState) => void) => void) => void; /** * Warns the developer if the {@linkcode onFrame | onFrame(...)} * callback did not call `render(...)`. * * Disable this if you intentionally want to skip a render. * @default true */ warnIfRenderSkipped?: boolean; /** * Selects the {@linkcode TargetVideoPixelFormat} for the * Frame Output using the Skia rendering pipeline. * * It is recommended to use {@linkcode TargetVideoPixelFormat | 'native'} * if the negotiated {@linkcode CameraSessionConfig}'s * {@linkcode CameraSessionConfig.nativePixelFormat | nativePixelFormat} * is supported by Skia as this is a zero-copy GPU-only path. * * Only resort back to {@linkcode TargetVideoPixelFormat | 'yuv'} * (or possibly even {@linkcode TargetVideoPixelFormat | 'rgb'}) if * CPU-based Frame access is required. * * @note * Use {@linkcode TargetVideoPixelFormat | 'native'} with caution, * as the device's native format could be a format that is not * supported by Skia - for example * {@linkcode VideoPixelFormat | 'raw-bayer-packed96-12-bit'}. * The {@linkcode PixelFormat | 'private'} pixel format is the * most efficient GPU-only pixel format supported by Skia. * * @default * 'native' or 'yuv' */ pixelFormat?: TargetVideoPixelFormat; /** * Physically rotates buffers to the desired target {@linkcode CameraOrientation} * and {@linkcode MirrorMode}. * * By default, it is disabled as Skia rotates and mirrors the * Frame via efficient GPU-based transforms. * Enabling this results in the {@linkcode Frame} always being * upright and never mirrored. * * @default false */ enablePhysicalBufferRotation?: boolean; /** * Configures the underlying {@linkcode CameraVideoOutput} * to downscale {@linkcode Frame}s to a size suitable for * preview, such as the screen size. * * This may be more efficient if the {@linkcode CameraSession} * negotiated a high-resolution output, as Skia doesn't * have to operate on high-resolution {@linkcode Frame}s. * Ideally, configure a matching {@linkcode ResolutionBiasConstraint} * upfront so no scaling would be necessary at any point * in the pipeline. * * @default false */ enablePreviewSizedOutputBuffers?: boolean; } declare function SkiaCameraImpl({ ref, style, outputs, onFrame, pixelFormat, enablePhysicalBufferRotation, enablePreviewSizedOutputBuffers, device, orientationSource, warnIfRenderSkipped, ...props }: SkiaCameraProps): React.ReactElement; /** * Represents a Camera view component that uses * [Skia](https://github.com/Shopify/react-native-skia) * for rendering. * * Instead of a native Preview View, the {@linkcode SkiaCamera} * uses a {@linkcode CameraFrameOutput} to stream * {@linkcode Frame | Frames}, which will be converted to * Skia Textures (see {@linkcode SkImage}) to be renderable. * * You must ensure that the {@linkcode Frame} * is actually rendered to the {@linkcode SkCanvas} * inside your {@linkcode SkiaCameraProps.onFrame | onFrame(...)} * callback. * * @note Your {@linkcode SkiaCameraProps.onFrame | onFrame(...)} * callback must be a `'worklet'`. * @note It is recommended to manually set a * {@linkcode SkiaCameraProps.pixelFormat | pixelFormat}, * for example {@linkcode TargetVideoPixelFormat | 'yuv'} for * efficiency, or {@linkcode TargetVideoPixelFormat | 'rgb'} * for compatibility with ML detection libraries. * @example * Simple rendering _as-is_: * ```tsx * function App() { * return ( * { * 'worklet' * render(({ canvas, frameTexture }) => { * canvas.drawImage(frameTexture, 0, 0) * }) * frame.dispose() * }} * /> * ) * } * ``` * @example * Drawing Frames with a custom pass-through shader: * ```tsx * // Simple pass-through Shader (just renders pixels as-is) * const effect = Skia.RuntimeEffect.Make(` * uniform shader src; * half4 main(float2 xy) { * return src.eval(xy); * } * `)! * const paint = Skia.Paint() * * function App() { * return ( * { * 'worklet' * render(({ canvas, frameTexture }) => { * // Prepare the shader with the `frameTexture` as an input * const imageShader = frameTexture.makeShaderOptions( * TileMode.Clamp, * TileMode.Clamp, * FilterMode.Linear, * MipmapMode.None, * ) * const shader = effect.makeShaderWithChildren([], [imageShader]) * paint.setShader(shader) * * // Draw the Frame with the shader/paint * canvas.drawImage(frameTexture, 0, 0, paint) * }) * frame.dispose() * }} * /> * ) * } * ``` */ export declare const SkiaCamera: React.MemoExoticComponent; export {};