react-native-image-crop-picker vs react-native-image-resizer vs react-native-image-zoom-viewer
Image Handling Architecture in React Native
react-native-image-crop-pickerreact-native-image-resizerreact-native-image-zoom-viewerSimilar Packages:

Image Handling Architecture in React Native

react-native-image-crop-picker, react-native-image-resizer, and react-native-image-zoom-viewer address three distinct stages of the image lifecycle in React Native applications. react-native-image-crop-picker provides native UI components for selecting and cropping images from the gallery or camera. react-native-image-resizer focuses on processing image files locally to reduce size or change dimensions before upload. react-native-image-zoom-viewer offers a full-screen component for displaying images with pinch-to-zoom and pan gestures. Together, they form a complete stack for image intake, optimization, and presentation.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-native-image-crop-picker06,3482.2 MB6549 months agoMIT
react-native-image-resizer01,662-45 years agoMIT
react-native-image-zoom-viewer02,445117 kB194-MIT

Image Handling Architecture in React Native: Picker, Resizer, and Viewer

Building a feature that involves images in React Native usually requires three steps: getting the image, optimizing it, and showing it. The packages react-native-image-crop-picker, react-native-image-resizer, and react-native-image-zoom-viewer each handle one of these steps. While they often work together, understanding their individual architectures helps you decide when to use them — or when to find alternatives.

🔗 Installation and Native Dependencies

Integration complexity varies because some packages rely on native code while others are pure JavaScript.

react-native-image-crop-picker requires native modules for both iOS and Android. You must link native libraries and update configuration files.

// react-native-image-crop-picker: iOS Pod install
cd ios && pod install

// android/app/build.gradle
apply from: "../../node_modules/react-native-image-crop-picker/android/build.gradle"

react-native-image-resizer also relies on native code for image processing. It requires linking native modules to access device storage and image codecs.

// react-native-image-resizer: React Native 0.60+ autolinking
cd ios && pod install

// Android may require manual linking in older versions
react-native link react-native-image-resizer

react-native-image-zoom-viewer is primarily JavaScript-based. It builds on top of React Native's ScrollView and Animated APIs, so it needs no native linking.

// react-native-image-zoom-viewer: Pure JS installation
npm install react-native-image-zoom-viewer
// No pod install or native linking required

🛠️ Core API Usage Patterns

Each package exposes a different interface style based on its job. Pickers and resizers use imperative promises, while viewers use declarative components.

react-native-image-crop-picker uses static methods to open native UI. It returns a Promise with image data.

// react-native-image-crop-picker: Imperative API
import ImagePicker from 'react-native-image-crop-picker';

const image = await ImagePicker.openPicker({
  width: 300,
  height: 300,
  cropping: true
});
console.log(image.path);

react-native-image-resizer uses a static method to process a file path. It returns a Promise with the new file location.

// react-native-image-resizer: Imperative API
import ImageResizer from 'react-native-image-resizer';

const resized = await ImageResizer.createResizedImage(
  image.path, 1000, 1000, 'JPEG', 80
);
console.log(resized.uri);

react-native-image-zoom-viewer uses a React component that wraps your content. It controls display via props.

// react-native-image-zoom-viewer: Declarative API
import ImageViewer from 'react-native-image-zoom-viewer';

<ImageViewer 
  imageUrls={[{ url: image.uri }]} 
  onCancel={() => setVisible(false)} 
/>

⚠️ Maintenance and Stability

Long-term support is critical for native modules. Breaking changes in React Native can break native libraries.

react-native-image-crop-picker is widely adopted and generally keeps pace with React Native updates. It has a large user base reporting issues quickly.

// react-native-image-crop-picker: Active community support
// Check GitHub issues for RN version compatibility before upgrading

react-native-image-resizer has shown signs of slower maintenance in recent years. Many teams now evaluate forks or alternatives like react-native-image-manipulator for better long-term safety.

// react-native-image-resizer: Verify active maintenance
// Consider testing react-native-image-manipulator as a backup plan

react-native-image-zoom-viewer is stable because it avoids native code. It is less likely to break during React Native upgrades.

// react-native-image-zoom-viewer: Low risk during upgrades
// Pure JS means fewer breaking changes between RN versions

🔄 Error Handling and Async Flow

All three packages handle asynchronous operations, but they report errors differently.

react-native-image-crop-picker rejects the Promise if the user cancels or an error occurs. You must wrap calls in try/catch blocks.

