当前位置: 代码网 > it编程>编程语言>Asp.net > C#实现高性能拍照与水印添加功能完整方案

C#实现高性能拍照与水印添加功能完整方案

2025年09月24日 Asp.net 我要评论
1. 概述在工业检测、质量追溯等应用场景中,经常需要对产品进行拍照并添加相关信息水印。本文将详细介绍如何使用c#实现一个高性能的拍照和水印添加功能,包含完整的代码实现和优化技巧。2. 功能架构设计本功

1. 概述

在工业检测、质量追溯等应用场景中,经常需要对产品进行拍照并添加相关信息水印。本文将详细介绍如何使用c#实现一个高性能的拍照和水印添加功能,包含完整的代码实现和优化技巧。

2. 功能架构设计

本功能主要分为以下几个模块:

  • 相机控制与分辨率设置
  • 图像捕获与处理
  • 水印信息生成与添加
  • 文件保存与ui更新

3. 核心代码实现

3.1 主拍照方法

/// <summary>
/// 拍照并添加水印信息
/// </summary>
/// <returns>保存的图片路径,失败返回空字符串</returns>
private string takepictures()
{
    console.writeline("开始拍照");
    string filepath = string.empty;
    
    try
    {
        this.dispatcher.invoke(() =>
        {
            // 1. 设置ui背景
            imgbox.background = new solidcolorbrush(system.windows.media.color.fromrgb(75, 76, 69));
            
            // 2. 设置相机分辨率
            if (!setcameraresolutionwithoutstop(3840, 2160))
            {
                console.writeline("设置分辨率失败");
                return;
            }

            // 3. 检查视频帧有效性
            if (player?.getcurrentvideoframe()?.gethbitmap() == intptr.zero)
            {
                console.writeline("获取视频帧失败");
                return;
            }

            // 4. 获取并处理图像
            using (var hbitmap = new safehbitmaphandle(player.getcurrentvideoframe().gethbitmap()))
            {
                bitmapsource bitmapsource = createbitmapsourcefromhbitmap(hbitmap);
                if (bitmapsource == null)
                {
                    console.writeline("创建bitmapsource失败");
                    return;
                }

                // 5. 旋转图像(如果需要)
                if (shouldrotateimage())
                {
                    bitmapsource = rotateimage(bitmapsource, 180);
                }

                // 6. 保存图像
                filepath = generatefilepath();
                if (string.isnullorempty(filepath))
                {
                    console.writeline("生成文件路径失败");
                    return;
                }

                saveimagetofile(bitmapsource, filepath);

                // 7. 添加水印
                addwatermarktoimage(filepath, currentscancoderecord);

                // 8. 更新ui显示
                updateimagedisplay(filepath);
                
                console.writeline($"照片已保存到: {path.getfullpath(filepath)}");
                systeminfo.writefile($"照片已保存到: {path.getfullpath(filepath)}", "生产日志");
            }
        });
        
        return filepath;
    }
    catch (exception ex)
    {
        console.writeline($"照片保存出错: {ex}");
        systeminfo.writefile($"照片保存出错: {ex}", "error");
        return string.empty;
    }
}

3.2 安全hbitmap处理类

// 安全释放hbitmap的包装类
private class safehbitmaphandle : idisposable
{
    private readonly intptr _hbitmap;
    private bool _disposed = false;

    public safehbitmaphandle(intptr hbitmap)
    {
        _hbitmap = hbitmap;
    }

    public static implicit operator intptr(safehbitmaphandle handle) => handle._hbitmap;

    public void dispose()
    {
        if (!_disposed && _hbitmap != intptr.zero)
        {
            deleteobject(_hbitmap);
            _disposed = true;
        }
        gc.suppressfinalize(this);
    }

    ~safehbitmaphandle()
    {
        dispose();
    }

    [system.runtime.interopservices.dllimport("gdi32.dll")]
    private static extern bool deleteobject(intptr hobject);
}

4. 关键技术点详解

4.1 相机分辨率设置

private bool setcameraresolutionwithoutstop(int width, int height)
{
    try
    {
        if (player?.videosource is not videocapturedevice videodevice)
            return false;

        var targetresolution = videodevice.videocapabilities?
            .firstordefault(cap => cap.framesize.width == width && cap.framesize.height == height);

        if (targetresolution != null)
        {
            videodevice.videoresolution = targetresolution;
            console.writeline($"已设置分辨率为: {width}x{height}");
            return true;
        }

        console.writeline($"未找到 {width}x{height} 分辨率支持");
        return false;
    }
    catch (exception ex)
    {
        console.writeline($"设置分辨率失败: {ex.message}");
        return false;
    }
}

技术要点

  • 使用videocapturedevice类控制相机设备
  • 通过videocapabilities枚举设备支持的分辨率
  • 采用异常处理确保程序稳定性

4.2 图像处理与旋转

private bitmapsource rotateimage(bitmapsource source, double angle)
{
    try
    {
        rotatetransform rotatetransform = new rotatetransform(angle);
        return new transformedbitmap(source, rotatetransform);
    }
    catch
    {
        return source;
    }
}

4.3 文件路径生成策略

