@aquienpz/asset-compressor-native
v0.2.0
Published
Native (iOS/Android) image compression for the @aquienpz upload pipeline. JS API mirrors @aquienpz/asset-compressor-web so call sites are identical across web and React Native.
Downloads
264
Readme
@aquienpz/asset-compressor-native
Fast, native (iOS + Android) image compression for React Native apps that
upload to the aquienpz asset platform. Pairs with
@aquienpz/asset-uploader-expo and mirrors the API of
@aquienpz/asset-compressor-web so call sites are identical across
platforms.
Why this exists
expo-image-manipulator is the default option in Expo apps, but it
runs the resize + re-encode through the JS bridge and ships an
intermediate bitmap as a JS-heap allocation. On a 12MP iPhone HEIC, a
single resize-to-2880px + JPEG q=0.85 takes ~2–4 seconds — long enough
to make a 10-photo batch upload feel broken.
This package wraps react-native-compressor,
which calls libjpeg-turbo (iOS) / Bitmap.compress (Android) on a
background thread and never moves pixel data across the bridge. The
same operation runs in ~250–350ms — roughly 5–10× faster than the
Expo equivalent on identical hardware.
Install
# in your Expo / RN app
npm install @aquienpz/asset-compressor-native react-native-compressor
# Expo: also run the config-plugin once
npx expo prebuildAdd the plugin entry to app.json:
{
"expo": {
"plugins": ["react-native-compressor"]
}
}Usage
import { compressImage, compressImages } from "@aquienpz/asset-compressor-native";
// Single image
const result = await compressImage({
uri: pickerAsset.uri,
filename: pickerAsset.fileName ?? "photo.jpg",
});
// → { uri: 'file:///.../photo.jpg', size: 412903, originalSize: 4218876, compressionRatio: 0.097 }
// Batch
const { successful, failed } = await compressImages(
pickerAssets.map((a, i) => ({ uri: a.uri, filename: a.fileName ?? `photo-${i}.jpg`, id: a.assetId })),
{ quality: 0.85, maxWidth: 2880, concurrency: 1 },
(id, status, index) => console.log(`[${index}] ${id} → ${status}`),
);Output format
Output is always JPEG. react-native-compressor natively supports
only jpg / png, and the asset-manager re-encodes every uploaded
image to WebP server-side anyway when generating size variants — so
forcing WebP on device would cost binary size + native module
maintenance for zero net bandwidth win.
The on-device savings (HEIC/big-JPEG → 2880px JPEG q=0.85) are already ~80–95% before the upload starts.
API parity with @aquienpz/asset-compressor-web
| Web | Native |
| ---------------------------------------- | ----------------------------------------------- |
| input Blob | input uri (file://, content://, ph://) |
| output Blob (mime configurable) | output file uri on disk (always JPEG) |
| compressionStatus: convertingHeic | not emitted (HEIC decode is part of compressing) |
| concurrency: p-limit / navigator.hwc | concurrency: bounded worker pool, default 1 |
| HEIC fallback: heic2any | HEIC handled natively by ImageIO / android-heif |
Everything else (quality default 0.85, maxWidth/Height 2880, status
callback shape, error collection in compressImages) is identical.
Cleanup
react-native-compressor writes outputs to the app's cache directory.
iOS will reclaim it under memory pressure; Android does the same when
the cache exceeds cacheQuotaBytes. If you upload + don't need the
local copy, delete it yourself with expo-file-system or
react-native-fs once the upload completes.
