Documentation Index
Fetch the complete documentation index at: https://mintlify.com/shopify/react-native-skia/llms.txt
Use this file to discover all available pages before exploring further.
Images are essential for creating rich visual experiences. React Native Skia provides powerful tools for loading, displaying, and manipulating images from various sources.
Loading Images
useImage Hook
The useImage hook is the primary way to load images. It returns an SkImage instance or null while loading.
import { useImage } from "@shopify/react-native-skia";
// From JavaScript bundle
const image1 = useImage(require("./assets/oslo.jpg"));
// From network
const image2 = useImage("https://picsum.photos/200/300");
// From native bundle (Android/iOS)
const image3 = useImage("Logo");
Error Handling
The hook provides an optional error handler:
const image = useImage(
require("./assets/photo.jpg"),
(error) => {
console.error("Failed to load image:", error);
}
);
MakeImageFromEncoded
Create images from encoded data:
import { Skia } from "@shopify/react-native-skia";
// From base64 string
const data = Skia.Data.fromBase64(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="
);
const image = Skia.Image.MakeImageFromEncoded(data);
MakeImage
Create images from raw pixel data:
import { Skia, AlphaType, ColorType } from "@shopify/react-native-skia";
// Create a 256x256 image with custom pixels
const pixels = new Uint8Array(256 * 256 * 4);
pixels.fill(255);
let i = 0;
for (let x = 0; x < 256; x++) {
for (let y = 0; y < 256; y++) {
pixels[i++] = (x * y) % 255; // Red
pixels[i++] = x % 255; // Green
pixels[i++] = y % 255; // Blue
pixels[i++] = 255; // Alpha
}
}
const data = Skia.Data.fromBytes(pixels);
const image = Skia.Image.MakeImage(
{
width: 256,
height: 256,
alphaType: AlphaType.Opaque,
colorType: ColorType.RGBA_8888,
},
data,
256 * 4 // bytes per row
);
Image Component
The Image component displays images on the canvas.
Props
| Name | Type | Description |
|---|
| image | SkImage | The image instance to display |
| x | number | Left position of the destination |
| y | number | Top position of the destination |
| width | number | Width of the destination |
| height | number | Height of the destination |
| fit | Fit | How the image fits in the rectangle (default: contain) |
| sampling | Sampling | Sampling method for quality control |
Basic Example
import { Canvas, Image, useImage } from "@shopify/react-native-skia";
const ImageDemo = () => {
const image = useImage(require("./assets/oslo.jpg"));
if (!image) {
return null; // Still loading
}
return (
<Canvas style={{ flex: 1 }}>
<Image
image={image}
fit="contain"
x={0}
y={0}
width={256}
height={256}
/>
</Canvas>
);
};
Fit Modes
Control how images fit within their bounds:
contain
Fits the entire image within the bounds, maintaining aspect ratio:
<Image image={image} fit="contain" x={0} y={0} width={256} height={256} />
cover
Covers the entire bounds, may crop the image:
<Image image={image} fit="cover" x={0} y={0} width={256} height={256} />
fill
Stretches the image to fill the bounds:
<Image image={image} fit="fill" x={0} y={0} width={256} height={256} />
fitWidth
Scales to match width, maintains aspect ratio:
<Image image={image} fit="fitWidth" x={0} y={0} width={256} height={256} />
fitHeight
Scales to match height, maintains aspect ratio:
<Image image={image} fit="fitHeight" x={0} y={0} width={256} height={256} />
scaleDown
Like contain, but never scales up:
<Image image={image} fit="scaleDown" x={0} y={0} width={256} height={256} />
none
No fitting applied, uses image’s natural size:
<Image image={image} fit="none" x={0} y={0} width={256} height={256} />
Sampling Options
Control image quality and performance:
Cubic Sampling (Best Quality)
Use cubic sampling for high-quality rendering:
import { Canvas, Image, useImage, CubicSampling } from "@shopify/react-native-skia";
const HighQuality = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
<Image
image={image}
fit="contain"
x={0}
y={0}
width={256}
height={256}
sampling={CubicSampling}
/>
</Canvas>
);
};
Custom Cubic Sampling
import { Canvas, Image, useImage } from "@shopify/react-native-skia";
const CustomCubic = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
<Image
image={image}
fit="contain"
x={0}
y={0}
width={256}
height={256}
sampling={{ B: 0, C: 0.5 }}
/>
</Canvas>
);
};
Filter and Mipmap Modes
import { Canvas, Image, useImage, FilterMode, MipmapMode } from "@shopify/react-native-skia";
const FilterExample = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
{/* Nearest filter - fastest, lowest quality */}
<Image
image={image}
x={0}
y={0}
width={128}
height={128}
sampling={{ filter: FilterMode.Nearest, mipmap: MipmapMode.None }}
/>
{/* Linear filter - better quality */}
<Image
image={image}
x={128}
y={0}
width={128}
height={128}
sampling={{ filter: FilterMode.Linear, mipmap: MipmapMode.Linear }}
/>
</Canvas>
);
};
Image Instance Methods
Once loaded, SkImage instances provide useful methods:
Dimensions
const width = image.width();
const height = image.height();
const info = image.getImageInfo();
Encoding
Export images to various formats:
// As bytes (PNG by default)
const bytes = image.encodeToBytes();
// As JPEG with quality
const jpegBytes = image.encodeToBytes(ImageFormat.JPEG, 90);
// As base64 string
const base64 = image.encodeToBase64();
const jpegBase64 = image.encodeToBase64(ImageFormat.JPEG, 80);
Reading Pixels
// Read all pixels
const pixels = image.readPixels();
// Read a region
const regionPixels = image.readPixels(10, 10, {
width: 100,
height: 100,
alphaType: AlphaType.Premul,
colorType: ColorType.RGBA_8888,
});
Creating Shaders
import { TileMode } from "@shopify/react-native-skia";
// With filter options
const shader = image.makeShaderOptions(
TileMode.Repeat,
TileMode.Repeat,
FilterMode.Linear,
MipmapMode.None
);
// With cubic sampling
const cubicShader = image.makeShaderCubic(
TileMode.Clamp,
TileMode.Clamp,
0,
0.5
);
Advanced Techniques
Image Clipping
import { Canvas, Image, useImage, Circle } from "@shopify/react-native-skia";
const ClippedImage = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
<Circle cx={128} cy={128} r={100}>
<Image image={image} fit="cover" x={0} y={0} width={256} height={256} />
</Circle>
</Canvas>
);
};
import { Canvas, Group, Image, useImage } from "@shopify/react-native-skia";
const TransformedImage = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
<Group transform={[{ rotate: Math.PI / 4 }]}>
<Image image={image} x={0} y={0} width={256} height={256} />
</Group>
</Canvas>
);
};
Image with Effects
import { Canvas, Image, useImage, Blur, ColorMatrix } from "@shopify/react-native-skia";
const ImageWithEffects = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
<Image image={image} x={0} y={0} width={256} height={256}>
<Blur blur={5} />
<ColorMatrix
matrix={[
0.95, 0, 0, 0, 0.05,
0.65, 0, 0, 0, 0.15,
0.15, 0, 0, 0, 0.5,
0, 0, 0, 1, 0,
]}
/>
</Image>
</Canvas>
);
};
- Cache loaded images with
useImage
- Use appropriate sampling modes for your use case
- Consider image dimensions - smaller is faster
- Preload images when possible
- Use
fitWidth or fitHeight when appropriate
- Optimize image formats (WebP, JPEG) before bundling
Common Patterns
Conditional Rendering
const ImageDemo = () => {
const image = useImage(require("./assets/photo.jpg"));
return (
<Canvas style={{ flex: 1 }}>
{image && (
<Image image={image} x={0} y={0} width={256} height={256} />
)}
</Canvas>
);
};
Multiple Images
const Gallery = () => {
const image1 = useImage(require("./assets/photo1.jpg"));
const image2 = useImage(require("./assets/photo2.jpg"));
return (
<Canvas style={{ flex: 1 }}>
{image1 && <Image image={image1} x={0} y={0} width={128} height={128} />}
{image2 && <Image image={image2} x={128} y={0} width={128} height={128} />}
</Canvas>
);
};
See Also