react-native-image-resizer
Resize and compress local images in React Native apps using native Android and iOS APIs.
Repository Health
Technical Analysis
react-native-image-resizer gives React Native apps a single createResizedImage API for scaling and compressing local images before upload or display, using native Android and iOS image processing instead of slow JavaScript canvas approaches. It supports JPEG, PNG, and WEBP (Android) output formats, configurable rotation, optional EXIF metadata preservation, and three resize modes (contain, cover, stretch) that mirror React Native’s own Image component resizeMode semantics.
Since version 3.0 the library moved to the @bam.tech npm scope and ships as a Turbo Module with New Architecture support, while remaining backward compatible with the legacy bridge for apps still on the old architecture. It’s commonly paired with camera-roll, image-picker, or vision-camera libraries to shrink photos before they’re uploaded to a server or persisted on device.
What You Get
- A single
createResizedImageAPI for resizing local image files or base64 strings - Native Android and iOS resizing instead of slow canvas/WebView workarounds
- JPEG, PNG, and WEBP (Android) output format support with adjustable quality
- Turbo Module support for React Native’s New Architecture, with legacy bridge fallback
- Optional EXIF metadata preservation for JPEG images
Common Use Cases
- Compressing camera-roll photos before uploading them to a backend
- Generating thumbnail-sized images for gallery or chat UIs
- Downscaling images from react-native-image-picker or vision-camera before storage
- Reducing image payload size for slow network conditions
Under The Hood
Architecture A thin TypeScript wrapper (src/index.tsx) merges default resize options and delegates to a native module, resolved at runtime either through the legacy bridge (NativeModules.ImageResizer) or, when React Native’s New Architecture is active, through a generated TurboModule spec (NativeImageResizer.ts via TurboModuleRegistry). All actual image processing lives natively: ImageResizerModule.java on Android runs decode/scale/compress inside a GuardedAsyncTask off the bridge thread, while ImageResizer.mm and ImageHelpers.m mirror the same contract in Objective-C++ on iOS. Separate oldarch/newarch ImageResizerSpec.java files isolate the codegen-vs-manual-bridge difference so the module implementation itself stays untouched across architectures. Because the public surface is a single async function, swapping the native imaging implementation would only touch the platform folders, not the JS API.
Tech Stack TypeScript defines the public Options/Response/ResizeFormat types and the TurboModule spec, built via react-native-builder-bob into commonjs, ESM, and typescript output targets; react and react-native are peer dependencies rather than pinned versions. Android relies on the platform’s own Bitmap APIs with no third-party imaging library, wrapped in AsyncTask for background execution. iOS uses Objective-C++ with UIKit/ImageIO for decode, scale, and compression, with podspec branches that pull in Folly/RCTRequired/ReactCommon turbomodule dependencies only when the New Architecture flag is enabled. Tooling around the library includes Yarn workspaces, Jest, an ESLint/Prettier setup built on a community React Native config, lefthook git hooks, and release-it for versioned releases.
Code Quality JavaScript-level test coverage is effectively absent — the sole test file contains a single pending test stub rather than real assertions — and the native Android/iOS code has no visible unit tests either. Typing is comprehensive for the public API surface, and linting/formatting are enforced through pre-commit hooks. Error handling follows idiomatic per-platform patterns (typed exceptions rejecting a Promise on Android, an analogous error-based reject path on iOS), and naming is consistent across the JS, Android, and iOS layers. Overall this reads as a well-typed, well-linted library with a real gap in automated test coverage.
API Design The library exposes one function, createResizedImage, keeping the common case low-boilerplate while an options object handles the newer resize-mode and scale-down behavior. Resize modes are deliberately named to mirror React Native’s own Image component resizeMode values, lowering the conceptual overhead for anyone already familiar with RN’s Image API. The README documents every parameter and is candid about a known limitation with camera-roll integration under the New Architecture — unusually thorough documentation for a small native module. The main friction point is a long, largely positional function signature with several optional trailing arguments, which a fully options-object API would simplify.