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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-nitro-image

v0.10.2

Published

A superfast in-memory Image type and view component for React Native, built with Nitro!

Readme

Nitro Image is a superfast Image core type and view component for React Native, built with Nitro!

  • Powered by Nitro Modules for highly efficient native bindings! 🔥
  • Instance-based Image type with byte-buffer pixel data access 🔗
  • Supports in-memory image operations like resizing and cropping without saving to file 📐
  • Supports deferred ImageLoader types to optimize for displaying large lists of Images ⏳
  • Fast Web Image loading and caching using SDWebImage (iOS) and Coil (Android) 🌎
  • ThumbHash support for elegant placeholders 🖼️
function App() {
  return (
    <NitroImage
      image={{ filePath: '/tmp/image.jpg' }}
      style={{ width: 400, height: 400 }}
    />
  )
}

Installation

Install react-native-nitro-image from npm:

npm i react-native-nitro-image
npm i react-native-nitro-modules
cd ios && pod install

[!NOTE] Since NitroImage is built with Nitro Views, it requires the new architecture to be enabled.

Web Images

To keep NitroImage super lightweight, it does not ship a web image loader and caching system. If you want to load images from the web, install react-native-nitro-web-image as well:

npm i react-native-nitro-web-image
cd ios && pod install

Then, since SDWebImage does not enable modular headers for static linkage, you need to enable those yourself in your app's Podfile:

target '…' do
  config = use_native_modules!

  # Add this line:
  pod 'SDWebImage', :modular_headers => true

Usage

Creating Images

The simplest way to load an Image is to use the exported loadImage(…) method:

const webImage      = await loadImage({ url: 'https://picsum.photos/seed/123/400' })
const fileImage     = await loadImage({ filePath: 'file://my-image.jpg' })
const resourceImage = await loadImage({ resource: 'my-image.jpg' })
const symbolImage   = await loadImage({ symbol: 'star' })
const requireImage  = await loadImage(require('./my-image.jpg'))

Under the hood, this uses the native methods from Images or WebImages:

const webImage      = await WebImages.loadFromURLAsync('https://picsum.photos/seed/123/400')
const fileImage     = await Images.loadFromFileAsync('file://my-image.jpg')
const resourceImage = Images.loadFromResources('my-resource.jpg')
const symbolImage   = Images.loadFromSymbol('star')

Creating a blank Image

Additionally, you can also create a new blank Image:

const blank = Images.createBlankImage(100, 100, /*enableAlpha:*/ true)

If you want to fill the blank image with a specific background color, pass the color in RGB:

const blankRedImage = Images.createBlankImage(100,
                                              100,
                                              /*enableAlpha:*/ true,
                                              { r: 1, g: 0, b: 0 })

Load with Options

When loading from a remote URL, you can tweak options such as priority:

const image1 = await WebImages.loadFromURLAsync(URL1, { priority: 'low' })
const image2 = await WebImages.loadFromURLAsync(URL2, { priority: 'high' })

Preloading

If you know what Images are going to be rendered soon, you can pre-load them using the preload(...) API:

WebImages.preload(profilePictureLargeUrl)

require(…)

