Dispenser/DispenserCore/Service/ImageService.cs

188 lines
6.2 KiB
C#
Raw Normal View History

2024-08-16 07:20:09 +00:00
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();
/// <summary>
/// 保存 芯片飞拍照片
/// </summary>
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;
});
}
/// <summary>
/// 保存PCB图片
/// </summary>
/// <param name="batchCode"></param>
/// <param name="pcbCode"></param>
/// <param name="image"></param>
/// <returns></returns>
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;
});
}
/// <summary>
/// 保存动打检测图片
/// </summary>
/// <param name="batchCode"></param>
/// <param name="pcbCode"></param>
/// <param name="image"></param>
/// <returns></returns>
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);
/// <summary>
/// 将照片保存到文件
/// </summary>
/// <param name="bitmap"></param>
/// <param name="filePath"></param>
/// <param name="format"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
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);
}
}
}
}