最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#實(shí)現(xiàn)高性能拍照與水印添加功能完整方案

 更新時(shí)間:2025年09月24日 10:58:08   作者:almighty27  
在工業(yè)檢測(cè)、質(zhì)量追溯等應(yīng)用場(chǎng)景中,經(jīng)常需要對(duì)產(chǎn)品進(jìn)行拍照并添加相關(guān)信息水印,本文將詳細(xì)介紹如何使用C#實(shí)現(xiàn)一個(gè)高性能的拍照和水印添加功能,包含完整的代碼實(shí)現(xiàn)和優(yōu)化技巧,需要的朋友可以參考下

1. 概述

在工業(yè)檢測(cè)、質(zhì)量追溯等應(yīng)用場(chǎng)景中,經(jīng)常需要對(duì)產(chǎn)品進(jìn)行拍照并添加相關(guān)信息水印。本文將詳細(xì)介紹如何使用C#實(shí)現(xiàn)一個(gè)高性能的拍照和水印添加功能,包含完整的代碼實(shí)現(xiàn)和優(yōu)化技巧。

2. 功能架構(gòu)設(shè)計(jì)

本功能主要分為以下幾個(gè)模塊:

  • 相機(jī)控制與分辨率設(shè)置
  • 圖像捕獲與處理
  • 水印信息生成與添加
  • 文件保存與UI更新

3. 核心代碼實(shí)現(xiàn)

3.1 主拍照方法

/// <summary>
/// 拍照并添加水印信息
/// </summary>
/// <returns>保存的圖片路徑,失敗返回空字符串</returns>
private string TakePictures()
{
    Console.WriteLine("開(kāi)始拍照");
    string filePath = string.Empty;
    
    try
    {
        this.Dispatcher.Invoke(() =>
        {
            // 1. 設(shè)置UI背景
            ImgBox.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(75, 76, 69));
            
            // 2. 設(shè)置相機(jī)分辨率
            if (!SetCameraResolutionWithoutStop(3840, 2160))
            {
                Console.WriteLine("設(shè)置分辨率失敗");
                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("創(chuàng)建BitmapSource失敗");
                    return;
                }

                // 5. 旋轉(zhuǎn)圖像(如果需要)
                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)}", "生產(chǎn)日志");
            }
        });
        
        return filePath;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"照片保存出錯(cuò): {ex}");
        SystemInfo.WriteFile($"照片保存出錯(cuò): {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. 關(guān)鍵技術(shù)點(diǎn)詳解

4.1 相機(jī)分辨率設(shè)置

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($"已設(shè)置分辨率為: {width}x{height}");
            return true;
        }

        Console.WriteLine($"未找到 {width}x{height} 分辨率支持");
        return false;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"設(shè)置分辨率失敗: {ex.Message}");
        return false;
    }
}

技術(shù)要點(diǎn)

  • 使用VideoCaptureDevice類控制相機(jī)設(shè)備
  • 通過(guò)VideoCapabilities枚舉設(shè)備支持的分辨率
  • 采用異常處理確保程序穩(wěn)定性

4.2 圖像處理與旋轉(zhuǎn)

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;
    }
}

目錄結(jié)構(gòu)設(shè)計(jì)

basePath/
├── photos/
│   ├── Input/
│   │   ├── 2023-11-20/
│   │   │   ├── ProductCode001/
│   │   │   └── ProductCode002/
│   │   └── 2023-11-21/

4.4 高質(zhì)量圖像保存

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. 智能水印實(shí)現(xiàn)

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))
        {
            // 設(shè)置高質(zhì)量繪制
            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}m3",
        DateTime.Now.ToString("yyyy.MM.dd HH:mm")
    };

    // 計(jì)算顯示長(zhǎng)度(考慮中英文)
    int[] partLengths = parts.Select(GetDisplayLength).ToArray();
    int totalLength = partLengths.Sum();

    // 計(jì)算間隔
    int totalGaps = 126 - totalLength;
    int gapCount = 4;
    int baseGapSize = totalGaps / gapCount;
    int extraSpace = totalGaps % gapCount;

    // 構(gòu)建結(jié)果
    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($"最終長(zhǎng)度: {GetDisplayLength(result.ToString())}/126");
    return result.ToString();
}

// 計(jì)算字符串顯示長(zhǎng)度(支持中英文混合)
private int GetDisplayLength(string text)
{
    if (string.IsNullOrEmpty(text)) return 0;
    
    return text.Sum(c => c >= 0x4E00 && c <= 0x9FA5 ? 2 : 1);
}

6. 性能優(yōu)化技巧

  1. 資源管理:使用using語(yǔ)句和SafeHBitmapHandle確保資源正確釋放
  2. 異常處理:完善的異常處理機(jī)制保證程序穩(wěn)定性
  3. 配置化:通過(guò)配置文件管理路徑、旋轉(zhuǎn)設(shè)置等參數(shù)
  4. 高質(zhì)量渲染:設(shè)置合適的圖形渲染參數(shù)保證圖像質(zhì)量
  5. 日志記錄:詳細(xì)的日志記錄便于問(wèn)題排查

7. 實(shí)際應(yīng)用建議

  1. 相機(jī)選型:根據(jù)實(shí)際需求選擇合適分辨率的工業(yè)相機(jī)
  2. 存儲(chǔ)規(guī)劃:考慮圖片數(shù)量和大小,合理規(guī)劃存儲(chǔ)空間
  3. 性能監(jiān)控:監(jiān)控拍照過(guò)程的耗時(shí),優(yōu)化瓶頸環(huán)節(jié)
  4. 錯(cuò)誤處理:增加重試機(jī)制應(yīng)對(duì)臨時(shí)性故障
  5. 內(nèi)存管理:定期清理不必要的資源,防止內(nèi)存泄漏