A React Native require(…) returns a resource-ID. In debug, resources are streamed over Metro (localhost://…), while in release, they are embedded in the resources bundle. NitroImage wraps those APIs so you can just pass a require(…) to useImage(…), useImageLoader(…), or <NitroImage /> directly:

const image = useImage(require('./image.png'))

RawPixelData (ArrayBuffer)

The Image type can be converted to- and from- an ArrayBuffer, which gives you access to the raw pixel data in an RGB format:

const image           = ...
const pixelData       = await image.toRawPixelData()
const sameImageCopied = await Images.loadFromRawPixelData(pixelData)

EncodedImageData (ArrayBuffer)

The Image type can be encoded to- and decoded from- an ArrayBuffer using a container format like jpg, png or heic:

const image           = ...
const imageData       = await image.toEncodedImageData('jpg', 90)
const sameImageCopied = await Images.loadFromEncodedImageData(imageData)

Resizing

An Image can be resized entirely in-memory, without ever writing to- or reading from- a file:

const webImage = await WebImages.loadFromURLAsync('https://picsum.photos/seed/123/400')
const smaller  = await webImage.resizeAsync(200, 200)

Cropping

An Image can be cropped entirely in-memory, without ever writing to- or reading from- a file:

const webImage = await WebImages.loadFromURLAsync('https://picsum.photos/seed/123/400')
const smaller  = await webImage.cropAsync(100, 100, 50, 50)

Rotating

An Image can be rotated entirely in-memory, without ever writing to- or reading from- a file:

const webImage   = await WebImages.loadFromURLAsync('https://picsum.photos/seed/123/400')
const upsideDown = await webImage.rotateAsync(180)

Render into another Image

An Image can be rendered into another Image entirely in-memory. This creates a third image (the result):

const image1 = ...
const image2 = ...
const result = await image1.renderIntoAsync(image2, 10, 10, 80, 80)

Saving

An in-memory Image object can also be written/saved to a file:

const image  = ...
const path   = await image.saveToTemporaryFileAsync('jpg', 90)

Compressing

Images can be compressed using the jpg container format - either in-memory or when writing to a file:

const image      = ...
const path       = await image.saveToTemporaryFileAsync('jpg', 50) // 50% compression
const compressed = await image.toEncodedImageData('jpg', 50)       // 50% compression

HEIC/HEIF

NitroImage supports HEIC/HEIF format if the host OS natively supports it.

| | iOS | Android | |--------------|----------------|----------------| | Loading HEIC | ✅ | ✅ (>= SDK 28) | | Writing HEIC | ✅ (>= iOS 17) | ❌ |

You can check whether your OS supports HEIC via NitroImage:

import { supportsHeicWriting } from 'react-native-nitro-modules'

const image  = ...
const format = supportsHeicWriting ? 'heic' : 'jpg'
const path   = await image.saveToTemporaryFileAsync(format, 100)

Hooks

The useImage() hook

The useImage() hook asynchronously loads an Image from the given source and returns it as a React state:

function App() {
  const image = useImage({ filePath: '/tmp/image.jpg' })
  return …
}

The useImageLoader() hook

The useImageLoader() hook creates an asynchronous ImageLoader which can be passed to a <NitroImage /> view to defer image loading:

function App() {
  const loader = useImageLoader({ filePath: '/tmp/image.jpg' })
  return (
    <NitroImage
      image={loader}
      style={{ width: 400, height: 400 }}
    />
  )
}

The <NitroImage /> view

The <NitroImage /> view is a React Native view that allows you to render Image - either asynchronously (by wrapping ImageLoaders), or synchronously (by passing Image instances directly):

function App() {
  return (
    <NitroImage
      image={{ filePath: '/tmp/image.jpg' }}
      style={{ width: 400, height: 400 }}
    />
  )
}

The <NativeNitroImage /> view

The <NativeNitroImage /> view is the actual native Nitro View component for rendering an Image instance. It is recommended to use abstractions like <NitroImage /> instead of the actual native component. However if you need to use the native component instead, it is still exposed:

function App() {
  const image = …
  return (
    <NativeNitroImage
      image={image}
      style={{ width: 400, height: 400 }}
    />
  )
}

Dynamic width or height

To achieve a dynamic width or height calculation, you can use the image's dimensions:

function App() {
  const { image, error } = useImage({ filePath: '/tmp/image.jpg' })
  const aspect = (image?.width ?? 1) / (image?.height ?? 1)
  return (
    <NitroImage
      image={image}
      style={{ width: '100%', aspectRatio: aspect }}
    />
  )
}

This will now resize the height dimension to match the same aspect ratio as the image - in this case it will be 1:1 since the image is 400x400.

If the image is 400x200, the height of the view will be half of the width of the view, i.e. a 0.5 aspect ratio.

ThumbHash

A ThumbHash is a short binary (or base64 string) representation of a blurry image. Since it is a very small buffer (or base64 string), it can be added to a payload (like a user object in your database) to immediately display an image placeholder while the actual image loads.

For example, your users database could have a users.profile_picture_url field which you use to asynchronously load the web Image, and a users.profile_picture_thumbhash field which contains the ThumbHash buffer (or base64 string) which you can display on-device immediately.

  • users
    • users.profile_picture_url: Load asynchronously
    • users.profile_picture_thumbhash: Decode & Display immediately

Everytime you upload a new profile picture for the user, you should encode the image to a new ThumbHash again and update the users.profile_picture_thumbhash field. This should ideally happen on your backend, but can also be performed on-device if needed.

ThumbHash (ArrayBuffer) <> Image

NitroImage supports conversion from- and to- ThumbHash representations out of the box.

For performance reasons, a ThumbHash is represented as an ArrayBuffer.

const thumbHash      = ...from server
const image          = Images.loadFromThumbHash(thumbHash)
const thumbHashAgain = image.toThumbHash()
ThumbHash (ArrayBuffer) <> Base64 String

If your ThumbHash is a string, convert it to an ArrayBuffer first, since this is more efficient:

const thumbHashBase64      = ...from server
const thumbHashArrayBuffer = thumbHashFromBase64String(thumbHashBase64)
const thumbHashBase64Again = thumbHashToBase64String(thumbHashArrayBuffer)
Async ThumbHash

Since ThumbHash decoding or encoding can be a slow process, you should consider using the async methods instead:

const thumbHash      = ...from server
const image          = await Images.loadFromThumbHashAsync(thumbHash)
const thumbHashAgain = await image.toThumbHash()

Using the native Image type in a third-party library

To use the native Image type in your library (e.g. in a Camera library), you need to follow these steps:

  1. Add the dependency on react-native-nitro-image
    • JS: Add react-native-nitro-image to peerDependencies and devDependencies
    • Android: Add :react-native-nitro-image to your build.gradle's dependencies, and react-native-nitro-image::NitroImage to your CMake's dependencies (it's a prefab)
    • iOS: Add NitroImage to your *.podspec's dependencies
  2. In your Nitro specs (*.nitro.ts), just import Image from 'react-native-nitro-image' and use it as a type
  3. In your native implementation, you can either;
    • Implement HybridImageSpec, HybridImageLoaderSpec or HybridImageViewSpec with your custom implementation, e.g. to create a Image implementation that doesn't use UIImage but instead uses CGImage, or an AVPhoto
    • Use the HybridImageSpec, HybridImageLoaderSpec or HybridImageViewSpec types. You can either use them abstract (with all the methods that are also exposed to JS), or by downcasting them to a specific type - all of them follow a protocol like NativeImage:
      class HybridCustom: HybridCustomSpec {
        func doSomething(image: any HybridImageSpec) throws {
          guard let image = image as? NativeImage else { return }
          let uiImage = image.uiImage
          // ...
        }
      }
  4. Done! 🎉 Now you can benefit from a common, shared Image type - e.g. your Camera library can directly return an Image instance in takePhoto(), which can be instantly rendered using <NitroImage /> - no more file I/O!