✅作者简介: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);
// 将照片解码为BitmapSource
SoftwareBitmap 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线程上创建BitmapSource
await 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知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。