8. 總結(jié)

本文詳細(xì)介紹了C#實(shí)現(xiàn)拍照和水印添加功能的完整方案,涵蓋了從相機(jī)控制、圖像處理到文件保存的各個(gè)環(huán)節(jié)。代碼中體現(xiàn)了良好的資源管理、異常處理和性能優(yōu)化實(shí)踐,可以直接應(yīng)用于工業(yè)檢測(cè)、質(zhì)量追溯等實(shí)際場(chǎng)景。

通過(guò)合理的架構(gòu)設(shè)計(jì)和細(xì)節(jié)處理,這個(gè)方案能夠穩(wěn)定高效地完成拍照和水印添加任務(wù),為后續(xù)的圖像分析和數(shù)據(jù)處理提供可靠的基礎(chǔ)。

以上就是C#實(shí)現(xiàn)高性能拍照與水印添加功能完整方案的詳細(xì)內(nèi)容,更多關(guān)于C#拍照與水印添加功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#實(shí)現(xiàn)MySQL中Clickhouse建表語(yǔ)句的轉(zhuǎn)換工具

    C#實(shí)現(xiàn)MySQL中Clickhouse建表語(yǔ)句的轉(zhuǎn)換工具

    這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)MySQL中Clickhouse建表語(yǔ)句的轉(zhuǎn)換工具,文中的示例代碼簡(jiǎn)潔易懂,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-10-10
  • C#使用Thrift作為RPC框架入門詳細(xì)教程

    C#使用Thrift作為RPC框架入門詳細(xì)教程

    這篇文件我們講了從0到1使用thrift框架的方法,也講了一些該框架的基本知識(shí),本文將詳細(xì)介紹 Thrift 在C#語(yǔ)言下的使用方式,并且提供豐富的實(shí)例代碼加以解釋說(shuō)明,幫助使用者快速構(gòu)建服務(wù),感興趣的朋友一起看看吧
    2021-11-11
  • Unity3D UGUI特效之Image高斯模糊效果

    Unity3D UGUI特效之Image高斯模糊效果

    這篇文章主要為大家詳細(xì)介紹了Unity3D UGUI特效之Image高斯模糊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C#文件復(fù)制異常:"未能找到文件"的解決方案與預(yù)防措施

    C#文件復(fù)制異常:"未能找到文件"的解決方案與預(yù)防措施

    在C#開(kāi)發(fā)中,文件操作是基礎(chǔ)中的基礎(chǔ),但有時(shí)最基礎(chǔ)的File.Copy()方法也會(huì)拋出令人困惑的異常,當(dāng)targetFilePath設(shè)置為D:\25Q1\MR3.6.6.1_C1.2.37_PB250623\bin\gc_data時(shí),系統(tǒng)拋出"未能找到文件"的異常,本文將深入分析這個(gè)問(wèn)題的原因,并提供全面的解決方案
    2025-08-08
  • C#利用緩存分塊讀寫大文件

    C#利用緩存分塊讀寫大文件

    這篇文章主要為大家詳細(xì)介紹了C#利用緩存分塊讀寫大文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C#9特性record 類型、模式匹配、init 屬性詳情

    C#9特性record 類型、模式匹配、init 屬性詳情

    這篇文章主要介紹了C#的record 類型、模式匹配(Pattern Matching)、屬性的 init 訪問(wèn)器三大特性,感興趣的小伙伴請(qǐng)參考下面文章內(nèi)容
    2021-09-09
  • 輕松學(xué)習(xí)C#的結(jié)構(gòu)和類

    輕松學(xué)習(xí)C#的結(jié)構(gòu)和類

    輕松學(xué)習(xí)C#的結(jié)構(gòu)和類,對(duì)C#的結(jié)構(gòu)和類感興趣的朋友可以參考本篇文章,幫助大家更靈活的運(yùn)用C#的結(jié)構(gòu)和類
    2015-11-11
  • C#屬性(Attribute)用法實(shí)例解析

    C#屬性(Attribute)用法實(shí)例解析

    這篇文章主要介紹了C#屬性(Attribute)用法實(shí)例解析,需要的朋友可以參考下
    2014-08-08
  • Unity 如何獲取鼠標(biāo)停留位置下的物體

    Unity 如何獲取鼠標(biāo)停留位置下的物體

    這篇文章主要介紹了Unity 如何獲取鼠標(biāo)停留位置下的物體,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值(示例代碼)

    C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值(示例代碼)

    這篇文章主要介紹了C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01

最新評(píng)論

安泽县| 天门市| 浦江县| 华亭县| 淮南市| 天津市| 赞皇县| 涡阳县| 乐山市| 泰安市| 应城市| 阿拉善左旗| 瑞安市| 日喀则市| 扶余县| 额敏县| 大理市| 和田县| 南昌县| 江山市| 伊宁市| 泰宁县| 通海县| 高唐县| 纳雍县| 乐陵市| 襄樊市| 丰都县| 瑞丽市| 铁岭县| 铁岭县| 裕民县| 黄浦区| 衡水市| 景宁| 谢通门县| 长丰县| 阿拉善右旗| 和龙市| 望城县| 浦北县|