【问题标题】:Do image files of type XFile have less quality than images of type File in Flutter?Flutter 中 XFile 类型的图像文件质量是否低于 File 类型的图像?
【发布时间】:2021-06-09 14:34:38
【问题描述】:

我在 Flutter 中使用 Camera plugin,默认情况下,当它捕获图像时,它会以 XFile 格式返回它。我注意到拍摄前在相机预览屏幕内的图像质量非常好,它与我手机上的原生相机应用程序具有相同的质量。但是当我捕获图像并尝试将图像文件发送到另一个屏幕并在Image.file() 小部件中显示时,质量下降并且变得非常颗粒状。我试图找出这是否与 XFile 格式或相机插件本身有关。

我尝试在拍摄前添加延迟,并尝试使用两种不同的设备,但这并不能解决照片颗粒感问题。 下面你会找到一些屏幕截图来更好地演示问题,以及我用来在屏幕上捕获、保存和显示图像的代码。

附:我已经尝试对 XFile 进行更多研究,但除了文档之外,网络上没有太多内容,而且它没有提供很多有用的信息,因此非常感谢任何帮助。

截图:

在相机预览中(实时相机,质量很好):

在 PreviewScreen 中(捕捉后,您可以看到质量有点颗粒感):

在 PhotoTakenScreen 中(颗粒感很强,质量很差):

代码

在 CameraScreen 内部(按下拍摄按钮时):

onPressed: () async{
var path;

if (cameraController!.value.isInitialized) {
      await cameraController!.takePicture().then((XFile file) {
        if (mounted) {
          path = file.path;
          print(path);
        }

Future.delayed(const Duration(milliseconds: 500), () {
                Navigator.pushNamed(
                  context,
                  cameraPreviewRoute,
                  arguments: PreviewScreen(
                    imageFile: File(file.path),
                  ),
                );
              });
       }

在预览屏幕中:

....
Scaffold(
body: body: Container(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(
            flex: 2,
            child: Image.file(
              File(widget.imageFile.path),
              fit: BoxFit.cover,
            ),
          ),
        ],
      ),
    ),
  )

PreviewScreen 小部件中有一个按钮可以转到 PhotoTakenScreen,它的作用是:

onPressed: () async {
        try {
          //adding a toast here because saving _loadImage takes a few seconds before moving to the next screen
          showToast("Please wait while image is being processed..", false,
              info: true);

          File savedImage;
          await _loadImage(widget.imageFile.path).then((value) {
            savedImage = value!; 
            // for debugging
            print(savedImage.path);

            //send the image object over to phototaken
            Navigator.pushNamed(
              context,
              photoTakenScreen,
              arguments: PhotoTakenScreen(
                imagePath: savedImage.path,
              ),
            );
           }

loadImage() 是一个调用saveImageToDisk() 的函数,它将图像在单独的线程中保存到磁盘并返回保存的文件。他们在这里:

Future<File?> _loadImage(String imagePath) async {
try {
  File mFile;
  Directory directory = await getTemporaryDirectory();
  Map map = Map();
  map['path'] = imagePath;
  map['directory'] = directory;
  // run _saveImageToDisk in a separate thread
  mFile = await compute(saveImageToDisk, map);
  return mFile;
} catch (err) {
  rethrow;
 }
}

Future<File> saveImageToDisk(Map pathAndDirectory) async {
  try {
    String path = pathAndDirectory['path'];
    Directory directory = pathAndDirectory['directory'];
    File tempFile = File(path);
    Img.Image? image = Img.decodeImage(tempFile.readAsBytesSync());
    if (image == null) throw ('Error: Could not decode image');
    Img.Image mImage = Img.copyResizeCropSquare(image, 224);
    String imgType = path.split('.').last;
    String mPath =
        '${directory.path.toString()}/image_${DateTime.now()}.$imgType';
    mPath = mPath.replaceAll(
        new RegExp(r"\s+\b|\b\s"), ""); //remove all spaces from img path
    File dFile = File(mPath);
    if (imgType == 'jpg' || imgType == 'jpeg') {
      dFile.writeAsBytesSync(Img.encodeJpg(mImage));
    } else {
      dFile.writeAsBytesSync(Img.encodePng(mImage));
    }
    return dFile;
  } catch (e) {
    rethrow; //rethrow to alert _loadImage in PreviewScreen()
  }
}

【问题讨论】:

    标签: flutter file plugins camera


    【解决方案1】:

    也许检查 CameraController 构造函数的第二个参数“ResolutionPreset”。也许更改为 ResolutionPreset.max

    【讨论】:

      猜你喜欢
      • 2012-11-25
      • 2015-11-23
      • 2022-11-23
      • 2020-06-28
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 2020-10-18
      • 1970-01-01
      相关资源
      最近更新 更多