JPEG thumbnailing and lossless transformations using libjpeg-turbo via Dart's FFI. Unlike platform-specific plugins it should be readily usable from within isolates.

The lossy recompress method can reduce quality & optionally downsize. Resizing is done by libjpeg-turbo during decompression so it should be fast, but a limited set of scaling factors are supported (including 1/2, 1/4, 1/8). EXIF data can be copied from the original image.

The "lossless" transformations are similar to those than can be made using the jpegtran tool, e.g. cropping and rotations. Since JPEG data doesn't need to be decoded or encoded they should be fast as well.


void cropToSquareAndRotate() {
    var jpegtran = JpegTransformer(_imageBytes);
    try {
        var info = jpegtran.getInfo();

        var cropSize = min(info.width, info.height);
        var crop = JpegCrop(
            w: cropSize,
            h: cropSize,
            x: (info.width - cropSize) ~/ 2,
            y: (info.height - cropSize) ~/ 2,
            alignIfRequired: true,

        var rotate = JpegRotation(
            angle: 90,
            crop: crop,
            options: JpegOptions(grayscale: false),

        var newImage = jpegtran.transform(rotate);
        setState(() {
            _imageBytes = newImage;
    } catch (err) {
        _showError(err, context);
    } finally {
Uint8List recompress(Uint8List jpegBytes) {
  var jpegtran = JpegTransformer(jpegBytes);
  try {
    return jpegtran.recompress(
      scale: 0.25,
      quality: 70,
      preserveEXIF: true,
  } finally {


  • Remove unneeded parts of libjpeg-turbo