我想将用户在我的应用中选择的照片发送到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中是否有任何压缩和调整照片大小的方法?我对质量的损失感到满意。
答案 0 :(得分:17)
我遇到了这个并且能够使用Dart caches class definitions和image package完成压缩/调整大小。您可以查看dart path provider和image 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存储。您可以使用quality属性调整jpg保存的质量,在我的情况下,我选择85(满分100)。
希望这有帮助!如果您有任何问题,请告诉我。
答案 1 :(得分:5)
image_picker插件目前非常简单。可以直接添加用于指定所选图像的所需大小/质量的选项。如果您这样做,请向我们发送拉取请求!
答案 2 :(得分:1)
下面的代码是我用相机拍摄然后压缩的代码:
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);
答案 3 :(得分:1)
除了提及此本地库: https://pub.dartlang.org/packages/flutter_image_compress
这是一个完全基于 dart的带有隔离器的压缩器,它可能使压缩与多核CPU中的UI线程并行。
您可能想使用计算功能,该功能使使用隔离更简单: 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);
}
答案 4 :(得分:1)
使用image_picker插件并将调用图片功能用作
Future<File> imageFile = ImagePicker.pickImage(source: ImageSource.gallery , maxHeight: 200 , maxWidth: 200 );
将maxHeight和maxWidth更改为所需的图像大小。
答案 5 :(得分:1)
有很多解决方案:
您可以使用 ImagePicker 的内置 imageQuality
属性来压缩图像。此属性采用介于 0
和 100
之间的值,表示原始图像质量的百分比。
首先,在 pubspec.yaml 文件中添加 image_picker
作为依赖项。
使用
File _image;
Future getImage() async {
var image = await ImagePicker.pickImage(
source: ImageSource.gallery,
imageQuality: 25,
);
setState(() {
_image = image;
});
}
<块引用>
这种方法的优点是它嵌入在 image_picker 包,因此非常易于使用。
使用 filterQuality
设置图像的 FilterQuality
。
示例:
Image.asset('assets/kab1.png', filterQuality: FilterQuality.high,),
这些属性存在于 AssetImage
、NetworkImage
、FileImage
和 MemoryImage
中。
您也可以简单地调整图像大小(调整图像大小可以压缩它)。为此,请尝试使用 ResizeImage 小部件
另一种解决方案是使用 flutter_image_compress 包
答案 6 :(得分:0)
我正在使用
package:image / image.dart
面对下面的问题
然后使用下面的插件,同样可以正常工作,没有任何问题,甚至更快,而且我期望的是
https://github.com/btastic/flutter_native_image.git
以上链接中提供的步骤和方法。
答案 7 :(得分:0)
您可以使用名为flutter_image_compress
的插件// Active image file
File _imageFile;
// Select an image via gallery or camera
Future<void> _pickImage(ImageSource source) async {
File selected = await ImagePicker.pickImage(source: source);
// Compress plugin
File compressedImage = await FlutterImageCompress.compressAndGetFile(
selected.path,
selected.path,
quality: 50,
);
setState(() {
_imageFile = compressedImage;
print('compressedimagesize: ${_imageFile.lengthSync()}');
});
}
Voila!压缩文件图像
答案 8 :(得分:0)
由于您使用的是Firebase,因此一种选择是使用“扩展程序-调整图像大小”。它为您提供了保留或删除原始图像的选项,安装和使用非常简单。
答案 9 :(得分:0)
不建议使用2020更新'pickImage'。请改用imagePicker.getImage()方法 **
ImagePicker picker = ImagePicker();
PickedFile compressedImage = await imagePicker.getImage(
source: ImageSource.camera,
imageQuality: 80,
);
ImageQuality文档:
返回一个包装了所拾取图像的PickedFile对象。的 返回的PickedFile旨在在单个APP中使用 会议。不要保存文件路径并在会话之间使用它。的 源参数控制图像的来源。这可以是 ImageSource.camera或ImageSource.gallery。 iOS支持的地方 HEIC图片,Android 8及更低版本没有。仅适用于Android 9及更高版本 支持HEIC图像(如果除尺寸修改外使用) 用法说明如下。如果指定,图像将位于 最大maxWidth宽和maxHeight高。否则图像将是 返回其原始宽度和高度。 imageQuality参数 修改图像的质量,范围是0-100,其中100是 原始/最高质量。如果imageQuality为null,则带有 原始质量将被退回。仅支持压缩 某些图像类型(例如JPEG)以及Android PNG和WebP上的图像。如果 所选择的图像不支持压缩,警告 消息将被记录。使用preferredCameraDevice指定 源为ImageSource.camera时要使用的相机。的 当源为ImageSource.gallery时,preferredCameraDevice被忽略。 如果摄像机不支持所选摄像机,也会被忽略。 设备。默认为CameraDevice.rear。请注意,Android没有 文档化的参数,用于指定前面还是后面 应该打开相机,不能保证此功能在 Android设备。在Android中,MainActivity可以销毁 很多原因。如果发生这种情况,结果将在此丢失 呼叫。然后,当您的应用重新启动到时,您可以调用getLostData 检索丢失的数据。
答案 10 :(得分:0)
您可以按照以下操作,
//Compressing Image
File compressedImg = await FlutterNativeImage.compressImage(
_image.path,
quality: 70,
);
//Compressing Image
答案 11 :(得分:0)
嗯
<强>1.如果您使用的是移动设备,您可以使用flutter_image_compress: ^1.0.0
来完成这项工作
例如。 通过 Uint8List 和质量,您将立即获得压缩图像。
Future<Uint8List> testComporessList(Uint8List uint8List) async {
var result = await FlutterImageCompress.compressWithList(
uint8List,
quality: 50,
);
return result;
}
2.但是,如果您使用的是 flutter web,那么除了图像选择器等之外,您将无法获得任何其他选项。
我最终使用了 javascript。你可以在这里找到答案。
Flutter Web: How Do You Compress an Image/File?