WPF实现签名拍照功能

在这里插入图片描述

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:WPF 案例及知识分享专栏
✨特色专栏:乐趣国学-心性养成之路
🥭本文内容:WPF实现签名拍照功能
  当你使用WPF(Windows Presentation Foundation)技术编写一个签名拍照软件时,需要使用C#来处理界面和相机操作。以下是一个简单示例,展示如何创建一个WPF应用程序来实现这一功能。

在这里插入图片描述

  首先,确保你已经安装了Visual Studio和.NET框架。然后,创建一个新的WPF应用程序项目,我们将称之为"SignatureCaptureApp"。

  在MainWindow.xaml中,创建界面布局,包括一个显示相机预览的区域、一个签名区域、一个按钮来拍照并保存签名。

<Window x:Class="SignatureCaptureApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Signature Capture App" Height="400" Width="600"><Grid><Image Name="CameraPreview" Width="400" Height="300" Stretch="UniformToFill" Margin="10"/><InkCanvas Name="SignatureCanvas" Width="400" Height="100" Margin="10"/><Button Content="拍照并保存签名" Click="CaptureSignature_Click" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,10"/></Grid>
</Window>

  在MainWindow.xaml.cs中,添加相机和签名捕捉的逻辑。

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Media.Imaging;
using System.Windows.Media.Imaging;namespace SignatureCaptureApp
{public partial class MainWindow : Window{private CameraCapture _cameraCapture;public MainWindow(){InitializeComponent();_cameraCapture = new CameraCapture(CameraPreview);_cameraCapture.InitializeCamera();}private void CaptureSignature_Click(object sender, RoutedEventArgs e){// 拍照BitmapSource photo = _cameraCapture.CapturePhoto();// 保存签名if (SignatureCanvas.Strokes.Count > 0 && photo != null){SaveSignatureAndPhoto(SignatureCanvas.Strokes, photo);}}private void SaveSignatureAndPhoto(StrokeCollection strokes, BitmapSource photo){try{// 为签名创建一个独一无二的文件名string signatureFileName = $"Signature_{DateTime.Now:yyyyMMddHHmmss}.png";string photoFileName = $"Photo_{DateTime.Now:yyyyMMddHHmmss}.jpg";// 获取保存签名和照片的文件夹路径string saveFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);// 创建签名图片文件SaveSignatureToFile(strokes, Path.Combine(saveFolderPath, signatureFileName));// 创建照片文件SavePhotoToFile(photo, Path.Combine(saveFolderPath, photoFileName));}catch (Exception ex){// 处理错误,例如显示错误消息框MessageBox.Show($"保存签名和照片时发生错误:{ex.Message}");}}private void SaveSignatureToFile(StrokeCollection strokes, string filePath){// 创建一个RenderTargetBitmap用于绘制签名RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(400, 100, 96, 96, PixelFormats.Default);renderTargetBitmap.Render(SignatureCanvas);// 创建一个PngBitmapEncoder保存签名PngBitmapEncoder encoder = new PngBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));// 将签名保存到文件using (FileStream fileStream = new FileStream(filePath, FileMode.Create)){encoder.Save(fileStream);}}private void SavePhotoToFile(BitmapSource photo, string filePath){// 创建一个JpegBitmapEncoder保存照片JpegBitmapEncoder encoder = new JpegBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(photo));// 将照片保存到文件using (FileStream fileStream = new FileStream(filePath, FileMode.Create)){encoder.Save(fileStream);}}}
}

  生成唯一的文件名,然后获取用于保存的文件夹路径(这里以"我的图片"文件夹为例)。接下来,它使用RenderTargetBitmap将签名画布渲染为位图,然后使用PngBitmapEncoder保存签名。同时,也使用JpegBitmapEncoder保存相机拍摄的照片。

  创建CameraCapture.cs类来处理相机操作。你需要使用WPF的MediaElement和System.Windows.Media.Imaging来实现相机预览和拍照功能。这里提供一个简化的示例,实际应用中需要更多的处理和错误处理。

  当你需要在WPF应用中初始化相机并进行拍照时,你可以使用MediaCapture类来实现。下面是更详细的示例,展示如何初始化相机并进行拍照:

using System;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Threading;
using System.Windows;
using System.IO;
using System.Threading.Tasks;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Storage;
using Windows.Storage.Streams;namespace SignatureCaptureApp
{public class CameraCapture{private MediaElement _cameraPreview;private MediaCapture _mediaCapture;public CameraCapture(MediaElement cameraPreview){_cameraPreview = cameraPreview;}public async void InitializeCamera(){try{// 初始化MediaCapture对象_mediaCapture = new MediaCapture();await _mediaCapture.InitializeAsync();// 将相机预览显示在MediaElement中_cameraPreview.SetMediaPlayer(_mediaCapture);// 启动相机预览await _mediaCapture.StartPreviewAsync();}catch (Exception ex){// 处理错误,例如显示错误消息框MessageBox.Show($"初始化相机时发生错误:{ex.Message}");}}public async Task<BitmapSource> CapturePhoto(){try{// 创建一个临时文件来保存照片StorageFile photoFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("TempPhoto.jpg", CreationCollisionOption.GenerateUniqueName);// 拍照并保存到临时文件ImageEncodingProperties imageProperties = ImageEncodingProperties.CreateJpeg();await _mediaCapture.CapturePhotoToStorageFileAsync(imageProperties, photoFile);// 从临时文件中读取照片数据using (IRandomAccessStream photoStream = await photoFile.OpenReadAsync()){// 创建一个BitmapDecoder来解码照片数据BitmapDecoder decoder = await BitmapDecoder.CreateAsync(photoStream);// 将照片解码为BitmapSourceSoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);BitmapSource photo = await ConvertToBitmapSource(softwareBitmapBGR8);// 删除临时文件await photoFile.DeleteAsync();// 返回照片return photo;}}catch (Exception ex){// 处理错误,例如显示错误消息框MessageBox.Show($"拍照时发生错误:{ex.Message}");return null;}}private async Task<BitmapSource> ConvertToBitmapSource(SoftwareBitmap softwareBitmap){// 创建一个WriteableBitmap来保存照片数据WriteableBitmap bitmap = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);softwareBitmap.CopyToBuffer(bitmap.PixelBuffer);// 等待UI线程空闲,然后在UI线程上创建BitmapSourceawait Application.Current.Dispatcher.BeginInvoke(new Action(() =>{bitmap.Invalidate();}), DispatcherPriority.ApplicationIdle);return bitmap;}}
}

  在InitializeCamera方法中,我们使用MediaCapture类来初始化相机,并将相机预览显示在MediaElement中。在CapturePhoto方法中,我们使用CapturePhotoToStorageFileAsync方法拍照并将照片保存到临时文件中。然后,我们使用BitmapDecoder类解码照片数据,并将其转换为BitmapSource对象。最后,我们删除临时文件并返回照片。

  请注意,这段代码使用了异步方法,因此需要在方法前面加上async关键字,并使用await关键字来等待异步操作完成。此外,我们还使用了SoftwareBitmap和WriteableBitmap来处理照片数据。


  码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/113163.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何理解OSI七层模型?

一、是什么 OSI &#xff08;Open System Interconnect&#xff09;模型全称为开放式通信系统互连参考模型&#xff0c;是国际标准化组织 ( ISO ) 提出的一个试图使各种计算机在世界范围内互连为网络的标准框架 OSI 将计算机网络体系结构划分为七层&#xff0c;每一层实现各自…

element-ui中表格树类型数据的显示

项目场景&#xff1a; 1&#xff1a;非懒加载的情况 1&#xff1a;效果展示 2&#xff1a;问题描述以及解决 1&#xff1a;图片展示 2&#xff1a;html <-- default-expand-all 代表默认展开 如果不展开删除就行 --> <el-tableref"refsTable"v-loadin…

Linux_Shell运行原理(命令行解释器)

一般我们叫Linux操作系统&#xff0c;狭义上就是指Linux内核&#xff08;kernel&#xff09;&#xff0c;广义上就是Linux内核Linux外壳程序对应的配套程序&#xff0c;这里我们来详细介绍一下这个“外壳程序”。 在我们使用指令时&#xff0c;这个外壳程序会将我们的解释指令并…

【Arduino TFT】基于 ESP32S3 S7789 240x240 TFT实现的龙猫太空人天气时钟

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-10-21 ❤️❤️ 本篇更新记录 2023-10-21 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

【趣味随笔】农业机器人的种类与发展前景

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

关于Mysql中的索引与事务

索引 定义 索引&#xff1a;为了提高查找效率而使用的一种数据结构把数据组织起来&#xff0c;可以把索引理解在书的目录或字典的检索表&#xff08;拼音检索&#xff09; 索引是一种特殊的文件&#xff0c;可以包含着对数据表里的所有记录的引用指针&#xff0c;对表中的一…

重磅发布!RflySim Cloud 智能算法云仿真平台亮相,助力大规模集群算法高效训练

RflySim Cloud智能算法云仿真平台&#xff08;以下简称RflySim Cloud平台&#xff09;是由卓翼智能及飞思实验室为无人平台集群算法验证、大规模博弈对抗仿真、人工智能模型训练等前沿研究领域研发的平台。主要由环境仿真模块、物理效应计算模块、多智能体仿真模块、分布式网络…

代码随想录Day24 LeetCode T491 递增子序列 LeetCode T46 全排列 LrrtCode T47 全排列II

LeetCode T491 递增子序列 题目链接:491. 递增子序列 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 首先这里的测试用例很容易误导我们,这道题不能使用上次子集的思路对数组先排序,使用一个used数组来解决问题. 我们用[4,7,6,7]举例这道题的递增序列不存在[4,6,7,7]这个…

合同管理系统

合同管理系统 功能介绍&#xff1a; 功能特性&#xff1a; 根据对合同管理系统系统分析合同管理由以下模块组成&#xff0c;相对方管理、合同文本管理、合同审批管理、合同履行审批、风险事件管理、合同查询、合同统计、系统提醒、系统管理。 1、相对方管理 1.有“相对方…

SpringBoot环境搭建与初创程序

一&#xff1a;IDEA环境准备 IDEA社区版版本: 2021.1-2022.1.4 IDEA专业版版本: 无要求 &#x1f31f;如果个人电脑安装的IEDA不在这个范围&#xff0c;需要卸载重新安装&#xff1b;且⼀定要删除注册表 参考文章➜IDEA卸载和删除注册表 二&#xff1a; Maven (1)Maven的概念…

第六届“中国法研杯”司法人工智能挑战赛进行中!

第六届“中国法研杯”司法人工智能挑战赛 赛题上新&#xff01; 第六届“中国法研杯”司法人工智能挑战赛&#xff08;LAIC2023&#xff09;目前已发布司法大模型数据和服务集成调度 、证据推理、司法大数据征文比赛、案件要素识别四大任务。本届大赛中&#xff0c;“案件要素…

克隆的虚拟机,查不到IP号

文章目录 问题解决描述解决步骤重新生成MAC地址修改一修改二 相关操作查看当前所有网卡修改网络配置文件文件内容修改修改文件名 问题解决 描述 使用克隆的虚拟机&#xff0c;网卡和原虚拟机的相同&#xff0c;会导致克隆虚拟机的网卡不可用&#xff0c;从而使用ip addr查看不…

上新啦!请查收云原生虚拟数仓 PieCloudDB 十月动态

PieCloudDB Database 最新动态 PieCloudDB 压缩效率得到提升 为了节省存储空间&#xff0c;降低用户存储费用&#xff0c;PieCloudDB 在压缩率上不断优化&#xff0c;包括&#xff1a; 对 HLL&#xff08;HyperLogLog&#xff09;支持游程编码&#xff08;Run Length Encodi…

Visual Studio2019 与 MySQL连接 版本关系

Refer: VS 连接MySQL | mysql-for-visualstudio 的安装-CSDN博客 【精选】用VS2019&#xff08;C#&#xff09;连接MYSQL(从0入门&#xff0c;手把手教学&#xff09;_mysql-for-visualstudio-1.2.9.msi_Flying___rabbit的博客-CSDN博客 一、工具&#xff1a;VS2019需要连接M…

Qt 官方文档及阅读方法

文章目录 选择 All Qt Modules 查找模块选择 C Classes 查看该模块的所有的类当前类说明文档 QT 官方文档参考&#xff1a;https://doc.qt.io/qt-5 选择 All Qt Modules 查找模块 选择 C Classes 查看该模块的所有的类 当前类说明文档 包括 属性公共函数重新实现的公共功能公…

巡检管理系统哪一款简单实用?如何解决传统巡检难题,实现高效监管?

在电力、燃气、水务等公共服务领域&#xff0c;线路巡检工作是保障公众安全、避免事故发生的重要环节。然而&#xff0c;传统的巡检方式存在一些显著的问题&#xff0c;可能会对公共安全和稳定运行产生不利的影响。为了解决这些问题&#xff0c;需要一种能够实现高效、精准的线…

SystemVerilog学习(1)——验证导论

写在最前 选课不慎&#xff0c;选修课选了个SystemVerilog&#xff0c;事情比必修还多&#xff0c;上课老师讲的一点用没有&#xff0c;但是学分还得修&#xff0c;只能自学了&#xff0c;既来之则安之。 一、什么是SystemVerilog SystemVerilog简称为SV语言&#xff0c;是一种…

react native 使用夜神模拟器开发调试 windows+android

执行adb devices, 提示List of devices attached 打开本地sdk目录中的platform-tools文件夹&#xff0c;复制下面3个文件 打开夜神模拟器安装目录中的bin目录&#xff0c;把复制出来的文件复制替换到bin目录中 在复制一份platform-tools目录中的adb.exe&#xff0c;重命名为…

python基础教程:递归函数教程

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 1.递归的定义&#xff1a; 在函数内部直接或者间接调用函数本身 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资…

四川云汇优想:短视频矩阵运营方案

短视频矩阵运营方案是为了提高短视频平台的用户黏性和活跃度&#xff0c;从而增强用户粘性和平台的商业价值而制定的。下面四川百幕晟小编将对短视频矩阵运营方案进行详细的介绍和分析。 首先&#xff0c;短视频矩阵运营方案要注重用户精细化运营。通过用户画像和兴趣标签&…