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 iconExpo Image

A cross-platform and performant React component that loads and renders images.

Android
iOS
tvOS
Web
Included in Expo Go
Recommended version:
~56.0.13

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-fit and object-position properties (see contentFit and contentPosition props)
  • Uses performant SDWebImage and Glide under the hood

Supported image formats

FormatAndroidiOSWeb
WebP
PNG / APNG
AVIF
HEIC not adopted yet
JPEG
GIF
SVG
ICO
ICNS
PSD (composite preview)

Installation

Terminal
- npx expo install expo-image
- yarn expo install expo-image
- pnpm expo install expo-image
- bun expo install expo-image

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

app.json
{ "expo": { "plugins": [ [ "expo-image", { "disableLibdav1d": true } ] ] } }

Configurable properties

NameDefaultDescription
disableLibdav1dfalse
Only for: 
iOS

When true, skips adding the bundled libavif/libdav1d Pod. Use this when another dependency (such as FFmpegKit) already links libdav1d. Disabling the Pod removes AVIF image support on iOS unless another decoder is available.

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.

Terminal
- npm install multer sharp blurhash
- yarn add multer sharp blurhash
- pnpm add multer sharp blurhash
- bun add multer sharp blurhash

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.