From 8a59259ebddf896fa272b2beb376538bfe8cd0f2 Mon Sep 17 00:00:00 2001 From: wells.liu <wells.liu@broconcentric.com> Date: 星期一, 06 七月 2020 11:30:25 +0800 Subject: [PATCH] 板卡底层优化 --- src/Bro.Common.Device/DeviceBase/CameraBase.cs | 191 ++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 154 insertions(+), 37 deletions(-) diff --git a/src/Bro.Common.Device/DeviceBase/CameraBase.cs b/src/Bro.Common.Device/DeviceBase/CameraBase.cs index c8a80ba..a7f721c 100644 --- a/src/Bro.Common.Device/DeviceBase/CameraBase.cs +++ b/src/Bro.Common.Device/DeviceBase/CameraBase.cs @@ -13,6 +13,7 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using static Bro.Common.Helper.EnumHelper; @@ -70,7 +71,7 @@ #endregion #region 鍥剧墖鐩稿叧 - public event Action<CameraBase, Bitmap, string> OnImageUpdated; + public Action<CameraBase, Bitmap, string> OnImageUpdated; public Action<CameraBase, HObject, string> OnHImageOutput { get; set; } public event Action OnCameraOpModeChanged; @@ -140,22 +141,21 @@ /// </summary> /// <returns></returns> public abstract void Snapshot(); + public abstract IImageSet Snapshot(IOperationConfig config); - public virtual ImageSet Snapshot(IOperationConfig config) + public virtual void InitialImageSet(IImageSet set, ImageSaveOption saveOption) { OpMode = CameraOpMode.SingleSnapShot; - ImageSet set = new ImageSet(); - CameraOprerationConfigBase opConfig = config as CameraOprerationConfigBase; - set.ImageSaveOption.DataFrom(opConfig.ImageSaveOption); + //CameraOprerationConfigBase opConfig = config as CameraOprerationConfigBase; + set.ImageSaveOption.DataFrom(saveOption); set.IsOriginSaved = !set.ImageSaveOption.IsSaveOriginImage; set.IsFitSaved = !set.ImageSaveOption.IsSaveFitImage; set.IsAddtionalSaved = !string.IsNullOrWhiteSpace(set.ImageSaveOption.AddtionalSaveType); set.OnImageSetTimeout += ImageSet_OnImageSetTimeout; - _imageSetList.Add(set); - return set; + _imageSetList.Add(set); } /// <summary> @@ -171,13 +171,13 @@ #endregion #region 鍩哄厓澶勭悊 - public event Action<CameraBase, List<IShapeElement>, string> OnElementsUpdated; + public Action<CameraBase, List<IShapeElement>, string> OnElementsUpdated; #endregion #region 鍥剧墖缂撳瓨/淇濆瓨 - readonly ConcurrentBag<ImageSet> _imageSetList = new ConcurrentBag<ImageSet>(); + public readonly ConcurrentBag<IImageSet> _imageSetList = new ConcurrentBag<IImageSet>(); - public void NewImageSet(ImageSet set) + public void NewImageSet(IImageSet set) { set.IsOriginSaved = !set.ImageSaveOption.IsSaveOriginImage; set.IsFitSaved = !set.ImageSaveOption.IsSaveFitImage; @@ -196,12 +196,12 @@ public virtual async void SaveOriginImage(Bitmap map, Bitmap showImage, string imgSetId) { - Task.Run(() => + await Task.Run(() => { OnImageUpdated?.Invoke(this, showImage, imgSetId); }); - ImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId); + IImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId); if (set == null) return; @@ -224,10 +224,6 @@ { LogAsync(DateTime.Now, $"{set.Id}鍘熷浘淇濆瓨澶辫触", ex.GetExceptionMessage()); } - //finally - //{ - // set.IsOriginSaved = true; - //} } set.IsOriginSaved = true; ClearImageSet(set); @@ -240,7 +236,7 @@ if (eleList.Count > 0) OnElementsUpdated?.BeginInvoke(this, eleList, imgSetId, null, null); - ImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId); + IImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId); if (set == null) return; @@ -304,7 +300,7 @@ { await Task.Run(() => { - ImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId); + IImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId); if (set == null) return; @@ -340,7 +336,7 @@ }); } - private string CheckImageDirectory(string subDir, string prefix) + protected string CheckImageDirectory(string subDir, string prefix) { if (string.IsNullOrWhiteSpace(subDir)) { @@ -362,7 +358,7 @@ return imgDir; } - private void SaveImageByNameAndType(Bitmap map, string imageName, ImageFormat imgFormat, string imageDir) + protected void SaveImageByNameAndType(Bitmap map, string imageName, ImageFormat imgFormat, string imageDir) { string filePath = Path.Combine(imageDir, $"{imageName}.{imgFormat.ToString().ToLower()}"); map.Save(filePath, imgFormat); @@ -370,7 +366,7 @@ //private Timer clearImageSetTimer = null; - public void ClearImageSet(ImageSet set) + public void ClearImageSet(IImageSet set) { try { @@ -401,7 +397,7 @@ public void ClearImageSet(string imgSetId) { - ImageSet set = _imageSetList.First(u => u.Id == imgSetId); + IImageSet set = _imageSetList.First(u => u.Id == imgSetId); if (set != null) ClearImageSet(set); } @@ -483,6 +479,110 @@ private System.Threading.Timer clearImageTimer = null; #endregion + + #region 鍥剧墖杞崲 + [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] + public static extern void CopyMemory(IntPtr dest, IntPtr src, long count); + + protected async void Generate8GrayImageByPointer(int width, int height, IntPtr dataPtr, string imgSetId) + { + await Task.Run(() => + { + //************************Mono8 杞� Bitmap******************************* + Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed); + Bitmap showImage = new Bitmap(width, height, PixelFormat.Format8bppIndexed); + + ColorPalette cp = bmp.Palette; + for (int i = 0; i < 256; i++) + { + cp.Entries[i] = Color.FromArgb(i, i, i); + } + bmp.Palette = cp; + + ColorPalette cp1 = showImage.Palette; + for (int i = 0; i < 256; i++) + { + cp1.Entries[i] = Color.FromArgb(i, i, i); + } + showImage.Palette = cp1; + + long[] ptr = new long[3]; + Rectangle rect = new Rectangle(0, 0, width, height); + BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); + BitmapData showImageData = showImage.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); + int PixelSize = Bitmap.GetPixelFormatSize(bitmapData.PixelFormat) / 8; + + if (width % 4 == 0) + { + CopyMemory(bitmapData.Scan0, dataPtr, width * height * PixelSize); + CopyMemory(showImageData.Scan0, dataPtr, width * height * PixelSize); + } + else + { + ptr[0] = bitmapData.Scan0.ToInt64(); + ptr[1] = showImageData.Scan0.ToInt64(); + ptr[2] = (long)dataPtr; + for (int i = 0; i < height - 1; i++) + { + ptr[2] += width; + + CopyMemory((IntPtr)ptr[0], (IntPtr)ptr[2], width * PixelSize); + CopyMemory((IntPtr)ptr[1], (IntPtr)ptr[2], width * PixelSize); + ptr[0] += bitmapData.Stride; + ptr[1] += showImageData.Stride; + } + } + bmp.UnlockBits(bitmapData); + showImage.UnlockBits(showImageData); + + SaveOriginImage(bmp, showImage, imgSetId); + }); + } + + protected async void Generate16GrayImageByPointer(int width, int height, IntPtr dataPtr, string imgSetId) + { + await Task.Run(() => + { + Thread.Sleep(1000); + int widthIn4 = (int)Math.Ceiling(width / 4.0) * 4; + + Bitmap bmp = new Bitmap(widthIn4, height, PixelFormat.Format48bppRgb); + Bitmap showImage = new Bitmap(widthIn4, height, PixelFormat.Format48bppRgb); + + Rectangle rect = new Rectangle(0, 0, widthIn4, height); + BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format48bppRgb); + BitmapData showImageData = showImage.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format48bppRgb); + unsafe + { + byte* data = (byte*)dataPtr; + byte* bitmapBuffer = (byte*)bitmapData.Scan0; + byte* showBitmapBuffer = (byte*)showImageData.Scan0; + + //Parallel.For(0, height, i => + // { + // Parallel.For(0, width, j => + // { + // showBitmapBuffer[(i * widthIn4 + j) * 6] = bitmapBuffer[(i * widthIn4 + j) * 6] = data[(i * width + j) * 2]; + // showBitmapBuffer[(i * widthIn4 + j) * 6 + 1] = bitmapBuffer[(i * widthIn4 + j) * 6 + 1] = data[(i * width + j) * 2 + 1]; + // }); + // }); + + Parallel.For(0, width * height, i => + { + int index = (i + 1) % width + widthIn4 * ((i + 1) / width) - 1; + + showBitmapBuffer[index * 6] = bitmapBuffer[index * 6] = data[i * 2]; + showBitmapBuffer[index * 6 + 1] = bitmapBuffer[index * 6 + 1] = data[i * 2 + 1]; + }); + } + + bmp.UnlockBits(bitmapData); + showImage.UnlockBits(showImageData); + + SaveOriginImage(bmp, showImage, imgSetId); + }); + } + #endregion } #region Config @@ -496,7 +596,7 @@ [Category("鍙栧儚閰嶇疆")] [Description("鏇濆厜")] [DisplayName("鏇濆厜")] - public float Exposure + public virtual float Exposure { get => exposure; set @@ -515,17 +615,17 @@ [Category("鍙栧儚閰嶇疆")] [Description("澧炵泭")] [DisplayName("澧炵泭")] - public float Gain { get; set; } + public virtual float Gain { get; set; } [Category("鍙栧儚閰嶇疆")] [Description("鏇濆厜淇敼鍚庣瓑寰呮椂闂达紝鍗曚綅ms銆傞拡瀵归儴鍒嗗満鏅‘淇濇洕鍏変慨鏀瑰強鏃剁敓鏁堛��")] [DisplayName("鏇濆厜绛夊緟")] - public int ExposureWaitTime { get; set; } + public virtual int ExposureWaitTime { get; set; } [Category("鍙栧儚閰嶇疆")] [Description("鎷嶆憚鍚庢洕鍏夊�笺�傚彲鍦ㄤ竴娆℃媿鎽勫悗灏嗘洕鍏変慨鏀逛负涓嬫鎷嶆憚鐨勬洕鍏夊�硷紝鑺傜害鏇濆厜鐢熸晥鏃堕棿銆�")] [DisplayName("鎷嶆憚鍚庢洕鍏�")] - public float ExposureAfterSnap { get; set; } + public virtual float ExposureAfterSnap { get; set; } [Category("绠楁硶閰嶇疆")] [Description("绠楁硶璺緞")] @@ -581,42 +681,42 @@ [Category("鐩告満璁剧疆")] [Description("鐩告満IP鍦板潃")] [DisplayName("鐩告満IP鍦板潃")] - public string CameraIP { get; set; } + public virtual string CameraIP { get; set; } [Category("鐩告満璁剧疆")] [Description("涓婁綅鏈篒P鍦板潃")] [DisplayName("涓婁綅鏈篒P鍦板潃")] - public string ComputerIP { get; set; } + public virtual string ComputerIP { get; set; } [Category("淇濆瓨璁剧疆")] [Description("鍥剧墖淇濆瓨鐩綍")] [DisplayName("鍥剧墖淇濆瓨鐩綍")] [Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))] - public string ImgDirectory { get; set; } = @"../Images"; + public virtual string ImgDirectory { get; set; } = @"../Images"; [Category("淇濆瓨璁剧疆")] [Description("鍥剧墖淇濆瓨澶╂暟")] [DisplayName("鍥剧墖淇濆瓨澶╂暟")] - public int SaveImageDayLimit { get; set; } = 0; + public virtual int SaveImageDayLimit { get; set; } = 0; [Category("淇濆瓨璁剧疆")] [Description("鍥剧墖淇濆瓨榛樿閰嶇疆锛屼富瑕佺敤浜庣‖瑙﹀彂绛夋病鏈夋槑纭搷浣滈厤缃鏄庣殑鍥剧墖淇濆瓨")] [DisplayName("鍥剧墖淇濆瓨榛樿閰嶇疆")] [TypeConverter(typeof(ComplexObjectConvert))] [Editor(typeof(PropertyObjectEditor), typeof(UITypeEditor))] - public ImageSaveOption ImageSaveOption { get; set; } = new ImageSaveOption(); + public virtual ImageSaveOption ImageSaveOption { get; set; } = new ImageSaveOption(); [Category("鎷嶆憚璁剧疆")] [Description("榛樿鏇濆厜鍊硷紝鐩告満寮�鍚悗灏辫缃鏇濆厜鍊�")] [DisplayName("榛樿鏇濆厜鍊�")] - public float DefaultExposure { get; set; } + public virtual float DefaultExposure { get; set; } } #endregion #region Converter & Editor public class HalconSerialNumConverter : ComboBoxItemTypeConvert { - public override Hashtable GetConvertHash() + public override Hashtable GetConvertHash(ITypeDescriptorContext context) { Hashtable table = new Hashtable(); HTuple deviceList = null; @@ -654,7 +754,7 @@ public class CameraDeviceConverter : ComboBoxItemTypeConvert { - public override Hashtable GetConvertHash() + public override Hashtable GetConvertHash(ITypeDescriptorContext context) { Hashtable table = new Hashtable(); using (var scope = GlobalVar.Container.BeginLifetimeScope()) @@ -733,7 +833,24 @@ } } - public class ImageSet : IDisposable + public interface IImageSet : IDisposable + { + DateTime InitialTime { get; set; } + string Id { get; } + HImage HImage { get; set; } + Bitmap Image { get; set; } + + object SaveLock { get; set; } + + ImageSaveOption ImageSaveOption { get; set; } + bool IsOriginSaved { get; set; } + bool IsFitSaved { get; set; } + bool IsAddtionalSaved { get; set; } + + event Action<ImageSet> OnImageSetTimeout; + } + + public class ImageSet : IImageSet { public DateTime InitialTime { get; set; } = DateTime.Now; @@ -768,7 +885,7 @@ //public bool IsInvokeSaveNG { get; set; } = false; public bool IsAddtionalSaved { get; set; } = false; - public object SaveLock = new object(); + public object SaveLock { get; set; } = new object(); public event Action<ImageSet> OnImageSetTimeout; private Timer autoDisposeTimer = null; @@ -783,7 +900,7 @@ autoDisposeTimer = new Timer(OnAutoDispose, null, -1, 10 * 1000); } - public void Dispose() + public virtual void Dispose() { autoDisposeTimer.Change(-1, -1); autoDisposeTimer.Dispose(); -- Gitblit v1.8.0