// react-native-image-crop-picker: Promise rejection
try {
  const image = await ImagePicker.openPicker({});
} catch (e) {
  // Handle cancel or error
}

react-native-image-resizer also returns a Promise. It rejects if the file path is invalid or processing fails.

// react-native-image-resizer: Promise rejection
try {
  const resized = await ImageResizer.createResizedImage(...);
} catch (e) {
  // Handle processing failure
}

react-native-image-zoom-viewer uses callbacks for events like cancel or fail. It does not use Promises for interaction.

// react-native-image-zoom-viewer: Callback props
<ImageViewer 
  onCancel={() => console.log('Closed')} 
  onFail={() => console.log('Load failed')} 
/>

🌱 Similarities: Shared Ground Between Packages

Despite their different roles, these libraries share common patterns typical of the React Native ecosystem.

1. 📱 Mobile-First Design

  • All three are built specifically for iOS and Android touch interfaces.
  • They handle gesture interactions native to mobile devices.
// All packages support touch interactions
// Picker: Touch to select
// Resizer: Background process
// Viewer: Pinch to zoom

2. 📦 Async Operations

  • All three handle heavy operations without blocking the UI thread.
  • Pickers and Resizers use Promises; Viewer uses async loading.
// Picker and Resizer
await someAsyncFunction();

// Viewer
<Image source={{ uri }} /> // Loads asynchronously

3. 🔒 Permission Management

  • Pickers and Resizers require camera and storage permissions.
  • Viewer requires network permissions if loading URLs.
// iOS: Info.plist
// Android: AndroidManifest.xml
// Required for Picker and Resizer to access files

4. 🎨 Customization Limits

  • All three offer limited UI customization compared to building from scratch.
  • You trade control for speed of implementation.
// Picker: Limited crop UI colors
// Resizer: No UI
// Viewer: Limited toolbar customization

5. 🤝 Community Ecosystem

  • All three rely on open-source contributions for bug fixes.
  • They are often used together in production apps.
// Common stack
import Picker from 'react-native-image-crop-picker';
import Resizer from 'react-native-image-resizer';
import Viewer from 'react-native-image-zoom-viewer';

📊 Summary: Key Similarities

FeatureShared by All Three
Platform📱 iOS and Android
Async⏳ Non-blocking operations
Permissions🔒 Require manifest config
Usage🛠️ Common in production apps
License📄 MIT / Open Source

🆚 Summary: Key Differences

Featurereact-native-image-crop-pickerreact-native-image-resizerreact-native-image-zoom-viewer
Primary Goal📸 Select and Crop🗜️ Compress and Resize🔍 View and Zoom
Interface📱 Native UI⚙️ Background Process🖼️ React Component
Native Code✅ Yes✅ Yes❌ No (Pure JS)
API Style📞 Promise-based📞 Promise-based🧩 Props and Callbacks
Maintenance Risk🟢 Low🟡 Medium🟢 Low

💡 The Big Picture

react-native-image-crop-picker is the go-to solution for intake. Use it when you need users to pick or capture images with minimal effort. It handles the hard parts of native camera and gallery integration.

react-native-image-resizer solves the bandwidth problem. Use it when you need to shrink images before upload. However, keep an eye on maintenance — have a backup plan ready if updates lag behind React Native versions.

react-native-image-zoom-viewer completes the loop. Use it when users need to see the full image. Since it is pure JavaScript, it is the safest bet for long-term stability during framework upgrades.

Final Thought: These tools are often complementary. A robust image feature might use the picker to get the file, the resizer to optimize it, and the viewer to display it later. Choose based on which part of the pipeline you need to build — and always check maintenance status before committing to native modules.

How to Choose: react-native-image-crop-picker vs react-native-image-resizer vs react-native-image-zoom-viewer

  • react-native-image-crop-picker:

    Choose react-native-image-crop-picker when you need a robust, native-feeling interface for users to select or capture images with built-in cropping tools. It is the standard choice for profile pictures or posts where user control over framing is required. Be prepared to manage native dependencies for iOS and Android.

  • react-native-image-resizer:

    Choose react-native-image-resizer if you must compress or resize images on the device before uploading to save bandwidth. However, evaluate maintenance status carefully, as newer alternatives like react-native-image-manipulator exist. Use this when server-side resizing is not an option.

  • react-native-image-zoom-viewer:

    Choose react-native-image-zoom-viewer when you need to display images in a full-screen modal with gesture support. It is ideal for photo feeds, galleries, or any view where users need to inspect image details. It works purely in JavaScript, avoiding native module complexity.

