ImageConverter.cs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using System;
  2. using System.IO;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.Runtime.InteropServices;
  6. using System.Windows.Media.Imaging;
  7. namespace AutoFocusTool.Imaging
  8. {
  9. /// <summary>
  10. /// 图像转换工具:把相机的 24bpp BGR 原始字节转成可显示/可保存的位图。
  11. /// 相机原始数据上下颠倒,统一在这里做 FlipY,保证显示、存图、算分用的是同一朝向。
  12. /// </summary>
  13. public static class ImageConverter
  14. {
  15. /// <summary>
  16. /// 24bpp BGR 字节数组 → System.Drawing.Bitmap(已 FlipY 翻正)。
  17. /// 调用方负责 Dispose。
  18. /// </summary>
  19. public static Bitmap ToBitmap(byte[] bgr24, int width, int height)
  20. {
  21. var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
  22. BitmapData data = bmp.LockBits(
  23. new Rectangle(0, 0, width, height),
  24. ImageLockMode.WriteOnly, bmp.PixelFormat);
  25. // 注意 stride 可能 > width*3(行对齐),逐行拷贝避免错位
  26. int rowBytes = width * 3;
  27. if (data.Stride == rowBytes)
  28. {
  29. Marshal.Copy(bgr24, 0, data.Scan0, Math.Min(bgr24.Length, rowBytes * height));
  30. }
  31. else
  32. {
  33. for (int y = 0; y < height; y++)
  34. {
  35. Marshal.Copy(bgr24, y * rowBytes, data.Scan0 + y * data.Stride, rowBytes);
  36. }
  37. }
  38. bmp.UnlockBits(data);
  39. // 相机数据上下颠倒,翻正
  40. bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
  41. return bmp;
  42. }
  43. /// <summary>
  44. /// 24bpp BGR 字节 → WPF BitmapSource(冻结,可跨线程绑定到 Image.Source)。
  45. /// </summary>
  46. public static BitmapSource ToBitmapSource(byte[] bgr24, int width, int height)
  47. {
  48. using (var bmp = ToBitmap(bgr24, width, height))
  49. using (var ms = new MemoryStream())
  50. {
  51. bmp.Save(ms, ImageFormat.Bmp);
  52. ms.Position = 0;
  53. var bi = new BitmapImage();
  54. bi.BeginInit();
  55. bi.StreamSource = ms;
  56. bi.CacheOption = BitmapCacheOption.OnLoad;
  57. bi.EndInit();
  58. bi.Freeze();
  59. return bi;
  60. }
  61. }
  62. /// <summary>保存当前帧为 BMP(已翻正)。</summary>
  63. public static void SaveBmp(byte[] bgr24, int width, int height, string path)
  64. {
  65. using (var bmp = ToBitmap(bgr24, width, height))
  66. {
  67. bmp.Save(path, ImageFormat.Bmp);
  68. }
  69. }
  70. }
  71. }