Flutter: How to use "Multi Image Picker" to reduce image quality and get output as "File"?

2,701

Solution 1

First, multi_image_picker is deprecated. Use multi_image_picker2.

There are 2 ways of doing this as of October 2021.

First Way

Use flutter_image_compress library as following. Here I am using Uint8List but you can use File as well.

Future<Uint8List> compressUintImage(Uint8List list) async {
    var result = await FlutterImageCompress.compressWithList(
      list,
      minHeight: 1920,
      minWidth: 1080,
      quality: 96,
    );
    print(list.length);
    print(result.length);
    return result;
  }

Second Way

ByteData byteData = await file.getByteData(quality: 100);

This is by using the multi_image_picker2 itself. Here the file is an Asset.

Solution 2

You can do something as below:

  _getImageList() async {
    var resultList = await MultiImagePicker.pickImages(
      maxImages: 6,
      enableCamera: true,
    );

    // The data selected here comes back in the list
    for (var imageFile in resultList) {
      await postImage(imageFile).then((downloadUrl) {
        // Get the download URL and do your stuff here
      }).catchError((err) {
        print(err);
      });
    }
  }

And in postImage function, you can resize each image and change its quality.

Future<dynamic> postImage(Asset imageFile) async {
    double imageDesiredWidth = 500;

    double getAspectRatio(double originalSize, double desiredSize) => desiredSize / originalSize;
    final aspectRatio = getAspectRatio(imageFile.originalWidth.toDouble(), imageDesiredWidth);
    ByteData byteData = await imageFile.getThumbByteData(
        (imageFile.originalWidth * aspectRatio).round(),
        (imageFile.originalHeight * aspectRatio).round(),
        quality: 85
    );

    String fileName = DateTime
        .now()
        .millisecondsSinceEpoch
        .toString();
    StorageReference reference = _storage.ref().child(fileName);
    StorageUploadTask uploadTask =
    reference.putData(byteData.buffer.asUint8List());
    StorageTaskSnapshot storageTaskSnapshot = await uploadTask.onComplete;
    return await storageTaskSnapshot.ref.getDownloadURL();
  }
Share:
2,701
PeakGen
Author by

PeakGen

CTO

Updated on December 25, 2022

Comments

  • PeakGen
    PeakGen over 1 year

    I am using Flutter package to multi select images. Below is my code

    List<Asset>localAssetList = [];//new
    
    localAssetList = await MultiImagePicker.pickImages(
            maxImages: 5,
            enableCamera: true,
            
           selectedAssets: localAssetList,
            cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
            materialOptions: MaterialOptions(
              actionBarColor: "#abcdef",
              actionBarTitle: "Example App",
              allViewTitle: "All Photos",
              useDetailsView: false,
              selectCircleStrokeColor: "#000000",
            ),
          );
    

    I want to reduce the image quality by 60% in every image, then get the results as List<File>. How can I do this?

    • Ali Naderi
      Ali Naderi about 3 years
      You can do it as explained in this page. It worked for me.
  • PeakGen
    PeakGen over 3 years
    Than you. But in the document it says if the file is PNG, it will ignore quality parameters in iOS?
  • J Curti
    J Curti over 3 years
    Of course, since HEIC should already work on iOS, it's a format created by Apple
  • PeakGen
    PeakGen over 3 years
    Okay. So that means PNG will get compressed in iOS? Also what's the default photo format in iOS when we take a photo please?
  • PeakGen
    PeakGen over 3 years
    I tried your code. That gives the error RangeError: Value not in range: -1