Diag.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. using System;
  2. using System.IO;
  3. namespace AutoFocusTool
  4. {
  5. /// <summary>
  6. /// 自检用轻量图像诊断(不依赖 WPF)。
  7. /// 统计像素亮度,判断是全黑/全白/有图;裸写 24bpp BMP 存盘供肉眼确认。
  8. /// </summary>
  9. internal static class Diag
  10. {
  11. /// <summary>返回 (最小, 最大, 平均) 灰度。</summary>
  12. public static (int min, int max, double mean) Stats(byte[] bgr24)
  13. {
  14. int min = 255, max = 0;
  15. long sum = 0;
  16. // 每3字节取灰度,步进采样(每隔9像素)加速
  17. int n = 0;
  18. for (int i = 0; i + 2 < bgr24.Length; i += 27)
  19. {
  20. int g = (bgr24[i] * 29 + bgr24[i + 1] * 150 + bgr24[i + 2] * 77) >> 8;
  21. if (g < min) min = g;
  22. if (g > max) max = g;
  23. sum += g; n++;
  24. }
  25. return (min, max, n > 0 ? (double)sum / n : 0);
  26. }
  27. /// <summary>裸写 24bpp BMP(含 FlipY 翻正)。</summary>
  28. public static void SaveBmp(byte[] bgr24, int w, int h, string path)
  29. {
  30. int rowSize = ((w * 3 + 3) / 4) * 4; // 4字节对齐
  31. int imgSize = rowSize * h;
  32. int fileSize = 54 + imgSize;
  33. using var fs = new FileStream(path, FileMode.Create);
  34. using var bw = new BinaryWriter(fs);
  35. // BMP 文件头 14
  36. bw.Write((byte)'B'); bw.Write((byte)'M');
  37. bw.Write(fileSize); bw.Write(0); bw.Write(54);
  38. // DIB 头 40
  39. bw.Write(40); bw.Write(w); bw.Write(h); // h>0 → 自底向上,正好翻正相机的倒像
  40. bw.Write((short)1); bw.Write((short)24);
  41. bw.Write(0); bw.Write(imgSize);
  42. bw.Write(2835); bw.Write(2835); bw.Write(0); bw.Write(0);
  43. // 像素:BMP 自底向上存,相机数据是倒的,直接顺序写即翻正
  44. byte[] pad = new byte[rowSize - w * 3];
  45. for (int y = 0; y < h; y++)
  46. {
  47. int row = y * w * 3;
  48. bw.Write(bgr24, row, w * 3);
  49. if (pad.Length > 0) bw.Write(pad);
  50. }
  51. }
  52. }
  53. }