How to Compress Image Before Uploading to Firebase and Flutter?

· 5 min read
Compress Image Before Uploading to Firebase
Compress Image Before Uploading to Firebase

Earlier we have been through Step By Step Guide to How to Integrate Firebase in Flutter Mobile Application Where users will follow certain steps. Sometimes the user needs to store images into Firebase and It may also happen that it has a large amount of data so in this article we will go through How to Compress Image Before Uploading to Firebase and Flutter?

How to Compress Image Before Uploading to Firebase and Flutter?

In this case, we have considered that the user has made use of the image_picker plugin for the same. The image_picker plugin now supports an imageQuality parameter. Code Snippet will look like below:

ImagePicker imagePicker = ImagePicker();
PickedFile compressedImage = await imagePicker.getImage(
  source: ImageSource.camera,
  imageQuality: 85,
);

Compress an image without using the ImagePicker plugin

import 'package:image/image.dart' as Im;
import 'package:path_provider/path_provider.dart';
import 'dart:math' as Math;

void compressImage() async {
  File imageFile = await ImagePicker.pickImage();
  final tempDir = await getTemporaryDirectory();
  final path = tempDir.path;
  int rand = new Math.Random().nextInt(10000);

  Im.Image image = Im.decodeImage(imageFile.readAsBytesSync());
  Im.Image smallerImage = Im.copyResize(image, 500); // choose the size here, it will maintain aspect ratio
  
  var compressedImage = new File('$path/img_$rand.jpg')..writeAsBytesSync(Im.encodeJpg(image, quality: 85));
}

Users can also set maxHeight,maxWidth. Consider a code snippet like the below:

Future<File> imageFile = ImagePicker.pickImage(source: ImageSource.gallery  , maxHeight:  200 , maxWidth: 200 );

This is a fully dart based compressor with isolates, which might make the compression parallel to UI thread in multi-core CPUs. Consider a code snippet like the below:

import 'package:image/image.dart' as ImageLib;
import 'package:path_provider/path_provider.dart';

Future<void> getCompressedImage(SendPort sendPort) async {
  ReceivePort receivePort = ReceivePort();

  sendPort.send(receivePort.sendPort);
  List msg = (await receivePort.first) as List;

  String srcPath = msg[0];
  String name = msg[1];
  String destDirPath = msg[2];
  SendPort replyPort = msg[3];

  ImageLib.Image image =
      ImageLib.decodeImage(await new File(srcPath).readAsBytes());

  if (image.width > 500 || image.height > 500) {
    image = ImageLib.copyResize(image, 500);
  }

  File destFile = new File(destDirPath + '/' + name);
  await destFile.writeAsBytes(ImageLib.encodeJpg(image, quality: 60));

  replyPort.send(destFile.path);
}

Future<File> compressImage(File f) async {
  ReceivePort receivePort = ReceivePort();

  await Isolate.spawn(getCompressedImage, receivePort.sendPort);
  SendPort sendPort = await receivePort.first;

  ReceivePort receivePort2 = ReceivePort();

  sendPort.send([
    f.path,
    f.uri.pathSegments.last,
    (await getTemporaryDirectory()).path,
    receivePort2.sendPort,
  ]);

  var msg = await receivePort2.first;

  return new File(msg);
}
if (false ==
    await SimplePermissions.checkPermission(
        Permission.ReadExternalStorage)) {
  await SimplePermissions.requestPermission(
    Permission.ReadExternalStorage);
}

File img = await ImagePicker.pickImage(
    source: ImageSource.gallery);
if (null != img) {
  img = await compressImage(img);
}

Consider a custom function like the below:

import 'dart:async' show Future;
import 'dart:io' show File;
import 'package:flutter/foundation.dart' show compute;
import 'package:flutter/material.dart' show BuildContext;
import 'package:image/image.dart' as Im;
import 'dart:math' as Math;
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart' show getTemporaryDirectory;

Future<File> takeCompressedPicture(BuildContext context) async {
  var _imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
  if (_imageFile == null) {
    return null;
  }

  // You can have a loading dialog here but don't forget to pop before return file;

  final tempDir = await getTemporaryDirectory();
  final rand = Math.Random().nextInt(10000);
  _CompressObject compressObject =
      _CompressObject(_imageFile, tempDir.path, rand);
  String filePath = await _compressImage(compressObject);
  print('new path: ' + filePath);
  File file = File(filePath);

  // Pop loading

  return file;
}

Future<String> _compressImage(_CompressObject object) async {
  return compute(_decodeImage, object);
}

String _decodeImage(_CompressObject object) {
  Im.Image image = Im.decodeImage(object.imageFile.readAsBytesSync());
  Im.Image smallerImage = Im.copyResize(
      image, 1024); // choose the size here, it will maintain aspect ratio
  var decodedImageFile = File(object.path + '/img_${object.rand}.jpg');
  decodedImageFile.writeAsBytesSync(Im.encodeJpg(smallerImage, quality: 85));
  return decodedImageFile.path;
}

class _CompressObject {
  File imageFile;
  String path;
  int rand;

  _CompressObject(this.imageFile, this.path, this.rand);
}

You can call this very easy with this:

import 'path/to/compress_image.dart' as CompressImage;
// ...
File file = await CompressImage.takeCompressedPicture(context);

Conclusion:

In this article, We have been through How to Compress Image Before Uploading to Firebase and Flutter?

Keep Learning !!! Keep Fluttering !!!

Still, need a Support for Flutter Development? Do let us know.

FlutterAgency.com is our portal Platform dedicated to Flutter Technology and Flutter Developers. The portal is full of cool resources from Flutter like Flutter Widget GuideFlutter ProjectsCode libs and etc.

FlutterAgency.com is one of the most popular online portal dedicated to Flutter Technology and daily thousands of unique visitors come to this portal to enhance their knowledge on Flutter.

Leave a Reply