waferMap图像渲染

定义数据类

csharp 复制代码
    /// <summary>
    /// 晶圆地图数据
    /// </summary>
    public class WaferMapData
    {
        /// <summary>
        /// 行数
        /// </summary>
        public int Rows { get; set; }
        /// <summary>
        /// 列数
        /// </summary>
        public int Columns { get; set; }
        /// <summary>
        /// 数据
        /// </summary>
        public string[,] Matrix { get; set; }
    }

增加helper类

csharp 复制代码
/// <summary>
/// 晶圆地图帮助类
/// </summary>
public class WaferMapHelper
{
    /// <summary>
    /// 晶圆图数据解析
    /// </summary>
    /// <param name="lines">数据</param>
    /// <param name="datas">解析数组</param>
    /// <param name="isInterval">是否存在间隔</param>
    /// <param name="interval">间隔字符串</param>
    /// <returns></returns>
    public static WaferMapData Parse(string[] lines, Dictionary<string, string> datas, bool isInterval, string interval = " ")
    {
        int rows = 0, cols = 0;
        List<string[]> matrix = new List<string[]>();

        // 先按 key 长度倒序排列(先匹配长的,防止例如 "___" 和 "_" 冲突)
        var keys = datas.Keys.OrderByDescending(k => k.Length).ToList();

        foreach (var line in lines)
        {
            if (line.StartsWith("ROWCT:"))
                rows = int.Parse(line.Substring(6));
            else if (line.StartsWith("COLCT:"))
                cols = int.Parse(line.Substring(6));
            else if (line.StartsWith("RowData:"))
            {
                string raw = line.Substring(8).Trim();
                if (isInterval)
                {
                    raw = raw.Replace(interval, ""); // 如果是间隔分割,则移除间隔字符
                }

                List<string> rowData = new List<string>();
                int i = 0;
                while (i < raw.Length)
                {
                    bool matched = false;
                    foreach (var key in keys)
                    {
                        if (i + key.Length <= raw.Length && raw.Substring(i, key.Length) == key)
                        {
                            rowData.Add(key);
                            i += key.Length;
                            matched = true;
                            break;
                        }
                    }

                    if (!matched)
                    {
                        // 若没有匹配上任何 key,可选择跳过或抛异常,这里添加 '?' 占位
                        rowData.Add("?");
                        i += 1;
                    }
                }

                matrix.Add(rowData.ToArray());
            }
        }

        // 修正行列数
        if (rows != matrix.Count)
            rows = matrix.Count;

        if (matrix.Count > 0 && cols != matrix[0].Length)
            cols = matrix[0].Length;

        // 构建结果矩阵
        string[,] result = new string[rows, cols];
        for (int y = 0; y < rows; y++)
        {
            for (int x = 0; x < cols; x++)
            {
                var rawVal = matrix[y][x];
                result[y, x] = datas.TryGetValue(rawVal, out var mapped) ? mapped : "?";
            }
        }

        return new WaferMapData
        {
            Rows = rows,
            Columns = cols,
            Matrix = result
        };
    }

    /// <summary>
    /// 晶圆图渲染
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="dieColorMap">渲染颜色选择</param>
    /// <param name="dieSizeX">芯片X尺寸</param>
    /// <param name="dieSizeY">芯片Y尺寸</param>
    /// <param name="gridThickness">栅格尺寸 等于0则不显示栅格</param>
    /// <param name="gridColor">栅格颜色</param>
    /// <returns></returns>
    public static BitmapSource Render(WaferMapData data, Dictionary<string, Color> dieColorMap, int dieSizeX = 6, int dieSizeY = 6, int gridThickness = 1, Color? gridColor = null)
    {
        int width = data.Columns * dieSizeX;
        int height = data.Rows * dieSizeY;

        WriteableBitmap bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
        bitmap.Lock();

        unsafe
        {
            IntPtr pBackBuffer = bitmap.BackBuffer;
            int stride = bitmap.BackBufferStride;
            Color actualGridColor = gridColor ?? Colors.LightGray;

            for (int y = 0; y < data.Rows; y++)
            {
                for (int x = 0; x < data.Columns; x++)
                {
                    string value = data.Matrix[y, x];
                    Color fillColor = dieColorMap.TryGetValue(value, out var c) ? c : Colors.Gray;

                    for (int dy = 0; dy < dieSizeY; dy++)
                    {
                        for (int dx = 0; dx < dieSizeX; dx++)
                        {
                            int px = x * dieSizeX + dx;
                            int py = y * dieSizeY + dy;

                            // 当 gridThickness > 0 时才绘制边线
                            bool isGridLine = gridThickness > 0 &&
                                              (dx < gridThickness || dy < gridThickness);

                            Color color = isGridLine ? actualGridColor : fillColor;

                            int offset = py * stride + px * 4;
                            byte* pPixel = (byte*)pBackBuffer + offset;
                            pPixel[0] = color.B;
                            pPixel[1] = color.G;
                            pPixel[2] = color.R;
                            pPixel[3] = color.A;
                        }
                    }
                }
            }
        }

        bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
        bitmap.Unlock();
        return bitmap;
    }

