Skip to content

Open sourceFlutter package

flutter_bicubic_resize

The fastest image resize, crop and compress for Flutter - pure native C, identical results on every platform.

DocsOverview

Why the whole image pipeline runs in native C, how fast it is, and how to get your first resize working.

source: README.md (opens in a new tab)
On this page8 sections

What it is

flutter_bicubic_resize runs the entire image pipeline - decode, crop, resize and encode - in native C, so a 4K photo becomes a 224×224 tensor in roughly 15-30 ms and the output is byte-identical on Android, iOS and macOS. It uses stb_image_resize2 with the Catmull-Rom spline, the same interpolation as OpenCV cv2.INTER_CUBIC and PIL Image.BICUBIC, which is why it is a good fit for ML preprocessing that must match a Python training pipeline.

Why identical output matters

Default platform APIs use different algorithms - Android is typically bilinear, iOS depends on context (Lanczos, bilinear, and others). This package runs the same C code on every platform, so the same input always produces the same pixels.

  • 3-4x faster than other Flutter image libraries (pure native C pipeline)
  • 100% native C performance (stb_image + stb_image_resize + stb_image_write)
  • Identical results on iOS, Android and macOS
  • Bicubic interpolation (Catmull-Rom, same as OpenCV INTER_CUBIC and PIL BICUBIC)
  • RGB and RGBA support, JPEG and PNG with alpha preservation
  • EXIF orientation support - rotates JPEG photos correctly
  • Flexible crop system - anchor position, aspect ratio modes, custom ratios
  • Edge handling modes - clamp, wrap, reflect, zero
  • ML preprocessing - tensor normalization, HWC/CHW layouts, RGB/BGR ordering
  • Async wrappers - every method has an *Async() variant using Isolate.run()
  • File I/O and JPEG↔PNG format conversion without resizing
  • Zero external Dart dependencies (only ffi)

Performance

The whole pipeline runs in native C - there is no Dart image-processing overhead. Operations are synchronous but extremely fast, and there is no memory copying between Dart and native code thanks to direct FFI.

  • Resize a 4K JPEG to 224×224 in about 15-30 ms.
  • Crop, resize and compress in a single pass.
  • No memory copying between Dart and native (direct FFI).

Architecture

A single call walks the image through five native stages. No Dart image libraries are involved at any point.

  1. 1

    Decode

    stb_image decodes JPEG/PNG to raw pixels.

  2. 2

    EXIF orientation

    For JPEG: parses EXIF metadata and applies the correct rotation/flip (optional).

  3. 3

    Crop

    Extracts a region based on anchor position and aspect ratio mode.

  4. 4

    Resize

    stb_image_resize2 applies bicubic interpolation with the selected edge mode.

  5. 5

    Encode

    stb_image_write encodes back to JPEG/PNG.

Installation

Add the dependency to your pubspec.yaml:

pubspec.yamlyaml
dependencies:
  flutter_bicubic_resize: ^1.7.0

Or add it from the command line:

bash
flutter pub add flutter_bicubic_resize

Version

The current published version is 1.7.0. Older README snippets may still reference ^1.5.3 - use ^1.7.0 to get macOS support and the Swift Package Manager fixes.

Quickstart

Every operation is a static method on BicubicResizer. Pass the encoded bytes and the target size - the return value is the resized, re-encoded bytes.

Resize a JPEGdart
import 'package:flutter_bicubic_resize/flutter_bicubic_resize.dart';

final resized = BicubicResizer.resizeJpeg(
  jpegBytes: originalBytes,
  outputWidth: 224,
  outputHeight: 224,
  quality: 95, // optional, default 95
);
Resize a PNGdart
final resized = BicubicResizer.resizePng(
  pngBytes: originalBytes,
  outputWidth: 224,
  outputHeight: 224,
  compressionLevel: 6, // optional, 0-9 (default: 6)
);

Requirements & platforms

These constraints come from pubspec.yaml at v1.7.0 and are authoritative - the README lists an older, looser baseline.

  • Dart SDK >=3.5.0 <4.0.0, Flutter >=3.24.0.
  • Android SDK 21+, iOS 13.0+, macOS 10.15+.
  • FFI plugin platforms: Android, iOS and macOS (macOS added in 1.7.0).
  • Only one external dependency: ffi: ^2.1.0.

Recent highlights

1.7.0

macOS support - fixes the missing bicubic_resize_rgb symbol lookup; Package.swift declares .macOS(10.15).

1.6.0

Swift Package Manager support for iOS; Android compileSdk raised to 36; min Dart >=3.5.0, Flutter >=3.24.0.

1.5.4

ImageFormatX extension - mimeType and fileExtension getters on ImageFormat.

1.5.0

getImageInfo() + BicubicImageInfo, resizeFile()/resizeFileToFile(), JPEG↔PNG conversion, formatUnknown (-6) error code.

1.4.0

Async wrappers via Isolate.run(), BicubicNativeError enum + BicubicResizeException, zero-std ArgumentError validation.

1.3.0

resizeForModel() ML preprocessing (NormalizationType, ChannelOrder, TensorLayout) with pre-computed scale/offset.

Where next

Let's make something together.

No overengineering. No wasted time. Just straight-up execution.

Or book a call with Eryk (opens the booking calendar)[email protected]
Who are you?
Budget