Perfect pixel-art scaling for your Expo apps. No blur, no artifacts - just crisp, clean pixels.
- Crisp nearest-neighbor scaling (no blurry pixels!)
- Advanced fractional scaling for non-integer scale factors
- Works with remote and base64 images
- Platform-specific rendering modes (software/hardware) for quality vs performance
- Native performance
- Loading states with customizable components
- Error handling with fallback options
- Type-safe with full TypeScript support
- Zero configuration needed
| Platform | Supported |
|---|---|
| iOS | ✅ New Architecture |
| Android | ✅ New Architecture |
| Web | ❌ |
Note: This module requires the New Architecture (Fabric) to be enabled in your Expo project. It will not work with the old architecture.
Web Platform: This module uses native implementations for pixel-perfect scaling and does not support web platforms. For web-specific pixel art needs, consider using CSS solutions or a web-specific library.
npx expo install expo-pixel-perfectimport ExpoPixelPerfectView from 'expo-pixel-perfect';
export default function Game() {
// Base64 encoded pixel art
const pixelArtBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...';
return (
<ExpoPixelPerfectView
source={{
base64: pixelArtBase64,
width: 16, // Original width is required
height: 16 // Original height is required
}}
scale={3}
/>
);
}import ExpoPixelPerfectView from 'expo-pixel-perfect';
import { useWindowDimensions } from 'react-native';
export default function ResponsiveGameElement() {
const { width } = useWindowDimensions();
const spriteOriginalWidth = 32;
// Calculate a non-integer scale factor to fit screen width
const scaleFactor = width / spriteOriginalWidth / 2; // Fit 2 sprites side by side
return (
<ExpoPixelPerfectView
source={require('./assets/game-element.png')}
scale={scaleFactor}
scaleMode="fractional-optimized" // Use optimized scaling for non-integer scales
/>
);
}| Prop | Type | Description |
|---|---|---|
| source | { uri: string } | { base64: string, width: number, height: number } | Image source (remote or base64) |
| Prop | Type | Default | Description |
|---|---|---|---|
| scale | number | { targetWidth: number } | { targetHeight: number } | 1 | Scaling factor or target dimensions |
| style | ViewStyle | undefined | Standard React Native view styles |
| loadingComponent | ReactNode | null | Component shown during loading |
| fallback | ReactNode | null | Component shown on error |
| onError | (error: Error) => void | undefined | Error callback |
| onLoad | () => void | undefined | Success callback |
| scaleMode | "nearest" | "fractional-optimized" | "nearest" | Algorithm used for scaling |
| android_renderMode | "software" | "hardware" | "hardware" | Android-specific rendering mode |
| ios_renderMode | "software" | "hardware" | "hardware" | iOS-specific rendering mode |
This module provides platform-specific rendering modes to balance between visual quality and performance:
- software: Uses CPU-based rendering (View.LAYER_TYPE_SOFTWARE) for highest quality pixel-perfect rendering. Best for static UI elements or when visual quality is critical.
- hardware: Uses GPU-accelerated rendering (View.LAYER_TYPE_HARDWARE) for better performance. May have slightly less precise scaling but offers better battery life and performance.
- software: Uses CoreGraphics (CPU-based) rendering with precise nearest-neighbor scaling. Best for static UI elements or when visual quality is critical.
- hardware: Uses Core Image (GPU-accelerated) rendering for better performance. May have slightly less precise scaling but offers better battery life and performance.
This module offers two different scaling algorithms to handle different types of pixel art scaling:
- Default scaling mode
- Best for integer scaling (2x, 3x, 4x, etc.)
- Fast and efficient
- May appear slightly blurry with non-integer scaling factors
- Advanced scaling algorithm designed for non-integer scaling factors
- Uses a multi-step scaling process for sharper results
- Perfect for when you need to scale by factors like 1.5x, 2.3x, etc.
- Especially useful for responsive UIs or fitting to screen dimensions
- Uses more resources but produces significantly sharper results for fractional scales
// Responsive UI with sharp pixel art
<PixelImage
source={require('./assets/ui-element.png')}
scale={deviceWidth / spriteWidth} // Non-integer scale to fit screen
scaleMode="fractional-optimized"
/>- Start with small source images (8x8, 16x16, 32x32)
- Use PNG format for transparency support
- For fixed sizes, use integer scales (2x, 3x) with "nearest" mode for best performance
- For responsive UI, use "fractional-optimized" mode with calculated scale factors
- Provide fallback components for better user experience
- Handle loading and error states for smoother UX
- Use "software" rendering mode for static UI elements for best quality
- Use "hardware" rendering mode for animated elements for better performance
- When using base64 images, always specify the original width and height, if you can't you could render it using a native image and getting its layout
Make sure you're using the correct scale factor. For a 16x16 image to display at 64x64, use either:
scale={4}
// or
scale={{ targetWidth: 64 }}For non-integer scaling that still looks crisp, use the fractional-optimized mode:
scale={3.2} // Non-integer scale
scaleMode="fractional-optimized"If still blurry, try using the "software" rendering mode:
android_renderMode="software"
ios_renderMode="software"Check that your asset path is correct and the image exists. The onError callback can help debug:
onError={(error) => console.error('Loading failed:', error)}When using base64 images, you must specify the original width and height:
source={{
base64: myBase64String,
width: 16, // Important! Must be exact
height: 16 // Important! Must be exact
}}Made for ⚔️ Pixel Odyssey by Lino Iten