using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using System.Drawing.Imaging; using System.IO; //显示弹出信息 using System.Windows.Forms; using OINA.Extender; using OINA.Extender.MicroscopeControl; using OINA.Extender.Acquisition; using OINA.Extender.Acquisition.Image; using OINA.Extender.Data; using OINA.Extender.Data.Image; using OINA.Extender.Acquisition.Ed; using OINA.Extender.Acquisition.Quant; using OINA.Extender.Processing; using OINA.Extender.Processing.Ed; using OINA.Extender.Processing.Quant; using System.ComponentModel; using OINA.Extender.Data.Ed; using System.Threading; namespace Extender { enum OxfordCommand { //缩放 GetMagnification = 0, SetMagnification = 1, //焦距 GetWorkingDistance = 2, SetWorkingDistance = 3, //亮度 GetBrightness = 4, SetBrightness = 5, //对比度 GetContrast = 6, SetContrast = 7, //SEM电压 GetSEMVoltage = 8, SetSEMVoltage = 9, //样品台 GetStagePosition = 10, SetStagePosition = 11, GetStageAtX = 12, GetStageAtY = 13, GetStageAtZ = 14, GetStageAtT = 15, GetStageAtR = 16, SetStageGotoX = 17, SetStageGotoY = 18, SetStageGotoZ = 19, SetStageGotoT = 20, SetStageGotoR = 21, MoveStageXY = 22, //拍图 GrabImage = 23, //采集参数设置 SetImageAcquistionSetting = 24, //获取分辨率 GetImageStore = 25, //设置分辨率 SetImageStore = 26, //获取bitmap GetBitmap = 27, IsAcquiringSpectrum = 28, //X-ray //点采集 XrayPointCollectiong = 29, //面采集 XrayAreaCollectiong = 30, } public struct GrabImageParam { public GrabImageParam(string filename, short xoff, short yoff, short width, short height, short type) { this.filename = filename; this.xoff = xoff; this.yoff = yoff; this.width = width; this.height = height; this.type = type; } public string filename; public short xoff; public short yoff; public short width; public short height; public short type; } public struct PointXrayParam { public double dMilliSecondsTime; public int x; public int y; public long[] XrayData; public Dictionary listElement; } public struct AreaXrayParam { public double dMilliSecondsTime; public List a_listChord; public long[] XrayData; public Dictionary a_listElement; } public struct MoveStageParam { public float x; public float y; } public class ExtenderWrapper : IExtenderControl { struct oxfordCommandData { public OxfordCommand commandType; public bool returnType; public MoveStageParam moveStagePrm; public GrabImageParam grabImgParam; public PointXrayParam pointXrayPrm; public AreaXrayParam areaXrayPrm; } private Thread controlThread; private oxfordCommandData currentCommand; private Extender myExtender; AutoResetEvent startEvent= new AutoResetEvent(false); AutoResetEvent endEvent = new AutoResetEvent(false); public ExtenderWrapper() { myExtender = new Extender(); controlThread = new Thread(this.ControlerThread); controlThread.Start(); } private void ControlerThread() { while (true) { while (true) { if (startEvent.WaitOne(0, true)) { break; } Application.DoEvents(); } switch (currentCommand.commandType) { case OxfordCommand.MoveStageXY: { MoveStageParam p = currentCommand.moveStagePrm; if (myExtender.MoveStageXY(p.x, p.y)) { currentCommand.returnType = true; } else { currentCommand.returnType = false; } endEvent.Set(); } break; case OxfordCommand.GrabImage: { GrabImageParam p = currentCommand.grabImgParam; if (myExtender.GrabImage(p.filename, p.xoff, p.yoff, p.width, p.height, p.type)) { currentCommand.returnType = true; } else { currentCommand.returnType = false; } endEvent.Set(); } break; case OxfordCommand.XrayPointCollectiong: { PointXrayParam p = currentCommand.pointXrayPrm; if (myExtender.XrayPointCollectiong(p.dMilliSecondsTime, p.x, p.y, out p.XrayData,out p.listElement)) { currentCommand.returnType = true; } else { currentCommand.returnType = false; } endEvent.Set(); } break; case OxfordCommand.XrayAreaCollectiong: { AreaXrayParam p = currentCommand.areaXrayPrm; if (myExtender.XrayAreaCollectiong(p.dMilliSecondsTime, p.a_listChord,out p.XrayData, out p.a_listElement)) { currentCommand.returnType = true; } else { currentCommand.returnType = false; } endEvent.Set(); } break; } } } public Bitmap GetBitmap() { return myExtender.GetBitmap(); } public float GetBrightness() { return myExtender.GetBrightness(); } public float GetContrast() { return myExtender.GetContrast(); } public int[] GetImageStore() { return myExtender.GetImageStore(); } public float GetMagnification() { return myExtender.GetMagnification(); } public float GetSEMVoltage() { return myExtender.GetSEMVoltage(); } public float GetStageAtR() { return myExtender.GetStageAtR(); } public float GetStageAtT() { return myExtender.GetStageAtT(); } public float GetStageAtX() { return myExtender.GetStageAtX(); } public float GetStageAtY() { return myExtender.GetStageAtY(); } public float GetStageAtZ() { return myExtender.GetStageAtZ(); } public float[] GetStagePosition() { return myExtender.GetStagePosition(); } public float GetWorkingDistance() { return myExtender.GetWorkingDistance(); } public bool GrabImage(string filename, short xoff, short yoff, short width, short height, short type) { currentCommand.grabImgParam =new GrabImageParam(filename, xoff, yoff, width, height, type); currentCommand.commandType = OxfordCommand.GrabImage; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } } if (currentCommand.returnType == true) { return true; } else { return false; } } public bool IsAcquiringSpectrum() { return myExtender.IsAcquiringSpectrum(); } public bool MoveStageXY(float x, float y) { currentCommand.moveStagePrm = new MoveStageParam(); currentCommand.moveStagePrm.x = x; currentCommand.moveStagePrm.y = y; currentCommand.commandType = OxfordCommand.MoveStageXY; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } } if (currentCommand.returnType == true) { return true; } else { return false; } } public bool SetBrightness(float set) { return myExtender.SetBrightness(set); } public bool SetContrast(float set) { return myExtender.SetContrast(set); } public bool SetImageAcquistionSetting(double a_dDwellTime, int a_nImageType, double a_dImageScanSize) { return myExtender.SetImageAcquistionSetting(a_dDwellTime, a_nImageType, a_dImageScanSize); } public bool SetImageStore(float set) { return myExtender.SetImageStore(set); } public bool SetMagnification(float set) { return myExtender.SetMagnification(set); } public bool SetSEMVoltage(float set) { return myExtender.SetSEMVoltage(set); } public bool SetStageGotoR(float set) { return myExtender.SetStageGotoR(set); } public bool SetStageGotoT(float set) { return myExtender.SetStageGotoT(set); } public bool SetStageGotoX(float set) { return myExtender.SetStageGotoX(set); } public bool SetStageGotoY(float set) { return myExtender.SetStageGotoY(set); } public bool SetStageGotoZ(float set) { return myExtender.SetStageGotoZ(set); } public bool SetStagePosition(float[] set) { return myExtender.SetStagePosition(set); } public bool SetWorkingDistance(float set) { return myExtender.SetWorkingDistance(set); } public bool XrayAreaCollectiong(double dMilliSecondsTime, List a_listChord, out long[] XrayData, out Dictionary a_listElement) { currentCommand.areaXrayPrm = new AreaXrayParam(); var p = currentCommand.areaXrayPrm; p.dMilliSecondsTime = dMilliSecondsTime; p.a_listChord = a_listChord; currentCommand.commandType = OxfordCommand.XrayAreaCollectiong; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } } if (currentCommand.returnType == true) { XrayData=p.XrayData ; a_listElement=p.a_listElement ; return true; } else { XrayData = p.XrayData; a_listElement = p.a_listElement; return false; } } public bool XrayPointCollectiong(double dMilliSecondsTime, int x, int y, out long[] XrayData, out Dictionary a_listElement) { currentCommand.pointXrayPrm = new PointXrayParam(); var p = currentCommand.pointXrayPrm; p.dMilliSecondsTime = dMilliSecondsTime; p.x = x; p.y = y; currentCommand.commandType = OxfordCommand.XrayPointCollectiong; startEvent.Set(); while (true) { if (endEvent.WaitOne(0, false)) { break; } } if (currentCommand.returnType == true) { XrayData=p.XrayData ; a_listElement=p.listElement ; return true; } else { XrayData = p.XrayData; a_listElement = p.listElement; return false; } } } public class Extender : IExtenderControl { //构造函数 public Extender() { InitMicroscopeController(); InitImageAcquisition(); InitXrayAcquistion(); } //结束 public void CloseExtender() { CloseMicroscopeController(); CloseImageAcquisition(); CloaseXrayAcquistion(); } #region 电镜控制、样品台 //控制电镜 private IMicroscopeController microscopeController = null; //电压 private double m_dHighVoltage; //放大倍数 private double m_dMagnification; //工作距离 private double m_dWorkingDistance; //亮度 private double m_dBirghtness; //对比度 private double m_dContrast; //BeamOn private bool m_bBeamOn; //FilamentOn private bool m_bFilamentOn; //样品台位置 private double m_dStageX; private double m_dStageY; private double m_dStageZ; private double m_dStageR; private double m_dStageT; private double m_dStageXMax; public double StageXMax { get { return this.m_dStageXMax; } set { this.m_dStageXMax = value; } } private double m_dStageXMin; public double StageXMin { get { return this.m_dStageXMin; } set { this.m_dStageXMin = value; } } private double m_dStageYMax; public double StageYMax { get { return this.m_dStageYMax; } set { this.m_dStageYMax = value; } } private double m_dStageYMin; public double StageYMin { get { return this.m_dStageYMin; } set { this.m_dStageYMin = value; } } private double m_dStageZMax; public double StageZMax { get { return this.m_dStageZMax; } set { this.m_dStageZMax = value; } } private double m_dStageZMin; public double StageZMin { get { return this.m_dStageZMin; } set { this.m_dStageZMin = value; } } private double m_dStageTMax; public double StageTMax { get { return this.m_dStageTMax; } set { this.m_dStageTMax = value; } } private double m_dStageTMin; public double StageTMin { get { return this.m_dStageTMin; } set { this.m_dStageTMin = value; } } private double m_dStageRMax; public double StageRMax { get { return this.m_dStageRMax; } set { this.m_dStageRMax = value; } } private double m_dStageRMin; public double StageRMin { get { return this.m_dStageRMin; } set { this.m_dStageRMin = value; } } //控制电镜初始化 void InitMicroscopeController(float a_fStageXMin = 0, float a_fStageXMax = 130, float a_fStageYMin = 0, float a_fStageYMax = 130, float a_fStageZMin = 0, float a_fStageZMax = 40, float a_fStageTMin = 0, float a_fStageTMax = 90, float a_fStageRMin = 0, float a_fStageRMax = 360) { this.microscopeController = AcquireFactory.CreateMicroscopeControl(); this.microscopeController.ColumnChange += this.OnMicroscopeColumnChange; this.microscopeController.StageChange += this.OnMicroscopeStageChange; this.microscopeController.ColumnConnected += this.OnMicroscopeColumnConnected; this.microscopeController.StageConnected += this.OnMicroscopeStageConnected; this.microscopeController.ChangeCompleted += this.OnMicroscopeChangeCompleted; ReadMicroscopeColumn(); ReadStage(); StageXMax = a_fStageXMax; StageXMin = a_fStageXMin; StageYMax = a_fStageYMax; StageYMin = a_fStageYMin; StageZMax = a_fStageZMax; StageZMin = a_fStageZMin; StageTMax = a_fStageTMax; StageTMin = a_fStageTMin; StageRMax = a_fStageRMax; StageRMin = a_fStageRMin; } //控制电镜释放 void CloseMicroscopeController() { this.microscopeController.ColumnChange -= this.OnMicroscopeColumnChange; this.microscopeController.StageChange -= this.OnMicroscopeStageChange; this.microscopeController.ColumnConnected -= this.OnMicroscopeColumnConnected; this.microscopeController.StageConnected -= this.OnMicroscopeStageConnected; this.microscopeController.ChangeCompleted -= this.OnMicroscopeChangeCompleted; } //读取当前的电镜控制值 private void ReadMicroscopeColumn() { var columnCapabilities = this.microscopeController.ColumnCapabilities; var columnConditions = this.microscopeController.ColumnConditions; if (columnCapabilities.Magnification.CanRead) { m_dMagnification = columnConditions.Magnification; } if (columnCapabilities.WorkingDistance.CanRead) { m_dWorkingDistance = columnConditions.WorkingDistance; } if (columnCapabilities.HighVoltage.CanRead) { m_dHighVoltage = columnConditions.HighVoltage; } if (columnCapabilities.Brightness.CanRead) { m_dBirghtness = columnConditions.Brightness; } if (columnCapabilities.Contrast.CanRead) { m_dContrast = columnConditions.Contrast; } if (columnCapabilities.BeamOn.CanRead) { m_bBeamOn = Convert.ToBoolean(columnConditions.BeamOn); } if (columnCapabilities.FilamentOn.CanRead) { m_bFilamentOn = Convert.ToBoolean(columnConditions.FilamentOn); } } //读取样品台位置 private void ReadStage() { var stageCapabilities = this.microscopeController.StageCapabilities; var stageConditions = this.microscopeController.StageConditions; if (stageCapabilities.StageX.CanRead) { this.m_dStageX = stageConditions.StageX; } if (stageCapabilities.StageY.CanRead) { this.m_dStageY = stageConditions.StageY; } if (stageCapabilities.StageZ.CanRead) { this.m_dStageZ = stageConditions.StageZ; } if (stageCapabilities.StageT.CanRead) { this.m_dStageT = stageConditions.StageT; } if (stageCapabilities.StageR.CanRead) { this.m_dStageR = stageConditions.StageR; } } //电镜控制改变事件 private void OnMicroscopeColumnChange(object sender, EventArgs e) { //MessageBox.Show("电镜控制改变ColumnChange"); ReadMicroscopeColumn(); } //样品台控制改变事件 private void OnMicroscopeStageChange(object sender, EventArgs e) { //MessageBox.Show("样品控制改变StageChange"); ReadStage(); } //列控制连接或断开时的事件 private void OnMicroscopeColumnConnected(object sender, EventArgs e) { //MessageBox.Show("电镜控制连接ColumnConnected"); } //样品台控制连接或断开时的事件 private void OnMicroscopeStageConnected(object sender, EventArgs e) { //MessageBox.Show("样品台连接StageConnected"); ReadStage(); } //样品台控制、电镜控制、外围控制的事件改变完成 private void OnMicroscopeChangeCompleted(object sender, EventArgs e) { //MessageBox.Show("电镜控制完成ChangeCompleted"); ReadMicroscopeColumn(); ReadStage(); } //电镜控制 //电压 //放大倍数 //工作距离 //亮度 //对比度 //BeamOn //FilamentOn //缩放 public float GetMagnification() { return (float)m_dMagnification; } public Boolean SetMagnification(float set) { Dictionary columnDictionary = new Dictionary { { Column.Magnification, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //焦距 public float GetWorkingDistance() { return (float)m_dWorkingDistance; } public Boolean SetWorkingDistance(float set) { Dictionary columnDictionary = new Dictionary { { Column.WorkingDistance, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //亮度 public float GetBrightness() { return (float)m_dBirghtness; } public Boolean SetBrightness(float set) { Dictionary columnDictionary = new Dictionary { { Column.Brightness, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //对比度 public float GetContrast() { return (float)m_dContrast; } public Boolean SetContrast(float set) { Dictionary columnDictionary = new Dictionary { { Column.Contrast, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //SEM电压 public float GetSEMVoltage() { return (float)m_dHighVoltage; } public Boolean SetSEMVoltage(float set) { Dictionary columnDictionary = new Dictionary { { Column.HighVoltage, (double)set } }; this.microscopeController.SetColumnConditions(columnDictionary); return true; } //样品台 public float[] GetStagePosition() { float[] ret = new float[5]; ret[0] = (float)m_dStageX; ret[1] = (float)m_dStageY; ret[2] = (float)m_dStageZ; ret[3] = (float)m_dStageT; ret[4] = (float)m_dStageR; return ret; } public Boolean SetStagePosition(float[] set) { double stageX = (double)set[0]; if (stageX > StageXMax || stageX < StageXMin) { return false; } double stageY = (double)set[1]; if (stageY > StageYMax || stageY < StageYMin) { return false; } double stageZ = (double)set[2]; if (stageZ > StageZMax || stageZ < StageZMin) { return false; } double stageT = (double)set[3]; if (stageT > StageTMax || stageT < StageTMin) { return false; } double stageR = (double)set[4]; if (stageR > StageRMax || stageR < StageRMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageX, (double)stageX }, { Stage.StageY, (double)stageY }, { Stage.StageZ, (double)stageZ }, { Stage.StageT, (double)stageT }, { Stage.StageR, (double)stageR } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public float GetStageAtX() { return (float)m_dStageX; } public float GetStageAtY() { return (float)m_dStageY; } public float GetStageAtZ() { return (float)m_dStageZ; } public float GetStageAtT() { return (float)m_dStageT; } public float GetStageAtR() { return (float)m_dStageR; } public Boolean SetStageGotoX(float set) { double stageX = (double)set; if (stageX > StageXMax || stageX < StageXMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageX, (double)stageX } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoY(float set) { double stageY = (double)set; if (stageY > StageYMax || stageY < StageYMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageY, (double)stageY } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoZ(float set) { double stageZ = (double)set; if (stageZ > StageZMax || stageZ < StageZMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageZ, (double)stageZ } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoT(float set) { double stageT = (double)set; if (stageT > StageTMax || stageT < StageTMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageT, (double)stageT } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean SetStageGotoR(float set) { double stageR = (double)set; if (stageR > StageRMax || stageR < StageRMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageR, (double)stageR } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } public Boolean MoveStageXY(float x, float y) { double stageX = (double)x; if (stageX > StageXMax || stageX < StageXMin) { return false; } double stageY = (double)y; if (stageY > StageYMax || stageY < StageYMin) { return false; } var stageDictionary = new Dictionary { { Stage.StageX, (double)stageX }, { Stage.StageY, (double)stageY } }; this.microscopeController.SetStageConditions(stageDictionary); return true; } #endregion #region 拍图 /// /// IImageAcquisitionController object /// private IImageAcquisitionController imageAcquisitionController = null; /// /// IImageSettings object /// private IImageAcquisitionSettings imageAcquisitionSettings = null; //图像扫描尺寸 public double[] ImageScanSize = { 32, 64, 128, 256, 512, 1024, 4096, 8192 }; private byte[] m_ImageBit = null; private long m_nImageWidth = 0; private long m_nImageHeight = 0; bool m_bAcquistionDone = false; private Bitmap m_Bitmap = null; void InitImageAcquisition() { imageAcquisitionController = AcquireFactory.CreateImageServer(); imageAcquisitionSettings = AcquireFactory.CreateImageSettings(); imageAcquisitionController.ExperimentStarted += this.OnImageExperimentStarted; imageAcquisitionController.ExperimentFinished += this.OnImageExperimentFinished; } //控制电镜释放 void CloseImageAcquisition() { imageAcquisitionController.ExperimentStarted -= this.OnImageExperimentStarted; imageAcquisitionController.ExperimentFinished -= this.OnImageExperimentFinished; } /// /// OnImageExperimentStarted /// private void OnImageExperimentStarted(object sender, AcquisitionStartedEventArgs e) { } //int m_nState; /// /// OnImageExperimentFinished /// private void OnImageExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { IElectronImage electronImage = e.Value[0]; if (!ReadImageData(electronImage, out m_ImageBit, out m_nImageWidth, out m_nImageHeight)) { MessageBox.Show("图像采集完成,获取图像像素失败!"); } if (m_ImageBit != null && m_ImageBit.Length == m_nImageWidth * m_nImageHeight) { m_bAcquistionDone = true; } } bool ReadImageData(IElectronImage a_electronImage, out Byte[] a_pImageBits, out long a_nImageHeight, out long a_nImageWidth) { a_nImageHeight = 0; a_nImageWidth = 0; a_pImageBits = null; if (a_electronImage == null) { return false; } a_nImageHeight = a_electronImage.Height; a_nImageWidth = a_electronImage.Width; int nBytesPerPixel = a_electronImage.BytesPerPixel; long nImageSize = a_nImageHeight * a_nImageWidth; long nBufferSize = nImageSize * nBytesPerPixel; Byte[] imageData = new Byte[nBufferSize]; a_electronImage.GetData(imageData); a_pImageBits = new Byte[nImageSize]; // default, oxford will return short image, we need to convert to byte if (nBytesPerPixel == 2) { int nBSEValue = 0; for (int i = 0; i < nImageSize; ++i) { nBSEValue = imageData[0 + i * nBytesPerPixel] + imageData[1 + i * nBytesPerPixel] * 255; a_pImageBits[i] = (Byte)(nBSEValue / 128.0 + 0.5); } } else { string msg = string.Format("image byte per pixel other than 2({0}), image convert may wrong", nBytesPerPixel); MessageBox.Show(msg); int nOffset = nBytesPerPixel - 1; for (int i = 0; i < nImageSize; ++i) { a_pImageBits[i] = imageData[nOffset + i * nBytesPerPixel]; } } return true; } void AcquisitionParamInit() { m_ImageBit = null; m_nImageWidth = 0; m_nImageHeight = 0; m_bAcquistionDone = false; Bitmap m_Bitmap = null; } //a_dDwellTime : 1~100000之间的数 //a_sImageType : 1: SE, 2: Bse //a_dImageScanSize : 图像分辨率,图像的高 public bool SetImageAcquistionSetting(double a_dDwellTime, int a_nImageType, double a_dImageScanSize) { IImageSettings imageSettings = imageAcquisitionSettings.ImageSettings; IImageCapabilities imageCapabilities = imageAcquisitionSettings.ImageCapabilities; IImageScanSettings scanSettings = imageAcquisitionSettings.ScanSettings; if (a_dDwellTime > imageCapabilities.MaximumImageDwellMicroseconds) { imageSettings.DwellTimeMicroSeconds = imageCapabilities.MaximumImageDwellMicroseconds; } if (a_dDwellTime < imageCapabilities.MinimumImageDwellMicroseconds) { imageSettings.DwellTimeMicroSeconds = imageCapabilities.MinimumImageDwellMicroseconds; } else { imageSettings.DwellTimeMicroSeconds = a_dDwellTime; } imageSettings.InputSources.ToList().ForEach(i => imageSettings.EnableInputSource(i.Key, false)); imageSettings.EnableInputSource((ImageInputSources)a_nImageType, true); if (!ImageScanSize.Contains(a_dImageScanSize)) { MessageBox.Show("图像尺寸输入无效"); return false; } var pixelSize = 1d / a_dImageScanSize; scanSettings.AcquisitionRegion.CreateFullFieldRegion(pixelSize); return true; } ////拍图 public Boolean GrabImage(String filename, short xoff, short yoff, short width, short height, short type) { AcquisitionParamInit(); try { int lastingTime = 0; IEnumerable images = imageAcquisitionController.StartAcquisition(imageAcquisitionSettings); images.ToList().ForEach(i => { i.Label = string.Format(@"Code example image - {0:HH:mm:ss} - {1}", DateTime.Now, i.InputSource.ToString()); }); while (true) { if (m_bAcquistionDone) { // 图像对象 m_Bitmap = ToGrayBitmap(m_ImageBit, (int)m_nImageHeight, (int)m_nImageWidth); switch (Path.GetExtension(filename)) { case ".bmp": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp); break; case ".jpg": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); break; case ".gif": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Gif); break; case ".tif": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Tiff); break; case ".png": m_Bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Png); break; default: break; } break; } Application.DoEvents(); Thread.Sleep(100); lastingTime += 100; if (lastingTime > EDSColletionTimeOut*3) { return false; } } } catch (InvalidSettingsException settingsException) { var sb = new StringBuilder(@"Invalid settings have been supplied: "); sb.AppendLine(); settingsException.ValidationResults.ValidationErrors.ToList().ForEach(ve => sb.AppendFormat("{0}{1}", Environment.NewLine, ve)); MessageBox.Show(sb.ToString()); } catch (AcquisitionStartException startException) { string msg = string.Format(@"AcquisitionStartException: {0}", startException.Message); MessageBox.Show(msg); } return true; } /// /// 将一个byte的数组转换为8bit灰度位图 /// /// 数组 /// 图像宽度 /// 图像高度 /// 位图 Bitmap ToGrayBitmap(byte[] data, int width, int height) { // 申请目标位图的变量,并将其内存区域锁定 Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed); //BitmapData这部分内容 需要 using System.Drawing.Imaging; BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); // 获取图像参数 // 扫描线的宽度 int stride = bmpData.Stride; // 显示宽度与扫描线宽度的间隙 int offset = stride - width; // 获取bmpData的内存起始位置 IntPtr iptr = bmpData.Scan0; // 用stride宽度,表示这是内存区域的大小 int scanBytes = stride * height; // 下面把原始的显示大小字节数组转换为内存中实际存放的字节数组 int posScan = 0; int posReal = 0;// 分别设置两个位置指针,指向源数组和目标数组 byte[] pixelValues = new byte[scanBytes]; //为目标数组分配内存 for (int x = 0; x < height; x++) { int startIndex = x * width; //// 下面的循环节是模拟行扫描 for (int y = 0; y < width; y++) { pixelValues[posScan++] = data[posReal++]; } posScan += offset; //行扫描结束,要将目标位置指针移过那段“间隙” } // 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中 System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes); bmp.UnlockBits(bmpData); // 解锁内存区域 // 下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度 ColorPalette tempPalette; using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) { tempPalette = tempBmp.Palette; } for (int i = 0; i < 256; i++) { tempPalette.Entries[i] = Color.FromArgb(i, i, i); } bmp.Palette = tempPalette; return bmp; } //获取分辨率 public int[] GetImageStore() { int[] ImageStore = new int[8]; for (int i = 0; i < 8; i++) { ImageStore[i] = (int)ImageScanSize[i]; } return ImageStore; } //设置分辨率 public Boolean SetImageStore(float set) { IImageScanSettings scanSettings = imageAcquisitionSettings.ScanSettings; if (!ImageScanSize.Contains(set)) { MessageBox.Show("图像尺寸输入无效"); return false; } var pixelSize = 1d / (double)set; scanSettings.AcquisitionRegion.CreateFullFieldRegion(pixelSize); return true; } public Bitmap GetBitmap() { return m_Bitmap; } #endregion #region X-ray //控制器 private IEdSpectrumAcquisitionController EdSpectrumAcquisitionController = null; private IEdSpectrumSettings EdSpectrumSettings = null; private IEdSpectrumProcessing EdSpectrumProcessing = null; // Use the autoIdSettings to define elements that are known or elements that you want to exclude. They also list elements that cannot be identified private IAutoIdSettings autoIdSettings = null; private ISEMQuantSettings settings = null; private int XRayChannelLength = 2000; private long[] m_XrayData = null; private bool m_bXrayDone = false; private int EDSColletionTimeOut=5000; /// /// List of EdSpectrum objects /// private Dictionary listElement = null; void InitXrayAcquistion() { EdSpectrumSettings = AcquireFactory.CreateEdSpectrumSettings(); EdSpectrumAcquisitionController = AcquireFactory.CreateEdSpectrumServer(); EdSpectrumProcessing = ProcessingFactory.CreateSpectrumProcessing(); // Use the autoIdSettings to define elements that are known or elements that you want to exclude. They also list elements that cannot be identified autoIdSettings = ProcessingFactory.CreateAutoIdSettings(); settings = ProcessingFactory.CreateSEMQuantSettings(); EdSpectrumAcquisitionController.ExperimentFinished += this.OnEdSpectrumExperimentFinished; //EdSpectrumAcquisitionController.ExperimentStarted += this.OnEdSpectrumExperimentStarted; } void CloaseXrayAcquistion() { EdSpectrumAcquisitionController.ExperimentFinished -= this.OnEdSpectrumExperimentFinished; //EdSpectrumAcquisitionController.ExperimentStarted -= this.OnEdSpectrumExperimentStarted; } void SetXrayAcquisitionParam(double a_dMilliSecondsTime) { EdSpectrumSettings.EdSettings.AcquisitionMode = EdAcquireMode.LiveTime; // RealTime or LiveTime if (a_dMilliSecondsTime < 200) { a_dMilliSecondsTime = 200; } EdSpectrumSettings.EdSettings.AcquisitionTime = TimeSpan.FromMilliseconds(a_dMilliSecondsTime); EdSpectrumSettings.EdSettings.ProcessTime = 1; EdSpectrumSettings.EdSettings.EnergyRange = 20; EdSpectrumSettings.EdSettings.NumberOfChannels = 4096; EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreateFullFieldRegion(1.0 / 1024.0); } void SetPointAcquistionRegion(int a_nX, int a_nY) { Chord chord = new Chord(a_nX, a_nY, 1); List < Chord > chords = new List < Chord> (); chords.Add(chord); ChordList chordsList = null; if (m_nImageWidth != 0) { chordsList = new ChordList(chords, 1 / (double)m_nImageWidth); } else { chordsList = new ChordList(chords, 1 / 1024.0); } EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreateChordListRegion(chordsList); } void SetAreaAcquistionRegion(List a_nChords) { ChordList chordsList = null; if (m_nImageWidth != 0) { chordsList = new ChordList(a_nChords, 1 / (double)m_nImageWidth); } else { chordsList = new ChordList(a_nChords, 1 / 1024.0); } EdSpectrumSettings.ScanSettings.AcquisitionRegion.CreateChordListRegion(chordsList); } void XrayParamInit() { m_XrayData = null; m_bXrayDone = false; } /// /// Called when IEdSpectrumAcquisitionController Experiment Starting. /// /// The sender. /// The instance containing the event data. private void OnEdSpectrumExperimentStarting(object sender, AcquisitionStartingEventArgs e) { } /// /// Called when IEdSpectrumAcquisitionController Experiment Started. /// /// The sender. /// The instance containing the event data. private void OnEdSpectrumExperimentStarted(object sender, AcquisitionStartedEventArgs e) { } /// /// Called when IEdSpectrumAcquisitionController Experiment Finished /// /// sender object /// The instance containing the event data. private void OnEdSpectrumExperimentFinished(object sender, AcquisitionFinishedEventArgs e) { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = Test"); IEdSpectrumAcquisitionController edSpectrumAcquisitionController = sender as IEdSpectrumAcquisitionController; if (edSpectrumAcquisitionController != null) { // This only used for multiple acquisition: // If this is the last experiment, call EndMultipleAcquisition on the Acquisition // controller, to re-enable external scan switching edSpectrumAcquisitionController.EndMultipleAcquisition(); } IEdSpectrum edSpectrum = e.Value; if (!ReadXrayData(edSpectrum, out m_XrayData, XRayChannelLength)) { MessageBox.Show("Xray采集完成,获取图像像素失败!"); } //Quantify processing EdSpectrumProcessing.IdentifyElements(e.Value, autoIdSettings); // While it is possible to choose other elements, Oxygen is the only supported element by stoichiometry. settings.CombinedElement = 8; settings.Normalised = true; ISEMQuantStatus quantStatus = EdSpectrumProcessing.SEMQuantifySpectrum(e.Value, settings);//(a_nChannelData, OIHelper::SEMQuantSettings); IEnumerable < ISEMQuantResult > Results = quantStatus.Results; //Get element result for single point var ie = Results.GetEnumerator(); listElement = new Dictionary(); while (ie.MoveNext()) { ISEMQuantResult result = ie.Current; if (result.WeightPercent != 0) { listElement.Add(ElementProperties.GetElementSymbol(result.AtomicNumber), result.WeightPercent ); } } if (m_XrayData != null && m_XrayData.Length == XRayChannelLength) { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = True"); m_bXrayDone = true; } else { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = False"); } } bool ReadXrayData(IEdSpectrum a_spectrum, out long[] a_pSpectrumData, int a_nBufferSize) { a_pSpectrumData = new long[a_nBufferSize]; int[] xrayData = new int[a_spectrum.NumberOfChannels]; a_spectrum.GetChannelData(xrayData); double dZeroChannelValue = a_spectrum.ZeroChannelValue; int nChannelStart = 0; if (dZeroChannelValue < 0) // zero channel value should less than zero { nChannelStart = (int)(-dZeroChannelValue / a_spectrum.ChannelWidth + 0.5); } int nDataLength = (int)(a_spectrum.EnergyRange * 1000 / a_spectrum.ChannelWidth + 0.5); double dStep1 = 1.0 / nDataLength; double dStep2 = 1.0 / a_nBufferSize; for (int i = 0; i < nDataLength; ++i) { int nValue = xrayData[i + nChannelStart] > 0 ? xrayData[i + nChannelStart] : 0; double dBinPos = i * dStep1; long nLeftBin = (long)(dBinPos / dStep2); // calculate % into left bin double dLeft_Percent = (double)(nLeftBin + 1) - dBinPos / dStep2; // ((nLeftBin + 1)*dStep2 - dBinPos)/dStep2 // calculate data into the left bin long nValueToLeftBin = (long)((double)nValue * dLeft_Percent + 0.5); // put data into bins a_pSpectrumData[nLeftBin] += nValueToLeftBin; if ((nLeftBin + 1) < (long)a_nBufferSize) { a_pSpectrumData[nLeftBin + 1] += (nValue - nValueToLeftBin); } } return true; } /// /// Called when IEdSpectrum DataChanged /// /// Event source /// Event arguments private void OnDataChanged(object sender, EventArgs e) { } public bool IsAcquiringSpectrum() { return EdSpectrumAcquisitionController.IsAcquiring; } //点扫描 //X-ray public Boolean XrayPointCollectiong(double dMilliSecondsTime, int x, int y, out long[] XrayData, out Dictionary a_listElement) { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 1"); XrayParamInit(); Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 2"); XrayData = new long[XRayChannelLength]; a_listElement = new Dictionary(); Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 3"); SetXrayAcquisitionParam(dMilliSecondsTime); Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 4"); SetPointAcquistionRegion(x, y); Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 5"); // IEdSpectrumSettings.EdCapabilities will validate settings and hardware availability. if (EdSpectrumAcquisitionController.IsEdHardwareReady(EdSpectrumSettings)) { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 6"); // This only used for multiple acquisition: // if this is the first acquisition, call BeginMultipleAcquisition // on the IEdSpectrumAcquisitionController to suppress external scan switching Console.WriteLine(m_bXrayDone.ToString()); if (m_bXrayDone) { EdSpectrumAcquisitionController.BeginMultipleAcquisition(); } Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 7"); // Start spectrum acquisition try { int lastingTime = 0; IEdSpectrum edSpectrum = EdSpectrumAcquisitionController.StartAcquisition(EdSpectrumSettings); edSpectrum.Label = string.Format(@"Point({0},{1})",x,y); Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 8"); Console.WriteLine(m_bXrayDone.ToString()); while (true) { if (m_bXrayDone) { XrayData = m_XrayData; a_listElement =listElement; break; } Application.DoEvents(); Thread.Sleep(100); lastingTime += 100; if (lastingTime > EDSColletionTimeOut) { EdSpectrumAcquisitionController.EndMultipleAcquisition(); return false; } } } catch (InvalidSettingsException invalidSettingsException) { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 9"); string msg = string.Format(@"Invalid Settings Exception:{0}, {1}", invalidSettingsException.Message, invalidSettingsException.ValidationResults.ValidationErrors); MessageBox.Show(msg); } catch (AcquisitionStartException acquisitionStartException) { Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 10"); string msg = string.Format(@"Acquisition Start Exception:{0}",acquisitionStartException.Message); MessageBox.Show(msg); } } Console.WriteLine("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 11"); return true; } //面扫描 public Boolean XrayAreaCollectiong(double dMilliSecondsTime, List a_listChord, out long[] XrayData, out Dictionary a_listElement) { XrayParamInit(); XrayData = new long[XRayChannelLength]; a_listElement = new Dictionary(); SetXrayAcquisitionParam(dMilliSecondsTime); List Chords = new List(); foreach (Segment seg in a_listChord) { Chord chord = new Chord(seg.X, seg.Y, seg.Length); Chords.Add(chord); } SetAreaAcquistionRegion(Chords); // IEdSpectrumSettings.EdCapabilities will validate settings and hardware availability. if (EdSpectrumAcquisitionController.IsEdHardwareReady(EdSpectrumSettings)) { // This only used for multiple acquisition: // if this is the first acquisition, call BeginMultipleAcquisition // on the IEdSpectrumAcquisitionController to suppress external scan switching if (m_bXrayDone) EdSpectrumAcquisitionController.BeginMultipleAcquisition(); // Start spectrum acquisition try { int lastingTime = 0; IEdSpectrum edSpectrum = EdSpectrumAcquisitionController.StartAcquisition(EdSpectrumSettings); edSpectrum.Label = string.Format(@"chord"); while (true) { if (m_bXrayDone) { XrayData = m_XrayData; a_listElement = listElement; break; } Thread.Sleep(100); Application.DoEvents(); lastingTime += 100; if (lastingTime > EDSColletionTimeOut) { EdSpectrumAcquisitionController.EndMultipleAcquisition(); return false; } } } catch (InvalidSettingsException invalidSettingsException) { string msg = string.Format(@"Invalid Settings Exception:{0}, {1}", invalidSettingsException.Message, invalidSettingsException.ValidationResults.ValidationErrors); MessageBox.Show(msg); } catch (AcquisitionStartException acquisitionStartException) { string msg = string.Format(@"Acquisition Start Exception:{0}", acquisitionStartException.Message); MessageBox.Show(msg); } } return true; } #endregion } }