Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

246 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Native Image Compression Kit

Native-first image compression, resize, and format conversion for React Native.

Platforms: Android and iOS TypeScript: API available License: MIT

Compress supported local images to JPEG, PNG, or WebP, with optional resize, quality, target-size, and metadata controls. Use the runtime capability API to handle platform codec differences before compression.

Current status

  • Package version: 0.4.0
  • Release target: 0.4.0
  • Published npm latest: 0.4.0
  • Release state: release
  • Registry checked at: 2026-07-20

Version 0.4.0 is the current published release. It moves large image work to bounded background workers, downsamples resize requests during decode, rejects unsafe work before full decode, supports cancellation, and publishes only complete transactional cache files. npm latest, immutable tag v0.4.0, and the GitHub Release all resolve to the verified 0.4.0 artifact and source.

Installation

npm install react-native-image-compression-kit

Or with pnpm:

pnpm add react-native-image-compression-kit

For iOS, install pods after adding the package:

cd ios && pod install

Android 23+ and iOS 13.4+ are supported. The package declares React Native >=0.73 <1.0. The v0.4.0 release-target matrix verifies React Native 0.73.11 Legacy, React Native 0.86.0 Legacy and New Architecture, and Expo 57.0.7 with React Native 0.86.0 New Architecture on both platforms. Versions between the tested endpoints are accepted by the peer range but are not individually release tested. Expo requires a development build or prebuild; Expo Go and Snack cannot load this custom native module. See the exact compatibility evidence.

See the installation guide for Bare React Native, Expo development-build, rebuild, and URI integration steps.

Quick start

import {
  compressImage,
  getImageCompressionCapabilities,
} from 'react-native-image-compression-kit';

const capabilities = await getImageCompressionCapabilities();
const canWriteWebP = capabilities.formats.some(
  ({ format, output }) => format === 'webp' && output
);

const result = await compressImage({
  source: { uri: imageUri },
  resize: {
    maxWidth: 2048,
    maxHeight: 2048,
    mode: 'contain',
  },
  output: {
    format: canWriteWebP ? 'webp' : 'jpeg',
    quality: 80,
  },
  metadata: 'safe',
});

console.log(result.uri, result.byteSize, result.width, result.height);

Input must be a local URI accessible to the native app. Android supports file:// and content://; iOS supports file:// and best-effort local content:// loading.

Public API

compressImage(options, control?)

Returns Promise<CompressionResult>.

interface CompressionOptions {
  source: { uri: string };
  resize?: {
    maxWidth?: number;
    maxHeight?: number;
    mode?: 'contain' | 'cover' | 'stretch';
  };
  output: {
    format: 'jpeg' | 'png' | 'webp' | 'heic' | 'heif' | 'avif';
    quality?: number;
    maxBytes?: number;
  };
  metadata?: 'preserve' | 'safe' | 'strip';
}

interface CompressionResult {
  uri: string;
  format: 'jpeg' | 'png' | 'webp' | 'heic' | 'heif' | 'avif';
  width: number;
  height: number;
  byteSize: number;
  originalByteSize: number;
  compressionRatio: number;
}

interface CompressionControl {
  signal: CompressionAbortSignal;
}

The optional second argument accepts either an AbortSignal directly or a CompressionControl object. Aborts before dispatch, while queued, or while running reject with ERR_CANCELLED; aborting after completion is a no-op.

const controller = new AbortController();
const compression = compressImage(options, { signal: controller.signal });
controller.abort();
await compression;

getImageCompressionCapabilities()

Returns the current platform's input/output format availability, metadata policies, target-size and cancellation support, bounded concurrency, decode-downsampling support, and named source/working pixel limits. Check it at runtime; codec support is not identical across Android versions, devices, and iOS runtimes.

Other exports

  • ImageCompressionKitError
  • ImageCompressionKitErrorCode
  • IMAGE_FORMATS, OUTPUT_FORMATS, METADATA_POLICIES, RESIZE_MODES
  • Public TypeScript types for options, results, formats, resize, metadata, and capabilities

Compression examples

Quality and resize

const result = await compressImage({
  source: { uri: imageUri },
  resize: { maxWidth: 1600, maxHeight: 1600, mode: 'contain' },
  output: { format: 'jpeg', quality: 82 },
  metadata: 'safe',
});

Target size

const result = await compressImage({
  source: { uri: imageUri },
  output: { format: 'webp', quality: 90, maxBytes: 500_000 },
  metadata: 'strip',
});

quality is the upper bound when used with maxBytes. The native pipeline searches for the highest supported quality under the target. It returns the smallest generated result if the target cannot be reached. PNG does not support maxBytes.

Format conversion

const result = await compressImage({
  source: { uri: heicUri },
  output: { format: 'jpeg', quality: 85 },
  metadata: 'safe',
});

Error handling

import {
  compressImage,
  ImageCompressionKitError,
} from 'react-native-image-compression-kit';

