This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Expo Image
A cross-platform and performant React component that loads and renders images.
expo-image is a cross-platform React component that loads and renders images.
Main features:
- Designed for speed
- Support for many image formats (including animated ones)
- Disk and memory caching
- Supports BlurHash and ThumbHash - compact representations of a placeholder for an image
- Transitioning between images when the source changes (no more flickering!)
- Implements the CSS
object-fitandobject-positionproperties (seecontentFitandcontentPositionprops) - Uses performant
SDWebImageandGlideunder the hood
Supported image formats
Installation
If you are installing this in an existing React Native app, make sure to install expo in your project.
Configuration in app config
You can configure build-time settings for expo-image using its config plugin. Add the plugin to the plugins array in your app.json or app.config.js and rebuild the native project.
Example app.json with config plugin
Configurable properties
Are you using this library in an existing React Native app?
If you are not using Continuous Native Generation (CNG)
or you're using native ios project manually, then set the shell environment variable
EXPO_IMAGE_DISABLE_LIBDAV1D=1 before running pod install to achieve the same effect.
Alternatively, you can add ENV['EXPO_IMAGE_DISABLE_LIBDAV1D'] ||= '0' to the top of your
Podfile.
Usage
import { Image } from 'expo-image'; import { StyleSheet, View } from 'react-native'; const blurhash = '|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj['; export default function App() { return ( <View style={styles.container}> <Image style={styles.image} source="https://picsum.photos/seed/696/3000/2000" placeholder={{ blurhash }} contentFit="cover" transition={1000} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, image: { flex: 1, width: '100%', backgroundColor: '#0553', }, });
Using images from native resources
Images bundled in Xcode asset catalogs or Android drawable resources can be loaded by name with
source={{ uri: 'app_icon' }}. Omit the file extension and provide image dimensions manually:
import { Image } from 'expo-image'; export default function AppIcon() { return <Image source={{ uri: 'app_icon' }} style={{ width: 40, height: 40 }} />; }
API
import { Image } from 'expo-image';
No API data file found, sorry!
Generating a blurhash on a server
Images can significantly improve the visual experience, however, they can also slow down app/page loading times due to their large file sizes. To overcome this, you can create placeholder images using blurhash algorithm that provides an immersive experience while deferring the loading of the actual picture until later.
This guide demonstrates how to create a blurhash of an uploaded image on the backend using JavaScript and Express.js. The same techniques and principles apply to other languages and server technologies.
Start by installing a few dependencies: multer for handling multipart requests, sharp for converting files to a data buffer, and the official blurhash JavaScript package.
Next, import all required functions from installed packages and initialize multer:
// Multer is a middleware for handling `multipart/form-data`. const multer = require('multer'); // Sharp allows you to receive a data buffer from the uploaded image. const sharp = require('sharp'); // Import the encode function from the blurhash package. const { encode } = require('blurhash'); // Initialize `multer`. const upload = multer();
Assuming the app is a variable that holds a reference to the Express server, an endpoint can be created that accepts an image and returns a JSON response containing the generated blurhash.
app.post('/blurhash', upload.single('image'), async (req, res) => { const { file } = req; // If the file is not available we're returning with error. if (file === null) { res.status(400).json({ message: 'Image is missing' }); return; } // Users can specify number of components in each axes. const componentX = req.body.componentX ?? 4; const componentY = req.body.componentY ?? 3; // We're converting provided image to a byte buffer. // Sharp currently supports multiple common formats like JPEG, PNG, WebP, GIF, and AVIF. const { data, info } = await sharp(file.buffer).ensureAlpha().raw().toBuffer({ resolveWithObject: true, }); const blurhash = encode( new Uint8ClampedArray(data), info.width, info.height, componentX, componentY ); res.json({ blurhash }); });
Additionally, the request can include two parameters: componentX and componentY, are passed through the algorithm. These values can be calculated or hard-coded on the server or specified by the user. However, they must be within the range of 1 to 9 and have an aspect ratio similar to the uploaded image. A value of 9 will give the best results but may take longer to generate the hash.
The process of generating a blurhash can be accomplished in various languages and server technologies, similar to the one using JavaScript. The key step is to locate an encoder for your chosen language, which can often be found in the woltapp/blurhash repository. Once you have the encoder, you will need to obtain a representation of the image. Some libraries use a default image class (for example, the Swift implementation uses UIImage). In other cases, you will have to provide raw byte data. Make sure to check the encoder's documentation to confirm the expected data format.
When working with raw byte data, ensure that the alpha layer is present (each pixel is represented by red, green, blue, and alpha values). Failing to do so will lead to errors such as "width and height must match the pixels array".