1590 lines
64 KiB
C#
1590 lines
64 KiB
C#
/*
|
|
* Copyright (c) 2025 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using Aurora;
|
|
using Aurora.Api;
|
|
using Aurora.Api.DataType;
|
|
using VisionCommon;
|
|
using Hermes;
|
|
using Matrox.MatroxImagingLibrary;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Linq;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Runtime.InteropServices;
|
|
using System.Reactive.Linq;
|
|
using VisionCommonUI;
|
|
using VisionCommonUI.Resources;
|
|
|
|
namespace MilCommon {
|
|
/// <summary>
|
|
/// MIL 환경 변수 및 메소드 관리
|
|
/// </summary>
|
|
public class MilEnvironment : IDisposable {
|
|
private static readonly Logger _Logger = new Logger("MilEnvironment");
|
|
private static object LockObj = new object();
|
|
private MIL_INT _LicenseModules = 0;
|
|
private List<MIL_ID> DisplayList;
|
|
|
|
public MIL_ID Application { get; private set; }
|
|
|
|
// M_DEFAULT를 사용하는 경우, 시스템을 _DefaultSys 1개만 할당한다.
|
|
private MIL_ID _DefaultSys;
|
|
|
|
// M_DEFAULT가 아닐 경우, 시스템을 BoardType & Slot의 개수만큼 할당한다.
|
|
private Dictionary<eBoardType, Dictionary<eBoardSlotPos, MIL_ID>> Systems { get; set; }
|
|
= new Dictionary<eBoardType, Dictionary<eBoardSlotPos, MIL_ID>>();
|
|
|
|
private static MilEnvironment _instance = null;
|
|
/// <summary>
|
|
/// 싱글톤 객체
|
|
/// </summary>
|
|
public static MilEnvironment Instance {
|
|
get {
|
|
lock (LockObj) {
|
|
if (_instance == null) {
|
|
_instance = new MilEnvironment();
|
|
}
|
|
return _instance;
|
|
}
|
|
}
|
|
}
|
|
|
|
private MilEnvironment() {
|
|
IpAdapter.Instance.IpEnvironment = new IpEnvironment();
|
|
DisplayList = new List<MIL_ID>();
|
|
CheckLangToken();
|
|
AllocApp();
|
|
SetMilErrPrintType();
|
|
VisionEnv.AuroraEnv.EventObservable.AsObservable(AuroraSysEvent.SYS_SETTING_CHANGED)
|
|
.Where(msg => (string)msg.Param == VisionKeys.VisionSettingKey).Subscribe(x => UpdateVisionSettingActions());
|
|
}
|
|
|
|
private void CheckLangToken() {
|
|
string lastLanguage = (VisionEnv.AuroraEnv.SettingEntry[AuroraSettings.Equipment] as EquipmentInfo)?.Language ?? null;
|
|
if (lastLanguage != null && lastLanguage.Length > 0) {
|
|
System.Globalization.CultureInfo.CurrentCulture = new System.Globalization.CultureInfo(lastLanguage);
|
|
StrTokens.Culture = System.Globalization.CultureInfo.CurrentCulture;
|
|
}
|
|
}
|
|
|
|
private void AllocApp() {
|
|
try {
|
|
MIL_ID app = MIL.M_NULL;
|
|
|
|
MIL.MappAlloc(MIL.M_NULL, MIL.M_DEFAULT, ref app);
|
|
_Logger.FuncI(string.Format("MilApplication : {0}", app));
|
|
MIL.MappInquire(app, MIL.M_LICENSE_MODULES, ref _LicenseModules);
|
|
CheckMilVersion();
|
|
Application = app;
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.E(e.Message);
|
|
}
|
|
}
|
|
|
|
private void CheckMilVersion() {
|
|
if (!VersionChecker.CheckMilVersionAndType()) {
|
|
MessageBoxUtil.ShowMessageBoxWarning(
|
|
string.Format(StrTokens.MSG_W_MilVersion, VersionChecker.GetMilVersion(), VersionChecker.GetMilType()));
|
|
}
|
|
}
|
|
|
|
private void UpdateVisionSettingActions() {
|
|
SetMilErrPrintType();
|
|
}
|
|
|
|
private void SetMilErrPrintType() {
|
|
var visionSetting = VisionEnv.AuroraEnv.SettingEntry[VisionKeys.VisionSettingKey] as VisionSetting;
|
|
switch (visionSetting.MilErrPrint) {
|
|
case eMilErrPrint.PRINT_ENABLE:
|
|
MIL.MappControl(MIL.M_DEFAULT, MIL.M_ERROR, MIL.M_PRINT_ENABLE);
|
|
break;
|
|
case eMilErrPrint.PRINT_DISABLE:
|
|
MIL.MappControl(MIL.M_DEFAULT, MIL.M_ERROR, MIL.M_PRINT_DISABLE);
|
|
break;
|
|
case eMilErrPrint.THROW_EXCEPTION:
|
|
MIL.MappControl(MIL.M_DEFAULT, MIL.M_ERROR, MIL.M_THROW_EXCEPTION);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// MIL 시스템 가져오기
|
|
/// </summary>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns>MIL 시스템</returns>
|
|
public MIL_ID GetSystem(eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
AllocSys(boardType, boardSlotPos);
|
|
|
|
if (Systems.ContainsKey(boardType)) {
|
|
if (Systems[boardType].ContainsKey(boardSlotPos)) {
|
|
return Systems[boardType][boardSlotPos];
|
|
}
|
|
else {
|
|
_Logger.FuncE($"MilSystems[{boardType}] do not contain boardSlotPos [{boardSlotPos}]");
|
|
}
|
|
}
|
|
else {
|
|
_Logger.FuncE($"MilSystems do not contain boardType [{boardType}]");
|
|
}
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
/// <summary>
|
|
/// MIL 시스템 할당 여부 체크
|
|
/// </summary>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns></returns>
|
|
public bool IsSysAllocated(eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
if (Systems.ContainsKey(boardType)) {
|
|
if (Systems[boardType].ContainsKey(boardSlotPos)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지로 MIL 시스템 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>MIL 시스템</returns>
|
|
public static MIL_ID GetSystemOfBuffer(MIL_ID image) {
|
|
return (MIL_ID)MIL.MbufInquire(image, MIL.M_OWNER_SYSTEM, MIL.M_NULL);
|
|
}
|
|
|
|
/// <summary>
|
|
/// MIL 시스템 할당
|
|
/// </summary>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
public void AllocSys(eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
try {
|
|
lock (LockObj) {
|
|
if (IsSysAllocated(boardType, boardSlotPos)) {
|
|
return;
|
|
}
|
|
|
|
if (!Systems.ContainsKey(boardType)) {
|
|
Systems.Add(boardType, new Dictionary<eBoardSlotPos, MIL_ID>());
|
|
}
|
|
if (!Systems[boardType].ContainsKey(boardSlotPos)) {
|
|
MIL_ID sys = MIL.M_NULL;
|
|
string sysDescriptor = GetSystemDescriptor(boardType);
|
|
|
|
if (sysDescriptor == MIL.M_SYSTEM_DEFAULT) {
|
|
// M_SYSTEM_DEFAULT일 경우 MIL System이 1개만 있으면 된다.
|
|
if (_DefaultSys == MIL.M_NULL) {
|
|
MIL.MsysAlloc(MIL.M_DEFAULT, sysDescriptor, (int)boardSlotPos, MIL.M_DEFAULT, ref _DefaultSys);
|
|
}
|
|
sys = _DefaultSys;
|
|
}
|
|
else {
|
|
// M_SYSTEM_DEFAULT이 아닐 경우 MIL System은 Slot 개수만큼 존재한다.
|
|
MIL.MsysAlloc(MIL.M_DEFAULT, sysDescriptor, (int)boardSlotPos, MIL.M_DEFAULT, ref sys);
|
|
}
|
|
|
|
_Logger.FuncI(string.Format("BoardType : {0} / BoardSlotPos : {1} / MilSystem[{2}] : {3}",
|
|
sysDescriptor, (int)boardSlotPos, (int)boardSlotPos, sys));
|
|
|
|
Systems[boardType].Add(boardSlotPos, sys);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.E(e.Message);
|
|
}
|
|
}
|
|
|
|
private string GetSystemDescriptor(eBoardType boardType) {
|
|
if (EquipmentInfoManager.EquipmentInfo.SimulationMode) {
|
|
// M_SYSTEM_DEFAULT일 경우, 시뮬에서 eBoardSlotPos이 달라도 eBoardType이 같으면 할당이 안됨.
|
|
return MIL.M_SYSTEM_HOST;
|
|
}
|
|
|
|
switch (boardType) {
|
|
case eBoardType.MIL_GIGE:
|
|
return MIL.M_SYSTEM_GIGE_VISION;
|
|
case eBoardType.MIL_CL_SOLIOS:
|
|
return MIL.M_SYSTEM_SOLIOS;
|
|
case eBoardType.MIL_CXP_RADIENT:
|
|
return MIL.M_SYSTEM_RADIENTCXP;
|
|
case eBoardType.MIL_CXP_RAPIXO:
|
|
return MIL.M_SYSTEM_RAPIXOCXP;
|
|
case eBoardType.EURESYS_GIGELINK:
|
|
case eBoardType.EURESYS_COAXLINK:
|
|
case eBoardType.EURESYS_GRABLINK:
|
|
default:
|
|
return MIL.M_SYSTEM_DEFAULT;
|
|
}
|
|
}
|
|
|
|
public static bool IsValidContextId(MIL_ID contextId) {
|
|
if (contextId != MIL.M_NULL) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// MIL 라이센스 체크
|
|
/// </summary>
|
|
/// <returns>라이센스 여부</returns>
|
|
public bool HasValidLicense() {
|
|
return (_LicenseModules & MIL.M_LICENSE_MOD) != 0;
|
|
}
|
|
/// <summary>
|
|
/// 디스플레이 생성
|
|
/// </summary>
|
|
/// <param name="WinFormHandle">윈폼 핸들러(IntPtr)</param>
|
|
/// <param name="imageBuffer">이미지 버퍼 Mil_ID</param>
|
|
/// <returns>Display ID (MIL_ID)</returns>
|
|
public MIL_ID CreateDisplay(IntPtr WinFormHandle, MIL_ID imageBuffer) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
lock (LockObj) {
|
|
MIL_ID displayId = MIL.M_NULL;
|
|
MIL.MdispAlloc(GetSystemOfBuffer(imageBuffer), MIL.M_DEFAULT, "MIL.M_DEFAULT", MIL.M_DEFAULT, ref displayId);
|
|
MIL.MdispSelectWindow(displayId, imageBuffer, WinFormHandle);
|
|
DisplayList.Add(displayId);
|
|
|
|
return displayId;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 해당 디스플레이 선택
|
|
/// </summary>
|
|
/// <param name="WinFormHandle">윈폼 핸들러(IntPtr)</param>
|
|
/// <param name="imageBuffer">이미지 버퍼 Mil_ID</param>
|
|
/// <param name="displayId">선택할 Display Id (MIL_ID)</param>
|
|
public void SelectDisplay(IntPtr WinFormHandle, MIL_ID imageBuffer, MIL_ID displayId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return;
|
|
}
|
|
|
|
lock (LockObj) {
|
|
MIL.MdispSelectWindow(displayId, imageBuffer, WinFormHandle);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 디스플레이 해제/제거
|
|
/// </summary>
|
|
/// <param name="displayId">해제할 Display Id (MIL_ID)</param>
|
|
public void DestroyDisplay(MIL_ID displayId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return;
|
|
}
|
|
|
|
lock (LockObj) {
|
|
if (displayId != MIL.M_NULL) {
|
|
DisplayList.Remove(displayId);
|
|
MIL.MdispFree(displayId);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Obsolete]
|
|
public void Dispose() {
|
|
if (!Instance.HasValidLicense()) {
|
|
return;
|
|
}
|
|
|
|
foreach (var itemPairs in Systems) {
|
|
foreach (var systemPairs in itemPairs.Value) {
|
|
MIL_ID sys = systemPairs.Value;
|
|
if (sys != MIL.M_NULL) {
|
|
MIL.MsysFree(sys);
|
|
}
|
|
}
|
|
}
|
|
Systems.Clear();
|
|
|
|
if (Application != MIL.M_NULL) {
|
|
MIL.MappFree(Application);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 원본 이미지 버퍼 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="image">원본 이미지 버퍼</param>
|
|
/// <returns>성공 유무</returns>
|
|
public int AllocOriginalImage(CamConfig camConfig, ref MIL_ID image) {
|
|
switch (camConfig.ImageSize.Channel) {
|
|
case 1:
|
|
// 원본이미지는 항상 정사이즈 (W > H)
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Width,
|
|
camConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
case 3:
|
|
default:
|
|
// 원본이미지는 항상 정사이즈 (W > H)
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
camConfig.ImageSize.Width,
|
|
camConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flip & Rotation 이미지 버퍼 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="image">Flip & Rotation 이미지 버퍼</param>
|
|
/// <returns>성공 유무</returns>
|
|
public int AllocFilteredImage(CamConfig camConfig, ref MIL_ID image) {
|
|
switch (camConfig.ImageSize.Channel) {
|
|
case 1:
|
|
if (IsHeightLongerThanWidth(camConfig)) {
|
|
// 가로 < 세로
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Height,
|
|
camConfig.ImageSize.Width,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
else {
|
|
// 가로 > 세로
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Width,
|
|
camConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
case 3:
|
|
default:
|
|
if (IsHeightLongerThanWidth(camConfig)) {
|
|
// 가로 < 세로
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
camConfig.ImageSize.Height,
|
|
camConfig.ImageSize.Width,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
else {
|
|
// 가로 > 세로
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
camConfig.ImageSize.Width,
|
|
camConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crop 이미지 버퍼 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="image">Crop 이미지 버퍼</param>
|
|
/// <returns>성공 유무</returns>
|
|
public int AllocCroppedImage(CamConfig camConfig, ref MIL_ID image) {
|
|
switch (camConfig.ImageSize.Channel) {
|
|
case 1:
|
|
if (IsHeightLongerThanWidth(camConfig)) {
|
|
// 가로 < 세로
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
(int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY),
|
|
(int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX),
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
else {
|
|
// 가로 > 세로
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
(int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX),
|
|
(int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY),
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
case 3:
|
|
default:
|
|
if (IsHeightLongerThanWidth(camConfig)) {
|
|
// 가로 < 세로
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
(int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY),
|
|
(int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX),
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
else {
|
|
// 가로 > 세로
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
(int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX),
|
|
(int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY),
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref image);
|
|
ClearImage((MIL_ID)image);
|
|
|
|
return (image == MIL.M_NULL || image == 0) ? E1.GENERIC : E1.OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dig Process 이미지 배열 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="bufferSize">버퍼 사이즈</param>
|
|
/// <param name="images">Proc 이미지 버퍼 배열</param>
|
|
/// <returns></returns>
|
|
public int AllocProcImages(CamConfig camConfig, int bufferSize, ref object[] images) {
|
|
switch (camConfig.ImageSize.Channel) {
|
|
case 1:
|
|
for (int i = 0; i < bufferSize; i++) {
|
|
MIL_ID allocImage = MIL.M_NULL;
|
|
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Width,
|
|
camConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref allocImage);
|
|
|
|
ClearImage(allocImage);
|
|
images[i] = allocImage;
|
|
}
|
|
break;
|
|
case 3:
|
|
default:
|
|
for (int i = 0; i < bufferSize; i++) {
|
|
MIL_ID allocImage = MIL.M_NULL;
|
|
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
camConfig.ImageSize.Width,
|
|
camConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref allocImage);
|
|
|
|
ClearImage(allocImage);
|
|
images[i] = allocImage;
|
|
}
|
|
break;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Child 이미지 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="parentImage">부모 이미지 버퍼</param>
|
|
/// <param name="childImages">자식 이미지 버퍼 배열</param>
|
|
/// <returns></returns>
|
|
public int AllocChildImages(CamConfig camConfig, object parentImage, ref object[] childImages) {
|
|
try {
|
|
if (parentImage == null) {
|
|
_Logger.FuncE($"parentImage is null.");
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (camConfig.ChildImage.ChildBufRowCols.Count == 0) {
|
|
// Default 설정
|
|
for (int rowIdx = 0; rowIdx < camConfig.ChildImage.RowCnt; rowIdx++) {
|
|
for (int colIdx = 0; colIdx < camConfig.ChildImage.ColCnt; colIdx++) {
|
|
camConfig.ChildImage.ChildBufRowCols.Add(new ChildBufRowCol() { RowIdx = rowIdx, ColIdx = colIdx});
|
|
}
|
|
}
|
|
}
|
|
|
|
childImages = new object[camConfig.ChildImage.ChildBufRowCols.Count];
|
|
for (int i = 0; i < childImages.Length; i++) {
|
|
childImages[i] = MIL.M_NULL;
|
|
}
|
|
|
|
int childWidth = camConfig.ImageSize.Width;
|
|
int childHeight = camConfig.ImageSize.Height;
|
|
|
|
for (int i = 0; i < camConfig.ChildImage.ChildBufRowCols.Count; i++) {
|
|
var childBufRowCol = camConfig.ChildImage.ChildBufRowCols[i];
|
|
//if (!childBufRowCol.Enabled) {
|
|
// continue;
|
|
//}
|
|
|
|
int offsetX = childBufRowCol.ColIdx * childWidth;
|
|
int offsetY = childBufRowCol.RowIdx * childHeight;
|
|
|
|
MIL_ID childImage = MIL.M_NULL;
|
|
MIL.MbufChild2d((MIL_ID)parentImage, offsetX, offsetY, childWidth, childHeight, ref childImage);
|
|
|
|
if (childImages.Length > childBufRowCol.PosIdx) {
|
|
childImages[childBufRowCol.PosIdx] = childImage;
|
|
}
|
|
else {
|
|
_Logger.FuncE("[ERROR] childImages.Length <= childBufRowCol.PosIdx");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Child 이미지 사용시, 부모 이미지 버퍼 할당
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <param name="image">부모 이미지 버퍼</param>
|
|
/// <returns>성공 유무</returns>
|
|
public int AllocParentImage(CamConfig camConfig, ref object image) {
|
|
MIL_ID allocImage = MIL.M_NULL;
|
|
|
|
switch (camConfig.ImageSize.Channel) {
|
|
case 1:
|
|
MIL.MbufAlloc2d(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Width * camConfig.ChildImage.ColCnt,
|
|
camConfig.ImageSize.Height * camConfig.ChildImage.RowCnt,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref allocImage);
|
|
break;
|
|
case 3:
|
|
default:
|
|
MIL.MbufAllocColor(
|
|
GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos),
|
|
camConfig.ImageSize.Channel,
|
|
camConfig.ImageSize.Width * camConfig.ChildImage.ColCnt,
|
|
camConfig.ImageSize.Height * camConfig.ChildImage.RowCnt,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref allocImage);
|
|
break;
|
|
}
|
|
ClearImage(allocImage);
|
|
image = allocImage;
|
|
|
|
return image == null ? E1.GENERIC : E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 반전 유무 확인
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>이미지 반전 유무</returns>
|
|
public bool IsFlipEnabled(CamConfig camConfig) {
|
|
if (camConfig.FlipAndRotation.ImageFlip.Equals(eImageFlip.None))
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 회전 유무 확인
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>이미지 회전 유무</returns>
|
|
public bool IsRotationEnabled(CamConfig camConfig) {
|
|
if (camConfig.FlipAndRotation.ImageRotation.Equals(eImageRotation.None) &&
|
|
camConfig.FlipAndRotation.ImageRotationOffset == 0)
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 세로 사이즈가 가로 사이즈보다 큰지 확인
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>이미지 세로 사이즈가 가로 사이즈보다 크면 True</returns>
|
|
public bool IsHeightLongerThanWidth(CamConfig camConfig) {
|
|
switch (camConfig.FlipAndRotation.ImageRotation) {
|
|
case eImageRotation.CW_DEG_90:
|
|
case eImageRotation.CW_DEG_270:
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일경로</param>
|
|
/// <param name="imageId">이미지버퍼 MIL_ID</param>
|
|
/// <param name="roi">크롭(저장) 할 영역</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int SaveImage(string filePath, MIL_ID imageId, Rect roi) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
try {
|
|
MIL_ID childImage = CropImage(imageId, roi);
|
|
SaveImage(filePath, childImage);
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일경로</param>
|
|
/// <param name="imageId">이미지버퍼 MIL_ID</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int SaveImage(string filePath, MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
try {
|
|
var dirPath = Path.GetDirectoryName(filePath);
|
|
if (!Directory.Exists(dirPath)) {
|
|
new DirectoryInfo(dirPath).Create();
|
|
}
|
|
|
|
if (filePath.ToLower().EndsWith("bmp")) {
|
|
MIL.MbufExport(filePath, MIL.M_BMP, imageId);
|
|
}
|
|
else if (filePath.ToLower().EndsWith("png")) {
|
|
MIL.MbufExport(filePath, MIL.M_PNG, imageId);
|
|
}
|
|
else if (filePath.ToLower().EndsWith("jpg")) {
|
|
MIL.MbufExport(filePath, MIL.M_JPEG_LOSSY, imageId);
|
|
}
|
|
else {
|
|
MIL.MbufExport(filePath, MIL.M_PNG, imageId);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 로드
|
|
/// </summary>
|
|
/// <param name="filePath">불러올 이미지 경로</param>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns>이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID LoadImage(string filePath, CamConfig camConfig) {
|
|
return LoadImage(filePath, Instance.GetSystem(camConfig.CamConnConfig.BoardType, camConfig.CamConnConfig.BoardSlotPos));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 로드
|
|
/// </summary>
|
|
/// <param name="filePath">불러올 이미지 경로</param>
|
|
/// <param name="milSystemId">Mil 시스템 Id</param>
|
|
/// <returns>이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID LoadImage(string filePath, MIL_ID milSystemId) {
|
|
MIL_ID loadImage = MIL.M_NULL;
|
|
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
try {
|
|
if (!File.Exists(filePath)) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
MIL.MbufRestore(filePath, milSystemId, ref loadImage);
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return loadImage;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 복사
|
|
/// </summary>
|
|
/// <param name="srcImage">소스 이미지 버퍼</param>
|
|
/// <param name="dstImage">목적지 이미지 버퍼</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int CopyImage(MIL_ID srcImage, MIL_ID dstImage) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (IsCopyableBuffer(srcImage, dstImage)) {
|
|
MIL.MbufCopy(srcImage, dstImage);
|
|
return E1.OK;
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 버퍼 카피 가능한지 여부
|
|
/// </summary>
|
|
/// <param name="srcImage">소스 이미지 버퍼</param>
|
|
/// <param name="dstImage">목적지 이미지 버퍼</param>
|
|
/// <returns></returns>
|
|
public static bool IsCopyableBuffer(MIL_ID srcImage, MIL_ID dstImage) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return false;
|
|
}
|
|
|
|
var srcImageSize = GetImageSize(srcImage);
|
|
var dstImageSize = GetImageSize(dstImage);
|
|
|
|
if (srcImageSize.Width == dstImageSize.Width &&
|
|
srcImageSize.Height == dstImageSize.Height) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 복제
|
|
/// </summary>
|
|
/// <param name="imageId">복제할 이미지 ID</param>
|
|
/// <returns>복제된 이미지 MIL_ID</returns>
|
|
public static MIL_ID CloneImage(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
return CloneImage(imageId, GetSystemOfBuffer(imageId));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 복제
|
|
/// </summary>
|
|
/// <param name="imageId">복제할 이미지 ID</param>
|
|
/// <param name="systemId">MIL 시스템 ID</param>
|
|
/// <returns>복제된 이미지 MIL_ID</returns>
|
|
public static MIL_ID CloneImage(MIL_ID imageId, MIL_ID systemId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
return MIL.MbufClone(imageId, systemId,
|
|
MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_IMAGE + MIL.M_PROC + MIL.M_DISP, MIL.M_COPY_SOURCE_DATA, MIL.M_NULL);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 호환가능한 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns>호환가능한 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleImageBuffer(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
return GetCompatibleImageBuffer(imageSize, GetSystemOfBuffer(imageId));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 호환가능한 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns>호환가능한 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleImageBuffer(ImageSize imageSize, eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
return GetCompatibleImageBuffer(imageSize, Instance.GetSystem(boardType, boardSlotPos));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 호환가능한 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="systemId"> Mil 시스템 Id</param>
|
|
/// <returns>호환가능한 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleImageBuffer(ImageSize imageSize, MIL_ID systemId) {
|
|
if (imageSize.Channel == 1) {
|
|
return GetCompatibleGrayImageBuffer(imageSize, systemId);
|
|
}
|
|
else {
|
|
return GetCompatibleColorImageBuffer(imageSize, systemId);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 호환가능한 Gray 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns>호환가능한 Gray 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleGrayImageBuffer(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
return GetCompatibleGrayImageBuffer(imageSize, GetSystemOfBuffer(imageId));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 호환가능한 Gray이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns>호환가능한 Gray 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleGrayImageBuffer(ImageSize imageSize, eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
return GetCompatibleGrayImageBuffer(imageSize, Instance.GetSystem(boardType, boardSlotPos));
|
|
}
|
|
/// <summary>
|
|
/// 호환가능한 Gray 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="systemId"> Mil 시스템 Id</param>
|
|
/// <returns>호환가능한 Gray 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleGrayImageBuffer(ImageSize imageSize, MIL_ID systemId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
MIL_ID grayImageId = MIL.M_NULL;
|
|
|
|
MIL.MbufAlloc2d(
|
|
systemId,
|
|
imageSize.Width,
|
|
imageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref grayImageId);
|
|
MIL.MbufClear(grayImageId, 0);
|
|
|
|
return grayImageId;
|
|
}
|
|
/// <summary>
|
|
/// 호환가능한 Color 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns>호환가능한 Color 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleColorImageBuffer(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
return GetCompatibleColorImageBuffer(imageSize, GetSystemOfBuffer(imageId));
|
|
}
|
|
/// <summary>
|
|
/// 호환가능한 Color 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns>호환가능한 Color 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleColorImageBuffer(ImageSize imageSize, eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
return GetCompatibleColorImageBuffer(imageSize, Instance.GetSystem(boardType, boardSlotPos));
|
|
}
|
|
/// <summary>
|
|
/// 호환가능한 Color 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="systemId"> Mil 시스템 Id</param>
|
|
/// <returns>호환가능한 Color 이미지 버퍼 MIL_ID</returns>
|
|
public static MIL_ID GetCompatibleColorImageBuffer(ImageSize imageSize, MIL_ID systemId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
MIL_ID imageBuffer = MIL.M_NULL;
|
|
|
|
MIL.MbufAllocColor(
|
|
systemId,
|
|
3,
|
|
imageSize.Width,
|
|
imageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref imageBuffer);
|
|
MIL.MbufClear(imageBuffer, 0);
|
|
|
|
return imageBuffer;
|
|
}
|
|
/// <summary>
|
|
/// 이미지 크롭
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <param name="roi"></param>
|
|
/// <returns></returns>
|
|
public static MIL_ID CropImage(MIL_ID imageId, Rect roi) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
ImageSize imageSize = GetImageSize(imageId);
|
|
if (imageSize.Width == roi.Width && imageSize.Height == roi.Height) {
|
|
return imageId;
|
|
}
|
|
else {
|
|
// roi의 Angle을 고려한 Crop API가 있으면 좋을 것 같음. 현재는 Crop시, Angle을 고려하지 않음.
|
|
return MIL.MbufChild2d(imageId, (int)roi.Left, (int)roi.Top, (int)roi.Width, (int)roi.Height, MIL.M_NULL);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 이미지 크롭
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <param name="roi"></param>
|
|
/// <returns></returns>
|
|
public static MIL_ID CropImage(MIL_ID imageId, ROI roi) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
if (imageSize.Width > roi.Width && imageSize.Height > roi.Height) {
|
|
// roi의 Angle을 고려한 Crop API가 있으면 좋을 것 같음. 현재는 Crop시, Angle을 고려하지 않음.
|
|
return MIL.MbufChild2d(imageId, (int)roi.Left, (int)roi.Top, (int)roi.Width, (int)roi.Height, MIL.M_NULL);
|
|
}
|
|
else {
|
|
return imageId;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 리소스 회수
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 ID</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int FreeImage(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (imageId != MIL.M_NULL) {
|
|
MIL.MbufFree(imageId);
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 리소스 회수
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 ID</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int FreeImage(object imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (imageId != null) {
|
|
MIL.MbufFree((MIL_ID)imageId);
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Proc 이미지 배열 리소스 회수
|
|
/// </summary>
|
|
/// <param name="bufferSize">버퍼 사이즈</param>
|
|
/// <param name="images">Proc 이미지 배열</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int FreeProcImages(int bufferSize, object[] images) {
|
|
if (images == null) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
for (int i = 0; i < bufferSize; i++) {
|
|
FreeImage((MIL_ID)images[i]);
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 사각형 중심 포인트 가져오기
|
|
/// </summary>
|
|
/// <param name="roi"></param>
|
|
/// <returns></returns>
|
|
public static ImagePoint GetRectCenter(Rect roi) {
|
|
return new ImagePoint(roi.Left + roi.Width / 2, roi.Top + roi.Height / 2);
|
|
}
|
|
/// <summary>
|
|
/// 이미지 중심 포인트 가져오기
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns></returns>
|
|
public static ImagePoint GetImageCenter(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return new ImagePoint(0, 0);
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
return new ImagePoint(
|
|
imageSize.Width * 0.5,
|
|
imageSize.Height * 0.5);
|
|
}
|
|
/// <summary>
|
|
/// 이미지 사이즈 가져오기
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns>이미지 사이즈</returns>
|
|
public static ImageSize GetImageSize(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return new ImageSize();
|
|
}
|
|
|
|
int width = -1;
|
|
int height = -1;
|
|
int band = -1;
|
|
int bitDepth = -1;
|
|
|
|
try {
|
|
width = (int)MIL.MbufInquire(imageId, MIL.M_SIZE_X);
|
|
height = (int)MIL.MbufInquire(imageId, MIL.M_SIZE_Y);
|
|
band = (int)MIL.MbufInquire(imageId, MIL.M_SIZE_BAND);
|
|
bitDepth = (int)MIL.MbufInquire(imageId, MIL.M_SIZE_BIT);
|
|
}
|
|
catch (Exception e) {
|
|
}
|
|
|
|
return new ImageSize() {
|
|
Width = width,
|
|
Height = height,
|
|
Channel = band,
|
|
BitDepth = bitDepth
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 사이즈 가져오기
|
|
/// </summary>
|
|
/// <param name="camConfig">카메라 컨피그</param>
|
|
/// <returns>성공 유무</returns>
|
|
public ImageSize GetImageSize(CamConfig camConfig) {
|
|
var imageSize = new ImageSize();
|
|
|
|
if (IsHeightLongerThanWidth(camConfig)) {
|
|
imageSize.Width = (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY);
|
|
imageSize.Height = (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX);
|
|
}
|
|
else {
|
|
imageSize.Width = (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX);
|
|
imageSize.Height = (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY);
|
|
}
|
|
|
|
imageSize.Channel = camConfig.ImageSize.Channel;
|
|
imageSize.BitDepth = camConfig.ImageSize.BitDepth;
|
|
|
|
return imageSize;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 사이즈 동일 여부 체크
|
|
/// </summary>
|
|
/// <param name="image1">이미지1</param>
|
|
/// <param name="image2">이미지2</param>
|
|
/// <returns>이미지 사이즈 동일 여부</returns>
|
|
public static bool ImageSizeEquals(MIL_ID image1, MIL_ID image2) {
|
|
var imageSize1 = GetImageSize(image1);
|
|
var imageSize2 = GetImageSize(image2);
|
|
|
|
return ImageSizeEquals(imageSize1, imageSize2);
|
|
}
|
|
/// <summary>
|
|
/// 이미지 사이즈 동일 여부 체크
|
|
/// </summary>
|
|
/// <param name="imageSize1">이미지 사이즈 1</param>
|
|
/// <param name="imageSize2">이미지 사이즈 2</param>
|
|
/// <returns>이미지 사이즈 동일 여부</returns>
|
|
public static bool ImageSizeEquals(ImageSize imageSize1, ImageSize imageSize2) {
|
|
if (imageSize1.Width != imageSize2.Width ||
|
|
imageSize1.Height != imageSize2.Height ||
|
|
imageSize1.BitDepth != imageSize2.BitDepth ||
|
|
imageSize1.Channel != imageSize2.Channel) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// 이미지 사이즈 Null인지 여부
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <returns>True : Null</returns>
|
|
public static bool IsImageSizeNull(ImageSize imageSize) {
|
|
if (imageSize.Width == -1 && imageSize.Height == -1) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 이미지가 Color인지 여부
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns>True : ColorImage</returns>
|
|
public static bool IsColorImage(MIL_ID imageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return false;
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
|
|
return (imageSize.Channel != 1);
|
|
}
|
|
/// <summary>
|
|
/// Mil 이미지를 byte array로 변환
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <returns>변환된 이미지 byte array</returns>
|
|
public static byte[] ConvertMilToByteArry(MIL_ID imageId) {
|
|
ImageSize imageSize = GetImageSize(imageId);
|
|
byte[] byteArry = new byte[imageSize.Width * imageSize.Height * imageSize.Channel];
|
|
MIL.MbufGet2d(imageId, 0, 0, imageSize.Width, imageSize.Height, byteArry);
|
|
|
|
return byteArry;
|
|
}
|
|
/// <summary>
|
|
/// byte array를 mil 이미지 로 변환
|
|
/// </summary>
|
|
/// <param name="byteArry"></param>
|
|
/// <param name="width"></param>
|
|
/// <param name="height"></param>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
public static void ConvertByteArryToMil(byte[] byteArry, int width, int height, ref MIL_ID imageId) {
|
|
var imageSize = GetImageSize(imageId);
|
|
if (imageSize.Channel == 3) {
|
|
MIL.MbufPutColor2d(imageId, MIL.M_PACKED + MIL.M_BGR24, MIL.M_ALL_BANDS, 0, 0, width, height, byteArry);
|
|
}
|
|
else {
|
|
MIL.MbufPut2d(imageId, 0, 0, width, height, byteArry);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// color 이미지를 gray 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="colorImageId"></param>
|
|
/// <returns></returns>
|
|
public static MIL_ID ConvertToGray(MIL_ID colorImageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
MIL_ID grayImageId = GetCompatibleGrayImageBuffer(colorImageId);
|
|
ConvertToGray(colorImageId, grayImageId);
|
|
|
|
return grayImageId;
|
|
}
|
|
/// <summary>
|
|
/// color 이미지를 gray 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="colorImageId"></param>
|
|
/// <param name="grayImageId"></param>
|
|
/// <returns></returns>
|
|
public static int ConvertToGray(MIL_ID colorImageId, MIL_ID grayImageId) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
MIL.MimConvert(colorImageId, grayImageId, MIL.M_RGB_TO_L);
|
|
|
|
return E1.OK;
|
|
}
|
|
/// <summary>
|
|
/// gray 이미지를 rgb 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="imageId">이미지 버퍼 MIL_ID</param>
|
|
/// <param name="boardType">보드 타입</param>
|
|
/// <param name="boardSlotPos">보드 슬롯 위치</param>
|
|
/// <returns></returns>
|
|
public static MIL_ID ConvertGrayToRGB(MIL_ID imageId, eBoardType boardType, eBoardSlotPos boardSlotPos) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
var imageSize = GetImageSize(imageId);
|
|
|
|
if (IsColorImage(imageSize)) {
|
|
return CloneImage(imageId);
|
|
}
|
|
else {
|
|
MIL_ID rgbImageId = MIL.M_NULL;
|
|
MIL.MbufAllocColor(
|
|
Instance.GetSystem(boardType, boardSlotPos),
|
|
3,
|
|
imageSize.Width,
|
|
imageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref rgbImageId);
|
|
|
|
MIL.MbufCopyColor(imageId, rgbImageId, MIL.M_RED);
|
|
MIL.MbufCopyColor(imageId, rgbImageId, MIL.M_GREEN);
|
|
MIL.MbufCopyColor(imageId, rgbImageId, MIL.M_BLUE);
|
|
|
|
return rgbImageId;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// mil 이미지를 bitmap 이미지로 변환
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns></returns>
|
|
public static Bitmap ConvertToBitmap(MIL_ID image) {
|
|
if (image == MIL.M_NULL) {
|
|
return ThumbnailUtil.GetDefaultImage();
|
|
}
|
|
|
|
try {
|
|
var imageSize = GetImageSize(image);
|
|
byte[] byteData = new byte[imageSize.Width * imageSize.Height * imageSize.Channel];
|
|
|
|
Bitmap bitmap;
|
|
if (imageSize.Channel == 3) {
|
|
MIL.MbufGetColor2d(
|
|
image, MIL.M_PACKED + MIL.M_RGB24, MIL.M_ALL_BANDS, 0, 0, imageSize.Width, imageSize.Height, byteData);
|
|
bitmap = new Bitmap(imageSize.Width, imageSize.Height, PixelFormat.Format24bppRgb);
|
|
}
|
|
else {
|
|
MIL.MbufGet2d(image, 0, 0, imageSize.Width, imageSize.Height, byteData);
|
|
bitmap = new Bitmap(imageSize.Width, imageSize.Height, PixelFormat.Format8bppIndexed);
|
|
|
|
// 팔레트 설정 (그레이스케일)
|
|
ColorPalette palette = bitmap.Palette;
|
|
for (int i = 0; i < 256; i++) {
|
|
palette.Entries[i] = Color.FromArgb(i, i, i);
|
|
}
|
|
bitmap.Palette = palette;
|
|
}
|
|
|
|
var rowLength = bitmap.Width * imageSize.Channel;
|
|
var bitmapData = bitmap.LockBits(
|
|
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
|
ImageLockMode.WriteOnly,
|
|
bitmap.PixelFormat);
|
|
|
|
for (int h = 0; h < bitmap.Height; h++) {
|
|
Marshal.Copy(
|
|
byteData,
|
|
h * rowLength,
|
|
bitmapData.Scan0 + (h * bitmapData.Stride),
|
|
rowLength);
|
|
}
|
|
bitmap.UnlockBits(bitmapData);
|
|
|
|
return bitmap;
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.FuncE(e.Message);
|
|
}
|
|
|
|
return ThumbnailUtil.GetDefaultImage();
|
|
}
|
|
/// <summary>
|
|
/// 컬러 이미지인지 여부
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <returns></returns>
|
|
public static bool IsColorImage(ImageSize imageSize) {
|
|
return imageSize.Channel != 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 픽셀 클리어
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
public static void ClearImage(MIL_ID image) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return;
|
|
}
|
|
|
|
if (image != MIL.M_NULL) {
|
|
MIL.MbufClear(image, 0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 픽셀 클리어
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
public static void ClearImage(object image) {
|
|
if (!Instance.HasValidLicense()) {
|
|
return;
|
|
}
|
|
|
|
if (image != null) {
|
|
MIL.MbufClear((MIL_ID)image, 0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지의 ROI 내에서 Pixel Sharpness 값 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">Rect</param>
|
|
/// <returns>Pixel Sharpness 값</returns>
|
|
public static int GetSharpnessWithCropRoi(MIL_ID image, Rect cropRoi) {
|
|
MIL_ID cropImage = CropImage(image, cropRoi);
|
|
return GetSharpness(cropImage);
|
|
}
|
|
/// <summary>
|
|
/// 이미지의 ROI 내에서 Pixel Sharpness 값 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">ROI</param>
|
|
/// <returns>Pixel Sharpness 값</returns>
|
|
public static int GetSharpnessWithCropRoi(MIL_ID image, ROI cropRoi) {
|
|
MIL_ID cropImage = CropImage(image, cropRoi);
|
|
return GetSharpness(cropImage);
|
|
}
|
|
/// <summary>
|
|
/// 이미지 내에서 Pixel Sharpness 값 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>Pixel Sharpness 값</returns>
|
|
public static int GetSharpness(MIL_ID image) {
|
|
MIL_INT sharpness = 0;
|
|
MIL.MdigFocus(MIL.M_NULL, image, MIL.M_DEFAULT,
|
|
null, MIL.M_NULL, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_DEFAULT, MIL.M_EVALUATE, ref sharpness);
|
|
return (int)sharpness;
|
|
}
|
|
/// <summary>
|
|
/// 이미지의 ROI 내에서 Pixel Brightness 값 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">Rect</param>
|
|
/// <returns>Pixel Brightness 값</returns>
|
|
public static BrightnessResult GetBrightnessWithCropRoi(MIL_ID image, Rect cropRoi) {
|
|
MIL_ID cropImage = CropImage(image, cropRoi);
|
|
return GetBrightness(cropImage, GetRectCenter(cropRoi));
|
|
}
|
|
/// <summary>
|
|
/// 이미지의 ROI 내에서 Pixel Brightness 값 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="cropRoi">ROI</param>
|
|
/// <returns>Pixel Brightness 값</returns>
|
|
public static BrightnessResult GetBrightnessWithCropRoi(MIL_ID image, ROI cropRoi) {
|
|
MIL_ID cropImage = CropImage(image, cropRoi);
|
|
return GetBrightness(cropImage, cropRoi.Center);
|
|
}
|
|
/// <summary>
|
|
/// 이미지 Point에서 Pixel Brightness 값 가져오기
|
|
/// </summary>
|
|
/// <param name="image">이미지</param>
|
|
/// <param name="imagePoint">이미지 포인트</param>
|
|
/// <returns>Pixel Brightness 값</returns>
|
|
public static BrightnessResult GetBrightness(MIL_ID image, ImagePoint imagePoint) {
|
|
MIL_ID contextId = MIL.M_NULL;
|
|
MIL_ID resultBufId = MIL.M_NULL;
|
|
MIL_INT min = 0;
|
|
MIL_INT max = 0;
|
|
MIL_INT avg = 0;
|
|
|
|
MIL.MimAlloc(GetSystemOfBuffer(image), MIL.M_STATISTICS_CONTEXT, MIL.M_DEFAULT, ref contextId);
|
|
MIL.MimAllocResult(GetSystemOfBuffer(image), MIL.M_DEFAULT, MIL.M_STATISTICS_RESULT, ref resultBufId);
|
|
|
|
MIL.MimControl(contextId, MIL.M_STAT_MIN, MIL.M_ENABLE);
|
|
MIL.MimControl(contextId, MIL.M_STAT_MAX, MIL.M_ENABLE);
|
|
MIL.MimControl(contextId, MIL.M_STAT_MEAN, MIL.M_ENABLE);
|
|
|
|
MIL.MimStatCalculate(contextId, image, resultBufId, MIL.M_DEFAULT);
|
|
|
|
MIL.MimGetResult(resultBufId, MIL.M_STAT_MIN + MIL.M_TYPE_MIL_INT, ref min);
|
|
MIL.MimGetResult(resultBufId, MIL.M_STAT_MAX + MIL.M_TYPE_MIL_INT, ref max);
|
|
MIL.MimGetResult(resultBufId, MIL.M_STAT_MEAN + MIL.M_TYPE_MIL_INT, ref avg);
|
|
|
|
MIL.MimFree(resultBufId);
|
|
MIL.MimFree(contextId);
|
|
|
|
return new BrightnessResult(
|
|
imagePoint,
|
|
(int)min, (int)max, (int)avg);
|
|
}
|
|
/// <summary>
|
|
/// Overlay 이미지 가져오기
|
|
/// </summary>
|
|
/// <param name="milCameraDisplay">mil 카메라 디스플레이</param>
|
|
/// <param name="grabImage">그랩 이미지</param>
|
|
/// <returns>Overlay 이미지</returns>
|
|
public static MIL_ID GetOverlayImage(IMilCameraDisplay milCameraDisplay, object grabImage = null) {
|
|
MIL_ID image = MIL.M_NULL;
|
|
if (grabImage == null) {
|
|
image = milCameraDisplay.GetImage();
|
|
}
|
|
else {
|
|
image = (MIL_ID)grabImage;
|
|
}
|
|
|
|
var overlayImage = GetCompatibleColorImageBuffer(image);
|
|
CopyImage(image, overlayImage);
|
|
MIL.MgraDraw(milCameraDisplay.GetGraphicListId(), overlayImage, MIL.M_DEFAULT);
|
|
|
|
return overlayImage;
|
|
}
|
|
/// <summary>
|
|
/// Overlay 이미지 저장
|
|
/// </summary>
|
|
/// <param name="filePath">파일 경로</param>
|
|
/// <param name="fovInfos">모든 FOV 정보</param>
|
|
/// <param name="displayType">디스플레이 타입</param>
|
|
/// <param name="image">이미지 default:Null</param>
|
|
/// <returns>성공 유무</returns>
|
|
public static int SaveScreenShot(string filePath, List<FovInfo> fovInfos, eDisplayType displayType, object image = null) {
|
|
var overlayImages = new Dictionary<FovInfo, MIL_ID>();
|
|
MIL_ID screenShotImage = MIL.M_NULL;
|
|
|
|
try {
|
|
foreach (var fovInfo in fovInfos) {
|
|
var milCameraDisplay = CameraDisplayManager.GetDisplay(fovInfo, displayType) as IMilCameraDisplay;
|
|
var overlayImage = GetOverlayImage(milCameraDisplay, image);
|
|
overlayImages[fovInfo] = overlayImage;
|
|
}
|
|
|
|
if (0 < overlayImages.Count) {
|
|
var screenShotImageSize = GetScreenShotImageSize(overlayImages, displayType);
|
|
if (screenShotImageSize == null) {
|
|
return E1.GENERIC;
|
|
}
|
|
screenShotImage = GetCompatibleColorImageBuffer(screenShotImageSize, GetSystemOfBuffer(overlayImages.Values.ToList()[0]));
|
|
|
|
var (ltFovInfo, ltFovUiPos) = ScreenShotUtil.GetLeftTopFovInfo(overlayImages.Keys.ToList(), displayType);
|
|
var (ltFovUiPosRow, ltFovUiPosCol) = FovRecipe.GetFovUiPosRowCol(ltFovUiPos);
|
|
|
|
foreach (var fovInfo in fovInfos) {
|
|
var fovRecipe = VisionRecipeManager.GetFovRecipe(fovInfo);
|
|
eFovUiPos fovUiPos = new eFovUiPos();
|
|
|
|
foreach (var mainUiRecipe in fovRecipe.MainUiRecipes) {
|
|
if (mainUiRecipe.MainDisplayType == displayType) {
|
|
fovUiPos = mainUiRecipe.FovUiPos;
|
|
}
|
|
}
|
|
var (curFovUiPosRow, curFovUiPosCol) = FovRecipe.GetFovUiPosRowCol(fovUiPos);
|
|
|
|
var imageSize = GetImageSize(overlayImages[fovInfo]);
|
|
MIL.MbufCopyClip(
|
|
overlayImages[fovInfo],
|
|
screenShotImage,
|
|
(curFovUiPosCol - ltFovUiPosCol) * imageSize.Width,
|
|
(curFovUiPosRow - ltFovUiPosRow) * imageSize.Height);
|
|
}
|
|
SaveImage(filePath, screenShotImage);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
_Logger.E(e.Message);
|
|
}
|
|
finally {
|
|
FreeImage(screenShotImage);
|
|
foreach (var overlayImage in overlayImages.Values) {
|
|
FreeImage(overlayImage);
|
|
}
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private static ImageSize GetScreenShotImageSize(Dictionary<FovInfo, MIL_ID> overlayImages, eDisplayType displayType) {
|
|
if (0 < overlayImages.Count && 0 < overlayImages.Count) {
|
|
var (ltFovInfo, ltFovUiPos) = ScreenShotUtil.GetLeftTopFovInfo(overlayImages.Keys.ToList(), displayType);
|
|
if (ltFovInfo == null) {
|
|
return null;
|
|
}
|
|
|
|
var imageSize = GetImageSize(overlayImages[ltFovInfo]);
|
|
imageSize.Channel = 3;
|
|
|
|
if (ScreenShotUtil.HasRightFov(ltFovInfo, ltFovUiPos, overlayImages.Keys.ToList(), displayType)) {
|
|
imageSize.Width *= 2;
|
|
}
|
|
|
|
if (ScreenShotUtil.HasBottomFov(ltFovInfo, ltFovUiPos, overlayImages.Keys.ToList(), displayType)) {
|
|
imageSize.Height *= 2;
|
|
}
|
|
|
|
return imageSize;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|