using System.Diagnostics.CodeAnalysis; using System.Drawing.Imaging; using System.Runtime.InteropServices; using Masuit.Tools; using Serilog; using Bitmap = System.Drawing.Bitmap; namespace DispenserCore.Service; [SuppressMessage("Interoperability", "CA1416:验证平台兼容性")] public class ImageService { private const string BasePath = "Dispenser"; private static readonly SystemParamsService SystemParamsService = new(); /// /// 保存 芯片飞拍照片 /// public static void SaveWaferImage(string batchCode, string waferCode, Bitmap image) { Task.Run(() => { try { // 文件保存路径的规则是 {user BasePath}/Dispenser/images/{yyyyMMdd}/{batchCode}/wafer/{waferCode}/{timestamp}.bmp var today = DateTime.Now.ToString("yyyyMMdd"); var systemParams = SystemParamsService.GetSystemParams(); var imageStoragePath = systemParams!.ImageStoragePath ?? Environment.GetEnvironmentVariable("USERPROFILE"); var dir = Path.Combine(imageStoragePath, BasePath, today, batchCode, "wafer", waferCode); SaveImageToFile(image, dir); } catch (Exception e) { Log.Error(e, "保存芯片飞拍照片失败"); } return Task.CompletedTask; }); } /// /// 保存PCB图片 /// /// /// /// /// public static void SavePcbImage(string batchCode, string pcbCode, Bitmap image) { Task.Run(() => { try { // 文件保存路径的规则是 {user BasePath}/{yyyyMMdd}/{batchCode}/pcb/{pcbCode}/{timestamp}.bmp var today = DateTime.Now.ToString("yyyyMMdd"); var systemParams = SystemParamsService.GetSystemParams(); var imageStoragePath = systemParams!.ImageStoragePath ?? Environment.GetEnvironmentVariable("USERPROFILE"); var dir = Path.Combine(imageStoragePath, BasePath, today, batchCode, "pcb", pcbCode); SaveImageToFile(image, dir); } catch (Exception e) { Log.Error(e, "保存基板图片失败"); } return Task.CompletedTask; }); } /// /// 保存动打检测图片 /// /// /// /// /// public static void SaveDetectImage(string batchCode, string pcbCode, Bitmap image) { Task.Run(() => { try { // 文件保存路径的规则是 {user BasePath}/{yyyyMMdd}/{batchCode}/pcb/{pcbCode}/{timestamp}.bmp var today = DateTime.Now.ToString("yyyyMMdd"); var systemParams = SystemParamsService.GetSystemParams(); var imageStoragePath = systemParams!.ImageStoragePath ?? Environment.GetEnvironmentVariable("USERPROFILE"); var dir = Path.Combine(imageStoragePath, BasePath, today, batchCode, "detect", pcbCode); SaveImageToFile(image, dir); } catch (Exception e) { Log.Error(e, "保存动打检测图片失败"); } return Task.CompletedTask; }); } private static void SaveImageToFile(Bitmap bitmap, string dir) { dir = dir.Replace("\n","").TrimEnd(); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var timestamp = DateTime.Now.Ticks; var fileName = $"{timestamp}.bmp"; // 保持到文件 SaveToFile(bitmap, Path.Combine(dir, fileName), ImageFormat.Bmp); } [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)] private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); /// /// 将照片保存到文件 /// /// /// /// /// /// public static void SaveToFile(Bitmap bitmap, string filePath, ImageFormat format) { if (bitmap == null) throw new ArgumentNullException(nameof(bitmap)); if (string.IsNullOrEmpty(filePath)) throw new ArgumentException("File path cannot be null or empty", nameof(filePath)); if (format == null) throw new ArgumentNullException(nameof(format)); // 将 Bitmap 转换为字节数组 using (MemoryStream memoryStream = new MemoryStream()) { bitmap.Save(memoryStream, format); var imageBytes = memoryStream.ToArray(); // 分配未管理的内存 var unmanagedPointer = Marshal.AllocHGlobal(imageBytes.Length); try { // 将托管数组复制到未管理的内存中 Marshal.Copy(imageBytes, 0, unmanagedPointer, imageBytes.Length); // 创建目标缓冲区并使用 RtlMoveMemory 进行内存复制 var destinationArray = new byte[imageBytes.Length]; var handle = GCHandle.Alloc(destinationArray, GCHandleType.Pinned); try { var destPointer = handle.AddrOfPinnedObject(); CopyMemory(destPointer, unmanagedPointer, (uint)imageBytes.Length); } finally { handle.Free(); } // 将目标缓冲区写入文件 File.WriteAllBytes(filePath, destinationArray); } finally { // 释放未管理的内存 Marshal.FreeHGlobal(unmanagedPointer); } } } }