【发布时间】: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