using Aurora.Api;
using VisionCommon;
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
namespace VisionSequence.Camera {
///
/// 공정에서 사용되는 이미지의 정보
///
public class ImageInfo : IDisposable {
/// 공정 이미지
public object Image { get; set; } = null;
/// 점유(사용) 상태 플래그
public bool Occupied { get; set; } = false;
///
/// 생성자
///
/// 공정 이미지
/// 점유(사용) 상태 플래그
public ImageInfo(object image, bool occupied) {
Image = image;
Occupied = occupied;
}
///
/// 명시적 해제 (이미지 메모리 해제, Occupied = false)
///
public void Dispose() {
IpAdapter.Instance.IpEnvironment.FreeImage(Image);
Image = null;
Occupied = false;
}
}
///
/// 공정 이미지 매니저로 그랩 횟수를 최소화하기 위해 사용한다.
/// 패턴에서 동일한 조명 값을 사용하는 경우 카메라 그랩을 1회만 수행한다.
///
public class ProcGrabImageManager : IDisposable {
private readonly object _Lock = new object();
private List _ImageInfos = new List();
private Dictionary _GrabImages = new Dictionary();
private Logger _Logger;
private FovInfo _FovInfo;
private CameraAgentBase _CameraAgent;
private IDisposable _EventDisposable;
///
/// 생성자
///
/// FOV 키 정보
/// 카메라 에이전트
public ProcGrabImageManager(FovInfo fovInfo, CameraAgentBase cameraAgent) {
_Logger = new Logger(GetType().Name);
_FovInfo = fovInfo;
_CameraAgent = cameraAgent;
SetObservable();
}
private void SetObservable() {
var camRecipe = VisionRecipeManager.GetCamRecipe(_FovInfo);
if (_EventDisposable == null) {
_EventDisposable = VisionEnv.AuroraEnv.EventObservable.AsObservable(VisionEventId.CAMERA_UPDATE_GRAB_IMAGE_BUFFER).
Where(x => x.From == camRecipe.CamId.ToString()).
Subscribe(_ => UpdateGrabImageBuffer());
}
}
private void UpdateGrabImageBuffer() {
lock (_Lock) {
if (0 < _ImageInfos.Count) {
var camImageSize = _CameraAgent.GetImageSize();
var imageSize = IpAdapter.Instance.IpEnvironment.GetImageSize(_ImageInfos[0].Image);
if (!IpAdapter.Instance.IpEnvironment.ImageSizeEquals(camImageSize, imageSize)) {
DisposeImageInfos();
Clear();
}
}
}
}
///
/// 공정 이미지 초기화
///
public void Clear() {
lock (_Lock) {
_GrabImages.Clear();
ClearOccupied();
}
}
private void ClearOccupied() {
lock (_Lock) {
foreach (var imageInfo in _ImageInfos) {
imageInfo.Occupied = false;
}
}
}
///
/// 조명 값(LightInfo)의 공정 이미지 그랩 완료 여부
///
/// 조명 값
/// 완료 여부
public bool IsGrabDone(LightInfo lightInfo) {
lock (_Lock) {
return _GrabImages.ContainsKey(lightInfo);
}
}
///
/// 조명 값(LightInfo)으로 그랩된 공정 이미지를 등록
///
/// 조명 값
/// 공정 이미지
public void SetGrabImage(LightInfo lightInfo, object image) {
lock (_Lock) {
if (_GrabImages.ContainsKey(lightInfo)) {
_GrabImages[lightInfo] = image;
}
else {
_GrabImages.Add(lightInfo, image);
}
}
}
///
/// 공정이미지를 얻어 온다.
///
/// 조명 값
/// 공정 이미지
public object GetGrabImage(LightInfo lightInfo) {
lock (_Lock) {
if (_GrabImages.ContainsKey(lightInfo)) {
return _GrabImages[lightInfo];
}
else {
_GrabImages[lightInfo] = GetImage();
return _GrabImages[lightInfo];
}
}
}
private object GetImage() {
lock (_Lock) {
foreach (var imageInfo in _ImageInfos) {
if (!imageInfo.Occupied) {
imageInfo.Occupied = true;
return imageInfo.Image;
}
}
var newImageInfo = CreateImageInfo();
_ImageInfos.Add(newImageInfo);
return newImageInfo.Image;
}
}
private ImageInfo CreateImageInfo() {
return new ImageInfo(_CameraAgent.CloneImageBuffer(), occupied: true);
}
///
/// 명시적 해제
///
public void Dispose() {
lock (_Lock) {
DisposeImageInfos();
_EventDisposable.Dispose();
}
}
private void DisposeImageInfos() {
lock (_Lock) {
foreach (var imageInfo in _ImageInfos) {
imageInfo.Dispose();
}
_ImageInfos.Clear();
}
}
}
}