Ответ 1
Плагин image_picker в настоящее время очень прост. Было бы просто добавить опцию для указания желаемого размера/качества выбранного изображения. Если вы сделаете это, пожалуйста, отправьте нам запрос!
Я хочу отправить фотографию, выбранную пользователем в моем приложении, в Firebase Storage. У меня есть простой класс с свойством _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 для сжатия и изменения размера фотографии перед загрузкой? Я в порядке с потерей качества.
Плагин image_picker в настоящее время очень прост. Было бы просто добавить опцию для указания желаемого размера/качества выбранного изображения. Если вы сделаете это, пожалуйста, отправьте нам запрос!
Я столкнулся с этим и смог выполнить сжатие/изменение размера с помощью пакета изображений Dart вместе с поставщиком путей. Вы можете посмотреть анимированные изображения и примеры для других способов и помощи.
Вот что я сделал:
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 с использованием свойства качества, в моем случае я выбрал 85 (из 100).
Надеюсь это поможет! Дайте знать, если у вас появятся вопросы.
Следующий код - это то, что я использую, чтобы снять изображение с камеры, а затем сжать его:
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);
}
Вы можете назвать это очень легко с этим:
import 'path/to/compress_image.dart' as CompressImage;
// ...
File file = await CompressImage.takeCompressedPicture(context);
Помимо упоминания этой нативной библиотеки: https://pub.dartlang.org/packages/flutter_image_compress
Это полностью основанный на дротике компрессор с изоляторами, который может сделать сжатие параллельным потоку пользовательского интерфейса в многоядерных процессорах.
Возможно, вы захотите использовать функцию вычисления, которая упрощает использование изолятов: https://docs.flutter.io/flutter/foundation/compute.html https://flutter.io/cookbook/networking/background-parsing/
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);
}
Используйте плагин image_picker и вызовите функцию изображения как
Future<File> imageFile = ImagePicker.pickImage(source: ImageSource.gallery, maxHeight: 200, maxWidth: 200 );
измените maxHeight и maxWidth на любой размер изображения, который вам нужен.
Пока я использую
пакет: изображение /image.dart
столкнувшись с нижеуказанными вопросами
Затем использовал плагин ниже, тоже работает нормально, без проблем, даже быстрее и что я ожидал
https://github.com/btastic/flutter_native_image.git
шаги и метод доступны по ссылке выше.