using System.Drawing; using Emgu.CV; using Emgu.CV.CvEnum; namespace XP.Calibration.Core; /// /// RAW 投影数据读取器 | RAW projection data reader /// public static class RawReader { /// /// 从 RAW 文件读取 float32 投影序列 /// /// 文件路径 /// 图像宽度 /// 图像高度 /// 投影帧数 /// Mat 列表 (CV_32F) public static List ReadFloat32(string path, int width, int height, int count) { var projections = new List(count); int frameBytes = width * height * sizeof(float); using var stream = new FileStream(path, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[frameBytes]; for (int i = 0; i < count; i++) { int bytesRead = stream.Read(buffer, 0, frameBytes); if (bytesRead < frameBytes) throw new EndOfStreamException( $"帧 {i} 数据不足: 期望 {frameBytes} 字节, 实际 {bytesRead} 字节"); var mat = new Mat(height, width, DepthType.Cv32F, 1); System.Runtime.InteropServices.Marshal.Copy(buffer, 0, mat.DataPointer, frameBytes); projections.Add(mat); } return projections; } /// /// 读取单张 TIFF 图像, 返回 CV_32F 灰度 Mat /// /// TIFF 文件路径 /// Mat (CV_32F, 单通道) public static Mat ReadTiff(string path) { if (!File.Exists(path)) throw new FileNotFoundException($"TIFF 文件不存在: {path}"); // 以原始深度读取 (支持 8/16/32bit TIFF) var src = CvInvoke.Imread(path, ImreadModes.AnyDepth | ImreadModes.Grayscale); if (src.IsEmpty) throw new InvalidOperationException($"无法读取 TIFF: {path}"); // 统一转为 CV_32F if (src.Depth != DepthType.Cv32F) { var dst = new Mat(); src.ConvertTo(dst, DepthType.Cv32F); src.Dispose(); return dst; } return src; } /// /// 批量读取多张 TIFF 图像 (按文件名排序) /// /// TIFF 文件所在目录 /// 搜索模式, 默认 "*.tif" /// Mat 列表 (CV_32F) public static List ReadTiffSequence(string directory, string pattern = "*.tif") { if (!Directory.Exists(directory)) throw new DirectoryNotFoundException($"目录不存在: {directory}"); var files = Directory.GetFiles(directory, pattern) .Concat(Directory.GetFiles(directory, pattern + "f")) // 同时匹配 .tif 和 .tiff .Distinct() .OrderBy(f => f) .ToList(); if (files.Count == 0) throw new FileNotFoundException($"目录中未找到 TIFF 文件: {directory}"); return files.Select(ReadTiff).ToList(); } }