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