| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- import 'dart:io';
- import 'dart:typed_data';
- import 'dart:ui' as ui;
- import 'package:flutter/material.dart';
- import 'package:image_picker/image_picker.dart';
- import 'package:intl/intl.dart';
- import 'package:path_provider/path_provider.dart';
- import 'package:chicken_farm/core/utils/logger.dart';
- class WatermarkedCamera extends StatefulWidget {
- final Function(File)? onImageCaptured;
- final String? watermarkText;
- const WatermarkedCamera({
- super.key,
- this.onImageCaptured,
- this.watermarkText,
- });
- @override
- State<WatermarkedCamera> createState() => _WatermarkedCameraState();
- }
- class _WatermarkedCameraState extends State<WatermarkedCamera> {
- XFile? _capturedImage;
- File? _watermarkedImage;
- bool _isProcessing = false;
- Future<void> _takePicture() async {
- try {
- final ImagePicker picker = ImagePicker();
- final XFile? photo = await picker.pickImage(
- source: ImageSource.camera,
- imageQuality: 80,
- );
- if (photo != null) {
- setState(() {
- _capturedImage = photo;
- _isProcessing = true;
- });
- // 添加水印并处理图像
- await _addWatermark(photo);
- }
- } catch (e) {
- if (mounted) {
- ScaffoldMessenger.of(
- context,
- ).showSnackBar(SnackBar(content: Text('拍照失败: $e')));
- }
- logger.e('拍照失败: $e');
- }
- }
- Future<void> _addWatermark(XFile imageFile) async {
- try {
- // 获取水印文本
- String watermark =
- widget.watermarkText ??
- DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
- // 将图片转换为字节以便处理
- final Uint8List imageBytes = await imageFile.readAsBytes();
- // 创建图片对象
- final ui.Codec codec = await ui.instantiateImageCodec(imageBytes);
- final ui.FrameInfo frameInfo = await codec.getNextFrame();
- final ui.Image image = frameInfo.image;
- // 创建画布
- final ui.PictureRecorder recorder = ui.PictureRecorder();
- final ui.Canvas canvas = ui.Canvas(recorder);
- // 绘制原始图片
- canvas.drawImage(image, Offset.zero, ui.Paint());
- // 添加水印文字
- final ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(
- ui.ParagraphStyle(
- textAlign: TextAlign.left,
- fontSize: 24.0,
- textDirection: ui.TextDirection.ltr,
- ),
- );
- paragraphBuilder.pushStyle(
- ui.TextStyle(
- color: const ui.Color(0x80FFFFFF), // 半透明白色
- fontSize: 24.0,
- ),
- );
- paragraphBuilder.addText(watermark);
- final ui.Paragraph paragraph = paragraphBuilder.build()
- ..layout(ui.ParagraphConstraints(width: image.width.toDouble()));
- // 在右下角绘制水印
- canvas.drawParagraph(
- paragraph,
- Offset(
- image.width.toDouble() - paragraph.width - 20,
- image.height.toDouble() - 40,
- ),
- );
- // 完成绘制
- final ui.Picture picture = recorder.endRecording();
- final ui.Image watermarkedImage = await picture.toImage(
- image.width,
- image.height,
- );
- // 转换为字节数据
- final ByteData? byteData = await watermarkedImage.toByteData(
- format: ui.ImageByteFormat.png,
- );
- if (byteData != null) {
- // 保存到临时文件
- final tempDir = await getTemporaryDirectory();
- final file = File(
- '${tempDir.path}/watermarked_${DateTime.now().millisecondsSinceEpoch}.png',
- );
- await file.writeAsBytes(byteData.buffer.asUint8List());
- setState(() {
- _watermarkedImage = file;
- _isProcessing = false;
- });
- } else {
- setState(() {
- _isProcessing = false;
- });
- if (mounted) {
- ScaffoldMessenger.of(
- context,
- ).showSnackBar(const SnackBar(content: Text('处理图片失败')));
- }
- logger.e('处理图片失败');
- }
- } catch (e) {
- setState(() {
- _isProcessing = false;
- });
- if (mounted) {
- ScaffoldMessenger.of(
- context,
- ).showSnackBar(SnackBar(content: Text('添加水印失败: $e')));
- }
- logger.e('添加水印失败: $e');
- }
- }
- void _confirmImage() {
- if (_watermarkedImage != null && widget.onImageCaptured != null) {
- widget.onImageCaptured!(_watermarkedImage!);
- }
- Navigator.of(context).pop();
- }
- void _retakePicture() {
- setState(() {
- _capturedImage = null;
- _watermarkedImage = null;
- });
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: const Text('拍照签到'),
- leading: IconButton(
- icon: const Icon(Icons.close),
- onPressed: () => Navigator.of(context).pop(),
- ),
- ),
- body: Column(
- children: [
- Expanded(
- child: _capturedImage == null
- ? Center(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const Icon(
- Icons.camera_alt,
- size: 100,
- color: Colors.grey,
- ),
- const SizedBox(height: 20),
- const Text('点击按钮拍照', style: TextStyle(fontSize: 18)),
- ],
- ),
- )
- : _isProcessing
- ? const Center(child: CircularProgressIndicator())
- : Center(
- child: _watermarkedImage != null
- ? Image.file(_watermarkedImage!)
- : Image.file(File(_capturedImage!.path)),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(16.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- if (_capturedImage == null)
- FloatingActionButton(
- onPressed: _takePicture,
- child: const Icon(Icons.camera),
- )
- else if (!_isProcessing)
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- ElevatedButton(
- onPressed: _retakePicture,
- style: ElevatedButton.styleFrom(
- backgroundColor: Colors.grey,
- foregroundColor: Colors.white,
- ),
- child: const Text('重新拍照'),
- ),
- ElevatedButton(
- onPressed: _confirmImage,
- style: ElevatedButton.styleFrom(
- backgroundColor: Colors.green,
- foregroundColor: Colors.white,
- ),
- child: const Text('确认提交'),
- ),
- ],
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
- }
|