    /// <summary>
    /// 修改晶圆图数据中指定位置的芯片状态
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="row">目标芯片的行索引(从0开始)</param>
    /// <param name="col">目标芯片的列索引(从0开始)</param>
    /// <param name="newStatus">新的状态字符</param>
    /// <returns>是否成功修改</returns>
    public static bool UpdateDieStatus(WaferMapData data, int row, int col, string newStatus)
    {
        if (row < 0 || row >= data.Rows || col < 0 || col >= data.Columns)
            return false;
        // 修改状态
        data.Matrix[row, col] = newStatus;
        return true;
    }

    /// <summary>
    /// 批量修改晶圆图数据中多个芯片的位置状态
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="changes">每项包含 (row, col, newStatus)</param>
    /// <returns>成功修改的个数</returns>
    public static int UpdateDieStatuses(WaferMapData data, IEnumerable<(int row, int col, string newStatus)> changes)
    {
        if (data == null || data.Matrix == null)
            return 0;

        int successCount = 0;

        foreach (var (row, col, newStatus) in changes)
        {
            if (row >= 0 && row < data.Rows && col >= 0 && col < data.Columns)
            {
                data.Matrix[row, col] = newStatus;
                successCount++;
            }
        }

        return successCount;
    }

    /// <summary>
    /// 保存晶圆图为 PNG 文件
    /// </summary>
    /// <param name="filePath">PNG 文件路径</param>
    /// <param name="bitmap">晶圆图数据</param>
    public static void SaveBitmapToPng(string filePath, BitmapSource bitmap)
    {
        FileStream stream = new FileStream(filePath, FileMode.Create);
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bitmap));
        encoder.Save(stream);
    }

    /// <summary>
    /// 保存晶圆图数据到文件
    /// </summary>
    /// <param name="filePath">文件路径</param>
    /// <param name="data">晶圆图数据</param>
    /// <param name="dieDatas">反解析数组</param>
    /// <param name="isInterval">是否保留间隔</param>
    /// <param name="interval">间隔字符串</param>
    public static void SaveWaferDataToFile(string filePath, WaferMapData data, Dictionary<string, string> dieDatas, bool isInterval, string interval = " ")
    {
        StreamWriter writer = new StreamWriter(filePath);

        writer.WriteLine($"ROWCT:{data.Rows}");
        writer.WriteLine($"COLCT:{data.Columns}");

        for (int y = 0; y < data.Rows; y++)
        {
            StringBuilder sb = new StringBuilder("RowData:");
            for (int x = 0; x < data.Columns; x++)
            {
                foreach (var kvp in dieDatas)
                {
                    if (data.Matrix[y, x] == kvp.Key)
                    {
                        sb.Append(kvp.Value);
                        break;
                    }
                }
                if (isInterval)
                {
                    sb.Append(interval);
                }
            }
            writer.WriteLine(sb.ToString().TrimEnd());
        }
    }

    /// <summary>
    /// 获取晶圆图中所有芯片状态的总数量
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <returns></returns>
    public static Dictionary<string, int> CountAllDieStatuses(WaferMapData data)
    {
        Dictionary<string, int> statusCounts = new Dictionary<string, int>();

        if (data == null || data.Matrix == null)
            return statusCounts;

        for (int y = 0; y < data.Rows; y++)
        {
            for (int x = 0; x < data.Columns; x++)
            {
                string value = data.Matrix[y, x];
                if (!statusCounts.ContainsKey(value))
                    statusCounts[value] = 0;
                statusCounts[value]++;
            }
        }

        return statusCounts;
    }

    /// <summary>
    /// 获取晶圆图中指定芯片状态的总数量
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="targetStatus">要统计的目标状态(如 "001", "$$$", "X" 等)</param>
    /// <returns>该状态芯片的总数</returns>
    public static int CountDieStatus(WaferMapData data, string targetStatus)
    {
        if (data == null || data.Matrix == null)
            return 0;

        int count = 0;
        for (int y = 0; y < data.Rows; y++)
        {
            for (int x = 0; x < data.Columns; x++)
            {
                if (data.Matrix[y, x] == targetStatus)
                {
                    count++;
                }
            }
        }

        return count;
    }

    /// <summary>
    /// 统计指定行中某个芯片状态的数量
    /// </summary>
    public static int CountDieStatusInRow(WaferMapData data, int row, string targetStatus)
    {
        if (data == null || data.Matrix == null || row < 0 || row >= data.Rows)
            return 0;

        int count = 0;
        for (int x = 0; x < data.Columns; x++)
        {
            if (data.Matrix[row, x] == targetStatus)
                count++;
        }
        return count;
    }

    /// <summary>
    /// 统计指定列中某个芯片状态的数量
    /// </summary>
    public static int CountDieStatusInColumn(WaferMapData data, int col, string targetStatus)
    {
        if (data == null || data.Matrix == null || col < 0 || col >= data.Columns)
            return 0;

        int count = 0;
        for (int y = 0; y < data.Rows; y++)
        {
            if (data.Matrix[y, col] == targetStatus)
                count++;
        }
        return count;
    }

    /// <summary>
    /// 统计指定矩形区域内某个芯片状态的数量
    /// </summary>
    /// <param name="startRow">起始行索引(包含)</param>
    /// <param name="startCol">起始列索引(包含)</param>
    /// <param name="endRow">结束行索引(包含)</param>
    /// <param name="endCol">结束列索引(包含)</param>
    public static int CountDieStatusInRegion(WaferMapData data, int startRow, int startCol, int endRow, int endCol, string targetStatus)
    {
        if (data == null || data.Matrix == null)
            return 0;

        int count = 0;

        // 限制边界
        startRow = Math.Max(0, startRow);
        startCol = Math.Max(0, startCol);
        endRow = Math.Min(data.Rows - 1, endRow);
        endCol = Math.Min(data.Columns - 1, endCol);

        for (int y = startRow; y <= endRow; y++)
        {
            for (int x = startCol; x <= endCol; x++)
            {
                if (data.Matrix[y, x] == targetStatus)
                    count++;
            }
        }
        return count;
    }
}
相关推荐
唐青枫36 分钟前
C#.NET log4net 详解
c#·.net
Nemo_XP6 小时前
HttpHelper类处理两种HTTP POST请求
c#
lijingguang13 小时前
在C#中根据URL下载文件并保存到本地,可以使用以下方法(推荐使用现代异步方式)
开发语言·c#
¥-oriented13 小时前
【C#中路径相关的概念】
开发语言·c#
ArabySide14 小时前
【WCF】通过AOP实现基于JWT的授权与鉴权的实践
c#·jwt·aop·wcf
xiaowu08014 小时前
C# Task异步的常用方法
c#
阿蒙Amon14 小时前
C# Linq to Objects 详解:集合处理的终极方案
c#·solr·linq
钢铁男儿14 小时前
C# 委托(调用带引用参数的委托)
java·mysql·c#
weixin_4471035815 小时前
Wpf布局之Canvas面板!
wpf
番茄小能手15 小时前
【全网唯一】C# 纯本地离线文字识别Windows版dll插件
开发语言·c#