Flutter图片元数据获取插件native_exif的使用
Flutter图片元数据获取插件native_exif的使用
native_exif
是一个简单的EXIF元数据读取/写入插件,适用于Flutter应用。它利用了iOS和Android平台的原生功能来处理图像的EXIF数据。
使用方法
创建EXIF读取实例
首先需要通过指定图像路径来创建一个EXIF读取实例:
final exif = await Exif.fromPath(pickedFile!.path);
读取属性
可以通过预定义函数或获取所有属性来读取图像的EXIF信息:
final originalDate = await exif.getOriginalDate();
final latLong = await exif.getLatLong();
final attribute = await exif.getAttribute("key");
final attributes = await exif.getAttributes();
写入属性
可以将特定键的EXIF数据以字符串形式写入:
await exif.writeAttribute("key", "value");
await exif.writeAttributes({"key1": "value1", "key2": "value2"});
关闭EXIF接口
操作完成后应关闭EXIF接口:
await exif.close();
平台注意事项
该插件仅支持iOS和Android平台。
Android
- 使用
androidx ExifInterface
。 - 支持的EXIF和GPS属性有限,请参考相关代码文档。
- 目前只能正确写入ASCII字符。
GPSLatitude
和GPSLongitude
可以写入负值,但返回时为正值,需结合GPSLatitudeRef
和GPSLongitudeRef
或getLatLong()
来确定坐标。
iOS
- 支持的EXIF和GPS属性请参阅Apple官方文档。
- GPS字典键需要加上
GPS
前缀。 - 同样需要注意
GPSLatitude
和GPSLongitude
的正负值问题。
示例代码
以下是一个完整的示例应用程序,展示如何使用native_exif
插件:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:native_exif/native_exif.dart';
void main() {
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final picker = ImagePicker();
XFile? pickedFile;
Exif? exif;
Map<String, Object>? attributes;
DateTime? shootingDate;
ExifLatLong? coordinates;
Future<void> showError(Object e) async {
debugPrintStack(label: e.toString(), stackTrace: e is Error ? e.stackTrace : null);
return showDialog<void>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Error'),
content: SingleChildScrollView(
child: ListBody(
children: [Text(e.toString())],
),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
Future getImage() async {
pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile == null) {
return;
}
exif = await Exif.fromPath(pickedFile!.path);
attributes = await exif!.getAttributes();
shootingDate = await exif!.getOriginalDate();
coordinates = await exif!.getLatLong();
setState(() {});
}
Future closeImage() async {
await exif?.close();
shootingDate = null;
attributes = {};
exif = null;
coordinates = null;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Plugin example app')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (pickedFile == null)
const Text("Please open an image.")
else
Column(
children: [
Text("The selected image has ${attributes?.length ?? 0} attributes."),
Text("It was taken at ${shootingDate.toString()}"),
Text(attributes?["UserComment"]?.toString() ?? ''),
Text("Attributes: $attributes"),
Text("Coordinates: $coordinates"),
TextButton(
onPressed: () async {
try {
final dateFormat = DateFormat('yyyy:MM:dd HH:mm:ss');
await exif!.writeAttribute('DateTimeOriginal', dateFormat.format(DateTime.now()));
shootingDate = await exif!.getOriginalDate();
attributes = await exif!.getAttributes();
setState(() {});
} catch (e) {
showError(e);
}
},
child: const Text('Update date attribute'),
),
// 其他按钮...
ElevatedButton(
onPressed: closeImage,
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red)),
child: const Text('Close image'),
)
],
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: getImage,
child: const Text('Open image'),
),
if (pickedFile != null)
ElevatedButton(
onPressed: () async {
try {
final file = File(p.join(Directory.systemTemp.path, 'tempimage.jpg'));
final imageBytes = await pickedFile!.readAsBytes();
await file.create();
await file.writeAsBytes(imageBytes);
final _attributes = await exif?.getAttributes() ?? {};
final newExif = await Exif.fromPath(file.path);
_attributes['DateTimeOriginal'] = '2021:05:15 13:00:00';
_attributes['UserComment'] = "This file is user generated!";
await newExif.writeAttributes(_attributes);
shootingDate = await newExif.getOriginalDate();
attributes = await newExif.getAttributes();
coordinates = await newExif.getLatLong();
setState(() {});
} catch (e) {
showError(e);
}
},
child: const Text("Create file and write exif data"),
),
],
),
),
);
}
}
此示例展示了如何从相册中选择一张图片,读取并修改其EXIF数据,并在界面上显示相关信息。希望这些信息能帮助您更好地理解和使用native_exif
插件。
更多关于Flutter图片元数据获取插件native_exif的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片元数据获取插件native_exif的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用native_exif
插件来获取图片元数据的示例代码。这个插件允许你从图像文件中读取EXIF(Exchangeable Image File Format)数据。
首先,确保你的Flutter项目已经配置好了native_exif
插件。你可以通过以下步骤来添加这个插件:
- 在你的
pubspec.yaml
文件中添加依赖:
dependencies:
flutter:
sdk: flutter
native_exif: ^2.0.0 # 请检查最新版本号
- 运行
flutter pub get
来安装依赖。
接下来,下面是一个简单的示例代码,展示了如何使用native_exif
插件来获取图片元数据:
import 'package:flutter/material.dart';
import 'package:native_exif/native_exif.dart';
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter EXIF Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File? _imageFile;
Map<String, dynamic>? _exifData;
Future<void> _pickImage() async {
final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_imageFile = File(pickedFile.path);
});
// 获取EXIF数据
_exifData = await NativeExif.readExifFromBytes(await _imageFile!.readAsBytes());
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter EXIF Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _pickImage,
child: Text('Pick Image'),
),
if (_imageFile != null)
Image.file(_imageFile!),
if (_exifData != null)
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: _exifData!.entries.map((entry) {
return Text(
'${entry.key}: ${entry.value}',
style: TextStyle(fontSize: 16),
);
}).toList(),
),
),
),
),
],
),
),
);
}
}
在这个示例中,我们使用了image_picker
插件来选择图片,然后通过native_exif
插件读取图片的EXIF数据。请确保你也添加了image_picker
插件的依赖:
dependencies:
flutter:
sdk: flutter
native_exif: ^2.0.0 # 请检查最新版本号
image_picker: ^0.8.4+4 # 请检查最新版本号
并且运行flutter pub get
来安装它。
这个示例代码展示了如何从图片中选择文件,读取其EXIF数据,并在UI中显示这些数据。注意,EXIF数据可能包含很多字段,这里只是简单地遍历并显示所有字段及其值。你可以根据需要处理特定的EXIF字段。