アプリでユーザーが選択した写真を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 プラグインは現在非常にシンプルです。選択した画像の目的のサイズ/品質を指定するオプションを追加するのは簡単です。これを行う場合は、プルリクエストを送信してください。
image_picker プラグインはimageQuality
パラメータをサポートするようになりました。次のようなことができます
File compressedImage = await ImagePicker.pickImage(source: ImageSource.camera, imageQuality: 85);
私はこれに遭遇し、Dart image package と path provider で圧縮/サイズ変更を達成することができました。他の方法やその他のヘルプについては、Dart image api および examples をご覧ください。
私がやったことは次のとおりです。
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のうち)を選択しました。
お役に立てれば!ご質問がある場合はお知らせください。
image_picker プラグインを使用して、画像の選択関数を次のように呼び出します。
Future<File> imageFile = ImagePicker.pickImage(source: ImageSource.gallery , maxHeight: 200 , maxWidth: 200 );
maxHeightとmaxWidthを必要な画像のサイズに変更します。
次のコードは、カメラで画像を撮影して圧縮するために使用するものです。
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);
このnativeライブラリに言及する以外に: https://pub.dartlang.org/packages/flutter_image_compress
これは完全にDartベースのisolatesを備えたコンプレッサーであり、マルチコアCPUのUIスレッドに圧縮を並行させる可能性があります。
分離の使用をより簡単にする計算関数を使用することもできます。 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);
}
私が使用している間
パッケージ:image/image.Dart
以下の問題に直面している
次に、以下のプラグインを使用し、同じ問題なく問題なく動作し、さらに速く、私が期待したもの
https://github.com/btastic/flutter_native_image.git
上記のリンクで利用可能な手順と方法。