A Photo
Understanding the Photo type
A Photo is a RAW- or processed in-memory buffer, captured by a CameraPhotoOutput.
See "The Photo Output" for more information about capturing Photos.
Displaying a Photo
A Photo holds an in-memory buffer of its pixels, and can be converted to an Image (from react-native-nitro-image) entirely in-memory by using toImageAsync():
const photo = ...
const image = await photo.toImageAsync()The image can then be displayed in a <NitroImage /> view:
import { NitroImage } from 'react-native-nitro-image'
function App() {
const image = ...
return (
<NitroImage
style={{ flex: 1 }}
image={image}
/>
)
}Saving to a File
To save a Photo to an image file, use saveToTemporaryFileAsync(...) or saveToFileAsync(...):
const photo = ...
const path = await photo.saveToTemporaryFileAsync()Saving to the Camera Roll
After a Photo has been saved to a file, you can save it to the user's Camera Roll using a library like @react-native-camera-roll/camera-roll or expo-media-library.
Container Formats
Photos can be captured in different container formats (see PhotoContainerFormat), which adjusts the capture pipeline's processing steps accordingly - for example, 'dcm' is a RAW format and applies almost no processing in a capture pipeline, whereas 'jpeg' or 'heic' are processed formats and apply color-grading, compression, multi-capture-fusion, HDR, and other processing steps in the capture pipeline.
You can inspect a Photo's PhotoContainerFormat via the containerFormat property:
console.log(photo.containerFormat) // 'jpeg'Accessing a Photo's Pixel Buffer
Some Photos allow accessing their pixel buffer directly in-memory, without decoding.
On iOS, this is often only available on RAW photos (containerFormat == 'dcm'), while on Android this is available on all Photos.
if (photo.hasPixelBuffer) {
const pixelBuffer = photo.getPixelBuffer()
const rgba = new Uint8Array(pixelBuffer)
// process pixels
}A Photo's Pixel Buffer does not contain any container metadata (JPEG/HEIC headers), or EXIF flags - it's purely pixels.
Accessing the Pixel Buffer via NitroImage
Since a Photo can be converted to an Image (from react-native-nitro-image), it is also a common pattern to access pixels via the react-native-nitro-image APIs;
const photo = ...
const image = await photo.toImageAsync()
const pixelBuffer = await image.toRawPixelData()Note
It is worth noting that converting to an Image performs an encoding pass, and reading the Pixel Buffer requires a decoding pass.
Accessing a Photo's Pixel Buffer directly does not require any encoding/decoding passes.
Accessing a Photo's Encoded Image Data
The Photo also provides access to its Encoded Image Data - which is what would be written to a File if it was saved - including container metadata and EXIF flags.
You can get the Encoded Image Data via getFileDataAsync(), for example to write this to a network stream entirely in-memory;
const photo = ...
const encodedData = await photo.getFileDataAsync()
// Upload to backend:
await fetch('https://my-backend.com/upload', {
method: 'POST',
headers: { 'Content-Type': 'image/jpeg' },
body: Buffer.from(encodedData)
})Skia Images
A Photo can also be imported into @shopify/react-native-skia using the Encoded Image Data APIs, which allows you to apply shaders or custom drawing/rendering commands to it:
const photo = ...
const encodedData = await photo.getFileDataAsync()
// Convert Photo to SkImage:
const bytes = new Uint8Array(buffer)
const data = Skia.Data.fromBytes(bytes)
const image = Skia.Image.MakeImageFromEncoded(data)
// Render SkImage in SkCanvas now