compressImage static method

Future<File?> compressImage(
  1. {required File image,
  2. Compression? compression}
)

Compresses image and stores the image at target.

This method compresses the image at-least once and then keeps it compressing until Compression.maxFileSize is reached.

See also

Implementation

static Future<File?> compressImage({required File image, Compression? compression}) async {
  File? compressedImage;

  try {
    compression ??= const Compression.standard();

    final int maxFileSize = compression.maxFileSize;

    final int originalSize = await image.length();
    int quality = compression.quality;

    if (kDebugMode) print('Size before compression : $originalSize');

    compressedImage = image;

    //tempFile for more compression if needed
    final String dir = await zdsTempDirectory('compressed');
    final String imageExt = compression.format == CompressFormat.jpeg
        ? 'jpeg'
        : compression.format == CompressFormat.png
            ? 'png'
            : path.extension(compressedImage.absolute.path).toLowerCase();

    final String tmpName = 'TMP_${DateTime.now().microsecondsSinceEpoch}.$imageExt';
    final File tempFile = File(path.join(dir, tmpName));

    //targetFile
    final File targetFile = File('$dir/${path.basenameWithoutExtension(image.absolute.path)}.$imageExt');
    final ui.Image decodeImage = await decodeImageFromList(image.readAsBytesSync());
    final double scaleFactor = decodeImage.height > decodeImage.width
        ? compression.minHeight / decodeImage.height
        : compression.minWidth / decodeImage.width;

    final int newHeight = (decodeImage.height * scaleFactor).toInt();
    final int newWidth = (decodeImage.width * scaleFactor).toInt();

    int compressedSize;

    /// Compress at-least once
    do {
      if (targetFile.existsSync()) await targetFile.delete();
      final XFile? processedFile = await FlutterImageCompress.compressAndGetFile(
        compressedImage?.absolute.path ?? '',
        autoCorrectionAngle: compression.autoCorrectionAngle,
        format: compression.format,
        inSampleSize: compression.inSampleSize,
        keepExif: compression.keepExif,
        minHeight: newHeight,
        minWidth: newWidth,
        numberOfRetries: compression.numberOfRetries,
        quality: quality,
        rotate: compression.rotate,
        targetFile.absolute.path,
      );

      // Return if compression failed
      if (processedFile == null) throw PlatformException(code: 'PROCESS_ERR');

      //delete existing compressed file
      if (tempFile.existsSync()) await tempFile.delete();
      compressedImage = await File(processedFile.path).copy(tempFile.path);
      compressedSize = await compressedImage.length();

      if (compressedSize > originalSize) throw PlatformException(code: 'COMPRESS_ERR');

      if (kDebugMode) print('quality after compression $quality : $compressedSize');

      quality = quality - 5;
    } while (quality >= 50 && compressedSize >= maxFileSize);

    return targetFile;
  } catch (e) {
    if (kDebugMode) print(e);
    rethrow;
  } finally {
    await compressedImage?.delete();
  }
}