#include "stdafx.h" #include "Detector_CareRayRF.h" #include "CCOS.Dev.FPD.CareRayRF.h" extern Log4CPP::Logger* gLogger; Detector_CareRayRF* g_pCarerayInstance = NULL; constexpr auto FRAME_NUMBER = 60; constexpr auto RAD_HEADER_SIZE = 65536; //SDK Rad模式图像头 inline int GetReturnCode(int nCode) { return nCode / 100000; } Detector_CareRayRF* g_pDetector = nullptr; #define LOAD_PROC_ADDRESS(handle,func) \ if ((func = (CB_##func)GetProcAddress(handle, #func)) == NULL) { printf("Error occurs while loading entry point!!! \n'%s'\n", #func); }\ Detector_CareRayRF::Detector_CareRayRF() { g_pCarerayInstance = this; m_pDPC2PanelID = new map(); m_pPanelID2DPC = new map(); m_nPanelCount = 0; m_hCareRayRFModule = nullptr; m_pCallbackPtrs = nullptr; m_nCurrentPanelID = 0; m_nCurrentDetIndex = -1; m_mapModeInfo = nullptr; m_bFPDConnected = false; m_nFrmHeaderLen = 0; m_nLastLogicMode = -1; m_nCurrentLogicMode = -1; m_nExamType = CR_FluExtSync; m_pImageBuffer = nullptr; m_pRawImgBuffer = nullptr; m_pFullImgBuffer = nullptr; m_bSaveRaw = false; m_strWorkPath = ""; m_eCaliType = CCOS_CALIBRATION_TYPE_NONE; m_eStatus = DetStatus_NotIni; m_bAbortCalibration = false; m_bCancelFlag = false; m_nImageHeight = 0; m_nImageWidth = 0; m_nCropLeft = 0; m_nCropRight = 0; m_nCropTop = 0; m_nCropBottom = 0; m_nRawImgHeight = 0; m_nRawImgWidth = 0; m_nCbImgIndex = 0; m_nAcqReadyTimeout = 20; m_nGainReadyTimeout = 20; m_nOftRefreshTime = 20; m_bIsRadMode = false; m_bSendImgToUpper = true; m_nDropImgNum = 0; m_nDropImgCount = 0; m_nExamMode = APP_STATUS_MAX; m_bAbortRefreshOft = false; m_hFPDScanThread = nullptr; m_fFrameRate = 10.0f; //缺省值,10帧每秒 m_nReadoutTime = 0; m_nDelayTime = 0; m_nTimePercentage = 100; m_bStartGrab = false; m_nValidImgNum = 0; m_nExposureCount = 0; m_nExiThreshold = 200;//新增配置 m_nImageBits = 16; m_bFirstImage = true; m_nModeID = 0; m_nGainLevel = 3; m_nExpTime = 0; m_vCtrlDetectorModeList.clear(); m_bHaveRadMode = false; m_hStopScanEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hAcqEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hGainEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hDarkEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hProcessImgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hArrayEvent[0] = m_hStopScanEvent; m_hArrayEvent[1] = m_hAcqEvent; m_hArrayEvent[2] = m_hGainEvent; m_hArrayEvent[3] = m_hDarkEvent; m_hArrayEvent[4] = m_hProcessImgEvent; m_hStopOffsetEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hStartAllOffset = CreateEvent(NULL, FALSE, FALSE, NULL); m_hStartOffset = CreateEvent(NULL, FALSE, FALSE, NULL); m_hAbortOffset = CreateEvent(NULL, FALSE, FALSE, NULL); m_hOffsetEvent[0] = m_hStopOffsetEvent; m_hOffsetEvent[1] = m_hStartAllOffset; m_hOffsetEvent[2] = m_hStartOffset; m_hOffsetEvent[3] = m_hAbortOffset; m_hGainReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hImageEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } Detector_CareRayRF::~Detector_CareRayRF() { FINFO("~Detector_CareRayRF"); if (m_hStopScanEvent) { CloseHandle(m_hStopScanEvent); m_hStopScanEvent = nullptr; } if (m_hAcqEvent) { CloseHandle(m_hAcqEvent); m_hAcqEvent = nullptr; } if (m_hGainEvent) { CloseHandle(m_hGainEvent); m_hGainEvent = nullptr; } if (m_hGainReadyEvent) { CloseHandle(m_hGainReadyEvent); m_hGainReadyEvent = nullptr; } if (m_hDarkEvent) { CloseHandle(m_hDarkEvent); m_hDarkEvent = nullptr; } if (m_hProcessImgEvent) { CloseHandle(m_hProcessImgEvent); m_hProcessImgEvent = nullptr; } if (m_hImageEvent) { CloseHandle(m_hImageEvent); m_hImageEvent = nullptr; } if (m_pCallbackPtrs) { delete m_pCallbackPtrs; m_pCallbackPtrs = nullptr; } if (m_pImageBuffer) { free(m_pImageBuffer); m_pImageBuffer = nullptr; } if (m_pRawImgBuffer) { delete[]m_pRawImgBuffer; m_pRawImgBuffer = nullptr; } if (m_pFullImgBuffer != nullptr) { delete[]m_pFullImgBuffer; m_pFullImgBuffer = nullptr; } if (m_mapModeInfo != nullptr) { delete[]m_mapModeInfo; m_mapModeInfo = nullptr; } m_vCtrlDetectorModeList.clear(); } bool Detector_CareRayRF::DriverEntry(void* pDrvDPC, ResDataObject& Configuration) { printf("========DriverEntry %p\n", pDrvDPC); FINFO("========DriverEntry {$}", pDrvDPC); map::iterator DPCsIter = m_pDPC2PanelID->find(pDrvDPC); if (DPCsIter != m_pDPC2PanelID->end()) { //printf("This DPC already exist\n"); FERROR("This DPC already exist"); return false; } m_pDPC2PanelID->insert(pair(pDrvDPC, m_nPanelCount)); m_pPanelID2DPC->insert(pair(m_nPanelCount, pDrvDPC)); m_nPanelCount++; m_ModeConfig = Configuration; //记录配置 --目前只有一个平板,多板时应该分别存储 FINFO("m_ModeConfig:{$}", m_ModeConfig.encode()); return true; } bool Detector_CareRayRF::Connect(void* pDrvDPC, const char* szWorkPath, ResDataObject& DetectorModeList) { printf("========Connect detector begin \r\n"); FINFO("========Connect detector begin \n"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return true"); return true; } m_strWorkPath = szWorkPath; if (!LoadDll(szWorkPath)) { FERROR("Load dll failed, Connect failed \n"); return false; } if (!OpenDetector()) { FERROR("Open detector failed, Connect failed \n"); return false; } PrintModeList(DetectorModeList); GetSystemInfo(m_nCurrentDetIndex); try { int nModeCount = (int)m_ModeConfig["ModeTable"].size(); FINFO("nModeCount:{$}", nModeCount); //FINFO("m_ModeConfig[ModeTable][i]:{$}", m_ModeConfig["ModeTable"][0].encode()); for (int i = 0; i < nModeCount; i++) { int nAppModeID = (int)m_ModeConfig["ModeTable"][i]["LogicMode"]; int nModeID = (int)m_ModeConfig["ModeTable"][i]["OperationMode"]; int nGainID = (int)m_ModeConfig["ModeTable"][i]["GainValue"]; string strFrameRate = (string)m_ModeConfig["ModeTable"][i]["Frequency"]; float fFrameRate = stof(strFrameRate.c_str()); int nExpTime = (int)m_ModeConfig["ModeTable"][i]["ExpTime"];//为0时,探测器将赋值为真正的开窗时间(积分时间) int nTrigType = (int)m_ModeConfig["ModeTable"][i]["ExamType"]; m_nDelayTime = (int)m_ModeConfig["ModeTable"][i]["DelayTime"]; if (!RegisterAppMode(nAppModeID, nModeID, nGainID, fFrameRate, nExpTime, nTrigType))//Connect { FERROR("Connect-Register appmode failed, Connect failed!"); return false; } } m_nExiThreshold = (int)m_ModeConfig["ExiThreshold"]; FINFO("image exi threshold:{$}", m_nExiThreshold); m_nAcqReadyTimeout = (int)m_ModeConfig["WorkReadyTimeout"]; m_nGainReadyTimeout = (int)m_ModeConfig["GainReadyTimeout"]; m_nOftRefreshTime = (int)m_ModeConfig["OffsetInterval"]; FINFO("Acq ready timeout({$}), Gain timeout({$}), OftRefresh time({$})", m_nAcqReadyTimeout, m_nGainReadyTimeout, m_nOftRefreshTime); } catch (ResDataObjectExption &e) { FERROR("Get config error: {$}", e.what()); return false; } if (nullptr == m_hFPDScanThread) { unsigned uThreadId; _beginthreadex(NULL, 0, onFPDScanThread, this, 0, &uThreadId); m_hFPDScanThread = OpenThread(THREAD_ALL_ACCESS, TRUE, uThreadId); } if (nullptr == m_hOffsetThread) { unsigned uThreadId; _beginthreadex(NULL, 0, RefreshOffsetThread, this, 0, &uThreadId); m_hOffsetThread = OpenThread(THREAD_ALL_ACCESS, TRUE, uThreadId); } m_bFPDConnected = true; FINFO("Connect over"); printf("Connect over \n"); return true; } void Detector_CareRayRF::DisConnect() { printf("========DisConnect with detector \n"); FINFO("========DisConnect"); int nRet = CR_OK; if (DetStatus_XrayCalibration == GetCareRayDPCStatus() || DetStatus_Offset == GetCareRayDPCStatus()) { FINFO("DisConnect Calling StopCalibration"); nRet = CR_StopCalibration(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("StopCalibration command failed"); } m_bAbortRefreshOft = true; //退出时停止offset线程 } FINFO("Calling Disconnect"); nRet = CR_Disconnect(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("Disconnect command failed"); } } void Detector_CareRayRF::EnterExamMode(int nExamMode) { switch (nExamMode) { case APP_STATUS_WORK_BEGIN: FINFO("Enter into Exam Windows"); m_nExamMode = APP_STATUS_WORK_BEGIN; break; case APP_STATUS_WORK_END: FINFO("Quit Exam Windows"); m_nExamMode = APP_STATUS_WORK_END; break; case APP_STATUS_DETSHARE_BEGIN: FINFO("Enter into Detector Share Windows"); m_nExamMode = APP_STATUS_DETSHARE_BEGIN; break; case APP_STATUS_DETSHAR_END: m_nExamMode = APP_STATUS_IDLE; FINFO("Quit Detector Share Windows"); m_nExamMode = APP_STATUS_DETSHAR_END; break; case APP_STATUS_CAL_BEGIN: FINFO("Enter into Calibration Windows"); m_nExamMode = APP_STATUS_CAL_BEGIN; break; case APP_STATUS_CAL_END: FINFO("Quit Calibration Windows"); m_nExamMode = APP_STATUS_CAL_END; break; case APP_STATUS_WORK_IN_SENSITIVITY: FINFO("Enter into sensitivity test interface"); m_nExamMode = APP_STATUS_WORK_IN_SENSITIVITY; break; default: break; } if (APP_STATUS_WORK_END == m_nExamMode) { if (DetStatus_Acquire == GetCareRayDPCStatus()) { FINFO("quit exam but detector status is acquire,so stop acquire"); StopAcquisitionInside(); } } } bool Detector_CareRayRF::SetAcqMode(int nMode) { printf("========SetAcqMode nMode:%d \n", nMode); FINFO("========SetAcqMode nMode:{$}",nMode); if (m_nCurrentLogicMode == nMode) { FINFO("Same mode, return"); return true; } if (DetStatus_Acquire == GetCareRayDPCStatus()) { FINFO("SetAcqMode stop acquisition inside"); StopAcquisitionInside(); } //只有RAD模式读取全部的配置文件,CF和PF不读取全部配置,只读取部分 try { int nModeCount = (int)m_ModeConfig["ModeTable"].size(); for (int i = 0; i < nModeCount; i++) { int logicMode = (int)m_ModeConfig["ModeTable"][i]["LogicMode"];//SetAcqMode if (logicMode == nMode) { //FINFO("ModeTable22 {$}, {$}", i, m_ModeConfig["ModeTable"][i].encode()); printf("find LogicMode == nMode \n"); FINFO("find LogicMode == nMode"); if (nMode == RAD) { m_nRawImgWidth = (int)m_ModeConfig["ModeTable"][i]["RawImgHeight"]; m_nRawImgHeight = (int)m_ModeConfig["ModeTable"][i]["RawImgWidth"]; m_nImageWidth = (int)m_ModeConfig["ModeTable"][i]["ImageWidth"]; m_nImageHeight = (int)m_ModeConfig["ModeTable"][i]["ImageHeight"]; m_nModeID = (int)m_ModeConfig["ModeTable"][i]["OperationMode"]; string strFrameRate = (string)m_ModeConfig["ModeTable"][i]["Frequency"]; m_fFrameRate = stof(strFrameRate); FINFO("m_nRawImgWidth: {$}, m_nRawImgHeight: {$},m_nImageWidth: {$}, m_nImageHeight: {$}, m_nModeID: {$}, m_fFrameRate: {$}", m_nRawImgWidth, m_nRawImgHeight, m_nImageWidth, m_nImageHeight, m_nModeID, m_fFrameRate); //1800RF单独的点片模式ID是16 if (m_bHaveRadMode && m_nModeID == 16) { m_bIsRadMode = true; } } else { m_bIsRadMode = false; } //每次采集前裁剪值都重新从模型文件中读取,避免点片和透视使用相同的裁剪值 m_nCropLeft = (int)m_ModeConfig["ModeTable"][i]["CropLeft"]; m_nCropRight = (int)m_ModeConfig["ModeTable"][i]["CropRight"]; m_nCropTop = (int)m_ModeConfig["ModeTable"][i]["CropTop"]; m_nCropBottom = (int)m_ModeConfig["ModeTable"][i]["CropBottom"]; FINFO("m_nCropLeft: {$}, m_nCropRight: {$}, m_nCropTop: {$}, m_nCropBottom:{$}", m_nCropLeft, m_nCropRight, m_nCropTop, m_nCropBottom); m_nImageBits = (int)m_ModeConfig["ModeTable"][i]["PhySizeInfoBit"]; m_nDropImgCount = (int)m_ModeConfig["ModeTable"][i]["DropImgCount"]; m_bSaveRaw = (int)m_ModeConfig["ModeTable"][i]["IsSaveRaw"]; m_nReadoutTime = (int)m_ModeConfig["ModeTable"][i]["ReadoutTime"]; m_nTimePercentage = (int)m_ModeConfig["ModeTable"][i]["TimePercentage"]; FINFO("m_nImageBits: {$}, DropImgCount: {$}, SaveRaw: {$}, ReadoutTime:{$}, TimePercentage:{$}", m_nImageBits, m_nDropImgCount, m_bSaveRaw, m_nReadoutTime, m_nTimePercentage); m_nGainLevel = (int)m_ModeConfig["ModeTable"][i]["GainValue"]; m_nExpTime = (int)m_ModeConfig["ModeTable"][i]["ExpTime"];//为0时,探测器将赋值为真正的开窗时间(积分时间) m_nExamType = (int)m_ModeConfig["ModeTable"][i]["ExamType"]; FINFO("GainValue:{$},ExpTime:{$},ExamType:{$}", m_nGainLevel, m_nExpTime, m_nExamType); break; } } } catch (ResDataObjectExption& e) { FERROR("Read configuration failed, Error code: {$}", e.what()); return false; } m_nCurrentLogicMode = nMode; m_nValidImgNum = 0; //选择模式,恢复初值 return true; } /*** ** 说明:曝光开始时调用 ***/ bool Detector_CareRayRF::SetXrayOnNum() { printf("========SetXrayOnNum \n"); FINFO("========SetXrayOnNum"); m_bStartGrab = true; //曝光第一次,表示开始采集 m_dwBeginTime = GetTickCount64(); FINFO("SetXrayOnNum m_dwBeginTime:{$}", m_dwBeginTime); return true; } /*** ** 说明:设置曝光总数 ** TOMO模式根据这个值自动停止采集 ** 参数:nTimes,曝光总数,如果小于0,则不用这个逻辑来停止采集 ***/ bool Detector_CareRayRF::SetExposureTimes(int nTimes) { FINFO("========SetExposureTimes({$})", nTimes); m_nExposureCount = nTimes; return true; } bool Detector_CareRayRF::PrepareAcquisition(void* pDrvDPC) { printf("========PrepareAcquisition \n"); FINFO("========PrepareAcquisition "); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } if (-1 == m_nCurrentLogicMode) { FERROR("Illegal exam mode"); return false; } return true; } bool Detector_CareRayRF::StartAcquisition(void* pDrvDPC) { printf("========StartAcquisition \n"); FINFO("========StartAcquisition "); bool bRet = false; int nRet = 0; if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return bRet; } if (-1 == m_nCurrentLogicMode) { FERROR("Illegal exam mode"); } else { m_bSendImgToUpper = true; //开始采集,恢复初值 m_bValidImage = false; //开始采集,恢复初值 m_nDropImgNum = 0; //开始采集,恢复初值 m_bFirstImage = true; } //重新注册模式相关信息 FINFO("StartAcquisition RegisterAppMode appModeKey:{$},m_nModeID:{$},m_nGainLevel:{$},m_fFrameRate:{$},m_nExpTime:{$},m_nExamType:{$}", m_nCurrentLogicMode, m_nModeID, m_nGainLevel, m_fFrameRate, m_nExpTime, m_nExamType); if (!RegisterAppMode(m_nCurrentLogicMode, m_nModeID, m_nGainLevel, m_fFrameRate, m_nExpTime, m_nExamType))//StartAcquisition { FERROR("StartAcquisition-Register appmode failed!"); return bRet; } FINFO("StartAcquisition m_nLastLogicMode:{$},m_nCurrentLogicMode:{$}", m_nLastLogicMode, m_nCurrentLogicMode); //模式发生变化,重新加载校正文件 if (m_nLastLogicMode != m_nCurrentLogicMode) { m_nLastLogicMode = m_nCurrentLogicMode; LoadCalibrationFiles(); } m_bCancelFlag = false; if (m_bIsRadMode) { SetEvent(m_hAcqEvent); bRet = true; } else { //开始采集 int nBuffSize = (m_stSystemInfo.nRawImageWidth * m_stSystemInfo.nRawImageHeight * sizeof(unsigned short) + m_stSystemInfo.nFrmHeaderLen) * FRAME_NUMBER; FINFO("Calling CR_StartAcquisition appmode:{$},nBuffSize:{$}", m_nCurrentLogicMode, nBuffSize); nRet = CR_StartAcquisition(m_nCurrentDetIndex, m_nCurrentLogicMode, m_pImageBuffer, nBuffSize, -1);//StartAcquisition if (TestError(nRet)) { FERROR("Call CR_StartAcquisition failed!"); } else { SetCareRayDPCStatus(DetStatus_Acquire); //动态模式激活采集,设置状态 bRet = true; } } return bRet; } bool Detector_CareRayRF::StopAcquisition(void* pDrvDPC) { printf("========StopAcquisition \n"); FINFO("========StopAcquisition "); bool bRet = false; if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { //printf("Not current DPC, return\n"); FERROR("Not current DPC, return"); return bRet; } if (DetStatus_Acquire == GetCareRayDPCStatus()) { if (m_nExposureCount > 0 && m_bStartGrab) { //TOMO模式等图 //1.窗口最大1000ms,所以每次等1000ms int nLoop = 0; int nLoopCount = m_nExposureCount - m_nValidImgNum + 2; FINFO("Exposure count: {$}, valid image count: {$}", m_nExposureCount, m_nValidImgNum); while (m_bStartGrab && (m_nValidImgNum < m_nExposureCount) && (nLoop < nLoopCount)) { DWORD dwRet = WaitForSingleObject(m_hImageEvent, 1000); if (WAIT_TIMEOUT == dwRet) { FINFO("Waited 1000ms ({$}/{$})", nLoop, nLoopCount); } nLoop++; } } m_bCancelFlag = true; //rad采集,如果没采集到图像,设置标记位,退出采集 FINFO("Calling StopAcquisition"); int nRet = CR_StopAcquisition(m_nCurrentDetIndex);//StopAcquisition if (TestError(nRet)) { FERROR("StopAcquisition command failed"); } else { bRet = true; } m_bStartGrab = false; //停止采集,恢复初值 m_nValidImgNum = 0; //停止采集,恢复初值 m_nExposureCount = 0; //停止采集,恢复初值 SetCareRayDPCStatus(DetStatus_Standby); //停止采集,设置状态 } else { FINFO("Not in acquire status"); //切换到静态采集后,进入了ready状态。但此时可以不开始采集,切换到别的模式, //因此需要将m_bCancelFlag置为true,停止轮询 m_bCancelFlag = true; //rad采集,如果没采集到图像,设置标记位,退出采集 // RAD PrepareAcquisition时,会设置m_bCancelFlag为false bRet = true; } return bRet; } bool Detector_CareRayRF::StopAcquisitionInside() { printf("========StopAcquisitionInside \n"); FINFO("========StopAcquisitionInside "); bool bRet = false; if (DetStatus_Acquire == GetCareRayDPCStatus()) { if (m_nExposureCount > 0 && m_bStartGrab) { //TOMO模式等图 //1.窗口最大1000ms,所以每次等1000ms int nLoop = 0; int nLoopCount = m_nExposureCount - m_nValidImgNum + 2; FINFO("Exposure count: {$}, valid image count: {$}", m_nExposureCount, m_nValidImgNum); while (m_bStartGrab && (m_nValidImgNum < m_nExposureCount) && (nLoop < nLoopCount)) { DWORD dwRet = WaitForSingleObject(m_hImageEvent, 1000); if (WAIT_TIMEOUT == dwRet) { FINFO("Waited 1000ms ({$}/{$})", nLoop, nLoopCount); } nLoop++; } } m_bCancelFlag = true; //rad采集,如果没采集到图像,设置标记位,退出采集 FINFO("Calling StopAcquisition"); int nRet = CR_StopAcquisition(m_nCurrentDetIndex);//StopAcquisitionInside if (TestError(nRet)) { FERROR("StopAcquisition command failed"); } else { bRet = true; } m_bStartGrab = false; //停止采集,恢复初值 m_nValidImgNum = 0; //停止采集,恢复初值 m_nExposureCount = 0; //停止采集,恢复初值 SetCareRayDPCStatus(DetStatus_Standby); //停止采集,设置状态 } else { FINFO("Not in acquire status"); //切换到静态采集后,进入了ready状态。但此时可以不开始采集,切换到别的模式, //因此需要将m_bCancelFlag置为true,停止轮询 m_bCancelFlag = true; //rad采集,如果没采集到图像,设置标记位,退出采集 // RAD PrepareAcquisition时,会设置m_bCancelFlag为false bRet = true; } return bRet; } bool Detector_CareRayRF::ActiveCalibration(void* pDrvDPC, CCOS_CALIBRATION_TYPE eType) { printf("========ActiveCalibration \n"); FINFO("========ActiveCalibration "); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { //printf("Not current DPC, return\n"); FERROR("Not current DPC, return"); return false; } if (-1 == m_nCurrentLogicMode) { FERROR("Illegal exam mode"); return false; } if (CCOS_CALIBRATION_TYPE_XRAY == eType) { SetCareRayDPCStatus(DetStatus_XrayCalibration); } m_eCaliType = eType; return true; } /*** ** 校正时响应上层调用的FramePrep ** 目前只有纯点片模式,例如 1800RF的mode 16需要这个流程 ***/ bool Detector_CareRayRF::PrepareCalibration(void* pDrvDPC) { printf("========PrepareCalibration \n"); FINFO("========PrepareCalibration "); bool bRet = false; if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { //printf("Not current DPC, return\n"); FERROR("Not current DPC, return"); return bRet; } if (GetCareRayDPCStatus() != DetStatus_XrayCalibration) { FINFO("Current status is not XrayCalibration, return succeed"); return true; } if (m_nExamType == CR_RadExtSync)//PrepareCalibration { //这里应该只在第一次prepare时setevent,但第一次setevent之后,线程一直被占用着, //所以每次setevent也无所谓了,线程执行完毕后resetevent SetEvent(m_hGainEvent); DWORD dwRet = WaitForSingleObject(m_hGainReadyEvent, m_nGainReadyTimeout * 1000); if (dwRet != WAIT_OBJECT_0) { FERROR("Prepare calibration failed({$}), cancle it", dwRet); m_bAbortCalibration = true; //异常,多数是超时,终止校正轮询 } else { bRet = true; } } else { bRet = true; } return bRet; } bool Detector_CareRayRF::StartCalibration(void* pDrvDPC) { printf("========StartCalibration \n"); FINFO("========StartCalibration "); bool bRet = false; if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { //printf("Not current DPC, return\n"); FERROR("Not current DPC, return"); return bRet; } if (CCOS_CALIBRATION_TYPE_DARK == m_eCaliType) { SetEvent(m_hDarkEvent); bRet = true; } else if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType) { bRet = StartGainCalibration(); } return bRet; } bool Detector_CareRayRF::StopCalibration(void* pDrvDPC) { printf("========StopCalibration \n"); FINFO("========StopCalibration "); bool bRet = false; int nRet = CR_OK; if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { //printf("Not current DPC, return\n"); FERROR("Not current DPC, return"); return bRet; } FINFO("StopCalibration Calling StopCalibration"); nRet = CR_StopCalibration(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("StopCalibration command failed"); } else { bRet = true; } return bRet; } bool Detector_CareRayRF::LoadDll(string strWorkPath) { printf("========LoadDll \n"); FINFO("========LoadDll start"); string strSDKPath = ""; try { strSDKPath = (string)m_ModeConfig["SDKPath"]; } catch (ResDataObjectExption& e) { FERROR("Read configuration failed, Error code: {$}", e.what()); return false; } string workpath = strWorkPath + strSDKPath; string drvpath = workpath + "\\CRInterface.dll"; SetDllDirectory(workpath.c_str()); m_hCareRayRFModule = LoadLibrary(drvpath.c_str()); if (m_hCareRayRFModule == nullptr) { DWORD dw = GetLastError(); FERROR("Load {$} failed! error code:{$}", drvpath, dw); return false; } LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_InitializeLibrary); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_DeinitializeLibrary); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetDetectorIndexAndIPAddress); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_Connect); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_Disconnect); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_ResetDetector); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetSystemInformation); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetApplicationMode); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_RegisterApplicationMode); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_StartAcquisition); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_StopAcquisition); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_StartDarkCalibration); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_StartGainCalibration); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_StopCalibration); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_QueryCalibrationStatus); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetDetrStatus); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_RegisterEventCallback); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_LoadReference); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_UnloadReference); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_QueryAcquisitionStatus); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_PermitExposure); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetImage); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetConnectionStatus); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_StartDarkAcquisition); LOAD_PROC_ADDRESS(m_hCareRayRFModule, CR_GetLastIntlMsg); FINFO("LoadDll end"); return true; } bool Detector_CareRayRF::OpenDetector() { printf("========OpenDetector \n"); FINFO("========OpenDetector "); FINFO("Calling InitializeLibrary"); CR_InitializeLibrary(); int nRet = CR_OK; int nDetrNum = 0; CR_DetrIdxAndIPAddr oDetrIdxAndIPAddr[16]; FINFO("Calling GetDetectorIndexAndIPAddress"); nRet = CR_GetDetectorIndexAndIPAddress(oDetrIdxAndIPAddr, &nDetrNum); if (TestError(nRet)) { FERROR("GetDetectorIndexAndIPAddress command failed"); return false; } for (int i = 0; i < nDetrNum; i++) { FINFO("Detector index:{$}, IP:{$}", oDetrIdxAndIPAddr[i].nIdx, oDetrIdxAndIPAddr[i].szIPAddr); } m_nCurrentDetIndex = oDetrIdxAndIPAddr[0].nIdx; //一般只能拿到1,除非在SDK db文件里配置"IP1;IP2" FINFO("OpenDetector m_nCurrentDetIndex:{$}", m_nCurrentDetIndex); m_pCallbackPtrs = new CallbackImp(); FINFO("Calling RegisterEventCallback"); CR_RegisterEventCallback(m_nCurrentDetIndex, m_pCallbackPtrs); FINFO("Calling Connect"); nRet = CR_Connect(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("Connect command failed"); //return false; } FINFO("Calling ResetDetector"); nRet = CR_ResetDetector(m_nCurrentDetIndex, false); if (TestError(nRet)) { FERROR("ResetDetector command failed"); //return false; } m_mapModeInfo = new CR_ModeInfo[16]; FINFO("Calling GetApplicationMode"); nRet = CR_GetApplicationMode(m_nCurrentDetIndex, m_mapModeInfo, &m_nModeNum); if (TestError(nRet)) { FERROR("GetApplicationMode command failed"); //return false; } FINFO("support mode number: {$}", m_nModeNum); FINFO("Open Detector Success--->"); return true; } bool Detector_CareRayRF::TestError(int nErrorCode) { if (GetReturnCode(nErrorCode) >= CR_WARN) { char info[256]; CR_GetLastIntlMsg(info, 256, -1); FINFO("ErrorCode:{$}, info:{$}", nErrorCode, info); //printf("ErrorCode:%d, %s \n", nErrorCode, info); if (GetReturnCode(nErrorCode) != CR_WARN) //warn返回成功,比如缺少校正文件,其它待考察 ys return nErrorCode; } return CR_OK; } void Detector_CareRayRF::PrintModeList(ResDataObject& DetectorModeList) { FINFO("========List of Supported Application Modes"); unsigned long dpi = 0; for (int i = 0; i < m_nModeNum; i++) { FINFO("--> ModeID {$} Image dimension: {$} x {$} ", m_mapModeInfo[i].nModeID, m_mapModeInfo[i].nImageWidth, m_mapModeInfo[i].nImageHeight); FINFO("CutOffX:{$} CutOffY:{$}", m_mapModeInfo[i].nCutoffX, m_mapModeInfo[i].nCutoffY); FINFO("Binning scheme:{$} x {$}", m_mapModeInfo[i].nBinX, m_mapModeInfo[i].nBinY); FINFO("Pixel depth:{$},Max frame rate:{$},Description:{$}", m_mapModeInfo[i].nPixelDepth, m_mapModeInfo[i].fMaxFrmRate, m_mapModeInfo[i].szDesc); FINFO("DefaultGainLevel:{$} MaxExpTime:{$}", m_mapModeInfo[i].nDefaultGainLevel, m_mapModeInfo[i].fMaxExpTime); if ((unsigned long)m_mapModeInfo[i].nImageWidth * (unsigned long)m_mapModeInfo[i].nImageHeight > dpi) { dpi = m_mapModeInfo[i].nImageWidth * m_mapModeInfo[i].nImageHeight; m_nRawImgWidth = m_mapModeInfo[i].nImageWidth; m_nRawImgHeight = m_mapModeInfo[i].nImageHeight; } ResDataObject ModeInfo; ModeInfo.add("ModeID", m_mapModeInfo[i].nModeID); ModeInfo.add("ImageWidth", m_mapModeInfo[i].nImageWidth); ModeInfo.add("ImageHeight", m_mapModeInfo[i].nImageHeight); ModeInfo.add("CutOffX", m_mapModeInfo[i].nCutoffX); ModeInfo.add("CutOffY", m_mapModeInfo[i].nCutoffY); string temp; temp = to_string(m_mapModeInfo[i].nBinX) + "x" + to_string(m_mapModeInfo[i].nBinY); ModeInfo.add("BinningMode", temp.c_str()); ModeInfo.add("MaxFrameRate", m_mapModeInfo[i].fMaxFrmRate); ModeInfo.add("GainID", m_mapModeInfo[i].nDefaultGainLevel); if (m_mapModeInfo[i].nModeID == 16) { ModeInfo.add("ExpTime", 500); } else { ModeInfo.add("ExpTime", 0); } DetectorModeList.add("ModeInfo", ModeInfo); } FINFO("DetectorModeList:{$}", DetectorModeList.encode()); FINFO("Max image width:{$}, Max image height:{$}", m_nRawImgWidth, m_nRawImgHeight); if (nullptr != m_pRawImgBuffer) { delete[]m_pRawImgBuffer; m_pRawImgBuffer = nullptr; } m_pRawImgBuffer = new WORD[(size_t)m_nRawImgWidth * (size_t)m_nRawImgHeight]; if (nullptr != m_pFullImgBuffer) { delete[]m_pFullImgBuffer; m_pFullImgBuffer = nullptr; } m_pFullImgBuffer = new WORD[(size_t)m_nRawImgWidth * (size_t)m_nRawImgHeight]; FINFO("End of List"); } bool Detector_CareRayRF::GetSystemInfo(int nFpdIndex) { CR_DetrStatus detrStatus; FINFO("Calling GetSystemInformation Get System information:"); int nRet = CR_GetSystemInformation(nFpdIndex, &m_stSystemInfo); if (CR_OK == nRet) { FINFO("Raw image width (unit: pixels) = {$}", m_stSystemInfo.nRawImageWidth);//探测器出图最大宽度 FINFO("Raw image height (unit: pixels) = {$}", m_stSystemInfo.nRawImageHeight);//探测器出图最大高度 FINFO("tHardware version = {$}", m_stSystemInfo.szHardwareVersion); FINFO("Serial number = {$}", m_stSystemInfo.szSerialNumber); FINFO("Software version = {$}", m_stSystemInfo.szSoftwareVersion); FINFO("Firmware version = {$}", m_stSystemInfo.szFirmwareVersion); FINFO("Machine ID = {$}", m_stSystemInfo.szDetrMachineID); FINFO("Detector description = {$}", m_stSystemInfo.szDetrDesc);//"Product Model: CareView 1800RF" "Product Model: CareView 560RF" strstr m_nFrmHeaderLen = m_stSystemInfo.nFrmHeaderLen; //256 FINFO("Frame Header Length:{$}", m_nFrmHeaderLen); //根据探测器描述识别当前探测器是否支持单独的点片(560RF不支持、1800RF支持) char* pTemp = nullptr; pTemp = strstr(m_stSystemInfo.szDetrDesc,"1800RF"); if (pTemp) { FINFO("Current detector have rad mode!"); m_bHaveRadMode = true; } else { FINFO("Current detector doesn't have rad mode!"); m_bHaveRadMode = false; } unsigned long nBuffSize = (m_stSystemInfo.nRawImageWidth * m_stSystemInfo.nRawImageHeight * sizeof(unsigned short) + m_stSystemInfo.nFrmHeaderLen) * FRAME_NUMBER; FINFO("m_stSystemInfo.nRawImageWidth:{$},m_stSystemInfo.nRawImageHeight:{$},nBuffSize:{$}", m_stSystemInfo.nRawImageWidth, m_stSystemInfo.nRawImageHeight, nBuffSize); if (nullptr == m_pImageBuffer) { m_pImageBuffer = (WORD*)malloc(nBuffSize); if (nullptr == m_pImageBuffer) { FERROR("Image buffer is NULL"); return false; } } memset(m_pImageBuffer, 0x0, nBuffSize); FINFO("Calling GetDetrStatus"); nRet = CR_GetDetrStatus(nFpdIndex, &detrStatus); if (CR_OK == nRet) { FINFO("Current operating temperature = {$}", detrStatus.oDetrTemperature.fCurrent); FINFO("Current degrees Celsius = {$} degrees Fahrenheit", 32 + 9 * detrStatus.oDetrTemperature.fAvg / 5); FINFO("Overheat = {$} ", (1 == detrStatus.oDetrTemperature.nOverheat) ? "true" : "false"); } } FINFO("Get System infor Over"); return true; } bool Detector_CareRayRF::RegisterAppMode(int nNewAppModeKey, int nModeID, int nGainID, float fFrameRate, int nExpTime, int nTrigType) { FINFO("RegisterAppMode nNewAppModeKey:{$},ModeID:{$},GainID:{$},FrameRate:{$},ExpTime:{$},TriggerType:{$}", nNewAppModeKey, nModeID, nGainID, fFrameRate, nExpTime, nTrigType); bool bFindModeID = false; for (int nModeIndex = 0; nModeIndex < m_nModeNum; nModeIndex++) { if (nModeID == m_mapModeInfo[nModeIndex].nModeID) { bFindModeID = true; } } if (!bFindModeID) { FERROR("No coresponding ModeID in detector"); return false; } switch (nTrigType) { case CR_RadExtSync: FINFO("1: rad external trigger"); break; case CR_RadSoftSync: FINFO("2: rad soft trigger"); break; case CR_RadAutoSync: FINFO("3: rad auto trigger"); break; case CR_RadManualSync: FINFO("4: rad manual trigger"); break; case CR_RadAedSync: FINFO("5: rad aed trigger"); break; case CR_RadDaecSync: FINFO("6: rad daec trigger"); break; case CR_FluReserved: FINFO("7: fluo free trigger"); break; case CR_FluExtSync: FINFO("8: fluo external trigger"); break; case CR_FluIntSync: FINFO("9: fluo internal trigger"); break; default: FINFO("Unkown trigger type"); break; } bool bIsFluoroMode = true; float fExpTime = nExpTime * 1.0f; int nRet = CR_OK; //rad mode id: 16,max frame rate:1; flu mode id: 101,max frame rate:4 如果mode id和triggertype 对不上会有问题,故配置文件中要慎重配置 FINFO("Calling RegisterApplicationMode mode id:{$},trigger type:{$} ", nModeID, nTrigType); nRet = CR_RegisterApplicationMode(m_nCurrentDetIndex, nNewAppModeKey, nModeID, &fFrameRate, &fExpTime, nTrigType, nGainID,0,0); if (TestError(nRet)) { FERROR("Register ApplicationMode failed!"); return false; } else { FINFO("Register AppMode:{$},FrameRate:{$},ExpTime:{$},TriggerType:{$} Success", nNewAppModeKey, fFrameRate, fExpTime, nTrigType); } return true; } bool Detector_CareRayRF::CalculateEXI(WORD* pImgData, int nImgWidth, int nImgHeight, int nImageBit, int nThreshold) { int nROIXL = static_cast(0.3 * nImgWidth); int nROIXR = static_cast(0.7 * nImgWidth); int nROIYL = static_cast(0.3 * nImgHeight); int nROIYR = static_cast(0.7 * nImgHeight); WORD* pSrc = NULL; long nCount = 0; DWORD64 nSum = 0; int nEXI = 0; try { for (int i = nROIYL; i < nROIYR; i++) { pSrc = pImgData + (i * nImgWidth); for (int j = nROIXL; j < nROIXR; j++) { nSum += *(pSrc + j); nCount++; } } nEXI = (int)(nSum / nCount); } catch (...) { return false; } FINFO("Image EXI:{$}, Threshold:{$}", nEXI, nThreshold); if (nEXI >= nThreshold) { FINFO("Image has xray!"); return true;//有x射线 } return false; } bool Detector_CareRayRF::CheckImageExi(WORD* pImgData, int nImgWidth, int nImgHeight, WORD dwExiThrethold) { if (dwExiThrethold <= 0) { return true; } FINFO("Check image exi..."); bool bResult = CalculateEXI(pImgData, nImgWidth, nImgHeight, 16, dwExiThrethold); if (bResult) { return true; } FINFO("Check image exi---black Image"); return false; } //nIndex 缺省-1,当使用缺省值时代表是静态模式,图像名不记录序号 void Detector_CareRayRF::OnProcessImage(int nWidth, int nHeight, int nIndex) { printf("========OnProcessImage \n"); FINFO("========OnProcessImage nWidth:{$},nHeight:{$},nIndex:{$}", nWidth, nHeight, nIndex); int ret = 0; bool bImageCrop = false; if (m_nCropLeft != 0 || m_nCropTop != 0 || m_nCropRight != 0 || m_nCropBottom != 0) { ret = CropImageMargin(m_pFullImgBuffer, m_nImageWidth, m_nImageHeight, m_pRawImgBuffer, m_nRawImgWidth, m_nRawImgHeight, m_nImageBits, m_nCropLeft, m_nCropTop, m_nCropRight, m_nCropBottom); if (ret) { FERROR("CropImageMargin fail!!"); } else { FINFO("CropImageMargin success!"); bImageCrop = true; } } //上图之前回调图像的宽高,使得上层在拷贝内存时是正确的图像大小 if (bImageCrop) { ConfFeedback(EVT_CONF_RAW_WIDTH, m_nCurrentPanelID, "", m_nImageWidth); ConfFeedback(EVT_CONF_RAW_HIGHT, m_nCurrentPanelID, "", m_nImageHeight); } else { ConfFeedback(EVT_CONF_RAW_WIDTH, m_nCurrentPanelID, "", m_nRawImgWidth); ConfFeedback(EVT_CONF_RAW_HIGHT, m_nCurrentPanelID, "", m_nRawImgHeight); } if (!m_bValidImage && m_nDelayTime > 0) { m_dwEndTime = GetTickCount64(); } /*** ** 1.康众探测器,第一个trigIn信号触发trigOut升高,此时代表读图,所以基本需要丢掉第一帧图像 ** 此处灵活应用,可配置丢图张数 ** 2.由于先采集,后曝光,此处还需要根据曝光和拿图时间间隔来判断是否为曝光图像 ****/ FINFO("OnProcessImage m_nDropImgNum:{$} m_nDropImgCount:{$}", m_nDropImgNum, m_nDropImgCount); if (m_nDropImgNum < m_nDropImgCount)//配置为0时表示不丢图 { m_nDropImgNum++; FINFO("Drop {$} image", m_nDropImgNum); } else if (!CheckTimeLimit(m_dwBeginTime, m_dwEndTime))//m_nDelayTime 配置为0时表示不延时 { m_nDropImgNum++; FERROR("CheckTimeLimit Drop {$} image", m_nDropImgNum); } else { //1800RF有单独的点片模式 if (m_bIsRadMode) { FINFO("OnProcessImage rad mode"); if (m_bSendImgToUpper) { FINFO("rad mode send image to upper!"); m_nValidImgNum++; m_bSendImgToUpper = false; //单帧点片,发送一张图像后不再发送图像 if (bImageCrop) { DataFeedback(EVT_DATA_RAW_IMAGE, m_pFullImgBuffer); } else { DataFeedback(EVT_DATA_RAW_IMAGE, m_pRawImgBuffer); } //自动停止采集(发送standby,触发上层流程) StatusFeedback(EVT_STATUS_PANEL, PANEL_END_ACQ); } else { FINFO("Already send image"); } } else { if (m_bFirstImage) { FINFO("m_bFirstImage is true"); StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); m_bFirstImage = false; } FINFO("OnProcessImage flu mode,m_nExamType:{$},m_nCurrentLogicMode:{$}", m_nExamType, m_nCurrentLogicMode); //560RF动态模式做点片 if (m_nExamType == CR_FluExtSync && m_nCurrentLogicMode == 1) { FINFO("m_nExamType == 8, m_nCurrentLogicMode == 1"); if (bImageCrop) { //计算图像EXI 不满足的不往上推 if (!CheckImageExi(m_pFullImgBuffer, m_nImageWidth, m_nImageHeight, m_nExiThreshold)) //true 有射线 false 没射线 { return; } } else { //计算图像EXI 不满足的不往上推 if (!CheckImageExi(m_pRawImgBuffer, m_nRawImgWidth, m_nRawImgHeight, m_nExiThreshold)) //true 有射线 false 没射线 { return; } } if (m_bValidImage) { //RAD模式已经推过图了就不在推图了 FINFO("RAD has send one image! return"); return; } } m_bValidImage = true; //合法图像,不再判断时间间隔 m_nValidImgNum++; SetEvent(m_hImageEvent); if (bImageCrop) { DataFeedback(EVT_DATA_RAW_IMAGE, m_pFullImgBuffer); } else { DataFeedback(EVT_DATA_RAW_IMAGE, m_pRawImgBuffer); } } } if (m_bSaveRaw) { SaveImage(nIndex, bImageCrop); } } void Detector_CareRayRF::SaveImage(int nIndex, bool bImageCrop) { FINFO("========Begin save image"); char szTemp[30] = { 0 }; FILE* fp; string strFileName = m_strWorkPath + "\\rawdata"; if (-1 == nIndex) { strFileName += "\\Image_Rad.raw"; } else { sprintf_s(szTemp, "\\Image_%d.raw", nIndex); strFileName += szTemp; } if ((fp = fopen(strFileName.c_str(), "wb+")) == NULL) { DWORD dw = GetLastError(); FERROR("fopen {$} failed, {$}", strFileName, dw); return; } if (bImageCrop) { fwrite(m_pFullImgBuffer, sizeof(WORD), m_nImageWidth * m_nImageHeight, fp); } else { fwrite(m_pRawImgBuffer, sizeof(WORD), m_nRawImgWidth * m_nRawImgHeight, fp); } fclose(fp); FINFO("Save {$} image over", strFileName); } /*** ** 说明:调用SDK接口,执行offset校正流程 ** dark校正、闲时offset刷新都会调用这个函数 ***/ bool Detector_CareRayRF::StartDarkCalibration(int nLogicMode) { printf("========StartDarkCalibration \n"); FINFO("========StartDarkCalibration Logic mode:{$}", nLogicMode); bool bRet = false; int nRet = CR_OK, nCurrFrmNum = 0, nPrevFrmNum = nCurrFrmNum - 1; FINFO("Calling StartDarkCalibration"); nRet = CR_StartDarkCalibration(m_nCurrentDetIndex, nLogicMode, true, false); if (TestError(nRet)) { FERROR("StartDarkCalibration command failed!"); return bRet; } CR_CalibrationInfo calProgInfo; FINFO("Calling QueryCalibrationStatus"); CR_QueryCalibrationStatus(m_nCurrentDetIndex, &calProgInfo); nCurrFrmNum = 0; nPrevFrmNum = nCurrFrmNum; while (-1 == calProgInfo.nResult) { if (m_bAbortCalibration || m_bAbortRefreshOft) { FINFO("StartDarkCalibration Calling CR_StopCalibration"); nRet = CR_StopCalibration(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("StopCalibration command failed!"); } return true; } if (nCurrFrmNum > nPrevFrmNum) { nPrevFrmNum = nCurrFrmNum; } nCurrFrmNum = calProgInfo.nCurrentFrameNum; CR_QueryCalibrationStatus(m_nCurrentDetIndex, &calProgInfo); Sleep(20); } nRet = calProgInfo.nResult; if (!TestError(nRet)) { FINFO("Appmode({$}) dark calibration completes successfully", nLogicMode); //printf("Appmode(%d) dark calibration completes successfully \n", nLogicMode); bRet = true; } else { FERROR("Appmode({$}) offset calibration failed!", nLogicMode); //printf("Appmode(%d) offset calibration failed \n", nLogicMode); } return bRet; } bool Detector_CareRayRF::StartGainCalibration() { printf("========StartGainCalibration \n"); FINFO("========StartGainCalibration "); if (-1 == m_nCurrentLogicMode) { FERROR("Illegal exam mode"); return false; } if (m_nExamType == CR_RadExtSync) //SDK Rad校正模式,准备工作已经在PrepareCalibration准备好,直接发ACQ状态就行 { return true; } int nCurrFrmNum = 0, nPrevFrmNum = 0; //改为先发状态,再调用SDK接口 //如果后发,SDK接口执行失败会导致不发送这个状态,进而导致停止校正流程不能正确执行 //静态点片模式的增益校正流程还需要考虑 FINFO("Calling StartGainCalibration"); int nRet = CR_StartGainCalibration(m_nCurrentDetIndex, m_nCurrentLogicMode); if (TestError(nRet)) { FERROR("StartGainCalibration command failed"); SetCareRayDPCStatus(DetStatus_Standby); //Gain校正执行失败,置回Standby StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); return false; } return true; } unsigned __stdcall Detector_CareRayRF::onFPDScanThread(PVOID pvoid) { Detector_CareRayRF* pOpr = (Detector_CareRayRF*)pvoid; FINFO("Enter scan thread"); bool bExit = false; while (!bExit) { DWORD dwRet = WaitForMultipleObjects(SCAN_EVENT_COUNT, pOpr->m_hArrayEvent, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwRet) //m_hStopScanEvent { bExit = true; } else if (WAIT_OBJECT_0 + 1 == dwRet) //m_hAcqEvent { pOpr->OnAcquireImage(); } else if (WAIT_OBJECT_0 + 2 == dwRet) //m_hGainEvent { pOpr->OnAcquireGainImage(); } else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hDarkEvent { pOpr->OnStartDarkCalibration(); } else if (WAIT_OBJECT_0 + 4 == dwRet) //m_hProcessImgEvent { pOpr->OnProcessImage(pOpr->m_nRawImgWidth, pOpr->m_nRawImgHeight, pOpr->m_nCbImgIndex); } } FINFO("Level scan thread"); return 0; } unsigned __stdcall Detector_CareRayRF::RefreshOffsetThread(PVOID pvoid) { Detector_CareRayRF* pOpr = (Detector_CareRayRF*)pvoid; FINFO("========Enter fresh offset thread"); bool bExit = false; while (!bExit) { DWORD dwRet = WaitForMultipleObjects(OFFSET_EVENT_COUNT, pOpr->m_hOffsetEvent, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwRet) //m_hStopOffsetEvent { bExit = true; } else if (WAIT_OBJECT_0 + 1 == dwRet) //m_hStartAllOffset { pOpr->RefreshAllOffset(pOpr->m_vCtrlDetectorModeList); } else if (WAIT_OBJECT_0 + 2 == dwRet) //m_hStartOffset { pOpr->OnRefreshOffset(); } else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hAbortOffset { pOpr->AbortFreshOffset(); } } FINFO("Level fresh offset thread"); return 0; } //1800RF支持单独的RAD模式 void Detector_CareRayRF::OnAcquireImage() { printf("========OnAcquireImage \n"); FINFO("========OnAcquireImage "); int nExpPermittedHint = 0, nWaitPermissionHint = 0, nLastExpStatus = CR_EXP_ERROR, nFrmSize = 0; int nAppMode = m_nCurrentLogicMode; FINFO("Call CR_StartAcquisition appmode:{$}", nAppMode); int nRet = CR_StartAcquisition(m_nCurrentDetIndex, nAppMode, NULL, 0, -1);//OnAcquireImage if (TestError(nRet)) { FERROR("OnAcquireImage StartAcquisition failed!"); return; } SetCareRayDPCStatus(DetStatus_Acquire); //动态模式激活采集,设置状态 CR_ExpProgress oExpProg; memset(&oExpProg, 0x0, sizeof(CR_ExpProgress)); do { //FINFO("Calling QueryAcquisitionStatus"); nRet = CR_QueryAcquisitionStatus(m_nCurrentDetIndex, &oExpProg); if (TestError(nRet)) { FERROR("QueryAcquisitionStatus command failed!"); break; } switch (oExpProg.nExpStatus) { case CR_EXP_INIT: if (nLastExpStatus != CR_EXP_INIT) { FINFO("CR_EXP_INIT(0)"); nLastExpStatus = CR_EXP_INIT; } break; case CR_EXP_READY: if (0 == nExpPermittedHint) { FINFO("CR_EXP_READY(1)"); nExpPermittedHint++; //StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); } break; case CR_EXP_WAIT_PERMISSION: if (0 == nWaitPermissionHint) { FINFO("CR_EXP_WAIT_PERMISSION(2)"); FINFO("Calling CR_PermitExposure"); nRet = CR_PermitExposure(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("PermitExposure command failed"); break; } nWaitPermissionHint++; } break; case CR_EXP_PERMITTED: if (nLastExpStatus != CR_EXP_PERMITTED) { FINFO("CR_EXP_PERMITTED(3)"); nLastExpStatus = CR_EXP_PERMITTED; } break; case CR_EXP_EXPOSE: if (nLastExpStatus != CR_EXP_EXPOSE) { FINFO("CR_EXP_EXPOSE(4)"); nLastExpStatus = CR_EXP_EXPOSE; } break; case CR_EXP_COMPLETE: if (nLastExpStatus != CR_EXP_COMPLETE) { FINFO("CR_EXP_COMPLETE(5)"); nLastExpStatus = CR_EXP_COMPLETE; } break; default: FINFO("Exp Status:{$}", oExpProg.nExpStatus); nExpPermittedHint = 0; break; } if (oExpProg.bIsFetchable) { FINFO("Image is fetchable now"); break; } else { if (m_bCancelFlag) //结束这个循环,否则一直在这个循环里 { m_bCancelFlag = false; //结束轮询,恢复初值 FINFO("[ Leave this loop ]"); break; } } Sleep(30); } while (true); if (oExpProg.bIsFetchable) { int nImageSize = m_nRawImgHeight * m_nRawImgWidth * 2; nFrmSize = nImageSize + RAD_HEADER_SIZE; unsigned char* pImage = (unsigned char*)malloc(nFrmSize); if (nullptr != pImage) { FINFO("Calling GetImage"); nRet = CR_GetImage(m_nCurrentDetIndex, pImage, nFrmSize, 9000); if (TestError(nRet)) { FERROR("GetImage command failed"); } else { FINFO("Get Image success!"); memcpy(m_pRawImgBuffer, pImage + RAD_HEADER_SIZE, nImageSize); OnProcessImage(m_nRawImgWidth, m_nRawImgHeight); SetCareRayDPCStatus(DetStatus_Standby); //rad采集结束,设置状态 } free(pImage); pImage = nullptr; } } else { FINFO("Calling StopAcquisition"); nRet = CR_StopAcquisition(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("StopAcquisition failed"); } SetCareRayDPCStatus(DetStatus_Standby); //rad采集失败,设置状态 } } //SDK Rad模式增益校正流程 void Detector_CareRayRF::OnAcquireGainImage() { printf("========OnAcquireGainImage \n"); FINFO("========OnAcquireGainImage "); int nRet = CR_OK, nCurrFrmNum = 0, nPrevFrmNum = nCurrFrmNum - 1; int nExpPermittedHint = 0, nExpForbiddenHint = 0; FINFO("Calling StartGainCalibration"); nRet = CR_StartGainCalibration(m_nCurrentDetIndex, m_nCurrentLogicMode); if (TestError(nRet)) { FERROR("StartGainCalibration command failed"); } else { CR_CalibrationInfo calProgInfo; FINFO("Calling QueryCalibrationStatus"); nRet = CR_QueryCalibrationStatus(m_nCurrentDetIndex, &calProgInfo); while (-1 == calProgInfo.nResult) { if (CR_EXP_READY == calProgInfo.nExpStatus) { if (0 == nExpPermittedHint) { FINFO("Detector is ready for Gain Acquisition"); SetEvent(m_hGainReadyEvent); //探测器ready,可以采图 nExpPermittedHint++; nExpForbiddenHint = 0; } } else { if (0 == nExpForbiddenHint) { FINFO("Now you can't press x-ray hand switch..."); nExpForbiddenHint++; nExpPermittedHint = 0; } } if (m_bAbortCalibration) { FINFO("OnAcquireGainImage Calling StopCalibration"); nRet = CR_StopCalibration(m_nCurrentDetIndex); if (TestError(nRet)) { FERROR("StopCalibration command failed"); } break; } if (nCurrFrmNum > nPrevFrmNum) { nPrevFrmNum = nCurrFrmNum; FINFO("Gain calibration progress:{$} / {$},current frame mean = {$} TargetGray={$}", calProgInfo.nCurrentFrameNum, calProgInfo.nTotalFrameNum, calProgInfo.nCurrentFrameMeanValue, calProgInfo.nTargetGrayValue); } nCurrFrmNum = calProgInfo.nCurrentFrameNum; StatusFeedback(EVT_STATUS_SINGLEEXP, DOSE_ACCEPT); CR_QueryCalibrationStatus(m_nCurrentDetIndex, &calProgInfo); Sleep(5); } nRet = calProgInfo.nResult; if (TestError(nRet)) { FERROR("Gain calibration failed"); } else { FINFO("Gain calibration over"); } SetCareRayDPCStatus(DetStatus_Standby); //rad校正结束,设置状态 StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } } /*** ** 说明:开始暗场校正 ***/ void Detector_CareRayRF::OnStartDarkCalibration() { printf("========OnStartDarkCalibration \n"); FINFO("========OnStartDarkCalibration "); SetCareRayDPCStatus(DetStatus_Offset); //开始offset校正 if (StartDarkCalibration(m_nCurrentLogicMode)) { StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } else { StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_ERROR); } SetCareRayDPCStatus(DetStatus_Standby); //offset校正完成,置回Standby } //获取只用于本DPC记录的探测器状态 eDetStatus Detector_CareRayRF::GetCareRayDPCStatus() { string strStatus = "Unknown"; switch (m_eStatus) { case DetStatus_NotIni: strStatus = "NotIni"; break; case DetStatus_NotConn: strStatus = "NotConn"; break; case DetStatus_Sleep: strStatus = "Sleep"; break; case DetStatus_Standby: strStatus = "Standby"; break; case DetStatus_Work: strStatus = "Work"; break; case DetStatus_Acquire: strStatus = "Acquire"; break; case DetStatus_Offset: strStatus = "Offset"; break; case DetStatus_XrayCalibration: strStatus = "XrayCalibration"; break; default: break; } FINFO("Driver status: {$}", strStatus.c_str()); return m_eStatus; } //设置只用于本DPC的探测器状态 bool Detector_CareRayRF::SetCareRayDPCStatus(eDetStatus status) { string strStatus = "Unknown"; bool bSetStatus = true; switch (status) { case DetStatus_NotIni: strStatus = "NotIni"; break; case DetStatus_NotConn: strStatus = "NotConn"; break; case DetStatus_Sleep: strStatus = "Sleep"; break; case DetStatus_Standby: strStatus = "Standby"; break; case DetStatus_Work: strStatus = "Work"; break; case DetStatus_Acquire: strStatus = "Acquire"; break; case DetStatus_Offset: strStatus = "Offset"; break; case DetStatus_XrayCalibration: strStatus = "XrayCalibration"; break; default: bSetStatus = false; break; } if (bSetStatus) { m_eStatus = status; FINFO("Set driver status: {$}", strStatus.c_str()); } else { FERROR("{$} {$} is a illegal status", strStatus.c_str(), (int)status); } return bSetStatus; } bool Detector_CareRayRF::LoadCalibrationFiles() { FINFO("Calling LoadReference m_nCurrentLogicMode:{$}", m_nCurrentLogicMode); int nRet = CR_LoadReference(m_nCurrentDetIndex, m_nCurrentLogicMode); if (TestError(nRet)) { FERROR("LoadReference command failed"); return false; } FINFO("LoadReference command succeed"); return true; } //参照RFOC康众动态代码整理的图像裁剪功能 int Detector_CareRayRF::CropImageMargin(LPVOID pDstData, int& nDstWidth, int& nDstHeight, LPVOID pScrData, int nSrcWidth, int nSrcHeight, int nBits, int nLeftMargin, int nTopMargin, int nRightMargin, int nBottomMargin) { printf("========CropImageMargin \n"); FINFO("========CropImageMargin "); if ((pDstData == NULL) || (pScrData == NULL) || (nSrcWidth <= 0) || (nSrcHeight <= 0) || (nBits <= 0)) return -1; if ((nLeftMargin >= nSrcWidth) || (nTopMargin >= nSrcHeight)) return -1; int nBitsToBYTE = (int)((nBits + 7) * 0.125); if (nBitsToBYTE < 1) return -1; int nXL, nXR, nYL, nYR; nXL = nLeftMargin;//32 nYL = nTopMargin; if (nSrcWidth - nRightMargin < 0) return -1; nXR = nSrcWidth - nRightMargin - 1; //2783 if (nXR < nXL) return -1; if (nSrcHeight - nBottomMargin < 0) return -1; nYR = nSrcHeight - nBottomMargin - 1; if (nYR < nYL) return -1; nDstWidth = nXR - nXL + 1; nDstHeight = nYR - nYL + 1; FINFO("TopCrop:{$};Bottom:{$},nDstWidth:{$},nDstHeight:{$},Bits:{$}", nYL, nYR, nDstWidth, nDstHeight, nBitsToBYTE); int i = 0; #pragma omp parallel private(i) { #pragma omp for for (i = nYL; i <= nYR; i++) { ::memcpy((WORD*)pDstData + (i - nYL) * nDstWidth, (WORD*)pScrData + (i * nSrcWidth + nXL), nDstWidth * nBitsToBYTE); } } return 0; } /*** ** 说明:初始化时刷新所有模式的offset 配置文件的OffsetInterval配置为0时则不会运行此段代码 ***/ bool Detector_CareRayRF::RefreshAllOffset(std::vector& v_DetectorModeList) { printf("========Refresh all mode offset begin \n"); FINFO("========Refresh all mode offset begin"); int nAppMode; //配置文件中LogicMode int nModeID; //SDK的operation mode int nGainID; float fFrameRate; int nExpTime; size_t nModeCount = v_DetectorModeList.size(); bool bRet; m_bAbortRefreshOft = false; SetCareRayDPCStatus(DetStatus_Offset); //开始全模式offset刷新 StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_START); StatusFeedback(EVT_STATUS_OFFSET_PROGRESS, 0); for (size_t i = 0; i < nModeCount; i++) { //初始化阶段的offset刷新流程不在整个软件的控制之内,所以不会给探测器外触发信号, //因此刷新之前将模式改成内触发重新注册,SDK可同时生成外触发的校正文件 nAppMode = (int)(i + 1); nModeID = v_DetectorModeList[i].modeID; nGainID = v_DetectorModeList[i].gainID; fFrameRate = v_DetectorModeList[i].maxFrameRate; nExpTime = v_DetectorModeList[i].expTime; //offset 都用内触发做,因为校正文件不区分内外触发,内触发不需要外部触发信号即可使用 if (nModeID == 16) { bRet = RegisterAppMode(nAppMode, nModeID, nGainID, fFrameRate, nExpTime, CR_RadExtSync);//RefreshAllOffset } else { bRet = RegisterAppMode(nAppMode, nModeID, nGainID, fFrameRate, nExpTime, CR_FluIntSync);//RefreshAllOffset } if (!bRet) { FERROR("RefreshAllOffset RegisterAppMode failed! appmode:{$}", nAppMode); StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_ERROR); continue; } if (m_bAbortRefreshOft) { FINFO("Abort Offset Refresh"); break; } bRet = StartDarkCalibration(nAppMode); //当前mode失败,仍可以进行下一个mode的刷新 if (!bRet) { FERROR("RefreshAllOffset StartDarkCalibration failed! appmode:{$}", nAppMode); StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_ERROR); continue; } if (m_bAbortRefreshOft) { FINFO("Abort Offset Refresh"); break; } StatusFeedback(EVT_STATUS_OFFSET_PROGRESS, (int)(i + 1)); } SetCareRayDPCStatus(DetStatus_Standby); //全模式offset刷新结束,置回Standby StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_OK); FINFO("Refresh all mode offset over"); return true; } /*** ** 说明:刷当前模式的offset,什么时候刷由前端控制 ***/ void Detector_CareRayRF::OnRefreshOffset() { FINFO("========OnRefreshOffset begin"); bool bRet = false; m_bAbortRefreshOft = false; SetCareRayDPCStatus(DetStatus_Offset); StatusFeedback(EVT_STATUS_OFFSET_PROGRESS, 0); StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_START); FINFO("OnRefreshOffset RegisterAppMode appModeKey:{$},m_nModeID:{$},m_nGainLevel:{$},m_fFrameRate:{$},m_nExpTime:{$}", m_nCurrentLogicMode, m_nModeID, m_nGainLevel, m_fFrameRate, m_nExpTime); if (RegisterAppMode(m_nCurrentLogicMode, m_nModeID, m_nGainLevel, m_fFrameRate, m_nExpTime, CR_FluIntSync))//OnRefreshOffset { bRet = StartDarkCalibration(m_nCurrentLogicMode); if (bRet) { StatusFeedback(EVT_STATUS_OFFSET_PROGRESS, 1); } else { StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_ERROR); } } else { FERROR("OnRefreshOffset RegisterAppMode failed!"); StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_ERROR); } //刷点片的offset int nAppMode = 0; float fFrequency = 0.0f; int nGainValue = 0; int nExpTime = 0; try { int nModeCount = (int)m_ModeConfig["ModeTable"].size(); for (int i = 0; i < nModeCount; i++) { int logicMode = (int)m_ModeConfig["ModeTable"][i]["LogicMode"];//OnRefreshOffset if (logicMode == RAD) { FINFO("find LogicMode == RAD"); nAppMode = (int)m_ModeConfig["ModeTable"][i]["OperationMode"]; string strFrameRate = (string)m_ModeConfig["ModeTable"][i]["Frequency"]; fFrequency = stof(strFrameRate.c_str()); nGainValue = (int)m_ModeConfig["ModeTable"][i]["GainValue"]; nExpTime = (int)m_ModeConfig["ModeTable"][i]["ExpTime"];//为0时,探测器将赋值为真正的开窗时间(积分时间) FINFO("nAppMode:{$}, fFrequency:{$}, GainValue:{$}, ExpTime:{$}", nAppMode, fFrequency, nGainValue, nExpTime); break; } } } catch (ResDataObjectExption& e) { FERROR("Read configuration failed, Error code: {$}", e.what()); } if (nAppMode == 16) { bRet = RegisterAppMode(RAD, nAppMode, nGainValue, fFrequency, nExpTime, CR_RadExtSync);//OnRefreshOffset } else { bRet = RegisterAppMode(RAD, nAppMode, nGainValue, fFrequency, nExpTime, CR_FluIntSync);//OnRefreshOffset } if (bRet) { bRet = StartDarkCalibration(RAD); if (bRet) { StatusFeedback(EVT_STATUS_OFFSET_PROGRESS, 2); } else { StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_ERROR); } } else { FERROR("OnRefreshOffset RegisterAppMode failed!"); StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_ERROR); } SetCareRayDPCStatus(DetStatus_Standby); StatusFeedback(EVT_STATUS_OFFSET, PANEL_EVENT_END_OK); FINFO("OnRefreshOffset over"); } bool Detector_CareRayRF::CheckTimeLimit(ULONGLONG dwBeginTime, ULONGLONG dwEndTime) { if (m_bValidImage) //合法图像,不再判断时间间隔,直接返回true { FINFO("CheckTimeLimit m_bValidImage is true!"); return true; } if (m_nDelayTime == 0) //没有开启延时机制 { FINFO("The delay time is invalid, return"); return true; } if ((int)(dwEndTime - dwBeginTime) > m_nDelayTime) { FINFO("The interval({$}) is ok", dwEndTime - dwBeginTime); return true; } FERROR("The interval({$}) is shorter than the delay({$})",dwEndTime - dwBeginTime, m_nDelayTime); return false; } bool Detector_CareRayRF::CallbackProcess(int nEventID, CR_Event* pEventParam) { //FINFO("CallbackProcess event id:{$}",nEventID); switch (nEventID) { case CR_EVT_SERVER_DISCONNECTED: { FINFO("CR_EVT_SERVER_DISCONNECTED"); break; } case CR_EVT_DETR_DISCONNECTED: { FINFO("CR_EVT_DETR_DISCONNECTED"); DisConnect(); break; } case CR_EVT_EXPOSURE_INFO: { FINFO("CR_EVT_EXPOSURE_INFO"); break; } case CR_EVT_TEMPERATURE_INFO: { //FINFO("CR_EVT_TEMPERATURE_INFO"); break; } case CR_EVT_BATTERY_INFO: { FINFO("CR_EVT_BATTERY_INFO"); break; } case CR_EVT_WIRELESS_INFO: { FINFO("CR_EVT_WIRELESS_INFO"); break; } case CR_EVT_NEW_FRAME: { FINFO("Image Arrived!"); int nBuffIdx = *(int*)pEventParam->pData; int nImageDataSize = pEventParam->nWidth * pEventParam->nHeight * 2; int nImgSize = nImageDataSize + m_nFrmHeaderLen; //SDK回调的宽和高都是原始宽高不是裁剪后的值 FINFO("Image Index:{$} Width:{$},Height:{$},nImageDataSize:{$},nImgSize:{$}", nBuffIdx, pEventParam->nWidth, pEventParam->nHeight, nImageDataSize, nImgSize); if (m_pImageBuffer != NULL) { char* pCurrFrame = (char*)m_pImageBuffer + nBuffIdx * nImgSize; int nFrameId = *(int*)(pCurrFrame + 8); FINFO("Frame ID:{$}", nFrameId); m_nRawImgWidth = pEventParam->nWidth; m_nRawImgHeight = pEventParam->nHeight; m_nCbImgIndex = nFrameId; memcpy(m_pRawImgBuffer, pCurrFrame + m_nFrmHeaderLen, nImageDataSize); //获取图像后需要调用停止采集,所以改到子线程处理 SetEvent(m_hProcessImgEvent); } break; } case CR_EVT_CALIBRATION_IN_PROGRESS: { FINFO("CR_EVT_CALIBRATION_IN_PROGRESS"); CR_CalibrationInfo calInfo = *(CR_CalibrationInfo*)pEventParam->pData; FINFO("Calibration progress:{$}/{$},current frame mean:{$}", calInfo.nCurrentFrameNum, calInfo.nTotalFrameNum, calInfo.nCurrentFrameMeanValue); break; } case CR_EVT_CALIBRATION_FINISHED: { FINFO("CR_EVT_CALIBRATION_FINISHED"); CR_CalibrationInfo calInfo = *(CR_CalibrationInfo*)pEventParam->pData; FINFO("Calibration result: {$}", calInfo.nResult); //printf("Calibration result: %d \r\n", calInfo.nResult); if (TestError(calInfo.nResult)) { //用于记录错误信息 } else { if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType) { SetCareRayDPCStatus(DetStatus_Standby); //rad校正结束,设置状态 StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } } break; } case CR_EVT_ACQ_STAT_INFO: { FINFO("CR_EVT_ACQ_STAT_INFO"); CR_AcquisitionStatInfo acqStatInfo = *(CR_AcquisitionStatInfo*)pEventParam->pData; FINFO("Statistic of current acquisition:duration:{$},received total frame:{$},lost frame:{$},frame rate:{$},Speed:{$}", acqStatInfo.nAcqDuration / 1000.0, acqStatInfo.nTotalFrameNum, acqStatInfo.nLostFrameNum, acqStatInfo.fStatFrameRate, acqStatInfo.fTransmissionSpeed); break; } case CR_EVT_RAD_ACQ_IN_PROGRESS: { FINFO("CR_EVT_RAD_ACQ_IN_PROGRESS"); break; } case CR_EVT_SERVER_RECONNECTED: { FINFO("CR_EVT_SERVER_RECONNECTED"); break; } case CR_EVT_DETR_RECONNECTED: { FINFO("CR_EVT_DETR_RECONNECTED"); break; } case CR_EVT_IMAGE_QUEUE_BLOCKED: { FINFO("CR_EVT_IMAGE_QUEUE_BLOCKED"); break; } case CR_EVT_DISCARD_FRAME: { FINFO("CR_EVT_DISCARD_FRAME"); break; } default: FINFO("default Event id:{$}", nEventID); break; } return true; } void Detector_CareRayRF::ConfFeedback(int nEventID, int nDetectorID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceCareRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_CONFIGURATION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void Detector_CareRayRF::InfoFeedback(int nEventID, int nDetectorID, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceCareRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_INFORMATOION, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void Detector_CareRayRF::StatusFeedback(int nEventID, int nParam1, const char* pszMsg, int nDetectorID, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceCareRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_STATUS, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void Detector_CareRayRF::DataFeedback(int nEventID, void* pParam, int nParam1, float fParam2, const char* pszMsg, int nPtrParamLen, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceCareRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_DATA, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void Detector_CareRayRF::WarnFeedback(int nEventID, const char* pszMsg, int nParam1, float fParam2, int nPtrParamLen, void* pParam, int nDetectorID) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceCareRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_WARNING, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } void Detector_CareRayRF::ErrorFeedback(int nEventID, const char* pszMsg, int nDetectorID, int nParam1, float fParam2, int nPtrParamLen, void* pParam) { if (-1 == nDetectorID) { nDetectorID = m_nCurrentPanelID; } ((FPDDeviceCareRay*)(*m_pPanelID2DPC)[nDetectorID])->OnFPDCallback(nDetectorID, nEventID, EVT_LEVEL_ERROR, pszMsg, nParam1, fParam2, nPtrParamLen, pParam); } float Detector_CareRayRF::SetFluPPS(float fPPS, std::vector& v_DetectorModeList) { FINFO("========SetFluPPS {$}", fPPS); //根据设置的帧率值查找符合帧率值的最大分辨率的模式 //首先查找支持的帧率大于等于当前设置帧率的模式集合 std::vector v_result;//保存符合条件的模式的索引值 float epsilon = (float)1e-9; int maxFrameRateIndex = 0;//帧率最大的模式的索引(此值不看分辨率) float fTempMax = 0.0f; for (int i = 0; i < v_DetectorModeList.size(); i++) { if (std::abs(v_DetectorModeList[i].maxFrameRate - fPPS) < epsilon)//相等 { v_result.push_back(i); } else if (v_DetectorModeList[i].maxFrameRate > fPPS) { v_result.push_back(i); } if (v_DetectorModeList[i].maxFrameRate > fTempMax) { fTempMax = v_DetectorModeList[i].maxFrameRate; maxFrameRateIndex = i; } } FINFO("v_result.size() == {$}, maxFrameRateIndex = {$}", v_result.size(), maxFrameRateIndex); //结果1:不止一个模式支持的情况 // 筛选后如果还有多个分辨率相同的模式那么就用第一个找到的 //结果2:只有一个模式支持 //结果3:没有模式支持当前帧率,那么就用帧率最高的那个模式的分辨率 unsigned long maxDpi = 0; int maxDpiIndex = 0; if (v_result.size() > 1) { for (size_t j = 0; j < v_result.size(); j++) { int currentIndex = v_result[j]; if ((unsigned long)v_DetectorModeList[currentIndex].imageWidth * (unsigned long)v_DetectorModeList[currentIndex].imageHeight > maxDpi) { maxDpi = (unsigned long)v_DetectorModeList[currentIndex].imageWidth * (unsigned long)v_DetectorModeList[currentIndex].imageHeight; maxDpiIndex = currentIndex; } } if (fPPS == 0.0f) { FINFO("fPPS == 0.0f"); m_fFrameRate = v_DetectorModeList[maxDpiIndex].maxFrameRate; } else { m_fFrameRate = fPPS; } } else if (v_result.size() == 1) { maxDpiIndex = v_result[0]; m_fFrameRate = fPPS; } else { maxDpiIndex = maxFrameRateIndex; m_fFrameRate = v_DetectorModeList[maxDpiIndex].maxFrameRate; } FINFO("maxDpiIndex:{$},m_fFrameRate:{$}", maxDpiIndex, m_fFrameRate); m_nModeID = v_DetectorModeList[maxDpiIndex].modeID; FINFO("m_nModeID:{$}", m_nModeID); //回调当前选中模式的图像宽高到上层,让上层存储图像的buffer重新调整为当前模式的出图大小 int nRawImageWidth = v_DetectorModeList[maxDpiIndex].imageWidth; int nRawImageHeight = v_DetectorModeList[maxDpiIndex].imageHeight; int nCutX = v_DetectorModeList[maxDpiIndex].cutOffX; int nCutY = v_DetectorModeList[maxDpiIndex].cutOffY; int nImageWidth = nRawImageWidth - 2 * nCutX; int nImageHeight = nRawImageHeight - 2 * nCutY; m_nRawImgWidth = nRawImageWidth; m_nRawImgHeight = nRawImageHeight; m_nCropLeft = nCutX; m_nCropRight = nCutX; m_nCropTop = nCutY; m_nCropBottom = nCutY; m_nImageWidth = nImageWidth; m_nImageHeight = nImageHeight; FINFO("SetFluPPS m_nRawImgWidth:{$},m_nRawImgHeight:{$},m_nCropLeft:{$},m_nCropRight:{$},m_nCropTop:{$},m_nCropBottom:{$},m_nImageWidth:{$},m_nImageHeight:{$}", m_nRawImgWidth, m_nRawImgHeight, m_nCropLeft, m_nCropRight, m_nCropTop, m_nCropBottom, m_nImageWidth, m_nImageHeight); return m_fFrameRate; } void Detector_CareRayRF::GetFluPPS(float& fFluPPS) { fFluPPS = m_fFrameRate; FINFO("========GetFluPPS {$}", fFluPPS); } void Detector_CareRayRF::AbortFreshOffset() { FINFO("========AbortFreshOffset"); m_bAbortRefreshOft = true; } void Detector_CareRayRF::SetAbortOffsetEvent() { FINFO("========SetAbortOffsetEvent"); SetEvent(m_hAbortOffset); } void Detector_CareRayRF::SetFreshAllOffsetEvent(std::vector& v_DetectorModeList) { FINFO("========SetFreshAllOffsetEvent"); m_vCtrlDetectorModeList = v_DetectorModeList; SetEvent(m_hStartAllOffset); } void Detector_CareRayRF::SetfreshOffsetEvent() { FINFO("========SetfreshOffsetEvent"); SetEvent(m_hStartOffset); } void Detector_CareRayRF::UpdateModeInRunning(int nMode, float fFrequency) { FINFO("========UpdateModeInRunning ModeID:{$},Frequency:{$}", nMode, fFrequency); m_nModeID = nMode; m_fFrameRate = fFrequency; //这里增加裁剪值的赋值 for (int i=0;i< m_nModeNum;i++) { if (m_mapModeInfo[i].nModeID == m_nModeID) { FINFO("Current mode cutX = {$}, cutY = {$}", m_mapModeInfo[i].nCutoffX, m_mapModeInfo[i].nCutoffY); m_nCropLeft = m_mapModeInfo[i].nCutoffX; m_nCropRight = m_mapModeInfo[i].nCutoffX; m_nCropTop = m_mapModeInfo[i].nCutoffY; m_nCropBottom = m_mapModeInfo[i].nCutoffY; } } }