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