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知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。
相关文章:

WPF实现签名拍照功能
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程的集成方法与步骤(二)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 前面讲了集成的后端部分内容,下面简单介绍一下前端的内容 1、前端生成的页面需要进行修改&…...

【Qt控件之微调框、进度条】QSpinBox、QDoubleSpinBox、QDial、QProgressBar介绍及使用
概述 QSpinBox类提供了一个微调框小部件。 QSpinBox适用于处理整数和离散的值集(例如,月份名称);对于浮点数值,请使用QDoubleSpinBox。 QSpinBox允许用户通过点击上下按钮或按键盘上的上下箭头来增加/减少当前显示的值…...

Python学习-----Day09
一、利用装饰器来获取函数运行的时间、 #导入time模块 import timedef decorated(fn):def inner():#time.time获取函数执行的时间a time.time() # func开始的时间fn()b time.time() # func结束的时间print(f"{fn.__name__}程序运行的总数时间:{b - a}秒")return…...

世界国家/地区行驶方向数据
Part1数据背景 道路通行方向规则是交通规则的重要部分之一。不同国家及地区通行方向并不一样,受风俗、习惯、风潮因素等影响。 最近也在学道路行驶,结果差强人意,继续努力吧。祝学车的小伙伴们一次过~ Part2数据详情 今天分享的国家/地区行…...

idgen导入Android11源码
文章目录 配置下载AS编译源码依赖导入玩一下andorid.iml 注意: 有些时候发现为啥自己编译就这么难呢?不是卡死就无数次重启虚拟机,一切的原罪在配置过低,换句话说就是穷。关于导入源码的下载参考 Android Studio for Platform (AS…...

大同小异!如何在苹果不同类型设备上更改AirDrop的名称
你可以更改你的AirDrop ID,让其他人看到你名字之外的东西。本文介绍了如何在iPhone、iPad和Mac上更改AirDrop名称。 如何在iPhone上更改AirDrop名称 在iPhone上更改AirDrop名称涉及到你可能不想做的更改。幸运的是,这在iPad和Mac上不是真的,…...

sqlmap --os-shell选项原理解析
文章目录 sqlmap --os-shell选项原理解析原理解析总结 sqlmap --os-shell选项原理解析 以sqli第一关为例。 --os-shell 是 SQLMap 工具的一个参数,用于在成功注入数据库后,执行操作系统命令并获取其输出。 sqlmap -u "http://192.168.188.199/sq…...
谈谈 Redis 持久化机制,RDB、AOF
谈谈 Redis 持久化机制,RDB,AOF RDB:相当于对内存中的数据,拍一张数据快照。存储的是数据。 AOF:存储的是具体的命令。 企业实践中,实际是使用RDB结合AOF。 这个方法是在 Redis 4.0 提出的,该方…...

并发编程——2.基础概念及其它相关的概述
这篇文章我们来讲一下并发编程中的线程及其相关的概述内容。 目录 1.J.U.C 2.进程、线程、协程 2.1进程 2.2线程 2.3纤程(协程) 2.4概念小结 3.并发、并行、串行 3.1并发 3.2并行 3.3串行 3.4概念小结 4.CPU核心数和线程数的关系 5.上下文…...

20231019 filezilla 配置 Windows与Ubuntu文件传输
SFTP协议,传文件,否则会报无权限错...
一个.Net开发的轻量级SQLite数据库ORM
SQLite是一种流行的开源关系型数据库,它的设计目标是提供轻量级、高效、可靠和易用的数据存储服务。由于SQLite无需单独的服务器进程,它通常被用于嵌入式系统和单机应用程序中,也可以用于网络应用程序的辅助数据库。 今天给大家推荐一个.NET开…...
gRPC通信
1. gRPC简介 gRPC是一种高性能、开源和通用的远程过程调用(RPC)框架,由Google开源并维护。它使用Protocol Buffers(protobuf)作为接口定义语言(IDL),提供跨平台、跨语言的RPC调用支…...
湖仓一体架构的特性
湖仓一体架构是一种数据架构模式,具有以下特性: 统一存储:湖仓一体架构将数据湖和数据仓库合并为一个整体,将结构化数据和非结构化数据存储在同一个存储系统中,如Hadoop分布式文件系统(HDFS)或云…...
Python中使用包含_和__的变量名之间的区别
_:单下划线 例子:_count、_temp 含义:成员的私有成员变量,就像Java中用private关键字修饰一样。 作用:只允许当前类创建的对象和子类对象访问此变量。外部无法访问此变量。 __:双下划线 例子:__count、__temp 含义&am…...

019-第三代软件开发-Git提交规范
第三代软件开发-Git提交规范 文章目录 第三代软件开发-Git提交规范项目介绍Git提交规范分支规范Commit Message FormatHeaderBodyFooterRevert 总结一下 关键字: Qt、 Qml、 git、 Commit、 release 项目介绍 欢迎来到我们的 QML & C 项目!这个…...

MTK APP实现动态修改logo和开机动画
MTK APP实现动态修改logo和开机动画 前言一、修改对新分区的权限1.修改开机动画对新分区的权限2.修改系统APP对新分区的权限3.修改SE权限,不然编译会报错4.修改开机动画文件,让其加载新分区中的文件 二、系统APP代码使用1.系统app修改开机logo2.系统app修改开机动画…...

Spring核心扩展点BeanDefinitionRegistryPostProcessor源码分析
我们知道,只要在一个Java类上加上Component、Service、Controller等注解,就可以被加载到Spring容器中,除了以上方式,加了Bean和Import好像也可以将对象添加到Spring容器中,究竟Spring是如何实现这些功能的呢࿱…...

C++实现AC自动机,剪枝、双数组压缩字典树!详解双数组前缀树(Double-Array Trie)剪枝字典树(Patricia Trie)
代码在:github.com/becomequantum 最近研究了一下字典树,什么AC自动机,双数组压缩字典树,剪枝字典树都自己写代码实现了一下。这本该是本科学数据结构时该玩明白的东西,我到现在才会玩。本视频主要介绍一下双数组和剪…...

防火墙规则顺序解决方案
防火墙是保护网络免受攻击的第一道防线,防火墙对互联网和公司IT网络之间的流量拥有绝对控制权,防火墙规则的配置处理调节流量的关键任务。 这些规则会仔细检查传入和传出流量,并根据规则中提到的条件允许或阻止它,防火墙规则越严…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...