README for react-native-image-crop-picker

react-native-image-crop-picker

Backers on Open Collective Sponsors on Open Collective

iOS/Android image picker with support for camera, video, configurable compression, multiple images and cropping

Result

Important notes

  • If you are using react-native new architecture, you have to use react-native-image-crop-picker version >= 0.50.0

Usage

Import library

import ImagePicker from "react-native-image-crop-picker";

Select from gallery

Call single image picker with cropping

ImagePicker.openPicker({
  width: 300,
  height: 400,
  cropping: true,
}).then((image) => {
  console.log(image);
});

Call multiple image picker

ImagePicker.openPicker({
  multiple: true,
}).then((images) => {
  console.log(images);
});

Select video only from gallery

ImagePicker.openPicker({
  mediaType: "video",
}).then((video) => {
  console.log(video);
});

Android: The prop 'cropping' has been known to cause videos not to be displayed in the gallery on Android. Please do not set cropping to true when selecting videos.

Select from camera

Image

ImagePicker.openCamera({
  width: 300,
  height: 400,
  cropping: true,
}).then((image) => {
  console.log(image);
});

Video

ImagePicker.openCamera({
  mediaType: "video",
}).then((image) => {
  console.log(image);
});

Crop picture

ImagePicker.openCropper({
  path: "my-file-path.jpg",
  width: 300,
  height: 400,
}).then((image) => {
  console.log(image);
});

Optional cleanup

Module is creating tmp images which are going to be cleaned up automatically somewhere in the future. If you want to force cleanup, you can use clean to clean all tmp files, or cleanSingle(path) to clean single tmp file.

ImagePicker.clean()
  .then(() => {
    console.log("removed all tmp images from tmp directory");
  })
  .catch((e) => {
    alert(e);
  });

Request Object