try {
  await compressImage(options);
} catch (error) {
  if (error instanceof ImageCompressionKitError) {
    console.warn(error.code, error.message);
  }
}

Platform capabilities and limitations

Capability Android iOS
JPEG/PNG/WebP input Yes Yes; WebP is static ImageIO decode
GIF input Static first frame Static ImageIO decode
HEIC/HEIF input SDK/device codec gated Static ImageIO decode
AVIF input Android 14+ (ImageDecoder) Runtime ImageIO source gated
JPEG output Yes Yes
PNG output Yes Yes
WebP output Yes Runtime ImageIO destination gated
HEIC/HEIF/AVIF output Not implemented Not implemented
maxBytes JPEG and WebP JPEG and runtime-available WebP
Resize modes contain, cover, stretch contain, cover, stretch
Decode downsampling BitmapFactory.inSampleSize / ImageDecoder target ImageIO thumbnail
Concurrent operations Maximum 2 Maximum 2
Cancellation Yes Yes

Important limitations:

  • HEIC, HEIF, and AVIF output reject with ERR_NOT_IMPLEMENTED.
  • GIF output and animation preservation for GIF/WebP/AVIF are not implemented.
  • metadata: 'preserve' is supported only for JPEG source to JPEG output.
  • Android safe copies a privacy-filtered JPEG EXIF allowlist. iOS safe and strip re-encode without copying source metadata.
  • JPEG orientation is rendered into pixels before resize/encode; preserved output orientation and dimensions are normalized.
  • Sources above 32,768 pixels on either axis or 100,000,000 total pixels reject with ERR_RESOURCE_LIMIT. Work requiring more than 25,000,000 decoded pixels must provide smaller resize bounds.
  • JPEG output flattens transparency onto white on both platforms. PNG and WebP alpha capability reflects decode-back validation.
  • Failed and cancelled operations remove temporary/partial cache files; a successful returned cache file retains the existing application ownership contract.
  • Capability checks should drive fallbacks for SDK-, device-, and runtime-dependent codecs.

Development verification

pnpm verify
pnpm example:typecheck
pnpm example:ios:decoder-test
pnpm example:ios:encoder-test
pnpm example:ios:output-test
pnpm example:ios:pipeline-test
pnpm example:ios:large-image-test
pnpm example:ios:metadata-test
pnpm example:ios:transformer-test
pnpm docs:check
pnpm site:check
pnpm site:build
pnpm fixtures:compatibility:check
git diff --check
pnpm pack --dry-run

pnpm verify runs TypeScript checks, Vitest, the build, offline fixture and release-evidence replay gates, workflow pin checks, and the Android repository doctor. pnpm docs:check is network-free and validates the repository status manifest, aligned README/RELEASE blocks, required documentation structure, local links/anchors, and npm package exclusions.

For release-oriented changes, also run:

pnpm smoke:consumer
pnpm release:dry-run

The release dry run never publishes. Its shared state matrix blocks a candidate and permits release only after package metadata, the release target, and document mirrors are aligned. The separately tracked published npm latest remains an observed registry value and is not rewritten before publish.

Registry monitoring

The daily Registry Health workflow reads publishedNpmLatest from docs/release-status.json, runs the real npm registry smoke with npm 12.0.1, and compares npm latest, exact-version metadata, the downloaded tarball, README/package inventory, and clean consumer install/typecheck with evidence/npm/<version>. It has only contents: read, uses no protected environment, and creates no provenance or attestation. The manual Registry Validation workflow is separate: maintainers dispatch it through npm-production when fresh provenance and attestation evidence is required.

Run the same read-only monitor locally without hardcoding the release version:

health_version="$(node -p "require('./docs/release-status.json').publishedNpmLatest")"
health_dir="$(mktemp -d)"
pnpm smoke:registry -- \
  --version "$health_version" \
  --expect-tag latest \
  --json \
  --artifact-dir "$health_dir/live"
pnpm verify:registry-health -- \
  --live-artifact-dir "$health_dir/live" \
  --json \
  --report-file "$health_dir/registry-health.json"

The canonical report compares package name, requested/resolved/tagged version, publish timestamp, tarball URL, SRI, shasum, SHA-256, packed bytes, file count, unpacked bytes, README status, forbidden files, and consumer smoke result. A failure is an investigation signal only: it grants no authority to republish, change a dist-tag, move a Git tag, or edit a GitHub Release. Inspect the report drift first, then the release-status handoff and matching evidence archive, then exact npm metadata and a fresh smoke. A release handoff is complete only when docs/release-status.json and evidence/npm/<version> identify the same published version.

Repository documentation

Operational material is repository-only and is not included in the npm tarball:

Security

See SECURITY.md for supported versions, private vulnerability reporting, package prohibitions, and repository-only execution procedures.

Contributing and support

License

MIT License. See LICENSE.

About

Capability-aware native image compression, resize, and format conversion for React Native.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages