C# 调用摄像头实现拍照并添加水印及保存功能
本文演示如何使用 C# WinForm 开发一个具备实时预览、拍照截图以及自动添加文本水印功能的桌面应用程序。核心依赖 AForge 系列库进行视频流处理,通过捕获特定界面区域的画面并结合 GDI+ 绘制文字实现带水印的照片生成与保存。
开发环境与准备工作
该功能基于 Windows Forms 窗体应用开发,主要涉及硬件通信与图像处理。使用前需引入必要的第三方类库:
- AForge.Video.dll:用于管理和驱动摄像头设备,提供视频帧回调。
- AForge.Video.FFMPEG.dll:支持多种视频格式的解码(视具体版本需求而定)。
- .NET Standard Libraries:包括 System.Drawing 等基础图形处理组件。
运行程序后,主窗口应包含视频显示控件、参数选择下拉框、控制按钮及状态显示区域,整体布局如图所示,旨在展示核心逻辑而非 UI 美化。
第1步:初始化与摄像头资源加载
在窗体加载事件中,首先需要枚举系统可用的视频输入设备,并对 UI 控件进行初始赋值。
- 入口:
Form_Load事件。- 创建
FilterInfoCollection对象,筛选类别为VideoInputDevice。 - 检查设备列表是否为空,若为空则提示“没有视频设备”并终止后续流程。
- 调用
LoadVedio()方法填充设备选择下拉框。
- 创建
- 关键代码:
private void Camera_Load(object sender, EventArgs e)
{
this.btnSave.Enabled = false;
FilterInfoCollection infos = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if ((infos != null) && (infos.Count > 0))
{
this.LoadVedio();
}
else
{
MessageBox.Show("没有视频设备");
}
// ... 其他 UI 初始化代码
}
设备加载完成后,用户可以从下拉列表中切换不同的摄像头源。选中设备后,需绑定新帧事件以更新预览画面。
第2步:处理实时视频预览
为了保持低延迟的预览效果,通常不直接全屏截图,而是利用 AForge 的事件机制获取每一帧图像。当用户选择了特定的摄像装置后,需要销毁旧的连接并建立新的绑定。
- 目的:确保切换摄像头或调整属性时不会引发内存泄漏或冲突。
- 动作:
- 判断当前采集器是否正在运行,若是则调用
SignalToStop()并等待停止。 - 重新实例化
VideoCaptureDevice,传入所选设备的MonikerString。 - 订阅
NewFrame事件,在该事件中接收 Bitmap 对象并赋值给 PictureBox 控件。
此步骤实现了手机或电脑摄像头画面的实时传输与显示,为后续的精准裁剪和水印添加提供基础素材。
第3步:定义拍摄区域与水印逻辑
本方案的一个独特之处在于采用“屏幕坐标映射”的方式来模拟拍照框,并在此区域内合成水印。这允许用户通过拖拽一个透明覆盖层(BorderForm)来精确框选人脸或物体范围。
1. 计算截图矩形
在触发拍照(Shoot)时,代码首先确认预览图和边框位置的有效性。随后利用 GDI+ 的 CopyFromScreen 方法,从屏幕坐标中截取对应大小的像素数据。
2. 绘制水印文字
截取到空白 Bitmap 后,使用 Graphics 对象在底部中央区域绘制自定义文本(如学号、姓名或身份证号)。
- 字体设置:
Font("宋体", 9)。 - 背景处理:先在绘制区域填充白色矩形,防止深色背景下文字不可见。
- 对齐方式:使用
StringFormat实现水平与垂直居中。
实现代码如下:
private void Shoot()
{
try
{
// 假设已通过 UI 配置好宽和高
int width = (int)this.numericUpDown1.Value;
int height = (int)this.numericUpDown2.Value;
Bitmap resultImage = new Bitmap(width, height);
Graphics g = Graphics.FromImage(resultImage);
// 1. 截取屏幕指定坐标(mf.Location 为水印框/取景框的绝对坐标)
g.CopyFromScreen(new Point(this.mf.Location.X + 1, this.mf.Location.Y + 1),
new Point(6, 6),
new Size(resultImage.Size.Width - 6, resultImage.Size.Height - 6));
// 2. 准备水印字符串(此处以 XH 为例)
string watermarkText = GetCurrentWatermarkText();
if (!string.IsNullOrEmpty(watermarkText))
{
Font font = new Font("宋体", 9);
SizeF textSize = g.MeasureString(watermarkText, font);
float txtWidth = textSize.Width * 1.1f;
Rectangle rec = new Rectangle((width - (int)txtWidth) / 2, height - 16, (int)txtWidth, 15);
// 绘制白底和黑字
g.FillRectangle(Brushes.White, rec);
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
g.DrawString(watermarkText, font, Brushes.Black, rec, sf);
}
// 3. 显示结果
this.pictureBox_tx.Image = resultImage;
this.btnSave.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "拍照错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
第4步:照片保存与路径管理
拍照预览无误后,点击保存按钮将 Bitmap 写入磁盘。逻辑中包含基本的文件存在性检查和格式转换。
- 路径拼接:使用
Path.Combine构建文件夹路径,避免路径分隔符错误。 - 命名规则:通常以唯一标识(如学号
XH)命名,扩展名统一为JPG。 - 覆盖保护:如果目标文件已存在且未勾选“强制覆盖”,弹出确认对话框询问用户。
保存操作成功执行后,重置定时器状态,恢复相机连续预览模式,以便下一次采集。
总结
通过上述步骤,我们完成了一个具备实用价值的 C# 摄像头拍照工具。该方法的优势在于灵活性高,用户可以通过界面自由拖拽取景框来调整构图,同时 GDI+ 绘图确保了水印可以完美融合到画面中,解决了通用抓拍工具水印位置固定或不美观的问题。以上就是 C# 实现手机拍照并且保存水印照片的详细内容,更多关于 C# 多媒体开发及 WinForm 控件应用的相关资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









