react-native-image-resizer: native image downscaling for React Native apps
🗻 Resize local images with React Native
At a glance
- What is it?
- The bamlab/react-native-image-resizer module resizes local images on the device through native Android and iOS code, returning a URI you can hand straight to an Image component. It has supported the React Native new architecture since 3.0.0, but its last published release was v3.0.11 in November 2024.
- Who is it for?
- Adopt react-native-image-resizer if your app must shrink a camera roll or picked image before upload, and you can live with a native module that last shipped a release in November 2024. Do not adopt it for remote images that the platform can already scale at display time, or if you need WEBP output on iOS.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Resizing on the device instead of in JavaScript
The problem this module solves is narrow and real. A React Native app that lets a user pick a photo from the camera roll usually ends up holding a several megabyte JPEG, and if the app is going to upload it, sending that file over a mobile connection is both slow and wasteful. React Native's Image component can scale a picture for display, but that is a rendering concern, and the underlying file on disk stays the size it was. The bamlab/react-native-image-resizer module does the actual rescale in native code on the device and hands you back a new file.
The result is a file, not a canvas. The promise resolves with an object holding path, uri, name, size in bytes, width and height in pixels, and the documentation says the returned URI can be used directly as the source of an Image component. That last point is what makes the module pleasant to use: there is no base64 round trip and no manual re-attachment to the image source, you swap one URI for another.
The repository is MIT licensed, its primary language is listed as Java, which reflects the Android side, and it carries both android/ and ios/ directories plus a react-native-image-resizer.podspec. The author is Florian Rival of bam.tech, and the package description is simply "Rescale local images with React Native".
The package name changed and the old one is frozen
The first thing any adopter needs to know is that the package moved. A warning at the top of the documentation states that since version 3.0.0 the library has been moved from react-native-image-resizer to @bam.tech/react-native-image-resizer, and the package manifest confirms the new scoped name at version 3.0.11. The unscoped name still exists on npm, but the documentation points older React Native projects to a fixed version of it, [email protected], which is the last release of the old package line.
That split by React Native version is the other half of the setup story. For React Native 0.61 and above, the documentation gives:
yarn add @bam.tech/react-native-image-resizer
cd ios && pod installFor React Native 0.60 and below, it gives a different install path, pinning the legacy package to 1.1.0 and running the same pod install step. The reason the modern path can be this simple is stated in the same section: since 3.0.0 the package supports the new architecture out of the box as a Turbo Module, and it keeps retrocompatibility with the old architecture. So there is no separate new-architecture package to choose, no config flag to flip, and no bridge-specific install to work around.
The pod install step is required for iOS in both cases. CocoaPods is where the native code gets linked into the Xcode project, and skipping it produces a build that cannot find the module at runtime.
One promise, seven positional arguments
The API is a single function with a fixed argument list, and the order matters, because several parameters are positional rather than named:
createResizedImage(
uri,
maxWidth,
maxHeight,
compressFormat,
quality,
(rotation = 0),
outputPath,
(keepMeta = false),
(options = {})
); // Returns a PromiseThe first argument accepts either a path or a uri, and the documentation says this has been tested against the output of @bam.tech/react-native-image-picker, react-native-vision-camera, @react-native-camera-roll/camera-roll, and an http link. A base64 encoded string prefixed with data:image/imagetype is also accepted, where the image type is jpeg or png.
Two defaults are baked into the signature. Rotation defaults to 0, and keepMeta defaults to false. The keepMeta default is destructive in a way that surprises people: when it is false all metadata is lost. Setting it to true attempts to preserve file metadata and exif information, with the exception of the orientation value, because the resizing also performs rotation correction on the original. There is a second constraint on keepMeta that is easy to miss: it can only be true for JPEG images loaded from the file system, not from the web.
Rotation is also asymmetric between platforms. The degrees value applies to images on Android, while on iOS rotation is limited, and rounded, to multiples of 90 degrees.
Output format, quality, and where the file lands
compressFormat accepts JPEG, PNG, or WEBP, and WEBP is marked as Android only. The quality parameter is a number between 0 and 100 and is used for JPEG compression. The outputPath parameter decides where the result goes, and if it is null the resized image is stored in the cache folder. If you do want a specific path, the documentation carries a small trap: you have to supply the rotation option as well, setting it to 0 if no rotation is needed. That is an odd requirement, but it exists so the native side has a complete set of arguments rather than a partially filled one.
The resizeMode option lives inside the options object and behaves like the resizeMode of the React Native Image component. It accepts contain, which is the default, or cover, or stretch. Contain fits the image within the given width and height while preserving its ratio, so the result may be smaller than the box you asked for in one dimension. Cover preserves the aspect ratio as well but fills the box, cropping the overflow. Stretch distorts to match exactly. Since the option is a property of the options object rather than a positional argument, it is also the one setting that cannot be changed without rewriting the call site.
Metadata behaviour and output location together are what make this module different from a pure scaling helper. If your pipeline needs to keep the capture time or device information attached to a photo, the defaults will not give it to you.
A Gradle dex collision and the manual linking escape hatch
There is one documented Android build problem, and it has a one-line fix. On recent React Native versions the Gradle build can fail with com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim. The documented remedy is to run:
cd android && ./gradlew cleanThis is a symptom of support library classes arriving twice in the same application, once from the old support library and once from AndroidX, and cleaning the build directory forces Gradle to regenerate the dex set. It is a recurring papercut rather than a fundamental problem, but it is the kind of thing that shows up on a machine that has never built the project before.
For projects that need to link the Android side by hand, the documentation points to a separate file, docs/android_manual_config.md, for the manual link information. The example application in the example folder shows the intended usage, resizing a photo from the camera roll, and the repository carries a full native project layout under it with android/, ios/, metro.config.js, a Gemfile, and a babel.config.js, so the wiring is inspectable before you copy it.
The module's own build setup is worth a note too. The package publishes both CommonJS and ES module builds plus TypeScript declarations, with the react-native field pointing at the TypeScript source, and the build itself is driven by bob build. Tests run under jest, types are checked with tsc --noEmit, and linting uses eslint. Release publishing goes through release-it, and the repository uses lefthook for git hooks and commitlint with the conventional config for commit messages.
Against doing it yourself, and against shipping the original
The realistic alternative is not to resize at all, and to let the server or the CDN do the work. That approach differs in a fundamental way: it costs no native dependency and no client CPU, but it requires uploading the full-size file first, which is the exact cost this module is meant to remove on a mobile connection. It also means the original image leaves the device, which matters for privacy reasons and for products that promise local-only processing.
A second alternative is to write the resizing yourself in JavaScript, for instance by drawing into a canvas and extracting a data URL. The reasons it is not equivalent are practical rather than aesthetic. The output is a base64 string in memory rather than a file on disk, so you have to manage the data size yourself and re-encode it before uploading, and the behaviour differs per platform because the underlying canvas implementations differ. The native module returns a file path and a URI, which is what an upload request and an Image source both want.
For the packaging question, a team that already depends on the old unscoped react-native-image-resizer should check what version it has pinned. The documentation points projects on React Native 0.60 and below to [email protected], and everything from 3.0.0 onwards lives under the @bam.tech scope with the Turbo Module support included.
The release gap is the thing to plan around
The published release history is where this project needs the most caution. The most recent GitHub release is v3.0.11 from 2024-11-25, preceded by v3.0.10 from 2024-05-30 and v3.0.9 from 2024-04-29. The last push to the repository was on 2026-10-09, so the source tree is still being worked on, but the npm artefact that most apps install has not been republished since November 2024.
That gap has a practical meaning for adopters. A native module is tied to the React Native and platform versions in your project, so a module whose published version predates a React Native release may not build against the newer toolchain, and you cannot simply bump the package to pick up a fix. Anyone starting a new project on a current React Native version should check whether the published 3.0.11 artefact compiles before committing to it, and should be prepared to patch the source if it does not, since the repository itself is being changed and the source is available.
None of this says the module is wrong for the job. The API is small, the behaviour is documented down to the metadata and rotation details, and the promise shape is a good fit for a React codebase. It says that adopting it is a decision about depending on a native module whose published cadence has slowed, and the honest way to make that decision is to build the example app against your own React Native version first.
Editorial conclusion
Adopt react-native-image-resizer if your app must shrink a camera roll or picked image before upload, and you can live with a native module that last shipped a release in November 2024. Do not adopt it for remote images that the platform can already scale at display time, or if you need WEBP output on iOS. Verify first that the resizeMode option, which defaults to contain, matches how your layout crops images, since that choice changes the output dimensions.
Frequently asked questions
What is the correct npm package name for react-native-image-resizer?
Since version 3.0.0 the library is published as @bam.tech/react-native-image-resizer, and the package manifest lists that scoped name at version 3.0.11. The documentation points projects on React Native 0.60 and below to the old unscoped package pinned at [email protected].
Does react-native-image-resizer support the React Native new architecture?
Yes. The documentation states that since 3.0.0 the package supports the new architecture out of the box as a Turbo Module, and it also keeps retrocompatibility with the old architecture, so no separate install is needed.
How do I keep EXIF metadata when resizing an image?
Pass keepMeta as true, which attempts to preserve file metadata and exif info, except the orientation value since resizing also applies rotation correction. It can only be true for JPEG images loaded from the file system, and it defaults to false, which loses all metadata.
Which output formats does react-native-image-resizer support?
The compressFormat parameter accepts JPEG, PNG, or WEBP, with WEBP marked as Android only. The quality parameter is a number between 0 and 100 and is used for JPEG compression.
How do I fix the Gradle error about multiple dex files on Android?
The documentation describes this as a possible error on the latest React Native versions, com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim, and the fix is to run cd android && ./gradlew clean to clean the build.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bamlab-react-native-image-resizer)Was this useful?