PropertyTypeDescription
croppingbool (default false)Enable or disable cropping
widthnumberWidth of result image when used with cropping option
heightnumberHeight of result image when used with cropping option
multiplebool (default false)Enable or disable multiple image selection
writeTempFile (ios only)bool (default true)When set to false, does not write temporary files for the selected images. This is useful to improve performance when you are retrieving file contents with the includeBase64 option and don't need to read files from disk.
includeBase64bool (default false)When set to true, the image file content will be available as a base64-encoded string in the data property. Hint: To use this string as an image source, use it like: <Image source={{uri: `data:${image.mime};base64,${image.data}`}} />
includeExifbool (default false)Include image exif data in the response
avoidEmptySpaceAroundImage (ios only)bool (default true)When set to true, the image will always fill the mask space.
cropperActiveWidgetColor (android only)string (default "#424242")When cropping image, determines ActiveWidget color.
cropperStatusBarLight (android only)bool (default true)When cropping image, true for light status bar (dark icons), false for dark status bar (light icons).
cropperNavigationBarLight (android only)bool (default false)When cropping image, true for light navigation bar (dark icons), false for dark navigation bar (light icons).
cropperToolbarColor (android only)string (default #424242)When cropping image, determines the color of Toolbar.
cropperToolbarWidgetColor (android only)string (default darker orange)When cropping image, determines the color of Toolbar text and buttons.
freeStyleCropEnabledbool (default false)Enables user to apply custom rectangle area for cropping
cropperToolbarTitlestring (default Edit Photo)When cropping image, determines the title of Toolbar.
cropperCircleOverlaybool (default false)Enable or disable circular cropping mask.
disableCropperColorSetters (android only)bool (default false)When cropping image, disables the color setters for cropping library.
minFiles (ios only)number (default 1)Min number of files to select when using multiple option
maxFilesnumber (default 5)Max number of files to select when using multiple option
waitAnimationEnd (ios only)bool (default true)Promise will resolve/reject once ViewController completion block is called
smartAlbums (ios only)array (supported values) (default ['UserLibrary', 'PhotoStream', 'Panoramas', 'Videos', 'Bursts'])List of smart albums to choose from
useFrontCamerabool (default false)Whether to default to the front/'selfie' camera when opened. Please note that not all Android devices handle this parameter, see issue #1058
compressVideoPreset (ios only)string (default MediumQuality)Choose which preset will be used for video compression
compressImageMaxWidthnumber (default none)Compress image with maximum width
compressImageMaxHeightnumber (default none)Compress image with maximum height
compressImageQualitynumber (default 1 (Android)/0.8 (iOS))Compress image with quality (from 0 to 1, where 1 is best quality). On iOS, values larger than 0.8 don't produce a noticeable quality increase in most images, while a value of 0.8 will reduce the file size by about half or less compared to a value of 1.
loadingLabelText (ios only)string (default "Processing assets...")Text displayed while photo is loading in picker
mediaTypestring (default any)Accepted mediaType for image selection, can be one of: 'photo', 'video', or 'any'
showsSelectedCount (ios only)bool (default true)Whether to show the number of selected assets
sortOrder (ios only)string (default 'none', supported values: 'asc', 'desc', 'none')Applies a sort order on the creation date on how media is displayed within the albums/detail photo views when opening the image picker
forceJpg (ios only)bool (default false)Whether to convert photos to JPG. This will also convert any Live Photo into its JPG representation
showCropGuidelines (android only)bool (default true)Whether to show the 3x3 grid on top of the image during cropping
showCropFrame (android only)bool (default true)Whether to show crop frame during cropping
hideBottomControls (android only)bool (default false)Whether to display bottom controls
enableRotationGesture (android only)bool (default false)Whether to enable rotating the image by hand gesture
cropperChooseText (ios only)string (default choose)Choose button text
cropperChooseColor (ios only)string (default #FFCC00)HEX format color for the Choose button. Default color is controlled by TOCropViewController.
cropperCancelText (ios only)string (default Cancel)Cancel button text
cropperCancelColor (ios only)string (default tint iOS color )HEX format color for the Cancel button. Default value is the default tint iOS color controlled by TOCropViewController
cropperRotateButtonsHidden (ios only)bool (default false)Enable or disable cropper rotate buttons

Smart Album Types (ios)

NOTE: Some of these types may not be available on all iOS versions. Be sure to check this to avoid issues.

['PhotoStream', 'Generic', 'Panoramas', 'Videos', 'Favorites', 'Timelapses', 'AllHidden', 'RecentlyAdded', 'Bursts', 'SlomoVideos', 'UserLibrary', 'SelfPortraits', 'Screenshots', 'DepthEffect', 'LivePhotos', 'Animated', 'LongExposure']

Response Object

PropertyTypeDescription
pathstringSelected image location. This is null when the writeTempFile option is set to false.
localIdentifier(ios only)stringSelected images' localidentifier, used for PHAsset searching
sourceURL(ios only)stringSelected images' source path, do not have write access
filenamestringSelected images' filename
widthnumberSelected image width
heightnumberSelected image height
mimestringSelected image MIME type (image/jpeg, image/png)
sizenumberSelected image size in bytes
durationnumberVideo duration time in milliseconds
database64Optional base64 selected file representation
exifobjectExtracted exif data from image. Response format is platform specific
cropRectobjectCropped image rectangle (width, height, x, y)
creationDate (ios only)stringUNIX timestamp when image was created
modificationDatestringUNIX timestamp when image was last modified

Install

Step 1

npm i react-native-image-crop-picker --save

Step 2

iOS

cd ios
pod install

Step 3

iOS

Step 1

In Xcode open Info.plist and add string key NSPhotoLibraryUsageDescription with value that describes why you need access to user photos. More info here https://forums.developer.apple.com/thread/62229. Depending on what features you use, you also may need NSCameraUsageDescription and NSMicrophoneUsageDescription keys.

(Optional) Step 2 - To localize the camera / gallery / cropper text buttons

  • Open your Xcode project
  • Go to your project settings by opening the project name on the Navigation (left side)
  • Select your project in the project list
  • Should be into the Info tab and add in Localizations the language your app was missing throughout the +
  • Rebuild and you should now have your app camera and gallery with the classic ios text in the language you added.

Android

  • [Optional] If you want to use camera picker in your project, add following to app/src/main/AndroidManifest.xml

    • <uses-permission android:name="android.permission.CAMERA"/>
  • [Optional] If you want to use front camera, also add following to app/src/main/ AndroidManifest.xml

    • <uses-feature android:name="android.hardware.camera" android:required="false" />
    • <uses-feature android:name="android.hardware.camera.front" android:required="false" />

TO DO

  • [Android] Standardize multiple select
  • [Android] Video compression

Contributors

This project exists thanks to all the people who contribute. [Contribute].

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

MIT