Flutter & Firebase: сжатие перед загрузкой изображения

Я хочу отправить фотографию, выбранную пользователем в моем приложении, в хранилище Firebase. У меня есть простой класс с собственность _imageFile который установлен следующим образом:

File _imageFile;

_getImage() async {
    var fileName = await ImagePicker.pickImage();
    setState(() {
        _imageFile = fileName;
    });
}

после этого я отправляю фото, как с этим кодом:

final String rand1 = "${new Random().nextInt(10000)}";
final String rand2 = "${new Random().nextInt(10000)}";
final String rand3 = "${new Random().nextInt(10000)}";
final StorageReference ref = FirebaseStorage.instance.ref().child('${rand1}_${rand2}_${rand3}.jpg');
final StorageUploadTask uploadTask = ref.put(_imageFile);
final Uri downloadUrl = (await uploadTask.future).downloadUrl;
print(downloadUrl);

проблема в том, что фотографии часто очень большие. Есть ли какой-либо метод в Flutter/Dart для сжатия и изменения размера фотографии перед загрузкой? Я в порядке с потерей качества.

3 ответов


на image_picker плагин в настоящее время очень прост. Было бы просто добавить опцию для указания желаемого размера/качества выбранного изображения. Если вы сделаете это, пожалуйста, пришлите нам запрос pull!


я столкнулся с этим и смог выполнить сжатие / изменение размера с помощью Dart пакет вместе с Provider путь. Вы можете посмотреть на dart api изображения и примеры дополнительные возможности и больше поможет.

вот что я сделал:

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));
}

затем я загрузил compressedImage в хранилище firebase. Вы можете настроить качество сохранения jpg с помощью свойства quality, в моем случае я выбрал 85 (из 100).

надеюсь, что это помогает! Дайте мне знать, если у вас возникнут вопросы.


следующий код-это то, что я использую для съемки изображения с помощью камеры, а затем сжимаю его:

import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
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';

class CompressImage{
  Future <File> takePicture(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();
    int rand = new Math.Random().nextInt(10000);
    CompressObject compressObject = new CompressObject(_imageFile, tempDir.path,     rand);
    String filePath = await _compressImage(compressObject);
    print('new path: ' + filePath);
    File file = new File(filePath);
    //pop loading
    return file;
  }

  Future<String> _compressImage(CompressObject object) async {
    return compute(decodeImage, object);
  }

  static 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 = new 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);
}

Вы можете назвать это очень легко с помощью этого:

File file = await compressImage.takePicture(context);