#include "stdafx.h" #include "CareRayCtrl.h" #include "CCOS.Dev.FPD.CareRay.h" extern Log4CPP::Logger* gLogger; CareRayCtrl* g_pDetector = nullptr; #define LOAD_PROC_ADDRESS(handle,func) \ if ((API_##func = (Func_##func)GetProcAddress(handle, #func)) == NULL) { FERROR("Error occurs while loading entry point!!! \r\n'{$}'\n", #func); }\ void __stdcall CREventCallback(int eventID, Event* eventData) { if (nullptr != g_pDetector) { g_pDetector->ProcessCREvent(eventID, eventData); } } CareRayCtrl::CareRayCtrl() { m_nExposureMode = DEFAULTMODE; m_nXWindowTime = 500; m_bDetectorReady = false; m_bIsAcqStatus = false; m_pDPC2PanelID = new map(); m_pPanelID2DPC = new map(); m_nPanelCount = 0; m_strWorkPath = ""; m_nCurrentPanelID = 0; m_nCurrentDetectorType = Unkown_Type; m_pStPanelStatus[0] = nullptr; m_pStPanelStatus[1] = nullptr; m_nSyncMode = SYNC_HARDWARE; m_nCurSyncMode = 0; m_nRawImgWidth = 0; m_nRawImgHeight = 0; m_pRawImgBuffer = nullptr; m_pImgBuffer = nullptr; m_pDarkImage = nullptr; m_nExamMode = APP_STATUS_IDLE; m_nSaveRaw = 0; m_bGetImage = true; m_bCancelFlag = false; m_eCaliType = CCOS_CALIBRATION_TYPE_NONE; m_bAbortOffset = false; m_bOneKeyConf = false; m_bOneKeyCalibration = false; m_calparams = { 0 }; m_nGainNodeCount = 0; m_nGainNodeIndex = 0; m_nGainExpCount = 0; m_nGainExpIndex = 0; m_nImageSize = 0; m_nCurrentMode = MODE_RAD; m_hRespond = CreateEvent(NULL, FALSE, FALSE, NULL); m_hFPDScanThread = nullptr; m_hStopScanEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hAcqEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hProcessImgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hXWinOnEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hDarkEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hGainEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hArrayEvent[0] = m_hStopScanEvent; m_hArrayEvent[1] = m_hAcqEvent; m_hArrayEvent[2] = m_hProcessImgEvent; m_hArrayEvent[3] = m_hXWinOnEvent; m_hArrayEvent[4] = m_hDarkEvent; m_hArrayEvent[5] = m_hGainEvent; m_hNotifyDetectorInfoThread = nullptr; m_bExitNotify = false; m_hCareRayModule = nullptr; API_CR_connect_detector = nullptr; API_CR_disconnect_detector = nullptr; API_CR_reset_detector = nullptr; API_CR_set_check_mode = nullptr; API_CR_set_sync_mode = nullptr; API_CR_set_cycle_time = nullptr; API_CR_set_normal_power = nullptr; API_CR_set_save_power = nullptr; API_CR_permit_exposure = nullptr; API_CR_start_acq_full_image = nullptr; API_CR_start_acq_prev_image = nullptr; API_CR_start_acq_def_image = nullptr; API_CR_stop_acq_frame = nullptr; API_CR_stop_acq_frame_cleanup = nullptr; API_CR_set_user_correction = nullptr; API_CR_get_user_correction = nullptr; API_CR_set_dose = nullptr; API_CR_get_API_Version = nullptr; API_CR_get_conn_state = nullptr; API_CR_get_detector_type = nullptr; API_CR_get_detector_info = nullptr; API_CR_get_mode_info = nullptr; API_CR_get_status_info = nullptr; API_CR_get_image_attr = nullptr; API_CR_get_image = nullptr; API_CR_get_unuploaded_img_info = nullptr; API_CR_query_prog_info = nullptr; API_CR_inpaint_bad_pixels = nullptr; API_CR_get_cal_params = nullptr; API_CR_set_offset_correction = nullptr; API_CR_cal_offset = nullptr; API_CR_linear_calibration = nullptr; API_CR_portable_calibration = nullptr; API_CR_get_active_detector_ID = nullptr; API_CR_execute_linear_cal = nullptr; API_CR_execute_portable_cal = nullptr; API_CR_stop_cal_procedure = nullptr; API_CR_set_active_detector = nullptr; API_CR_get_dual_detector_state = nullptr; API_CR_register_callback = nullptr; API_CR_send_exp_request = nullptr; API_CR_ready_state_request = nullptr; API_CR_start_soft_acquisition = nullptr; API_CR_get_one_key_cal = nullptr; API_CR_download_factory_cal_files = nullptr; API_CR_start_acq_dark_full_image = nullptr; API_CR_check_img_for_factory_cal = nullptr; API_CR_execute_one_key_cal = nullptr; } CareRayCtrl::~CareRayCtrl() { if (m_pRawImgBuffer) { delete[]m_pRawImgBuffer; m_pRawImgBuffer = nullptr; } if (m_pImgBuffer != nullptr) { delete[]m_pImgBuffer; m_pImgBuffer = nullptr; } if (m_pDarkImage != nullptr) { delete[]m_pDarkImage; m_pDarkImage = nullptr; } if (m_hRespond) { CloseHandle(m_hRespond); m_hRespond = nullptr; } if (m_hStopScanEvent) { CloseHandle(m_hStopScanEvent); m_hStopScanEvent = nullptr; } if (m_hAcqEvent) { CloseHandle(m_hAcqEvent); m_hAcqEvent = nullptr; } if (m_hProcessImgEvent) { CloseHandle(m_hProcessImgEvent); m_hProcessImgEvent = nullptr; } if (m_hXWinOnEvent) { CloseHandle(m_hXWinOnEvent); m_hXWinOnEvent = nullptr; } if (m_hDarkEvent) { CloseHandle(m_hDarkEvent); m_hDarkEvent = nullptr; } if (m_hGainEvent) { CloseHandle(m_hGainEvent); m_hGainEvent = nullptr; } m_bExitNotify = true; } bool CareRayCtrl::DriverEntry(FPDDeviceCareRay* pDrvDPC, ResDataObject& Configuration) { FINFO("--Func-- 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; } CPanelStatus* p = new CPanelStatus(); m_pStPanelStatus[m_nPanelCount] = p; m_pDPC2PanelID->insert(pair(pDrvDPC, m_nPanelCount)); m_pPanelID2DPC->insert(pair(m_nPanelCount, pDrvDPC)); m_nPanelCount++; m_ModeConfig = Configuration; //记录配置 --目前只有一个平板,多板时应该分别存储 //FINFO("Config: {$}", m_ModeConfig.encode()); return true; } bool CareRayCtrl::Connect(FPDDeviceCareRay* pDrvDPC, const char* szWorkPath) { FINFO("Connect detector begin"); if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return true"); return true; } m_strWorkPath = szWorkPath; if (!LoadDll(szWorkPath)) { return false; } if (!OpenDetector()) { FERROR("Open detector failed, Connect failed"); return false; } if (!InitDetector()) { FERROR("Init detector failed, Connect failed"); 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_hNotifyDetectorInfoThread) { unsigned uThreadId; m_hNotifyDetectorInfoThread = (HANDLE)_beginthreadex(NULL, 0, onNotifyDetectorInfoThread, this, 0, &uThreadId); } FINFO("Connect over"); return true; } void CareRayCtrl::Reconnect() { FINFO("Reconnect detector begin"); FINFO("Reconnect detector end"); } bool CareRayCtrl::GetDetectorAcqStatus() { FINFO("GetDetectorAcqStatus m_bIsAcqStatus:{$}", m_bIsAcqStatus); return m_bIsAcqStatus; } void CareRayCtrl::SetAcqStatus(bool bAcqStatus) { FINFO("SetAcqStatus bAcqStatus:{$}", bAcqStatus); m_bIsAcqStatus = bAcqStatus; } void CareRayCtrl::SetCanelFlag(bool bCancelFlag) { FINFO("SetCanelFlag bCancelFlag:{$}", bCancelFlag); m_bCancelFlag = bCancelFlag; } bool CareRayCtrl::Disconnect() { FINFO("Disconnect detector begin"); SetEvent(m_hStopScanEvent); //关闭Scan线程 m_bExitNotify = true;//退出通知探测器信息线程 FINFO("Call API_CR_disconnect_detector"); int nRet = API_CR_disconnect_detector(); if (TestError(nRet,"API_CR_disconnect_detector")) { FERROR("disconnect detector failed!"); return false; } FINFO("Disconnect over"); return true; } void CareRayCtrl::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 == nExamMode) { m_bCancelFlag = true; //退出检查,将标记位置为true //软同步在此处调用停止采集,其它同步模式在query过程调用 if (EVT_READY == m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState) { //int nRet = -1; //FINFO("Call stop acq"); //nRet = API_CR_stop_acq_frame(); //用于终止曝光流程 //if (TestError(nRet, "API_CR_stop_acq_frame")) //{ // FERROR("Stop acq failed"); //} //else //{ // m_bDetectorReady = false; // m_bIsAcqStatus = false; //} } } } /*** * 激活探测器 ***/ bool CareRayCtrl::ActiveDetector(int nDetectorID) { FINFO("ActiveDetector ID: {$}", nDetectorID); //每一次选择一个view都要激活一次探测器。 return true; } /*** ** 根据采集模式申请图像buffer ***/ bool CareRayCtrl::SetAcqMode(DetModeInfoStruct DetModeInfo, DetCalibInfo DetCalibInfo, int nMode) { FINFO("SetAcqMode[{$}]", nMode); m_stModeInfo = DetModeInfo; m_stCalibInfo = DetCalibInfo; //申请图像buffer if (nullptr != m_pImgBuffer) { delete[] m_pImgBuffer; m_pImgBuffer = nullptr; } m_pImgBuffer = new WORD[(size_t)m_stModeInfo.nImageHeight * (size_t)m_stModeInfo.nImageWidth]; FINFO("SetAcqMode, image width: {$}, image height:{$}",m_stModeInfo.nImageWidth, m_stModeInfo.nImageHeight); FINFO("Offset width: {$}, Offset height: {$}",m_stModeInfo.nWidthOffset, m_stModeInfo.nHeightOffset); //step 1 int nRet = -1; if(nMode == RAD) { nRet = API_CR_set_check_mode(MODE_RAD); m_nExposureMode = RAD; } else if (nMode == AEC) { nRet = API_CR_set_check_mode(MODE_PREV); m_nExposureMode = AEC; } if (TestError(nRet, "API_CR_set_check_mode")) { FERROR("Set check mode failed"); return false; } m_nSyncMode = m_stModeInfo.nSyncType; FINFO("m_nSyncMode:{$}", m_nSyncMode); //step2 int nSdkSyncMode = SOFT_SYNC; string strTemp = "SOFT_SYNC"; switch (m_nSyncMode) { case SYNC_MANUAL: nSdkSyncMode = MANUAL_SYNC; strTemp = "MANUAL_SYNC"; break; case SYNC_SOFTWARE: nSdkSyncMode = SOFT_SYNC; strTemp = "SOFT_SYNC"; break; case SYNC_HARDWARE: nSdkSyncMode = EXT_SYNC; strTemp = "EXT_SYNC"; break; case SYNC_AED: nSdkSyncMode = AUTO_SYNC; strTemp = "AUTO_SYNC"; break; case SYNC_HARDWARE_DIRECT: nSdkSyncMode = EXT_SYNC; strTemp = "EXT_SYNC"; break; default: break; } FINFO("nSdkSyncMode: {$} {$}", nSdkSyncMode, strTemp.c_str()); if (!SetSyncMode(nSdkSyncMode, m_stModeInfo.nXwindow)) { return false; } else { m_nCurSyncMode = m_nSyncMode; m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode = (SYNC_MODE)m_nCurSyncMode; } //step 3 LoadCareCalibration(true); m_nSaveRaw = m_stModeInfo.nIsSaveRaw; FINFO("SetAcqMode m_nSaveRaw:{$}", m_nSaveRaw); return true; } bool CareRayCtrl::PrepareAcquisition(FPDDeviceCareRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } FINFO("m_bIsAcqStatus:{$},m_bDetectorReady:{$}", m_bIsAcqStatus, m_bDetectorReady); //如果是采集状态那么就判断是不是ready了,如果不是采集状态就不判断是否ready了 if (m_bIsAcqStatus) { if (m_bDetectorReady) { FINFO("Detector already in ready status, return true"); return true; } } m_bCancelFlag = false; //准备采集前恢复初值 FINFO("SetEvent(m_hAcqEvent)"); SetEvent(m_hAcqEvent); //准备采集 return true; } bool CareRayCtrl::StartAcquisition(FPDDeviceCareRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } //未初始化、未连接 不执行 int nRet = -1; if (SYNC_SOFTWARE == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode && EVT_READY == m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState) //在ready时调用api,避免api时序混乱 { FINFO("Call exp request"); nRet = API_CR_send_exp_request(); if (TestError(nRet, "API_CR_send_exp_request")) { FERROR("Send exp request failed"); return false; } } return true; } bool CareRayCtrl::StopAcquisition(FPDDeviceCareRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } int nRet = -1; FINFO("Call stop acq"); nRet = API_CR_stop_acq_frame(); //用于终止曝光流程 if (TestError(nRet, "API_CR_stop_acq_frame")) { FERROR("Stop acq failed"); return false; } m_bDetectorReady = false; m_bIsAcqStatus = false; return true; } bool CareRayCtrl::ActiveCalibration(FPDDeviceCareRay* pDrvDPC, CCOS_CALIBRATION_TYPE eType) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } int nRet = -1; //启动后直接开始校正,需要设置一次同步模式 if (m_nCurSyncMode != m_nSyncMode) { int nSyncMode = SOFT_SYNC; string strTemp = "SOFT_SYNC"; switch (m_nSyncMode) { case SYNC_MANUAL: nSyncMode = MANUAL_SYNC; strTemp = "MANUAL_SYNC"; break; case SYNC_SOFTWARE: nSyncMode = SOFT_SYNC; strTemp = "SOFT_SYNC"; break; case SYNC_HARDWARE: nSyncMode = EXT_SYNC; strTemp = "EXT_SYNC"; break; case SYNC_AED: nSyncMode = MANUAL_SYNC; //探测器aed模式不支持校正,需要用manual strTemp = "MANUAL_SYNC(replace AUTO_SYNC in calibration)"; break; case SYNC_HARDWARE_DIRECT: nSyncMode = EXT_SYNC; strTemp = "EXT_SYNC"; break; default: break; } FINFO("Set SyncMode: {$} {$}", nSyncMode, strTemp.c_str()); if (!SetSyncMode(nSyncMode)) { return false; } else { m_nCurSyncMode = m_nSyncMode; m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode = (SYNC_MODE)m_nCurSyncMode; } } else { //探测器aed模式不支持校正,需要用manual if (SYNC_AED == m_nSyncMode) { FINFO("Set SyncMode: 4 MANUAL_SYNC(replace AUTO_SYNC in calibration)"); if (!SetSyncMode(MANUAL_SYNC)) { return false; } } } m_nExamMode = APP_STATUS_CAL_BEGIN; //激活校正,置为校正界面 m_eCaliType = eType; if (CCOS_CALIBRATION_TYPE_XRAY == m_eCaliType) { m_nGainNodeIndex = 0; //激活校正,恢复初值 m_nGainExpIndex = 0; //激活校正,恢复初值 //下载一键校正文件 FINFO("Call download factory cal files"); nRet = API_CR_download_factory_cal_files(); if (TestError(nRet, "API_CR_download_factory_cal_files")) { if (ERR_NO_CONFIGFILE == nRet || CR_SEND_ERR == nRet || CR_RECV_ERR == nRet) { //v2 DROC中下载失败也执行一键校正,和SDK demo不符 //m_bOneKeyCalibration = true; FERROR("Failed to download calibration files from detector"); } else { FERROR("Cannot find factory-calibrated files."); } m_bOneKeyCalibration = false; } //设置不应用校正 LoadCareCalibration(false); //获取SDK校正参数 FINFO("Call get cal params"); nRet = API_CR_get_cal_params(&m_calparams); if (TestError(nRet, "API_CR_get_cal_params")) { FERROR("get cal params failed!"); } else { FINFO("gain image dir: {$}", m_calparams.gain_image_dir); FINFO("num per dose: {$}", m_calparams.linear_num_per_dose); FINFO("dose: {$}", m_calparams.linear_dose_num); } } return true; } //使探测器ready bool CareRayCtrl::PrepareCalibration(FPDDeviceCareRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } if (m_bOneKeyCalibration) { PerformDarkAcquisition(); } m_bCancelFlag = false; //准备校正前恢复初值 SetEvent(m_hAcqEvent); //准备校正 return true; } //软同步调用接口,其它同步模式没有动作 bool CareRayCtrl::StartCalibration(FPDDeviceCareRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } //未初始化、未连接 不执行 if (CCOS_CALIBRATION_TYPE_DARK) { SetEvent(m_hDarkEvent); } else if (CCOS_CALIBRATION_TYPE_XRAY) { int nRet = -1; if (SYNC_SOFTWARE == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode && EVT_READY == m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState) //在ready时调用api,避免api时序混乱 { FINFO("Call exp request"); nRet = API_CR_send_exp_request(); if (TestError(nRet, "API_CR_send_exp_request")) { FERROR("Send exp request failed"); return false; } } } return true; } bool CareRayCtrl::StopCalibration(FPDDeviceCareRay* pDrvDPC) { if ((*m_pDPC2PanelID)[pDrvDPC] != m_nCurrentPanelID) { FERROR("Not current DPC, return"); return false; } m_bCancelFlag = true; Sleep(500); //探测器aed模式不支持校正,需要用manual,校正结束后切换回来 if (SYNC_AED == m_nSyncMode) { FINFO("Set SyncMode: 3 AUTO_SYNC(restore AUTO_SYNC in calibration)"); SetSyncMode(AUTO_SYNC); } LoadCareCalibration(true); return true; } bool CareRayCtrl::ConfirmCalExposure() { m_nGainExpIndex++; if (!m_bOneKeyCalibration) { char* path = m_calparams.gain_image_dir; char strImageName[STRLEN]; sprintf_s(strImageName, STRLEN, "70kv-%d%s%d%s", m_nGainExpIndex, "-", m_nGainExpCount, ".raw"); //70kv-1-15.raw 。。。 70kv-15-15.raw FILE* fp; if ((fp = fopen(path, "wb")) == NULL) { DWORD dw = GetLastError(); FERROR("fopen {$} failed, {$}", path, dw); return false; } fwrite(m_pRawImgBuffer, sizeof(WORD), (size_t)m_nRawImgWidth * (size_t)m_nRawImgHeight, fp); fclose(fp); FINFO("writeImageToDisk success."); } //处理已接受和未曝光的标记位 if (m_nGainExpIndex == m_nGainExpCount) //当前剂量点的曝光次数已经够了 { m_nGainNodeIndex++; if (m_nGainNodeIndex == m_nGainNodeCount) //所有剂量点已经曝光完成 { //校正结束的处理 if (m_bOneKeyCalibration) { double dMean = GetMean(m_pRawImgBuffer, m_nImageSize / sizeof(WORD)); if (dMean > 20000 * 1.25 || dMean < 20000 * 0.75) { FINFO("Call check image"); int nRet = API_CR_check_img_for_factory_cal(m_pRawImgBuffer); if (TestError(nRet, "API_CR_check_img_for_factory_cal")) { FERROR("It is strongly recommended to reject this image"); } } SurfaceFitResult fitResult; FINFO("CALL CR_execute_one_key_cal"); int nRet = API_CR_execute_one_key_cal(m_pRawImgBuffer, m_pDarkImage, &fitResult); //根据输入的亮场图像和暗场图像计算一键校准文件 if (TestError(nRet, "API_CR_execute_one_key_cal")) { FERROR("CR_execute_one_key_cal Failed"); } else { FINFO("CR_execute_one_key_cal Success"); } } FINFO("Gain calibration finished! set exammode to cali end"); m_bCancelFlag = true; //校正结束曝光流程 m_nExamMode = APP_STATUS_CAL_END; //增益结束,置为end //探测器aed模式不支持校正,需要用manual,校正结束后切换回来 if (SYNC_AED == m_nSyncMode) { FINFO("Set SyncMode: 3 AUTO_SYNC(restore AUTO_SYNC in calibration)"); SetSyncMode(AUTO_SYNC); } StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } } FINFO("Exp index and count({$} {$}), note index and count({$} {$})", m_nGainExpIndex, m_nGainExpCount, m_nGainNodeIndex, m_nGainNodeCount); return true; } void CareRayCtrl::RejectCalExposure() { //暂时什么都不处理 } bool CareRayCtrl::LoadDll(string strWorkPath) { 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 + "\\CrApi.dll"; //SetDllDirectory(workpath.c_str()); //将SDK路径加入环境变量 char* pathvar; pathvar = getenv("Path"); printf("pathvar = %s \n\n", pathvar); string strPath = "Path="; strPath += pathvar; strPath += ";"; strPath += workpath; printf("strPath:%s \n\n", strPath.c_str()); if (_putenv(strPath.c_str()) != 0) { DWORD dw = GetLastError(); printf("put env failed! last error:%ld \n", dw); return false; } m_hCareRayModule = LoadLibrary(drvpath.c_str()); if (m_hCareRayModule == nullptr) { DWORD dw = GetLastError(); FERROR("Load {$} failed: {$}", drvpath.c_str(), dw); return false; } LOAD_PROC_ADDRESS(m_hCareRayModule, CR_register_callback); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_connect_detector); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_disconnect_detector); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_reset_detector); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_dual_detector_state); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_detector_type); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_detector_info); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_status_info); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_set_check_mode); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_mode_info); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_set_sync_mode); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_set_cycle_time); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_set_normal_power); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_set_save_power); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_start_soft_acquisition); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_ready_state_request); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_send_exp_request); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_start_acq_full_image); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_image_attr); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_image); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_query_prog_info); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_permit_exposure); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_stop_acq_frame); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_stop_cal_procedure); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_cal_offset); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_download_factory_cal_files); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_set_user_correction); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_get_cal_params); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_check_img_for_factory_cal); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_execute_one_key_cal); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_start_acq_dark_full_image); LOAD_PROC_ADDRESS(m_hCareRayModule, CR_start_acq_prev_image); //共32个 return true; } /*** ** 连接探测器 ***/ bool CareRayCtrl::OpenDetector() { string strSDKPath = ""; try { strSDKPath = (string)m_ModeConfig["SDKPath"]; } catch (ResDataObjectExption& e) { FERROR("Read configuration failed, Error code: {$}", e.what()); return false; } string strWorkpath = m_strWorkPath + "\\" + strSDKPath + "\\CareRay"; char* szWorkpath = const_cast(strWorkpath.c_str()); int nRet = -1; FINFO("Call connect({$})", szWorkpath); nRet = API_CR_connect_detector(szWorkpath); if (CR_NO_ERR != nRet && CR_ALREADY_CONN_ERR != nRet) { FERROR("Connect return failed! reson:{$}", CrErrStrList(nRet)); return false; } FINFO("Connect executed successfully"); //测试发现,注册回调需要放在连接成功之后 FINFO("Register callback"); nRet = API_CR_register_callback(CREventCallback); if (TestError(nRet, "API_CR_register_callback")) { FERROR("register callback failed!"); } //如果是双板环境,输出两个平板的信息 if (m_nPanelCount > 1) { DetectorActiveState das; API_CR_get_dual_detector_state(&das); FINFO("Current Active Detector ID = {$}", das.activeDetectorID); FINFO("Detector Number = {$}, Detector A type = {$}, Detector B type = {$}", das.detectorNum, das.detectorAType, das.detectorBType); FINFO("Detector A connect state = {$}, Detector B connect state = {$}", das.detectorAstate, das.detectorBstate); if (das.detectorAstate) { m_pStPanelStatus[0]->bConnectState = true; } if (das.detectorBstate) { m_pStPanelStatus[1]->bConnectState = true; } if (0 != das.activeDetectorID) { //双板时,若第一块板不连接,API会自动切换到第二块探测器 //此处暂不处理 } } else { m_pStPanelStatus[0]->bConnectState = true; } return true; } /*** ** 初始化探测器 ***/ bool CareRayCtrl::InitDetector() { int nRet = -1; //初始化时先reset,恢复缺省状态 FINFO("Call reset"); nRet = API_CR_reset_detector(FALSE); if (TestError(nRet, "API_CR_reset_detector")) { FERROR("reset detector failed!"); } //获取实际的探测器类型 FINFO("Call gettype"); m_nCurrentDetectorType = API_CR_get_detector_type(); string strType = ""; GetDetectorType((DetectorType)m_nCurrentDetectorType, strType); FINFO("Detector type: {$} {$}", m_nCurrentDetectorType, strType.c_str()); //加载校正文件 //LoadCareCalibration(true); //输出探测器信息(图像相关、软件版本、SN) ShowDetectorInfo(); //获取探测器温度、电量、wifi信号 ShowStatusInfo(); //设置采集模式,输出该模式信息 FINFO("Call set mode"); nRet = API_CR_set_check_mode(m_nCurrentMode); if (TestError(nRet, "API_CR_set_check_mode")) { FERROR("Set mode failed"); return false; } if (CR_NO_ERR != ShowModeInfo()) { return false; } return true; } int CareRayCtrl::ShowDetectorInfo() { FINFO("Getting Detector Info"); DetectorInfo detectorInfo; int nRet = API_CR_get_detector_info(&detectorInfo); if (TestError(nRet, "API_CR_get_detector_info")) { FERROR("Get Detector Info Failed"); } else { FINFO("RawImageWidth is: {$}", detectorInfo.rawImageWidth); FINFO("RawImageHeight is: {$}", detectorInfo.rawImageHeight); FINFO("MaxPixelValue is: {$}", detectorInfo.maxPixelValue); FINFO("BitsPerPixel is: {$}", detectorInfo.bitsPerPixel); FINFO("SoftWareVerion is: {$}", detectorInfo.softWareVersion); FINFO("SerialNumber is: {$}", detectorInfo.serialNumber); ConfFeedback(EVT_CONF_PANEL_SERIAL, m_nCurrentPanelID, detectorInfo.serialNumber); } return nRet; } /*** ** 显示温度、电量、wifi等信息 ***/ int CareRayCtrl::ShowStatusInfo() { int nRet; StatusInfo stInfo; nRet = API_CR_get_status_info(&stInfo); if (TestError(nRet, "API_CR_get_status_info")) { FERROR("Get Detector Status Info Failed"); } else { FINFO("Current detector temperature:{$}", stInfo.temperature.maxTemperature); StatusFeedback(EVT_STATUS_TEMPERATURE, 0, "", m_nCurrentPanelID, stInfo.temperature.maxTemperature); bool bCharging = true; if (stInfo.batInfo.ave_current > 0.00001) { bCharging = false; } FINFO("Current detector battery: {$}% {$}", stInfo.batInfo.relative_state_of_charge * 100, bCharging ? "Charging" : "Not charging"); int nBatteryValue = 0; if (bCharging) //有线连接 { nBatteryValue = 100; } else { nBatteryValue = (int)(stInfo.batInfo.relative_state_of_charge * 100); } StatusFeedback(EVT_STATUS_BATTERY_VALUE, nBatteryValue, "", m_nCurrentPanelID); //string strLinkQuality = stInfo.wireless_info.link_quality; FINFO("Current detector wifi link quality: {$}", stInfo.wireless_info.link_quality); int nLinkQuality = 0; if (bCharging) //有线连接 { nLinkQuality = 100; } else { nLinkQuality = atoi(stInfo.wireless_info.link_quality); } StatusFeedback(EVT_STATUS_WIFI, nLinkQuality, "", m_nCurrentPanelID); } return nRet; } /*** ** 显示当前采集模式的图像信息 ***/ int CareRayCtrl::ShowModeInfo() { FINFO("Call get mode info"); ModeInfo stModeInfo; int nRet = API_CR_get_mode_info(m_nCurrentMode, &stModeInfo); if (TestError(nRet, "API_CR_get_mode_info")) { FERROR("Get Mode Info Failed"); } else { m_nRawImgWidth = stModeInfo.imageWidth; m_nRawImgHeight = stModeInfo.imageHeight; //imageSize = 图像数据+65535头的大小 FINFO("ImageWidth = {$}, ImageHeight = {$}, ImageSize = {$}", stModeInfo.imageWidth, stModeInfo.imageHeight, stModeInfo.imageSize); FINFO("LinesPerPixel = {$}, ColsPerPixel = {$}", stModeInfo.linesPerPixel, stModeInfo.colsPerPixel);//大于1时表示开启BINNING模式 } return nRet; } /*** ** 设置同步模式、采集窗口 ***/ bool CareRayCtrl::SetSyncMode(int nSyncMode, int nXWindowTime) { FINFO("SetSyncMode nSyncMode:{$},nXWindowTime:{$}", nSyncMode, nXWindowTime); int nResult = CR_NO_ERR; FINFO("Call API_CR_set_sync_mode"); nResult = API_CR_set_sync_mode(nSyncMode); if (TestError(nResult, "API_CR_set_sync_mode")) { FERROR("Set sync mode Failed"); return false; } if (nXWindowTime <= 0) { FERROR("XWindowTime <= 0, it's invalid!"); return false; } //设置探测器的曝光窗口时间 int nDelayTime = 0; int nWaitTime = 0; switch (nSyncMode) { case EXT_SYNC: if (m_nExposureMode == RAD) { //m_nXWindowTime = 2500; m_nXWindowTime = nXWindowTime; } else { m_nXWindowTime = 500; } nDelayTime = 100; nWaitTime = 5; break; case SOFT_SYNC: nDelayTime = 100; nWaitTime = 5; break; case AUTO_SYNC: nDelayTime = 5; nWaitTime = 5; break; case MANUAL_SYNC: nDelayTime = 500; nWaitTime = 5; break; case AED_SYNC: nDelayTime = 100; nWaitTime = 5; break; default: m_nXWindowTime = 500; nDelayTime = 100; nWaitTime = 5; break; } FINFO("m_nXWindowTime: {$}, Delay Time: {$}, WaitTime: {$}", m_nXWindowTime, nDelayTime, nWaitTime); FINFO("Call API_CR_set_cycle_time"); nResult = API_CR_set_cycle_time(m_nXWindowTime, nDelayTime, nWaitTime); if (TestError(nResult, "API_CR_set_cycle_time")) { FERROR("Set cycle Time Failed"); return false; } FINFO("Set cycle time success"); return true; } unsigned __stdcall CareRayCtrl::onFPDScanThread(PVOID pvoid) { CareRayCtrl* pOpr = (CareRayCtrl*)pvoid; FINFO("Enter scan thread"); bool bExit = false; DWORD dwTimeOut = INFINITE; while (!bExit) { DWORD dwRet = WaitForMultipleObjects(SCAN_EVENT_COUNT, pOpr->m_hArrayEvent, FALSE, dwTimeOut); 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_hProcessImgEvent { pOpr->OnProcessImg(); } else if (WAIT_OBJECT_0 + 3 == dwRet) //m_hXWinOnEvent { //SDK FINFO("Get XWinOnEvent"); ULONGLONG dwXrayOnT, dwXrayOffT; dwXrayOnT = dwXrayOffT = GetTickCount64(); FINFO("window on: {$}", dwXrayOnT); pOpr->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); while (dwXrayOffT - dwXrayOnT < 500) //窗口暂时写死 { dwXrayOffT = GetTickCount64(); } FINFO("window off: {$}", dwXrayOffT); pOpr->StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); } else if (WAIT_OBJECT_0 + 4 == dwRet) //m_hDarkEvent { pOpr->OnStartDarkCalibration(); } else if (WAIT_OBJECT_0 + 5 == dwRet) //m_hGainEvent { pOpr->OnAcquireGainImage(); } } FINFO("Level scan thread"); return 0; } //每5s向上通知一次状态 unsigned __stdcall CareRayCtrl::onNotifyDetectorInfoThread(PVOID pvoid) { CareRayCtrl* pOpr = (CareRayCtrl*)pvoid; FINFO("Enter notify info thread"); while (!pOpr->m_bExitNotify) { pOpr->ShowStatusInfo(); Sleep(5000); } FINFO("Level notify info thread"); return 0; } void CareRayCtrl::OnAcquireImage() { if (SYNC_SOFTWARE == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode && !m_bOneKeyCalibration) { PerformSoftSyncAcq(); } else { PerformRadAcquisition(); } } void CareRayCtrl::OnProcessImg() { if (SYNC_MANUAL == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode || SYNC_AED == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode || SYNC_HARDWARE == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode) { FINFO("OnProcessImg send window off"); StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_OFF); } int nRet = 0; FrameAttr stImgInfo = {0}; if (m_bGetImage) { FINFO("Call get image attr"); nRet = API_CR_get_image_attr(&stImgInfo); if (TestError(nRet, "API_CR_get_image_attr")) { FERROR("get image attr Failed"); } else { FINFO("Image attr, H: {$}, W: {$}, bits: {$}", stImgInfo.image_height, stImgInfo.image_width, stImgInfo.pixel_bits); } m_nImageSize = stImgInfo.image_height * stImgInfo.image_width * stImgInfo.pixel_bits / 8; if (m_pRawImgBuffer != nullptr) { delete[] m_pRawImgBuffer; m_pRawImgBuffer = nullptr; } m_pRawImgBuffer = new WORD[stImgInfo.image_width * stImgInfo.image_height]; FINFO("Call get image"); nRet = API_CR_get_image(m_nImageSize, FALSE, m_pRawImgBuffer); if (TestError(nRet, "API_CR_get_image")) { FERROR("Get image failed"); return; } } if (m_nExposureMode == AEC) { FINFO("OnProcessImg AEC"); DataFeedback(EVT_DATA_PREVIEW_IMAGE, m_pRawImgBuffer); StatusFeedback(EVT_STATUS_PANEL, PANEL_AEC_PRE_END); if (m_nSaveRaw > 1) { SaveRawFunc(m_pRawImgBuffer, stImgInfo.image_width, stImgInfo.image_height); } return; } //整个系统的有图校正流程还没做,先按无图处理 if (APP_STATUS_CAL_BEGIN == m_nExamMode) { ConfirmCalExposure(); if (m_nGainNodeIndex != m_nGainNodeCount) //增益曝光次数够了,这两个值会是相等的 { StatusFeedback(EVT_STATUS_SINGLEEXP, DOSE_ACCEPT); } return; } FINFO("m_stModeInfo.nWidthOffset:{$},m_stModeInfo.nHeightOffset:{$}", m_stModeInfo.nWidthOffset, m_stModeInfo.nHeightOffset); FINFO("Begin get effect image"); if (!GetEffectiveImage(m_pImgBuffer, m_pRawImgBuffer, stImgInfo.image_width)) { return; } FINFO("Get effect image over"); DataFeedback(EVT_DATA_RAW_IMAGE, m_pImgBuffer); if (m_nSaveRaw > 1) { SaveRawFunc(m_pImgBuffer, m_stModeInfo.nImageWidth, m_stModeInfo.nImageHeight); } FINFO("Call API_CR_set_save_power"); nRet = API_CR_set_save_power(); if (TestError(nRet, "API_CR_set_save_power")) { FERROR("Set save power failed"); } StatusFeedback(EVT_STATUS_PANEL, PANEL_END_ACQ); } void CareRayCtrl::OnStartDarkCalibration() { FINFO("Start dark calibration process"); int nRet = -1; FINFO("Call stop cal procedure(FALSE)"); nRet = API_CR_stop_cal_procedure(FALSE); //参照SDK demo流程,在开始前调用这个接口 if (TestError(nRet, "API_CR_stop_cal_procedure")) { FERROR("stop cal procedure failed!"); } FINFO("Call cal offset"); nRet = API_CR_cal_offset(m_nCurrentMode); if (TestError(nRet, "API_CR_cal_offset")) { FERROR("Start offset failed"); return; } FINFO("Query status"); int nFrameNum = 0; ExpProgress calProg; do { nRet = API_CR_query_prog_info(CR_CAL_PROG, &calProg); if (TestError(nRet, "API_CR_query_prog_info")) { FERROR("Query Prog Info Failed"); API_CR_reset_detector(FALSE); return; } Sleep(100); if (TestError(calProg.errorCode)) { break; } if (calProg.frame_number > nFrameNum) { FINFO("Now received {$} dark images ", calProg.frame_number); nFrameNum = calProg.frame_number; } if (m_bAbortOffset) { FINFO("Abort Offset Calibration!"); FINFO("Call stop cal procedure(TRUE)"); nRet = API_CR_stop_cal_procedure(TRUE); if (TestError(nRet, "API_CR_stop_cal_procedure")) { FERROR("stop cal procedure failed!"); } break; } } while (FALSE == calProg.calComplete); if (TRUE == calProg.calComplete) { FINFO("Offset calibration finished!"); StatusFeedback(EVT_STATUS_CALIBRATIOIN, PANEL_EVENT_END_OK); } else { FERROR("Error occurred in offset calibration!"); return; } } void CareRayCtrl::OnAcquireGainImage() { } void CareRayCtrl::OnNotifyDetectorInfo() { } /*** ** 启动软同步采集 ** 通过回调反馈进度 ***/ int CareRayCtrl::PerformSoftSyncAcq() { FINFO("PerformSoftSyncAcq start"); int nRet = -1; if (EVT_EXP_EN == m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState) { FERROR("Detector has Image unrecoved, Omit"); return nRet; } m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState = 0; //开始采集前,恢复初值 FINFO("Call soft acq"); nRet = API_CR_start_soft_acquisition(); if (TestError(nRet, "API_CR_start_soft_acquisition")) { FERROR("Start soft acq failed"); } else { FINFO("Call request ready"); nRet = API_CR_ready_state_request(); if (TestError(nRet, "API_CR_ready_state_request")) { FERROR("Request ready state failed"); } else { FINFO("Call start acq fullimg"); nRet = API_CR_start_acq_full_image(); if (TestError(nRet, "API_CR_start_acq_full_image")) { FERROR("Start acq fullimg failed"); } } } FINFO("PerformSoftSyncAcq end"); return nRet; } int CareRayCtrl::PerformRadAcquisition() { FINFO("PerformRadAcquisition start"); int nRet = -1; FINFO("Call normal power"); nRet = API_CR_set_normal_power(); if (TestError(nRet, "API_CR_set_normal_power")) { FERROR("Set normal power failed"); return nRet; } if (m_nExposureMode == AEC) { FINFO("Call start acq preview image in AEC"); nRet = API_CR_start_acq_prev_image(); if (TestError(nRet, "API_CR_start_acq_prev_image")) { FERROR("Start acq preview image failed"); return nRet; } } else { FINFO("Call start acq full img"); nRet = API_CR_start_acq_full_image(); if (TestError(nRet, "API_CR_start_acq_full_image")) { FERROR("Start acq fullimg failed"); return nRet; } } if (SYNC_MANUAL == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode || SYNC_AED == m_pStPanelStatus[m_nCurrentPanelID]->eSyncMode) { nRet = QueryAutoProgInfo(); } else { nRet = QueryRadProgInfo(); } //轮询采集状态没有返回图像或终止了采集 if (CR_NO_ERR != nRet) { FINFO("Call normal power"); nRet = API_CR_set_normal_power(); if (TestError(nRet, "API_CR_set_normal_power")) { FERROR("Set normal power failed"); } return nRet; } FINFO("Call normal power"); nRet = API_CR_set_normal_power(); if (TestError(nRet, "API_CR_set_normal_power")) { FERROR("Set normal power failed"); return nRet; } if (m_bCancelFlag)//点片退出检查不再上图 { FINFO("PerformRadAcquisition Cancel"); return -1; } m_bGetImage = true; //轮询拿到图像,置为true SetEvent(m_hProcessImgEvent); FINFO("PerformRadAcquisition over"); return nRet; } /*** ** 一键校正时获取一帧暗场图 ***/ int CareRayCtrl::PerformDarkAcquisition() { int nRet = -1; int printOver = 0, awaitOver = 0; ExpProgress expProg; FINFO("Call normal power"); nRet = API_CR_set_normal_power(); if (TestError(nRet, "API_CR_set_normal_power")) { FERROR("Set normal power failed"); return false; } FINFO("Call start acq dark fullimg"); nRet = API_CR_start_acq_dark_full_image(); if (TestError(nRet, "API_CR_start_acq_dark_full_image")) { FERROR("Acquire dark image failed"); return nRet; } memset(&expProg, 0x0, sizeof(ExpProgress)); FINFO("Query Detector Status"); do { Sleep(50); if (CR_NO_ERR != (nRet = API_CR_query_prog_info(CR_RAD_PROG, &expProg))) { FERROR("Error occurred when query detector status info!"); return nRet; } if (expProg.fetchable) { FINFO("Dark Image will Arrive"); break; } } while (TRUE); FINFO("Call normal power"); nRet = API_CR_set_normal_power(); if (TestError(nRet, "API_CR_set_normal_power")) { FERROR("Set normal power failed"); return false; } FrameAttr stImgInfo; FINFO("Call get image attr"); nRet = API_CR_get_image_attr(&stImgInfo); if (TestError(nRet, "API_CR_get_image_attr")) { FERROR("get image attr failed"); return nRet; } else { FINFO("Image attr, H: {$}, W: {$}, bits: {$}", stImgInfo.image_height, stImgInfo.image_width, stImgInfo.pixel_bits); } if (nullptr == m_pDarkImage) { m_pDarkImage = new WORD[stImgInfo.image_height * stImgInfo.image_width]; } FINFO("Call get image"); nRet = API_CR_get_image(stImgInfo.image_height * stImgInfo.image_width * 2, FALSE, m_pDarkImage); if (TestError(nRet, "API_CR_get_image")) { FERROR("Get image failed"); return nRet; } return nRet; } /*** ** 轮询Manual(SDK的半aed模式)、aed模式采集状态 ***/ int CareRayCtrl::QueryAutoProgInfo(bool bIsAED) { FINFO("Begin query auto exposure progress info"); ExpProgress expProg; memset(&expProg, 0x0, sizeof(ExpProgress)); bool bPrintOver = false; bool bAwaitOver = false; int nResult = -1; int nTime = 0; bool bReady = false; //aed时曝光0-1-0变化,通过这个变量忽略第一个0 //manual时曝光0-1-0-1...变化,通过这个变量忽略后面的1 do { Sleep(50); if ((nResult = API_CR_query_prog_info(CR_RAD_PROG, &expProg)) != CR_NO_ERR) { FERROR("Error occurred when query detector status info! {$}, {$}", nResult, expProg.fetchable); return nResult; } switch (expProg.expose_flag) { case FALSE: { if (bAwaitOver == false) { if (APP_STATUS_CAL_BEGIN == m_nExamMode) { StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP, "false"); } else { if (MANUAL_SYNC == m_nSyncMode) { StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP, "false"); } } bAwaitOver = true; bPrintOver = false; FINFO("Waiting for detector Ready..."); } } break; case TRUE: { if (!bPrintOver) { if (!bReady) { bReady = true; m_bDetectorReady = true; m_bIsAcqStatus = true; //通知ready状态 StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY); } if (APP_STATUS_CAL_BEGIN == m_nExamMode) { StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP, "true"); } else { if (MANUAL_SYNC == m_nSyncMode) { StatusFeedback(EVT_STATUS_PANEL, PANEL_READY_EXP, "true"); } } bPrintOver = true; bAwaitOver = false; FINFO("Detector is ready for Rad Acquisition, press x-ray hand switch now..."); } } break; default: break; }//end for switch if (expProg.fetchable) { FINFO("Image will arrive in auto exposure progress"); break; } else { if (m_bCancelFlag)//Manual AED时取消 { //没有图或退出do while循环的处理 int nRet = -1; FINFO("Cancel, Call stop acq"); nRet = API_CR_stop_acq_frame(); //用于终止曝光流程 if (TestError(nRet, "API_CR_stop_acq_frame")) { FERROR("Stop acq failed"); } else { m_bDetectorReady = false; m_bIsAcqStatus = false; } FINFO("Leave loop"); return -1; } } } while (true); return CR_NO_ERR; } /*** ** 轮询硬同步模式采集状态 ***/ int CareRayCtrl::QueryRadProgInfo() { FINFO("Begin query rad exposure progress info"); ExpProgress expProg; memset(&expProg, 0, sizeof(ExpProgress)); bool bExpError = false; bool bExpInit = false; bool bExpReady = false; bool bExpPermission = false; bool bExpPermitted = false; bool bExpExpose = false; bool bExpComplete = false; int nResult = -1; do { Sleep(20); if ((nResult = API_CR_query_prog_info(CR_RAD_PROG, &expProg)) != CR_NO_ERR) { FERROR("Error occurred when query detector status info! {$}, {$}", nResult, expProg.fetchable); return nResult; } switch (expProg.expStatus) { case CR_EXP_ERROR: if (!bExpError) { bExpError = true; FINFO("CR_EXP_ERROR(-1)"); } break; case CR_EXP_INIT: if (!bExpInit) { bExpInit = true; FINFO("CR_EXP_INIT(0)"); } break; case CR_EXP_READY: if (!bExpReady) { //通知ready状态 bExpReady = true; FINFO("CR_EXP_READY(1)"); m_bDetectorReady = true; m_bIsAcqStatus = true; StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY); } break; case CR_EXP_WAIT_PERMISSION: if (!bExpPermission) { bExpPermission = true; FINFO("CR_EXP_WAIT_PERMISSION(2) Call permit"); nResult = API_CR_permit_exposure(); if (TestError(nResult, "API_CR_permit_exposure")) { FERROR("Permit Exposure Failed!"); return nResult; } } break; case CR_EXP_PERMITTED: if (!bExpPermitted) { bExpPermitted = true; FINFO("CR_EXP_PERMITTED(3)"); } break; case CR_EXP_EXPOSE: if (!bExpPermitted) { bExpPermitted = true; FINFO("CR_EXP_EXPOSE(4)"); //这个事件基本上都能查询到 StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); } break; case CR_EXP_COMPLETE: if (!bExpComplete) { bExpComplete = true; FINFO("CR_EXP_COMPLETE(5)"); //这个事件不是每次都能查询到 StatusFeedback(EVT_STATUS_PANEL, PANEL_XWINDOW_ON); } break; default: break; }//end for switch if (TRUE == expProg.fetchable) { FINFO("Image will arrive in rad exposure progress"); break; } if (m_bCancelFlag) //硬同步时取消 { /*int nRet = -1; FINFO("Cancel Call stop acq"); nRet = API_CR_stop_acq_frame(); if (TestError(nRet, "API_CR_stop_acq_frame")) { FERROR("Stop acq failed"); } else { m_bDetectorReady = false; m_bIsAcqStatus = false; }*/ m_bDetectorReady = false; m_bIsAcqStatus = false; FINFO("Leave loop"); return -1; } } while (true); m_bDetectorReady = false; m_bIsAcqStatus = false; return CR_NO_ERR; } void CareRayCtrl::SaveRawFunc(WORD* pInImg, int nImgWidth, int nImgHeight) { FINFO("SaveRawFunc nImgWidth:{$},nImgHeight:{$}", nImgWidth, nImgHeight); FILE* fp = nullptr; string strFileName = ""; if (m_nExposureMode == AEC) { strFileName = m_strWorkPath + "\\rawdata\\Preview.raw"; } else { strFileName = m_strWorkPath + "\\rawdata\\Image.raw"; } if ((fp = fopen(strFileName.c_str(), "wb")) == NULL) { FERROR("fopen {$} failed, error code:{$}", strFileName, GetLastError()); return; } fwrite(pInImg, sizeof(WORD), (size_t)nImgWidth * (size_t)nImgHeight, fp); fclose(fp); FINFO("Save image over"); } /*** ** 裁剪图像 ** pOutImg: 裁剪后图像; pInImg: 裁剪前图像; nInWidth: 裁剪前图像宽度 ***/ bool CareRayCtrl::GetEffectiveImage(WORD* pOutImg, WORD* pInImg, int nInWidth) { if (pOutImg == NULL || pInImg == NULL || nInWidth < 0) { FERROR("Illegal parameter, can not get effective image"); return false; } try { for (int i = 0; i < m_stModeInfo.nImageHeight; i++) { memcpy(pOutImg + i * m_stModeInfo.nImageWidth, pInImg + (i + m_stModeInfo.nHeightOffset) * nInWidth + m_stModeInfo.nWidthOffset, m_stModeInfo.nImageWidth * sizeof(WORD)); } } catch (...) { FERROR("Get effective image crashed"); return false; } return true; } int CareRayCtrl::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; } bool CareRayCtrl::LoadCareCalibration(bool bLoad) { UserCorrection corr; memset(&corr, 0x0, sizeof(UserCorrection)); if (bLoad) { switch (m_nCurrentDetectorType) { case CareView_1500R: case CareView_500M: case CareView_1800R: case CareView_1800I: case CareView_1800L: case CareView_750M: case CareView_1500L: case CareView_1800RV2: { FINFO("Load Fixed Correction Files"); corr.fixedCorr = TRUE; } break; case CareView_500P: case CareView_1500P: case CareView_1500Rm: case CareView_1500C: case CareView_1500Cw: case CareView_300P: case CareView_1500PV2: case CareView_750Cw: { FINFO("Load Portable Correction Files"); corr.portableCorr = TRUE; } break; default: corr.fixedCorr = TRUE; } } FINFO("Call API_CR_set_user_correction"); int nResult = API_CR_set_user_correction(&corr); if (TestError(nResult, "API_CR_set_user_correction")) { FERROR("Set user Correction Failed!"); return false; } else { FINFO("Set user Correction Success"); } return true; } /*** ** 计算一键校正曝光的图像灰度 ***/ double CareRayCtrl::GetMean(WORD* imgNoHeader, int pixelNum) { double imgMean = 0; for (int i = 0; i < pixelNum; i++) { imgMean += imgNoHeader[i]; } imgMean = imgMean / pixelNum; return imgMean; } /*** ** 等待探测器操作执行完毕 ***/ bool CareRayCtrl::WaitRespond(int nTimeOut, const char* szPosition) { FINFO("--- {$} WaitRespond, {$}ms ---", szPosition, nTimeOut); DWORD dwRet = WaitForSingleObject(m_hRespond, nTimeOut); if (dwRet == WAIT_TIMEOUT) { FERROR("Timeout in wait respond"); return false; } ResetEvent(m_hRespond); return true; } void CareRayCtrl::StopWaiting(const char* szPosition) { FINFO("--- Stop waiting respond, {$} ---", szPosition); SetEvent(m_hRespond); } /*** ** 检测接口是否有错误,true:有错;false:没错 ***/ bool CareRayCtrl::TestError(int nRet, const char* szFuncName) { if (nRet == CR_NO_ERR) { FINFO("{$} executed successfully", szFuncName); return false; } else { FERROR("{$} return error {$}, reason: {$}", szFuncName, nRet, CrErrStrList(nRet)); return true; } } void CareRayCtrl::GetDetectorType(DetectorType eType, string& szType) { string strType = "Unkown_Type"; switch (eType) { case CareView_1500R: strType = "CareView_1500R"; break; case CareView_1500Rm: strType = "CareView_1500Rm"; break; case CareView_1500P: strType = "CareView_1500P"; break; case CareView_1500C: strType = "CareView_1500C"; break; case CareView_1800R: strType = "CareView_1800R"; break; case CareView_500M: strType = "CareView_500M"; break; case CareView_500I: strType = "CareView_500I"; break; case CareView_500P: strType = "CareView_500P"; break; case CareView_900F: strType = "CareView_900F"; break; case CareView_1800I: strType = "CareView_1800I"; break; case CareView_1500L: strType = "CareView_1500L"; break; case CareView_1500Cw: strType = "CareView_1500Cw"; break; case CareView_300P: strType = "CareView_300P"; break; case CareView_750M: strType = "CareView_750M"; break; case CareView_1800L: strType = "CareView_1800L"; break; case CareView_1800RV2: strType = "CareView_1800RV2"; break; case CareView_1500PV2: strType = "CareView_1500PV2"; break; case CareView_750Cw: strType = "CareView_750Cw"; break; case Unkown_Type: break; default: break; } szType = strType.c_str(); } void CareRayCtrl::ProcessCREvent(int eventID, Event* eventData) { FINFO("Start process event: {$}", eventID); switch (eventID) { case EVT_DISCONNECT: FINFO("EVT_DISCONNECT"); StatusFeedback(EVT_STATUS_PANEL, PANEL_DISCONNECT); break; case EVT_READY: FINFO("EVT_READY"); m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState = EVT_READY; m_bDetectorReady = true; m_bIsAcqStatus = true; //通知ready状态 StatusFeedback(EVT_STATUS_PANEL, PANEL_STANDBY); break; case EVT_EXP_EN: FINFO("EVT_EXP_EN"); m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState = EVT_EXP_EN; SetEvent(m_hXWinOnEvent); break; case EVT_IMAGE_ARRIVE: FINFO("EVT_IMAGE_ARRIVE, width: {$}, height: {$}", eventData->width, eventData->height); m_nImageSize = eventData->width * eventData->height * 2; m_pStPanelStatus[m_nCurrentPanelID]->nSoftAcqState = EVT_IMAGE_ARRIVE; memcpy(m_pRawImgBuffer, eventData->data, (size_t)eventData->width * (size_t)eventData->height * sizeof(WORD)); m_bGetImage = false; //回调拿到图像,置为false SetEvent(m_hProcessImgEvent); break; case EVT_AEC_PREV_MODE_READY: FINFO("EVT_AEC_PREV_MODE_READY"); break; case EVT_AEC_RAD_MODE_READY: FINFO("EVT_AEC_RAD_MODE_READY"); break; case EVT_AEC_PREV_IMG_ARRIVE: FINFO("EVT_AEC_PREV_IMG_ARRIVE"); break; case EVT_AEC_RAD_IMG_ARRIVE: FINFO("EVT_AEC_RAD_IMG_ARRIVE"); break; case EVT_DETECTOR_ERROR: FINFO("EVT_DETECTOR_ERROR"); break; case EVT_EXPOSE_FLAG_FALSE: FINFO("EVT_EXPOSE_FLAG_FALSE"); break; case EVT_EXPOSE_FLAG_TRUE: FINFO("EVT_EXPOSE_FLAG_TRUE"); break; case EVT_INITIAL: FINFO("EVT_INITIAL"); break; case EVT_UNUPLOADED_IMG_EXIST: FINFO("EVT_UNUPLOADED_IMG_EXIST"); break; case EVT_CONNECTED: FINFO("EVT_CONNECTED"); StatusFeedback(EVT_STATUS_PANEL, PANEL_CONNECT); break; case EVT_SECOND_PANEL_CONNECTED: FINFO("EVT_SECOND_PANEL_CONNECTED"); break; case EVT_SECOND_PANEL_DISCONNECTED: FINFO("EVT_SECOND_PANEL_DISCONNECTED"); break; case EVT_SHS_STATUS_CHANGED: FINFO("EVT_SHS_STATUS_CHANGED"); break; default: break; } FINFO("Process event {$} over", eventID); } void CareRayCtrl::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 CareRayCtrl::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 CareRayCtrl::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 CareRayCtrl::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 CareRayCtrl::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 CareRayCtrl::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); }