using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;
namespace AutoFocusTool.Imaging
{
///
/// 图像转换工具:把相机的 24bpp BGR 原始字节转成可显示/可保存的位图。
/// 相机原始数据上下颠倒,统一在这里做 FlipY,保证显示、存图、算分用的是同一朝向。
///
public static class ImageConverter
{
///
/// 24bpp BGR 字节数组 → System.Drawing.Bitmap(已 FlipY 翻正)。
/// 调用方负责 Dispose。
///
public static Bitmap ToBitmap(byte[] bgr24, int width, int height)
{
var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData data = bmp.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, bmp.PixelFormat);
// 注意 stride 可能 > width*3(行对齐),逐行拷贝避免错位
int rowBytes = width * 3;
if (data.Stride == rowBytes)
{
Marshal.Copy(bgr24, 0, data.Scan0, Math.Min(bgr24.Length, rowBytes * height));
}
else
{
for (int y = 0; y < height; y++)
{
Marshal.Copy(bgr24, y * rowBytes, data.Scan0 + y * data.Stride, rowBytes);
}
}
bmp.UnlockBits(data);
// 相机数据上下颠倒,翻正
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmp;
}
///
/// 24bpp BGR 字节 → WPF BitmapSource(冻结,可跨线程绑定到 Image.Source)。
///
public static BitmapSource ToBitmapSource(byte[] bgr24, int width, int height)
{
using (var bmp = ToBitmap(bgr24, width, height))
using (var ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.Bmp);
ms.Position = 0;
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
bi.Freeze();
return bi;
}
}
/// 保存当前帧为 BMP(已翻正)。
public static void SaveBmp(byte[] bgr24, int width, int height, string path)
{
using (var bmp = ToBitmap(bgr24, width, height))
{
bmp.Save(path, ImageFormat.Bmp);
}
}
}
}