npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

expo-pixel-perfect

v1.0.23

Published

Nearest-Neighbor scaling for React Native and Expo

Readme

🔍 expo-pixel-perfect

Perfect pixel-art scaling for your Expo apps. No blur, no artifacts - just crisp, clean pixels.

✨ Features

  • 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

🛠️ Supported Platforms

| 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.

📦 Installation

npx expo install expo-pixel-perfect

🚀 Usage

Basic Usage

import 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}
        />
    );
}

Responsive Game UI

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
        />
    );
}

🎯 Props

Required Props

| Prop | Type | Description | |----------|-------------------------------------------|---------------------------------| | source | { uri: string } | { base64: string, width: number, height: number } | Image source (remote or base64) |

Optional Props

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

🖥️ Render Modes

This module provides platform-specific rendering modes to balance between visual quality and performance:

Android Render Modes

  • 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.

iOS Render Modes

  • 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.

📏 Scaling Modes

This module offers two different scaling algorithms to handle different types of pixel art scaling:

Nearest Neighbor (scaleMode="nearest")

  • Default scaling mode
  • Best for integer scaling (2x, 3x, 4x, etc.)
  • Fast and efficient
  • May appear slightly blurry with non-integer scaling factors

Fractional-Optimized (scaleMode="fractional-optimized")

  • 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"
/>

🎨 Tips

  • 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

🤔 Common Issues

Image appears blurry

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"

Image not loading

Check that your asset path is correct and the image exists. The onError callback can help debug:

onError={(error) => console.error('Loading failed:', error)}

Base64 image has wrong dimensions

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