web-dev-qa-db-de.com

Flutter & Firebase: Komprimierung vor dem Hochladen des Bildes

Ich möchte ein vom Benutzer in meiner App ausgewähltes Foto an Firebase Storage senden. Ich habe eine einfache Klasse mit der Eigenschaft _imageFile, die wie folgt festgelegt ist:

File _imageFile;

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

danach sende ich gerne ein Foto mit diesem Code:

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

Das Problem ist, dass die Fotos oft sehr groß sind. Gibt es in Flutter/Dart eine Methode zum Komprimieren und Ändern der Größe von Fotos vor dem Hochladen? Ich bin mit Qualitätsverlust ok.

9

Das image_picker plugin ist derzeit sehr einfach. Es wäre einfach, eine Option zum Angeben der gewünschten Größe/Qualität des aufgenommenen Bildes hinzuzufügen. Wenn Sie dies tun, senden Sie uns bitte eine Pull-Anfrage!

5
Collin Jackson

Ich bin darauf gestoßen und konnte die Komprimierung/Größenänderung mit dem Dart Image - Paket zusammen mit Path Provider durchführen. Unter Dart image api und Beispielen können Sie nach anderen Wegen und mehr Hilfe suchen.

Folgendes habe ich getan: 

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

Dann habe ich compressedImage in den Firebase-Speicher hochgeladen. Sie können die Qualität, mit der das JPG gespeichert wird, mithilfe der Eigenschaft Qualität anpassen. In meinem Fall wählte ich 85 (von 100). 

Hoffe das hilft! Lassen Sie mich wissen, wenn Sie Fragen haben.

13
Mans

Verwenden Sie image_picker Plugin und rufen Sie pick image function as auf

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

ändern Sie maxHeight und maxWidth auf die gewünschte Bildgröße.

2
charan ghumman

Mit dem folgenden Code verwende ich ein Bild mit der Kamera und komprimiere es anschließend:

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

Das kann man sehr einfach nennen:

import 'path/to/compress_image.Dart' as CompressImage;
// ...
File file = await CompressImage.takeCompressedPicture(context);
1
Robert Brunhage

Neben der Erwähnung dieser native - Bibliothek: https://pub.dartlang.org/packages/flutter_image_compress

Hierbei handelt es sich um einen vollständig auf Dart basierenden Kompressor mit Isolaten, der die Komprimierung in Multi-Core-CPUs möglicherweise parallel zum UI-Thread führt.

Möglicherweise möchten Sie eine Berechnungsfunktion verwenden, die die Verwendung von Isolaten vereinfacht: https://docs.flutter.io/flutter/foundation/compute.htmlhttps://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);
}
0
zero.zero.seven

Während ich benutze

verpackung: image/image.Dart

unter Fragen konfrontiert

  • anzeige einer leeren Seite beim Konvertieren des Bilds (möglicherweise nimmt das Komprimieren des Bilds so viel Zeit in Anspruch)
  • Nach der Komprimierung wurde das Bild gestreckt und sieht nicht gut aus

Dann verwendet unter Plugin, das gleiche funktioniert ohne Probleme, noch schneller und was ich erwartet hatte

https://github.com/btastic/flutter_native_image.git

schritte und Methode im obigen Link.

0
Anand saga