private string generatefilepath()
{
    try
    {
        string basepath = configurationmanager.appsettings["picfileload"] ?? string.empty;
        if (string.isnullorempty(basepath))
            return string.empty;

        string datefolder = datetime.now.tostring("yyyy-mm-dd");
        string codefolder = string.isnullorempty(oldcode) ? "null" : oldcode;
        
        string directorypath = path.combine(basepath, "photos", "input", datefolder, codefolder);
        
        if (!directory.exists(directorypath))
            directory.createdirectory(directorypath);

        return path.combine(directorypath, $"photo_{datetime.now:yyyymmddhhmmss}.jpg");
    }
    catch
    {
        return string.empty;
    }
}

目录结构设计

basepath/
├── photos/
│   ├── input/
│   │   ├── 2023-11-20/
│   │   │   ├── productcode001/
│   │   │   └── productcode002/
│   │   └── 2023-11-21/

4.4 高质量图像保存

private void saveimagetofile(bitmapsource bitmapsource, string filepath)
{
    try
    {
        using (filestream fs = new filestream(filepath, filemode.create))
        {
            jpegbitmapencoder encoder = new jpegbitmapencoder { qualitylevel = 95 };
            encoder.frames.add(bitmapframe.create(bitmapsource));
            encoder.save(fs);
        }
    }
    catch (exception ex)
    {
        console.writeline($"保存图像失败: {ex.message}");
        throw;
    }
}

5. 智能水印实现

5.1 水印添加核心方法

private void addwatermarktoimage(string imagepath, t_scancoderecord record)
{
    try
    {
        using (var originalimage = image.fromfile(imagepath))
        using (var watermarkimage = new bitmap(originalimage.width, originalimage.height))
        using (var graphics = graphics.fromimage(watermarkimage))
        {
            // 设置高质量绘制
            graphics.smoothingmode = system.drawing.drawing2d.smoothingmode.highquality;
            graphics.interpolationmode = system.drawing.drawing2d.interpolationmode.highqualitybicubic;
            graphics.pixeloffsetmode = system.drawing.drawing2d.pixeloffsetmode.highquality;

            // 绘制原始图像
            graphics.drawimage(originalimage, 0, 0, originalimage.width, originalimage.height);

            // 添加水印
            string watermarktext = formatshippinginfo(record);
            addtextwatermark(graphics, watermarktext, originalimage.width, 80);

            // 保存处理后的图像
            watermarkimage.save(imagepath, system.drawing.imaging.imageformat.jpeg);
        }
    }
    catch (exception ex)
    {
        console.writeline($"添加水印失败: {ex.message}");
        throw;
    }
}

5.2 智能文本格式化

public string formatshippinginfo(t_scancoderecord record)
{
    if (record == null) return string.empty;

    string[] parts = 
    {
        record.shipping_mark ?? string.empty,
        record.code ?? string.empty,
        $"{record.weight}kg",
        $"{record.volume}m³",
        datetime.now.tostring("yyyy.mm.dd hh:mm")
    };

    // 计算显示长度(考虑中英文)
    int[] partlengths = parts.select(getdisplaylength).toarray();
    int totallength = partlengths.sum();

    // 计算间隔
    int totalgaps = 126 - totallength;
    int gapcount = 4;
    int basegapsize = totalgaps / gapcount;
    int extraspace = totalgaps % gapcount;

    // 构建结果
    var result = new stringbuilder();
    
    for (int i = 0; i < parts.length; i++)
    {
        result.append(parts[i]);
        
        if (i < gapcount)
        {
            int currentgapsize = basegapsize + (extraspace > 0 ? 1 : 0);
            result.append(' ', currentgapsize);
            if (extraspace > 0) extraspace--;
        }
    }

    console.writeline($"最终长度: {getdisplaylength(result.tostring())}/126");
    return result.tostring();
}

// 计算字符串显示长度(支持中英文混合)
private int getdisplaylength(string text)
{
    if (string.isnullorempty(text)) return 0;
    
    return text.sum(c => c >= 0x4e00 && c <= 0x9fa5 ? 2 : 1);
}

6. 性能优化技巧

  1. 资源管理:使用using语句和safehbitmaphandle确保资源正确释放
  2. 异常处理:完善的异常处理机制保证程序稳定性
  3. 配置化:通过配置文件管理路径、旋转设置等参数
  4. 高质量渲染:设置合适的图形渲染参数保证图像质量
  5. 日志记录:详细的日志记录便于问题排查

7. 实际应用建议

  1. 相机选型:根据实际需求选择合适分辨率的工业相机
  2. 存储规划:考虑图片数量和大小,合理规划存储空间
  3. 性能监控:监控拍照过程的耗时,优化瓶颈环节
  4. 错误处理:增加重试机制应对临时性故障
  5. 内存管理:定期清理不必要的资源,防止内存泄漏

8. 总结

本文详细介绍了c#实现拍照和水印添加功能的完整方案,涵盖了从相机控制、图像处理到文件保存的各个环节。代码中体现了良好的资源管理、异常处理和性能优化实践,可以直接应用于工业检测、质量追溯等实际场景。

通过合理的架构设计和细节处理,这个方案能够稳定高效地完成拍照和水印添加任务,为后续的图像分析和数据处理提供可靠的基础。

以上就是c#实现高性能拍照与水印添加功能完整方案的详细内容,更多关于c#拍照与水印添加功能的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com