Search code examples
fluttercompressionimage-compressionheic

Flutter Web: How to convert HEIC to JPEG?


I was trying to compress the image before sending it to the server. But HEIC format images cannot be compressed using the package (flutter_image_compress). Also, I did not find a package that can convert images for Flutter Web. What other options are there?

I tried to find a way to do this without using third-party packages but couldn't find one.


Solution

  • Since Flutter Web doesn't have a direct way to convert photos, I used the package "heic2any" for JavaScript.

    Update index.html file (./web/index.html)

    <!-- HEIC to any converter -->
    <script src="https://unpkg.com/heic2any"></script>
    <script>
      async function convertHeicToJpeg(heicFile) {
        try {
          const convertedBlob = await heic2any({
            blob: heicFile,
            toType: "image/jpeg",
          });
          return convertedBlob;
        } catch (error) {
          console.error("HEIC to JPEG conversion failed:", error);
          throw error;
        }
      }
    </script>
    

    My HeicToJpegService code:

    import 'dart:async';
    import 'dart:html'; // for using Blob
    import 'dart:js_util' as js_util;
    import 'dart:typed_data';
    
    import 'package:js/js.dart';
    
    @JS('convertHeicToJpeg')
    external Future<Blob> convertHeicToJpegBlob(Blob heicFile);
    
    class HeicToJpegService {
      /// Convert Blob to Uint8List
      Future<Uint8List> _blobToUint8List(Blob blob) async {
        final completer = Completer<Uint8List>();
        final reader = FileReader();
        reader.readAsArrayBuffer(blob);
        reader.onLoadEnd.listen((event) {
          completer.complete(Uint8List.fromList(reader.result as List<int>));
        });
        reader.onError.listen((event) {
          completer.completeError(reader.error ?? 'Unknown error');
        });
        return completer.future;
      }
    
      Future<Uint8List> convertHeicToJpeg(Uint8List fileBytes) async {
        final blob = Blob([fileBytes]);
        final convertedBlob = await js_util.promiseToFuture<Blob>(
          js_util.callMethod(window, 'convertHeicToJpeg', [blob]),
        );
        return await _blobToUint8List(convertedBlob);
      }
    }
    

    This code works as expected. There are no problems with it either.