
Nitro Image is a superfast Image core type and view component for React Native, built with Nitro!
- Powered by Nitro Modules for highly efficient native bindings! 🔥
- Instance-based
Image
type with byte-buffer pixel data access 🔗 - Supports in-memory image operations like resizing and cropping without saving to file 📐
- Fast Web Image loading and caching using SDWebImage (iOS) and Coil (Android) 🌎
- ThumbHash support for elegant placeholders 🖼️
function App() {
const image = useWebImage('https://picsum.photos/seed/123/400')
return (
<NitroImage
image={image}
style={{ width: 400, height: 400 }}
/>
)
}
Install react-native-nitro-image from npm:
npm i react-native-nitro-image
npm i react-native-nitro-modules
cd ios && pod install
Note
Since NitroImage is built with Nitro Views, it requires the new architecture to be enabled.
Then, since SDWebImage does not enable modular headers for static linkage, you need to enable those yourself in your app's Podfile
:
target '…' do
config = use_native_modules!
# Add this line:
pod 'SDWebImage', :modular_headers => true
There are numerous ways to create an Image
through the ImageFactory
:
const webImage = await loadImageFromURLAsync('https://picsum.photos/seed/123/400')
const fileImage = await loadImageFromFileAsync('file://my-image.jpg')
const resourceImage = loadImageFromResources('my-resource.jpg')
const symbolImage = loadImageFromSymbol('star')
When loading from a remote URL, you can tweak options such as priority
:
const image1 = await loadImageFromURLAsync(URL1, { priority: 'low' })
const image2 = await loadImageFromURLAsync(URL2, { priority: 'high' })
The Image
type can be converted to- and from- an ArrayBuffer
, which gives you access to the raw pixel data in ARGB format:
const webImage = await loadImageFromURLAsync('https://picsum.photos/seed/123/400')
const arrayBuffer = await webImage.toArrayBufferAsync()
const sameImageCopied = await loadImageFromArrayBufferAsync(arrayBuffer)
An Image
can be resized entirely in-memory, without ever writing to- or reading from- a file:
const webImage = await loadImageFromURLAsync('https://picsum.photos/seed/123/400')
const smaller = await webImage.resizeAsync(200, 200)
An Image
can be cropped entirely in-memory, without ever writing to- or reading from- a file:
const webImage = await loadImageFromURLAsync('https://picsum.photos/seed/123/400')
const smaller = await webImage.cropAsync(100, 100, 50, 50)
An in-memory Image
object can also be written/saved to a file:
const smaller = ...
const path = await smaller.saveToTemporaryFileAsync('jpg', 90)
The useWebImage()
hook loads an Image
from a remote URL and returns it as a React state:
function App() {
const image = useWebImage('https://picsum.photos/seed/123/400')
}
The <NitroImage />
view is a React Native view component for rendering an Image
instance:
function App() {
const image = useWebImage('https://picsum.photos/seed/123/400')
return (
<NitroImage
image={image}
style={{ width: 400, height: 400 }}
/>
)
}
The <NitroWebImage />
view is a JS-based React Native view component that fetches an Image
from a remote URL as soon as it is mounted and displays it:
function App() {
return (
<NitroWebImage
url="https://picsum.photos/seed/123/400"
placeholder={{ thumbHash: '…' }}
options={{ priority: 'high' }}
style={{ width: 400, height: 400 }}
/>
)
}
To achieve a dynamic width or height calculation, you can use the image
's dimensions:
function App() {
const image = useWebImage('https://picsum.photos/seed/123/400')
const aspect = (image?.width ?? 1) / (image?.height ?? 1)
return (
<NitroImage
image={image}
style={{ width: '100%', aspectRatio: aspect }}
/>
)
}
This will now resize the height
dimension to match the same aspect ratio as the image
- in this case it will be 1:1 since the image is 400x400.
If the image
is 400x200, the height
of the view will be half of the width
of the view, i.e. a 0.5 aspect ratio.
A ThumbHash is a short binary (or base64 string) representation of a blurry image.
Since it is a very small buffer (or base64 string), it can be added to a payload (like a user
object in your database) to immediately display an image placeholder while the actual image loads.
Usage Example
For example, your users
database could have a users.profile_picture_url
field which you use to asynchronously load the web Image, and a users.profile_picture_thumbhash
field which contains the ThumbHash buffer (or base64 string) which you can display on-device immediately.
users
users.profile_picture_url
: Load asynchronouslyusers.profile_picture_thumbhash
: Decode & Display immediately
Everytime you upload a new profile picture for the user, you should encode the image to a new ThumbHash again and update the users.profile_picture_thumbhash
field. This should ideally happen on your backend, but can also be performed on-device if needed.
NitroImage supports conversion from- and to- ThumbHash representations out of the box.
For performance reasons, a ThumbHash is represented as an ArrayBuffer
.
const thumbHash = // from server
const image = loadImageFromThumbHash(thumbHash)
const thumbHashAgain = image.toThumbHash()
If your ThumbHash is a string
, convert it to an ArrayBuffer
first, since this is more efficient:
const thumbHashBase64 = // from server
const thumbHashArrayBuffer = thumbHashFromBase64String(thumbHashBase64)
const thumbHashBase64Again = thumbHashToBase64String(thumbHashArrayBuffer)
Since ThumbHash decoding or encoding can be a slow process, you should consider using the async methods instead:
const thumbHash = // from server
const image = await loadImageFromThumbHashAsync(thumbHash)
const thumbHashAgain = await image.toThumbHash()