DocScannerCap.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568
  1. #include "stdafx.h"
  2. #include "DocScannerCap.h"
  3. #include "math.h"
  4. #include "UserEventCode.h"
  5. //template<typename T>
  6. //struct identity
  7. //{
  8. // typedef T type;
  9. //};
  10. //#define X(F, T) identity<T>::type& F = *reinterpret_cast<identity<T>::type*>( \
  11. // GetProcAddress(GetModuleHandle("user32.dll"), #F))
  12. //X(RegisterDeviceNotification, HDEVNOTIFY WINAPI(
  13. // IN HANDLE hRecipient,IN LPVOID NotificationFilter,IN DWORD Flags));
  14. //X(UnregisterDeviceNotification, BOOL(WINAPI *PUnregisterDeviceNotification)(IN HDEVNOTIFY Handle));
  15. //#undef X
  16. HWND g_hInnerWnd = NULL;
  17. HDEVNOTIFY g_hDevNotify = NULL;
  18. LRESULT CALLBACK CameraNotifierProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  19. pFnEventFinished OnEvtFinished = &CDocScannerCap::EvtFinishedHandle;
  20. int GetCameraInfors(CAMERA_BUCKET& vtCameraList)
  21. {
  22. // enumerate all video capture devices
  23. DestoryCamereBuckets(vtCameraList);
  24. ICreateDevEnum *pDevEnum = NULL;
  25. IEnumMoniker *pEnum = NULL;
  26. int deviceCounter = 0;
  27. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  28. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
  29. reinterpret_cast<void**>(&pDevEnum));
  30. if (SUCCEEDED(hr)) {
  31. // Create an enumerator for the video capture category.
  32. hr = pDevEnum->CreateClassEnumerator(
  33. CLSID_VideoInputDeviceCategory,
  34. &pEnum, 0);
  35. if (hr == S_OK) {
  36. //if (!silent)printf("SETUP: Looking For Capture Devices\n");
  37. IMoniker *pMoniker = NULL;
  38. while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
  39. IPropertyBag *pPropBag;
  40. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
  41. if (FAILED(hr)) {
  42. pMoniker->Release();
  43. continue; // Skip this one, maybe the next one will work.
  44. }
  45. PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
  46. if(item != NULL) {
  47. item->Cleanup();
  48. // Find the description or friendly name.
  49. VARIANT varName;
  50. VariantInit(&varName);
  51. hr = pPropBag->Read(L"Description", &varName, 0);
  52. if (FAILED(hr)) {
  53. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  54. }
  55. if (SUCCEEDED(hr)) {
  56. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  57. int maxLen = sizeof(item->szDevName) - 2;
  58. int nLen = WrapW2A(varName, &(item->szDevName[0]), maxLen);
  59. VariantClear(&varName);
  60. }
  61. VARIANT varCLSID;
  62. VariantInit(&varCLSID);
  63. hr = pPropBag->Read(L"CLSID", &varCLSID, 0);
  64. if (SUCCEEDED(hr)) {
  65. int maxLen = sizeof(item->szCLSID) - 2;
  66. int nLen = WrapW2A(varCLSID, &(item->szCLSID[0]), maxLen);
  67. VariantClear(&varCLSID);
  68. }
  69. VARIANT varDevPath;
  70. VariantInit(&varDevPath);
  71. hr = pPropBag->Read(L"DevicePath", &varDevPath, 0);
  72. if (SUCCEEDED(hr)) {
  73. int maxLen = sizeof(item->szDevPath) - 2;
  74. int nLen = WrapW2A(varDevPath, &(item->szDevPath[0]), maxLen);
  75. VariantClear(&varDevPath);
  76. }
  77. VARIANT varWaveID;
  78. VariantInit(&varWaveID);
  79. hr = pPropBag->Read(L"WaveInID", &varWaveID, 0);
  80. if (SUCCEEDED(hr)) {
  81. item->uWaveInID = varWaveID.lVal;
  82. VariantClear(&varWaveID);
  83. }
  84. vtCameraList.push_back(item);
  85. }
  86. pPropBag->Release();
  87. pPropBag = NULL;
  88. pMoniker->Release();
  89. pMoniker = NULL;
  90. deviceCounter++;
  91. }
  92. pDevEnum->Release();
  93. pDevEnum = NULL;
  94. pEnum->Release();
  95. pEnum = NULL;
  96. }
  97. }
  98. return deviceCounter;
  99. }
  100. int IsDeviceBusy(const char* lpcszDeviceName)
  101. {
  102. LOG_FUNCTION();
  103. int nRet = -2;
  104. ICreateDevEnum *pDevEnum = NULL;
  105. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  106. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum);
  107. IEnumMoniker *pEnum = NULL;
  108. hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
  109. if (SUCCEEDED(hr)) {
  110. // Create an enumerator for the video capture category.
  111. IMoniker *pMoniker = NULL;
  112. nRet = -1;
  113. while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
  114. IPropertyBag *pPropBag = NULL;
  115. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
  116. if (FAILED(hr)) {
  117. SAFE_RELEASE_IDEV(pPropBag);
  118. SAFE_RELEASE_IDEV(pMoniker);
  119. continue; // Skip this one, maybe the next one will work.
  120. }
  121. VARIANT varName;
  122. VariantInit(&varName);
  123. hr = pPropBag->Read(L"Description", &varName, 0);
  124. if (FAILED(hr)) {
  125. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  126. }
  127. if (SUCCEEDED(hr)) {
  128. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  129. int count = 255;
  130. char tmp[256] = {0};
  131. WrapW2A(varName, tmp, count);
  132. if(SUCCEEDED(hr)) {
  133. if(!strcmp(lpcszDeviceName, tmp)) {
  134. //Deal the specific device
  135. nRet = 0;
  136. LPBC* pbc = NULL;
  137. IBaseFilter *P_VCamTrans = NULL;
  138. IBaseFilter *pCap = NULL;
  139. CreateBindCtx(0, pbc);
  140. hr = pMoniker->BindToObject((IBindCtx *)pbc, 0, IID_IBaseFilter,(void **)&pCap);
  141. IGraphBuilder *m_pGB = NULL;
  142. IMediaControl *m_pMC = NULL;
  143. IVideoWindow *m_pVW = NULL;
  144. IMediaEventEx *m_pME = NULL;
  145. hr = CoCreateInstance(CLSID_FilterGraph, NULL,
  146. CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
  147. if (FAILED(hr)) {
  148. nRet = -2;
  149. SAFE_RELEASE_IDEV(m_pGB);
  150. SAFE_RELEASE_IDEV(pCap);
  151. SAFE_RELEASE_IDEV(pPropBag);
  152. SAFE_RELEASE_IDEV(pMoniker);
  153. goto PEnd;
  154. }
  155. m_pGB->AddFilter(pCap, NULL);
  156. ICaptureGraphBuilder2 *m_pCapGB = NULL;
  157. hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
  158. CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);
  159. if (FAILED(hr)) {
  160. nRet = -2;
  161. SAFE_RELEASE_IDEV(m_pCapGB);
  162. SAFE_RELEASE_IDEV(m_pGB);
  163. SAFE_RELEASE_IDEV(pCap);
  164. SAFE_RELEASE_IDEV(pPropBag);
  165. SAFE_RELEASE_IDEV(pMoniker);
  166. goto PEnd;
  167. }
  168. m_pCapGB->SetFiltergraph(m_pGB);
  169. IAMCrossbar *pXBar1 = NULL;
  170. hr = m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pCap,
  171. IID_IAMCrossbar,(void **)&pXBar1);
  172. if (SUCCEEDED(hr)) {
  173. long OutputPinCount;
  174. long InputPinCount;
  175. long PinIndexRelated;
  176. long PhysicalType;
  177. long inPort = 0;
  178. long outPort = 0;
  179. pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
  180. int videoBusy = 1;
  181. for (int i=0; i<InputPinCount; i++) {
  182. for (int j=0; j<OutputPinCount; j++) {
  183. if(S_OK == pXBar1->CanRoute(j, i)) {
  184. pXBar1->Route(j,i);
  185. m_pGB->AddFilter(pCap, L"Capture Filter");
  186. hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
  187. hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
  188. hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
  189. hr = m_pVW->put_Owner((OAHWND)NULL);
  190. hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
  191. hr = m_pVW->put_Visible(OAFALSE);
  192. hr = m_pVW->put_AutoShow(OAFALSE);
  193. HRESULT innhr = m_pMC->StopWhenReady();
  194. if (SUCCEEDED(innhr))
  195. {
  196. videoBusy = 0;
  197. }
  198. else {
  199. LogWarn(Severity_Low, Error_DevCommFailed, LOG_ERROR_PORTABLESCANNER_BUSY_ONE,
  200. CSimpleStringA::Format("%s stop failed: %d", lpcszDeviceName, innhr));
  201. }
  202. SAFE_RELEASE_IDEV(m_pVW);
  203. SAFE_RELEASE_IDEV(m_pMC);
  204. SAFE_RELEASE_IDEV(P_VCamTrans);
  205. }
  206. }
  207. }
  208. if (videoBusy == 1)
  209. {
  210. nRet = 1; //视频设备占用
  211. }
  212. SAFE_RELEASE_IDEV(pXBar1);
  213. }
  214. else //pXBar1
  215. {
  216. m_pGB->AddFilter(pCap, L"Capture Filter");
  217. m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
  218. hr = m_pGB->QueryInterface(IID_IMediaEventEx, (void**)&m_pME);
  219. hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
  220. hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
  221. hr = m_pVW->put_Owner((OAHWND)NULL);
  222. hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
  223. hr = m_pVW->put_Visible(OAFALSE);
  224. hr = m_pVW->put_AutoShow(OAFALSE);
  225. HRESULT innhr = m_pMC->StopWhenReady();
  226. if (FAILED(innhr))
  227. {
  228. LogWarn(Severity_Low, Error_DevCommFailed, LOG_ERROR_PORTABLESCANNER_BUSY_TWO,
  229. CSimpleStringA::Format("%s stop failed: %d", lpcszDeviceName, innhr));
  230. nRet = 1; //视频设备占用
  231. }
  232. SAFE_RELEASE_IDEV(m_pVW);
  233. SAFE_RELEASE_IDEV(m_pMC);
  234. SAFE_RELEASE_IDEV(P_VCamTrans);
  235. }
  236. SAFE_RELEASE_IDEV(m_pCapGB);
  237. SAFE_RELEASE_IDEV(m_pGB);
  238. SAFE_RELEASE_IDEV(pCap);
  239. break;
  240. }
  241. }
  242. }
  243. SAFE_RELEASE_IDEV(pPropBag);
  244. SAFE_RELEASE_IDEV(pMoniker);
  245. }
  246. }
  247. PEnd:
  248. SAFE_RELEASE_IDEV(pDevEnum);
  249. SAFE_RELEASE_IDEV(pEnum);
  250. if(nRet != 1) {
  251. nRet = 0;
  252. }
  253. return nRet;
  254. }
  255. int GetCameraCount()
  256. {
  257. ICreateDevEnum *pDevEnum = NULL;
  258. IEnumMoniker *pEnum = NULL;
  259. int deviceCounter = 0;
  260. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  261. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
  262. reinterpret_cast<void**>(&pDevEnum));
  263. if (SUCCEEDED(hr)) {
  264. hr = pDevEnum->CreateClassEnumerator(
  265. CLSID_VideoInputDeviceCategory,
  266. &pEnum, 0);
  267. if(hr == S_OK){
  268. IMoniker *pMoniker = NULL;
  269. while (pEnum->Next(1, &pMoniker, NULL) == S_OK){
  270. IPropertyBag *pPropBag;
  271. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
  272. (void**)(&pPropBag));
  273. if (FAILED(hr)){
  274. pMoniker->Release();
  275. continue; // Skip this one, maybe the next one will work.
  276. }
  277. pPropBag->Release();
  278. pPropBag = NULL;
  279. pMoniker->Release();
  280. pMoniker = NULL;
  281. deviceCounter++;
  282. }
  283. pEnum->Release();
  284. pEnum = NULL;
  285. }
  286. pDevEnum->Release();
  287. pDevEnum = NULL;
  288. }
  289. return deviceCounter;
  290. }
  291. int UpdateCameraInfors(CAMERA_BUCKET& vtCameraList)
  292. {
  293. int old_count = vtCameraList.size();
  294. if(old_count > 0) {
  295. DestoryCamereBuckets(vtCameraList);
  296. }
  297. GetCameraInfors(vtCameraList);
  298. return old_count;
  299. }
  300. int ExclusiveCameraBuckes(const CAMERA_BUCKET& lhs, const CAMERA_BUCKET& rhs, CAMERA_BUCKET& diff)
  301. {
  302. int count = 0;
  303. const size_t l_size = lhs.size();
  304. const size_t r_size = rhs.size();
  305. if(!diff.empty()) {
  306. DestoryCamereBuckets(diff);
  307. }
  308. //Is it necessary to sort before doing comparation job ?
  309. if(l_size > r_size) {
  310. for(CAMERA_BUCKET_CITER citer=lhs.cbegin(); citer!=lhs.cend(); ++citer) {
  311. auto aim = std::find_if(rhs.cbegin(), rhs.cend(),
  312. [citer](PCAMERA_INFOR_ITEM const item){
  313. return !strcmp(item->szDevPath, (*citer)->szDevPath);
  314. });
  315. if(aim == rhs.cend()) {
  316. PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
  317. if(item != NULL) {
  318. item->Copy((*citer));
  319. diff.push_back(item);
  320. count++;
  321. }
  322. }
  323. }
  324. } else if(l_size < r_size) {
  325. for(CAMERA_BUCKET_CITER citer=rhs.cbegin(); citer!=rhs.cend(); ++citer) {
  326. auto aim = std::find_if(lhs.cbegin(), lhs.cend(), [citer](PCAMERA_INFOR_ITEM const item){
  327. return !strcmp(item->szDevPath, (*citer)->szDevPath);
  328. });
  329. if(aim == lhs.cend()) {
  330. PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
  331. if(item != NULL) {
  332. item->Copy((*citer));
  333. diff.push_back(item);
  334. count++;
  335. }
  336. }
  337. }
  338. }
  339. return count;
  340. }
  341. void DisplayCameraInfos(const CAMERA_BUCKET& vtCameraList)
  342. {
  343. for(CAMERA_BUCKET_CITER it=vtCameraList.cbegin(); it!=vtCameraList.cend(); ++it) {
  344. if(*it) {
  345. (*it)->Display();
  346. }else {
  347. LOG_ASSERT(!"Empty elememt occurs !!");
  348. }
  349. }
  350. }
  351. void OnMouseTrace(int evt, int x, int y, int flags, void* param = NULL);
  352. const Scalar RED = Scalar(0,0,255);
  353. const Scalar PINK = Scalar(230,130,255);
  354. const Scalar BLUE = Scalar(255,0,0);
  355. const Scalar LIGHTBLUE = Scalar(255,255,160);
  356. const Scalar GREEN = Scalar(0,255,0);
  357. const Scalar BLACK = Scalar(0, 0, 0);
  358. const Scalar ERROR_GRAY = Scalar(205, 205, 205);
  359. const int WAITKEY_TIME = 30;
  360. const DWORD ERROR_CONTINUE_MILLSEC = 3000;
  361. const int ERROR_CONTINUE_TIMES = ERROR_CONTINUE_MILLSEC / WAITKEY_TIME;
  362. CDocScannerCap::CDocScannerCap(CPortableScannerFSM* pFSM)
  363. :m_videoID(-1)
  364. ,m_hrCoInited(S_FALSE)
  365. ,m_defWnd(NULL)
  366. ,m_dwErrCode(ERROR_SUCCESS)
  367. ,m_hPreviewPro(NULL)
  368. ,m_fPreviewing(false)
  369. ,m_colorMode(COLORFUL)
  370. ,m_roiMode(ROI_DEFAULT)
  371. ,m_roiRate(1.0f)
  372. ,m_bHide(FALSE)
  373. ,m_winSize(DR_X, DR_Y, DR_W, DR_H)
  374. ,rectStatus(NOT_SET)
  375. ,m_pFSM(pFSM)
  376. ,m_bHSPSType(false)
  377. {
  378. m_hrCoInited = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  379. }
  380. CDocScannerCap::~CDocScannerCap(void)
  381. {
  382. LOG_FUNCTION();
  383. #if 1
  384. //let VideoCapture object invoke release at destructor.
  385. _cleanup(false);
  386. RequestQueueCleanup();
  387. destroyAllWindows();
  388. #endif
  389. if(m_hrCoInited == S_OK) {
  390. CoUninitialize();
  391. }
  392. }
  393. void CDocScannerCap::Test()
  394. {
  395. // cv::VideoCapture videoCap(0);
  396. // if(!videoCap.isOpened())
  397. // {
  398. // return;
  399. // }
  400. // cv::Mat edges;
  401. //#define WINDOWS_TITLE "edges"
  402. // cv::namedWindow(WINDOWS_TITLE);
  403. // moveWindow(WINDOWS_TITLE, 0, 0);
  404. // setWindowProperty(WINDOWS_TITLE, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
  405. // //HWND hWin = FindWindow(NULL, WINDOWS_TITLE);
  406. // HWND hWin = (HWND)cvGetWindowHandle(WINDOWS_TITLE);
  407. // DWORD dwFlag = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER;
  408. // dwFlag &= ~SWP_NOSIZE;
  409. // if(hWin == NULL)
  410. // {
  411. // LOG_TRACE("Find %s window handle faiiled, GLE=%u", WINDOWS_TITLE, GetLastError());
  412. // }
  413. // SetWindowPos(hWin, HWND_NOTOPMOST, 128, 128, edges.cols, edges.rows, dwFlag);
  414. // //Bordorless
  415. // SetWindowLong(hWin, GWL_STYLE, GetWindowLong(hWin, GWL_EXSTYLE) | WS_EX_TOPMOST | WS_EX_LAYERED);
  416. // SetLayeredWindowAttributes(hWin, RGB(255,255,255), 0, LWA_COLORKEY);
  417. // SetWindowLong(hWin, GWL_STYLE, GetWindowLong(hWin, GWL_EXSTYLE)
  418. // & (~WS_CAPTION)
  419. // & (~WS_BORDER)
  420. // & (~WS_THICKFRAME));
  421. // ShowWindow(hWin, SW_SHOW);
  422. // for(;;)
  423. // {
  424. // cv::Mat cameraFrame;
  425. // videoCap >> cameraFrame ;
  426. // imshow(WINDOWS_TITLE, cameraFrame);
  427. // if(cv::waitKey(30) >= 0) {
  428. // cameraFrame.release();
  429. // destroyWindow(WINDOWS_TITLE);
  430. // break;
  431. // }
  432. // }
  433. }
  434. bool CDocScannerCap::InitHwndForNotify()
  435. {
  436. static char szWindowClass[] = "Win32_DocScannerCap";
  437. static char szTitle[] = "Win32 Document Scanner Notificer";
  438. //get instance of current program (self)
  439. HINSTANCE hInstance = GetModuleHandle (NULL);
  440. char szPcName[MAX_PATH] = {0};
  441. DWORD nSize = sizeof(szPcName);
  442. GetComputerName(szPcName, &nSize);
  443. WNDCLASSEX wcex;
  444. wcex.cbSize = sizeof(WNDCLASSEX);
  445. wcex.style = CS_HREDRAW | CS_VREDRAW;
  446. wcex.lpfnWndProc = CameraNotifierProc;
  447. wcex.cbClsExtra = 0;
  448. wcex.cbWndExtra = 0;
  449. wcex.hInstance = hInstance;
  450. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  451. wcex.lpszMenuName = NULL;
  452. wcex.lpszClassName = szWindowClass;
  453. wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
  454. if (!RegisterClassEx(&wcex))
  455. {
  456. return false;
  457. }
  458. HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
  459. CW_USEDEFAULT,
  460. CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
  461. if (!hWnd)
  462. {
  463. return false;
  464. }
  465. ShowWindow(hWnd, SW_HIDE);
  466. UpdateWindow(hWnd);
  467. g_hInnerWnd = hWnd;
  468. return true;
  469. }
  470. bool CDocScannerCap::RegisterVideoNotify()
  471. {
  472. DEV_BROADCAST_DEVICEINTERFACE filterData;
  473. ZeroMemory(&filterData, sizeof(DEV_BROADCAST_DEVICEINTERFACE));
  474. filterData.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  475. filterData.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  476. filterData.dbcc_classguid = AM_KSCATEGORY_VIDEO;
  477. g_hDevNotify = RegisterDeviceNotification(g_hInnerWnd, &filterData, DEVICE_NOTIFY_WINDOW_HANDLE);
  478. if (g_hDevNotify == NULL) {
  479. return false;
  480. }
  481. return true;
  482. }
  483. bool CDocScannerCap::UnRegisterVideoNotify()
  484. {
  485. if (g_hDevNotify != NULL) {
  486. UnregisterDeviceNotification(g_hDevNotify);
  487. g_hDevNotify = NULL;
  488. }
  489. return true;
  490. }
  491. bool CDocScannerCap::Open(unsigned int idx)
  492. {
  493. if(m_cvCap.isOpened()) {
  494. _cleanup();
  495. }
  496. //the method first call release to close alreay opened file or camera
  497. m_cvCap.open(idx);
  498. if(!m_cvCap.isOpened()) {
  499. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("open failed:");
  500. m_dwErrCode = ERROR_OPEN_FAILED;
  501. winName.clear();
  502. return false;
  503. }
  504. _setProperty();
  505. {
  506. CAMERA_INFOR_ITEM item;
  507. if(GetSpecificedCamInfor(idx, &item) > 0) {
  508. _setDevName(item.szDevName);
  509. winName = cv::String(DEFAULT_MAT_WINDOW_NAME) + "-" + devName;
  510. }else {
  511. CHAR szDevIndex[128] = {0};
  512. sprintf_s(szDevIndex, "%s-%d", DEFAULT_MAT_WINDOW_NAME, idx);
  513. winName = szDevIndex;
  514. _setDevName("");
  515. }
  516. }
  517. m_videoID = idx;
  518. m_dwErrCode = ERROR_SUCCESS;
  519. return true;
  520. }
  521. void CDocScannerCap::_setProperty()
  522. {
  523. //设置为不一样的分辨率,会出现耗时,1.5s 长城
  524. //SetResoultionRatio(1920, 1080);
  525. }
  526. bool CDocScannerCap::OpenCamera(LPCTSTR lpcszDev)
  527. {
  528. if(lpcszDev == NULL) {
  529. m_dwErrCode = ERROR_INVALID_PARAMETER;
  530. return false;
  531. }
  532. const int camId = _getCamIDByDevName(lpcszDev);
  533. if(camId < 0) {
  534. m_dwErrCode = ERROR_FILE_NOT_FOUND;
  535. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("not found camera id.");
  536. return false;
  537. }
  538. //const int nRes = IsDeviceBusy(lpcszDev);
  539. //if(nRes) {
  540. // if(nRes == -2) {
  541. // m_dwErrCode = ERROR_INVALID_ACCESS;
  542. // } else if(nRes == -1) {
  543. // m_dwErrCode = ERROR_FILE_NOT_FOUND;
  544. // } else if(nRes == 1) {
  545. // m_dwErrCode = ERROR_DEVICE_IN_USE;
  546. // } else {
  547. // m_dwErrCode = ERROR_BAD_ENVIRONMENT;
  548. // }
  549. // return false;
  550. //}
  551. if(Open(camId))
  552. {
  553. if(devName.empty())
  554. _setDevName(lpcszDev);
  555. return true;
  556. }
  557. return false;
  558. }
  559. bool CDocScannerCap::ScanImage(const char* lpcszFilePath)
  560. {
  561. if(!m_fPreviewing) {
  562. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Request scaning without in previewing.");
  563. m_dwErrCode = ERROR_INVALID_ENVIRONMENT;
  564. return false;
  565. }
  566. if(lpcszFilePath == NULL) {
  567. m_dwErrCode = ERROR_INVALID_PARAMETER;
  568. return false;
  569. }
  570. char szFileName[MAX_PATH] = {0};
  571. int len = strlen(lpcszFilePath);
  572. if(len == 0) {
  573. _combineFileName(szFileName, MAX_PATH);
  574. cv::String strFileName("C:\\");
  575. strFileName += szFileName;
  576. strFileName += ".jpg";
  577. strcpy_s(szFileName, strFileName.c_str());
  578. }
  579. else {
  580. strcpy_s(szFileName, lpcszFilePath);
  581. }
  582. len = strlen(szFileName);
  583. if(len == 0) {
  584. m_dwErrCode = ERROR_INVALID_PARAMETER;
  585. return false;
  586. }
  587. RequestEventPtr item = CreateRequestEvent(EVTCODE_SCAN);
  588. if(!item) {
  589. m_dwErrCode = ERROR_RESOURCE_FAILED;
  590. return false;
  591. }
  592. item->evtData = (CHAR*)malloc(sizeof(char)*(len+1));
  593. if(item->evtData == NULL) {
  594. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("malloc failed");
  595. m_dwErrCode = ERROR_RESOURCE_FAILED;
  596. delete item;
  597. return false;
  598. }
  599. memset(item->evtData, 0, sizeof(char)*(len+1));
  600. strcpy_s(item->evtData, sizeof(char)*(len+1), szFileName);
  601. item->dwDataLen = len+1;
  602. PostIntoRequestQueue(&item);
  603. int nRes = WaitForResponse(EVTCODE_SCAN, 30*1000);
  604. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("WaitForResponse returned: 0x%02x", nRes);
  605. if(nRes >= EVTSTATUS_ERROR_MASK) {
  606. }
  607. else if(nRes == EVTSTATUS_DONE_SUCC) {
  608. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Scan succ: %d[%s]", ExistsFileA(szFileName), szFileName);
  609. }
  610. return true;
  611. }
  612. bool CDocScannerCap::CloseCamera()
  613. {
  614. _cleanup();
  615. m_dwErrCode = ERROR_SUCCESS;
  616. return true;
  617. }
  618. bool CDocScannerCap::StartPreview()
  619. {
  620. if(!_isVal()){
  621. m_dwErrCode = ERROR_INVALID_ENVIRONMENT;
  622. return false;
  623. }
  624. if(m_fPreviewing) {
  625. m_dwErrCode = SCHED_E_ALREADY_RUNNING;
  626. return false;
  627. }
  628. m_hPreviewPro = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
  629. CDocScannerCap::WndPreviewDlgProc, this,
  630. CREATE_SUSPENDED,
  631. NULL));
  632. if(m_hPreviewPro == NULL || m_hPreviewPro == INVALID_HANDLE_VALUE)
  633. {
  634. m_hPreviewPro = NULL;
  635. m_dwErrCode = E_HANDLE;
  636. return false;
  637. }
  638. m_fPreviewing = true;
  639. if(ResumeThread(m_hPreviewPro) == (DWORD)-1) {
  640. m_dwErrCode = E_UNEXPECTED;
  641. m_fPreviewing = false;
  642. CloseHandle(m_hPreviewPro);
  643. m_hPreviewPro = NULL;
  644. return false;
  645. }
  646. m_dwErrCode = ERROR_SUCCESS;
  647. return true;
  648. }
  649. bool CDocScannerCap::TerminatePreview()
  650. {
  651. m_dwErrCode = ERROR_SUCCESS;
  652. if(m_fPreviewing) {
  653. m_dwErrCode = E_UNEXPECTED;
  654. m_tpStopPreview = true;
  655. //30 seconds to timeout?
  656. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Set StopPreivew flag true, waitting...");
  657. DWORD dwResult = WaitForSingleObject(m_hPreviewPro, 30 * 1000);
  658. if(dwResult == WAIT_OBJECT_0) {
  659. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Wait succ.");
  660. CloseHandle(m_hPreviewPro);
  661. m_hPreviewPro = NULL;
  662. m_dwErrCode = ERROR_SUCCESS;
  663. return true;
  664. }else if(dwResult == WAIT_TIMEOUT) {
  665. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Wait succ timeout: %d", m_fPreviewing);
  666. if(!m_fPreviewing) {
  667. CloseHandle(m_hPreviewPro);
  668. m_hPreviewPro = NULL;
  669. m_dwErrCode = ERROR_SUCCESS;
  670. return true;
  671. }
  672. m_dwErrCode = WAIT_TIMEOUT;
  673. }
  674. else {
  675. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("WaitForSingleObject failed returned: %u.", dwResult);
  676. m_dwErrCode = dwResult;
  677. }
  678. }
  679. return (m_dwErrCode == ERROR_SUCCESS);
  680. }
  681. bool CDocScannerCap::_initWindow(bool fShown)
  682. {
  683. if(m_defWnd) {
  684. _destroyWindow();
  685. }
  686. //TODO: Identify the window name to unique.
  687. DWORD wdFlags = WINDOW_NORMAL;
  688. namedWindow(winName, wdFlags);
  689. m_defWnd = FindWindow(NULL, winName.c_str());
  690. if(m_defWnd == NULL) {
  691. destroyWindow(winName);
  692. m_dwErrCode = ERROR_INVALID_WINDOW_HANDLE;
  693. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("Find %s window handle faiiled, GLE=%u", winName.c_str(), GetLastError());
  694. return false;
  695. }
  696. DWORD dwFlag = fShown ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  697. BOOL bRet = ::SetWindowPos(m_defWnd, HWND_TOPMOST,
  698. m_winSize.x, m_winSize.y, m_winSize.width, m_winSize.height, dwFlag);
  699. if(bRet) { m_bHide = !fShown; }
  700. m_dwErrCode = ERROR_SUCCESS;
  701. rectStatus = NOT_SET;
  702. return true;
  703. }
  704. void CDocScannerCap::_destroyWindow()
  705. {
  706. LOG_FUNCTION();
  707. if(!m_cmFrame.empty()) {
  708. m_cmFrame.release();
  709. }
  710. if(m_defWnd) {
  711. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("before destroyWindow with %s", winName.c_str());
  712. destroyWindow(winName);
  713. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("after destroyWindow with %s", winName.c_str());
  714. m_defWnd = NULL;
  715. m_bHide = FALSE;
  716. }
  717. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("before destroyAllWindow");
  718. destroyAllWindows();
  719. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("after destroyAllWindow");
  720. return;
  721. }
  722. size_t CDocScannerCap::_combineFileName(char* szFnBuf, size_t sizeLen)
  723. {
  724. if(sizeLen == 0 || szFnBuf == NULL) {
  725. return 0;
  726. }
  727. memset(szFnBuf, 0, sizeof(char)*sizeLen);
  728. SYSTEMTIME st;
  729. GetLocalTime(&st);
  730. sprintf_s(szFnBuf, sizeLen, "%04d%02d%02d%02d%02d%02d.jpg", st.wYear, st.wMonth, st.wDay,
  731. st.wHour, st.wMinute, st.wSecond);
  732. return strlen(szFnBuf);
  733. }
  734. UINT WINAPI CDocScannerCap::WndPreviewDlgProc(PVOID param)
  735. {
  736. CDocScannerCap *pCap = reinterpret_cast<CDocScannerCap*>(param);
  737. if(pCap == NULL) {
  738. return UINT(-1);
  739. }
  740. return (UINT)(pCap->_executePreview());
  741. }
  742. void CDocScannerCap::EvtFinishedHandle(USHORT evtCode, UCHAR result, UINT checksum)
  743. {
  744. }
  745. void CDocScannerCap::SetResoultionRatio(int width, int height, int nframes /*= -1*/)
  746. {
  747. // DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("before: width=%d, height=%d , nframes=%d", (int)m_cvCap.get(CAP_PROP_FRAME_WIDTH),
  748. // (int)m_cvCap.get(CAP_PROP_FRAME_HEIGHT), (int)m_cvCap.get(CAP_PROP_FRAME_COUNT));
  749. m_cvCap.set(CV_CAP_PROP_FRAME_WIDTH, width);
  750. m_cvCap.set(CV_CAP_PROP_FRAME_HEIGHT, height);
  751. // DDbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)g("after: width=%d, height=%d , nframes=%d", (int)m_cvCap.get(CAP_PROP_FRAME_WIDTH),
  752. // (int)m_cvCap.get(CAP_PROP_FRAME_HEIGHT), (int)m_cvCap.get(CAP_PROP_FRAME_COUNT));
  753. }
  754. void CDocScannerCap::_setMouseCallback()
  755. {
  756. cvSetMouseCallback(winName.c_str(), OnMouseTrace, this);
  757. }
  758. void CDocScannerCap::MouseClick(int event, int x, int y, int flags)
  759. {
  760. //static Rect origin;
  761. if(event == CV_EVENT_LBUTTONDOWN) {
  762. rectStatus = IN_PROCESS;
  763. rect = Rect(x, y, 0, 0);
  764. } else if(event == CV_EVENT_MOUSEMOVE) {
  765. if(rectStatus == IN_PROCESS) {
  766. rect = Rect(Point(rect.x, rect.y), Point(x,y));
  767. }
  768. }else if(event == CV_EVENT_LBUTTONUP) {
  769. if(rectStatus == IN_PROCESS) {
  770. if(rect.height == 0 || rect.width == 0) {
  771. rectStatus = NOT_SET;
  772. return;
  773. }
  774. rect = Rect(Point(rect.x, rect.y), Point(x,y));
  775. rectStatus = SET;
  776. }
  777. }
  778. }
  779. void CDocScannerCap::_setResizeArea(float ratio)
  780. {
  781. Rect area((1-ratio)/2*m_cmFrame.cols, (1-ratio)/2*m_cmFrame.rows, ratio*m_cmFrame.cols, ratio*m_cmFrame.rows);
  782. Mat roi = m_cmFrame(area);
  783. Mat res;
  784. res.create(roi.rows, roi.cols, m_cmFrame.type());
  785. roi.copyTo(res);
  786. m_cmFrame.release();
  787. m_cmFrame = res;
  788. }
  789. void CDocScannerCap::_setInterestArea()
  790. {
  791. if(rectStatus == IN_PROCESS || rectStatus == SET) {
  792. Rect area(rect);
  793. int suffix_x = rect.x - drawableRect.x;
  794. int suffix_y = rect.y - drawableRect.y;
  795. area.x = suffix_x > 0 ? rect.x : drawableRect.x;
  796. area.y = suffix_y > 0 ? rect.y : drawableRect.y;
  797. suffix_x = suffix_x > 0 ? suffix_x : 0;
  798. suffix_y = suffix_y > 0 ? suffix_y : 0;
  799. area.width = min(rect.width, drawableRect.width-suffix_x-rectangle_thickness);
  800. area.height = min(rect.height, drawableRect.height-suffix_y-rectangle_thickness);
  801. rectangle(m_cmFrame, Point(area.x, area.y),
  802. Point(area.x + area.width, area.y + area.height),
  803. GREEN, rectangle_thickness);
  804. assert(m_cmFrame.data);
  805. const CvScalar colorMask = cvScalarAll(-52);
  806. Mat res = Mat::ones(m_cmFrame.size(), CV_8UC1)*255;
  807. res(area).setTo(0);
  808. cv::add(m_cmFrame, (const cv::Scalar&)colorMask, m_cmFrame, res, m_cmFrame.type());
  809. rect = area;
  810. }
  811. }
  812. bool CDocScannerCap::_executePreview()
  813. {
  814. _initWindow(true);
  815. m_tpStopPreview = false;
  816. _setMouseCallback();
  817. if (GetWindowLong(m_defWnd, GWL_STYLE) & WS_POPUP) {
  818. SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
  819. }
  820. int eOccurTimes = 0, eClosedTimes = 0;
  821. DWORD dwEStartTick = 0;
  822. char szFileName[MAX_PATH] = {0};
  823. for(;;)
  824. {
  825. m_cvCap >> m_cmFrame;
  826. if(!m_cmFrame.data) {
  827. continue;
  828. }
  829. Mat gray = m_cmFrame.clone();
  830. cvtColor(m_cmFrame, gray, CV_BGR2GRAY);
  831. if(IsColorAbnormal(&IplImage(gray))) {
  832. IplImage* inner = &IplImage(gray);
  833. int B = CV_IMAGE_ELEM(inner, unsigned char, inner->height/2, (inner->width/2)*3+0);
  834. int G = CV_IMAGE_ELEM(inner, unsigned char, inner->height/2, (inner->width/2)*3+1);
  835. int R = CV_IMAGE_ELEM(inner, unsigned char, inner->height/2, (inner->width/2)*3+2);
  836. if(B == G && G == R && R == 205) {
  837. if(eOccurTimes == 0) {
  838. eOccurTimes++;
  839. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Wow! the scanner has problem");
  840. dwEStartTick = GetTickCount();
  841. }else if(eOccurTimes != -1) {
  842. eOccurTimes++;
  843. if(eOccurTimes >= ERROR_CONTINUE_TIMES
  844. || GetTickCount() > dwEStartTick + ERROR_CONTINUE_MILLSEC) {
  845. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Send Reset Event !! %d", eOccurTimes);
  846. eOccurTimes = -1;
  847. SetResetEvent();
  848. }
  849. }
  850. }else if(eOccurTimes != 0){
  851. eOccurTimes = 0;
  852. }
  853. if(B == G && G == R && B == 0) {
  854. if(eClosedTimes == 0) {
  855. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Eh, maybe forget to scratch the scanner");
  856. eClosedTimes = 1;
  857. }
  858. }else if(eClosedTimes != 0){
  859. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Ok, you achieve it");
  860. eClosedTimes = 0;
  861. }
  862. } else {
  863. if(eOccurTimes != 0 && eOccurTimes != -1) {
  864. eOccurTimes = 0;
  865. }
  866. if(eClosedTimes != 0){
  867. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Ok, you achieve it");
  868. eClosedTimes = 0;
  869. }
  870. }
  871. gray.release();
  872. if(m_roiMode != ROI_DEFAULT && m_bHSPSType) {
  873. _setResizeArea(m_roiRate);
  874. }
  875. if(m_colorMode == GRAY) {
  876. cvtColor(m_cmFrame, m_cmFrame, CV_BGR2GRAY);
  877. }
  878. Mat origin = m_cmFrame.clone();
  879. int cols = 0, rows = 0;
  880. {//填充边框以适应宽度
  881. Size origin_size = m_cmFrame.size();
  882. if(1.0*m_winSize.width / m_winSize.height > 1) {
  883. int aimWidth = (int)(1.0*origin_size.height*(1.0*m_winSize.width / m_winSize.height));
  884. if(aimWidth > origin_size.width) {
  885. cols = (aimWidth-origin_size.width) / 2;
  886. }else if(aimWidth < origin_size.width) {
  887. int aimHeigth = (int)(1.0*origin_size.width*(1.0*m_winSize.height / m_winSize.width));
  888. assert(aimHeigth >= origin_size.height);
  889. rows = (aimHeigth-origin_size.height) / 2;
  890. }
  891. }else if(1.0*m_winSize.width / m_winSize.height < 1) {
  892. int aimHeigth = (int)(1.0*origin_size.width*(1.0*m_winSize.height / m_winSize.width));
  893. if(aimHeigth > origin_size.height) {
  894. rows = (aimHeigth-origin_size.height) / 2;
  895. }else if(aimHeigth < origin_size.height) {
  896. int aimWidth = (int)(1.0*origin_size.height*(1.0*m_winSize.width / m_winSize.height));
  897. assert(aimWidth >= origin_size.width);
  898. cols = (aimWidth-origin_size.width) / 2;
  899. }
  900. }
  901. }
  902. if(cols > 0 || rows > 0) {
  903. copyMakeBorder(m_cmFrame, m_cmFrame, rows, rows, cols, cols, BORDER_CONSTANT, BLACK);
  904. }
  905. drawableRect.x = cols;
  906. drawableRect.width = origin.cols;
  907. drawableRect.y = rows;
  908. drawableRect.height = origin.rows;
  909. Mat picture = m_cmFrame.clone();
  910. _setInterestArea();
  911. imshow(winName, m_cmFrame);
  912. char keyCode = cvWaitKey(WAITKEY_TIME);
  913. //if(keyCode == 27) {
  914. // DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("ESC key press event recv.");
  915. // break;
  916. //}
  917. RequestEventPtr evtPtr = GetRequest();
  918. if(evtPtr) {
  919. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("0x%02x event recv.", evtPtr->evtCode);
  920. switch(evtPtr->evtCode)
  921. {
  922. case EVTCODE_SCAN:
  923. {
  924. assert(evtPtr->valType == RequestEvent::ReqLen);
  925. assert(evtPtr->dwDataLen > 0 && evtPtr->evtData);
  926. char szFileName[MAX_PATH+1] = {0};
  927. memcpy_s(szFileName, MAX_PATH*sizeof(char),
  928. evtPtr->evtData, sizeof(char)*evtPtr->dwDataLen);
  929. try
  930. {
  931. cv::Mat testMat;
  932. if(rectStatus == SET && (rect.width != 0 && rect.height != 0)) {
  933. Mat result(picture, rect);
  934. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ScanImage@1: %s %d", szFileName, result.size());
  935. testMat = result.clone();
  936. } else {
  937. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ScanImage@2: %s %d", szFileName, origin.size());
  938. testMat = origin.clone();
  939. }
  940. ImageWriteUntil(szFileName, testMat);
  941. evtPtr->evtStatus = EVTSTATUS_DONE_SUCC;
  942. }
  943. catch(cv::Exception& ex)
  944. {
  945. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("exception converting image to jpeg: %s", ex.what());
  946. evtPtr->evtStatus = EVTSTATUS_DONE_FAIL;
  947. }
  948. evtPtr->OnAnswer();
  949. }
  950. break;
  951. default:
  952. {
  953. }
  954. break;
  955. }
  956. }
  957. if(m_tpStopPreview) {
  958. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Stop previewing event recv.");
  959. break;
  960. }
  961. }
  962. SetThreadExecutionState(ES_CONTINUOUS);
  963. _destroyWindow();
  964. m_fPreviewing = false;
  965. return true;
  966. }
  967. int CDocScannerCap::GetSpecificedCamInfor(const int camID, PCAMERA_INFOR_ITEM info)
  968. {
  969. if(info == NULL) {
  970. return -2;
  971. }
  972. info->Cleanup();
  973. ICreateDevEnum *pSysDevEnum = NULL;
  974. HRESULT hr = CoCreateInstance(
  975. CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  976. IID_ICreateDevEnum, (void **)&pSysDevEnum);
  977. if (FAILED(hr)) {
  978. return -1;
  979. }
  980. BOOL done = false;
  981. int deviceCounter = 0;
  982. // Obtain a class enumerator for the video input category.
  983. IEnumMoniker *pEnumCat = NULL;
  984. hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
  985. if (hr == S_OK) {
  986. // Enumerate the monikers.
  987. IMoniker *pMoniker = NULL;
  988. ULONG cFetched;
  989. while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (!done)) {
  990. if(deviceCounter == camID) {
  991. // Bind the first moniker to an object
  992. IPropertyBag *pPropBag;
  993. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
  994. if (SUCCEEDED(hr)) {
  995. // To retrieve the filter's friendly name, do the following:
  996. VARIANT varName;
  997. VariantInit(&varName);
  998. hr = pPropBag->Read(L"Description", &varName, 0);
  999. if (FAILED(hr)) {
  1000. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  1001. }
  1002. if (SUCCEEDED(hr)) {
  1003. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  1004. int maxLen = sizeof(info->szDevName) - 2;
  1005. int nLen = WrapW2A(varName, &(info->szDevName[0]), maxLen);
  1006. VariantClear(&varName);
  1007. }
  1008. VARIANT varCLSID;
  1009. VariantInit(&varCLSID);
  1010. hr = pPropBag->Read(L"CLSID", &varCLSID, 0);
  1011. if (SUCCEEDED(hr)) {
  1012. int maxLen = sizeof(info->szCLSID) - 2;
  1013. int nLen = WrapW2A(varCLSID, &(info->szCLSID[0]), maxLen);
  1014. VariantClear(&varCLSID);
  1015. }
  1016. VARIANT varDevPath;
  1017. VariantInit(&varDevPath);
  1018. hr = pPropBag->Read(L"DevicePath", &varDevPath, 0);
  1019. if (SUCCEEDED(hr)) {
  1020. int maxLen = sizeof(info->szDevPath) - 2;
  1021. int nLen = WrapW2A(varDevPath, &(info->szDevPath[0]), maxLen);
  1022. VariantClear(&varDevPath);
  1023. }
  1024. VARIANT varWaveID;
  1025. VariantInit(&varWaveID);
  1026. hr = pPropBag->Read(L"WaveInID", &varWaveID, 0);
  1027. if (SUCCEEDED(hr)) {
  1028. info->uWaveInID = varWaveID.lVal;
  1029. VariantClear(&varWaveID);
  1030. }
  1031. pPropBag->Release();
  1032. pPropBag = NULL;
  1033. pMoniker->Release();
  1034. pMoniker = NULL;
  1035. done = TRUE;
  1036. }
  1037. }
  1038. deviceCounter++;
  1039. }
  1040. pEnumCat->Release();
  1041. pEnumCat = NULL;
  1042. }
  1043. pSysDevEnum->Release();
  1044. pSysDevEnum = NULL;
  1045. if (done) {
  1046. return 1;
  1047. }
  1048. return 0;
  1049. }
  1050. int CDocScannerCap::_getCamIDByDevName(LPCTSTR lpcszDevName)
  1051. {
  1052. if (lpcszDevName == NULL || strlen(lpcszDevName) == 0) {
  1053. return -2;
  1054. }
  1055. ICreateDevEnum *pDevEnum = NULL;
  1056. IEnumMoniker *pEnum = NULL;
  1057. int deviceCounter = 0;
  1058. int aimID = -1;
  1059. bool done = false;
  1060. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  1061. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
  1062. reinterpret_cast<void**>(&pDevEnum));
  1063. if (SUCCEEDED(hr)) {
  1064. // Create an enumerator for the video capture category.
  1065. hr = pDevEnum->CreateClassEnumerator(
  1066. CLSID_VideoInputDeviceCategory,
  1067. &pEnum, 0);
  1068. if(hr == S_OK) {
  1069. IMoniker *pMoniker = NULL;
  1070. while (pEnum->Next(1, &pMoniker, NULL) == S_OK && (!done)) {
  1071. IPropertyBag *pPropBag;
  1072. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
  1073. (void**)(&pPropBag));
  1074. if (FAILED(hr)){
  1075. pMoniker->Release();
  1076. continue; // Skip this one, maybe the next one will work.
  1077. }
  1078. // Find the description or friendly name.
  1079. VARIANT varName;
  1080. VariantInit(&varName);
  1081. hr = pPropBag->Read(L"Description", &varName, 0);
  1082. if (FAILED(hr)) hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  1083. if (SUCCEEDED(hr)){
  1084. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  1085. char szDevName[MAX_PATH + 2] = {0};
  1086. int count = 0;
  1087. WrapW2A(varName, szDevName, MAX_PATH);
  1088. if(strcmp(szDevName, lpcszDevName) == 0) {
  1089. done = true;
  1090. aimID = deviceCounter;
  1091. }
  1092. }
  1093. pPropBag->Release();
  1094. pPropBag = NULL;
  1095. pMoniker->Release();
  1096. pMoniker = NULL;
  1097. deviceCounter++;
  1098. }
  1099. pDevEnum->Release();
  1100. pDevEnum = NULL;
  1101. pEnum->Release();
  1102. pEnum = NULL;
  1103. }
  1104. }
  1105. return aimID;
  1106. }
  1107. bool CDocScannerCap::IsColorAbnormal(IplImage* src)
  1108. {
  1109. const int threshold = 3;
  1110. const int width = src->width;
  1111. const int height = src->height;
  1112. int imax = 0, imin = 255;
  1113. uchar *content = (uchar*)src->imageData;
  1114. int step = src->widthStep/sizeof(uchar);
  1115. for (int i=0; i<height; ++i) {
  1116. for(int j=0; j<width; ++j) {
  1117. int term = (int)content[i*step+j];
  1118. if(term > imax) {
  1119. imax = term;
  1120. }
  1121. if(term < imin) {
  1122. imin = term;
  1123. }
  1124. }
  1125. }
  1126. if(imax - imin < threshold) {
  1127. return true;
  1128. }
  1129. return false;
  1130. }
  1131. bool CDocScannerCap::IsFrameFuzzy(IplImage* data)
  1132. {
  1133. //图片每行字节数及高
  1134. int width=data->widthStep;
  1135. int height=data->height;
  1136. ushort* sobelTable = new ushort[width*height];
  1137. memset(sobelTable, 0, width*height*sizeof(ushort));
  1138. int i, j, mul;
  1139. //指向图像首地址
  1140. uchar* udata = (uchar*)data->imageData;
  1141. for(i = 1, mul = i*width; i < height - 1; i++, mul += width) {
  1142. for(j = 1; j < width - 1; j++) {
  1143. sobelTable[mul+j]=abs(udata[mul+j-width-1] + 2*udata[mul+j-1] + udata[mul+j-1+width] -\
  1144. udata[mul+j+1-width] - 2*udata[mul+j+1] - udata[mul+j+width+1]);
  1145. }
  1146. }
  1147. for(i = 1, mul = i*width; i < height - 1; i++, mul += width) {
  1148. for(j = 1; j < width - 1; j++) {
  1149. if(sobelTable[mul+j] < 50 || sobelTable[mul+j] <= sobelTable[mul+j-1] ||\
  1150. sobelTable[mul+j] <= sobelTable[mul+j+1]) sobelTable[mul+j] = 0;
  1151. }
  1152. }
  1153. int totLen = 0;
  1154. int totCount = 1;
  1155. uchar suddenThre = 50;
  1156. uchar sameThre = 3;
  1157. //遍历图片
  1158. for(i = 1, mul = i*width; i < height - 1; i++, mul += width) {
  1159. for(j = 1; j < width - 1; j++) {
  1160. if(sobelTable[mul+j]) {
  1161. int count = 0;
  1162. uchar tmpThre = 5;
  1163. uchar max = udata[mul+j] > udata[mul+j-1] ? 0 : 1;
  1164. for(int t = j; t > 0; t--) {
  1165. count++;
  1166. if(abs(udata[mul+t] - udata[mul+t-1]) > suddenThre) {
  1167. break;
  1168. }
  1169. if(max && udata[mul+t] > udata[mul+t-1]) {
  1170. break;
  1171. }
  1172. if(!max && udata[mul+t] < udata[mul+t-1]) {
  1173. break;
  1174. }
  1175. int tmp = 0;
  1176. for(int s = t; s > 0; s--) {
  1177. if(abs(udata[mul+t] - udata[mul+s]) < sameThre) {
  1178. tmp++;
  1179. if(tmp > tmpThre) {
  1180. break;
  1181. }
  1182. }
  1183. else {
  1184. break;
  1185. }
  1186. }
  1187. if(tmp > tmpThre) break;
  1188. }
  1189. max = udata[mul+j] > udata[mul+j+1] ? 0 : 1;
  1190. for(int t = j; t < width; t++) {
  1191. count++;
  1192. if(abs(udata[mul+t] - udata[mul+t+1]) > suddenThre) {
  1193. break;
  1194. }
  1195. if(max && udata[mul+t] > udata[mul+t+1]) {
  1196. break;
  1197. }
  1198. if(!max && udata[mul+t] < udata[mul+t+1]) {
  1199. break;
  1200. }
  1201. int tmp = 0;
  1202. for(int s = t; s < width; s++) {
  1203. if(abs(udata[mul+t] - udata[mul+s]) < sameThre) {
  1204. tmp++;
  1205. if(tmp > tmpThre) {
  1206. break;
  1207. }
  1208. }
  1209. else {
  1210. break;
  1211. }
  1212. }
  1213. if(tmp > tmpThre) {
  1214. break;
  1215. }
  1216. }
  1217. max = udata[mul+j] > udata[mul+j+1] ? 0 : 1;
  1218. for(int t = j; t < width; t++) {
  1219. count++;
  1220. if(abs(udata[mul+t] - udata[mul+t+1]) > suddenThre) {
  1221. break;
  1222. }
  1223. if(max && udata[mul+t] > udata[mul+t+1]) {
  1224. break;
  1225. }
  1226. if(!max && udata[mul+t] < udata[mul+t+1]) {
  1227. break;
  1228. }
  1229. int tmp = 0;
  1230. for(int s = t; s < width; s++) {
  1231. if(abs(udata[mul+t] - udata[mul+s]) < sameThre) {
  1232. tmp++;
  1233. if(tmp > tmpThre) {
  1234. break;
  1235. }
  1236. }
  1237. else {
  1238. break;
  1239. }
  1240. }
  1241. if(tmp > tmpThre) {
  1242. break;
  1243. }
  1244. }
  1245. count--;
  1246. totCount++;
  1247. totLen += count;
  1248. }
  1249. }
  1250. }
  1251. //模糊度
  1252. float result = (float)totLen/totCount;
  1253. delete[] sobelTable;
  1254. if(result > 5) {
  1255. return true;
  1256. }
  1257. return false;
  1258. }
  1259. bool CDocScannerCap::ResetCamera()
  1260. {
  1261. if(!_isVal() && m_videoID == -1) {
  1262. return true;
  1263. }
  1264. bool fPreview = m_fPreviewing;
  1265. BOOL bHide = m_bHide;
  1266. if(m_fPreviewing) {
  1267. TerminatePreview();
  1268. do {
  1269. Sleep(100);
  1270. } while (m_fPreviewing);
  1271. }
  1272. if(m_cvCap.isOpened()) {
  1273. m_cvCap.release();
  1274. }
  1275. CAMERA_INFOR_ITEM item;
  1276. if(GetSpecificedCamInfor(m_videoID, &item) <= 0) {
  1277. m_dwErrCode = ERROR_FILE_NOT_FOUND;
  1278. _cleanup();
  1279. return true;
  1280. }
  1281. int nRes = IsDeviceBusy(item.szDevName);
  1282. if(nRes) {
  1283. if(nRes == -2) {
  1284. m_dwErrCode = ERROR_INVALID_ACCESS;
  1285. } else if(nRes == -1) {
  1286. m_dwErrCode = ERROR_FILE_NOT_FOUND;
  1287. } else if(nRes == 1) {
  1288. m_dwErrCode = ERROR_DEVICE_IN_USE;
  1289. } else {
  1290. m_dwErrCode = ERROR_BAD_ENVIRONMENT;
  1291. }
  1292. _cleanup();
  1293. return true;
  1294. }
  1295. m_cvCap.open(m_videoID);
  1296. if(!m_cvCap.isOpened()) {
  1297. _cleanup();
  1298. return false;
  1299. }
  1300. _destroyWindow();
  1301. winName = cv::String(DEFAULT_MAT_WINDOW_NAME) + "-" + item.szDevName;
  1302. _setDevName(item.szDevName);
  1303. m_dwErrCode = ERROR_SUCCESS;
  1304. //SetWinShown(m_hideMode != 0 ? false : true);
  1305. if(fPreview && !StartPreview()) {
  1306. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("StartPreview failed");
  1307. return true;
  1308. }else if(fPreview && bHide) {
  1309. SetWinShown(false);
  1310. }
  1311. return true;
  1312. }
  1313. int CDocScannerCap::MatResize(const cv::Mat& src, cv::Mat& dest, int quantity)
  1314. {
  1315. const int aim_size = 1*1024*1024;
  1316. std::vector<int> params;
  1317. params.push_back(cv::IMWRITE_JPEG_QUALITY);
  1318. params.push_back(quantity);
  1319. std::vector<unsigned char> buff;
  1320. cv::imencode(".jpg", src, buff, params);
  1321. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("after buffer: size: %d, with quantity: %d", buff.size(), quantity);
  1322. dest = cv::imdecode(buff, CV_LOAD_IMAGE_COLOR);
  1323. if(buff.size() > aim_size)
  1324. return (int)(aim_size * 1.2f / buff.size() * 100);
  1325. return 0;
  1326. }
  1327. DWORD CDocScannerCap::GetFileSize(LPCTSTR srcFilePath)
  1328. {
  1329. FILE* fHandle = fopen(srcFilePath, "rb");
  1330. if(!fHandle)
  1331. return -1;
  1332. fseek(fHandle, 0, SEEK_END);
  1333. DWORD fileSize = ftell(fHandle);
  1334. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("get the file size: %lu", fileSize);
  1335. fclose(fHandle);
  1336. return fileSize;
  1337. }
  1338. int CDocScannerCap::ImageWriteUntil(LPCTSTR srcFilePath, const cv::Mat& src)
  1339. {
  1340. const int aim_size = 1*1024*1024;
  1341. int compatRates[] = {95, 90, 85, 80, 70, 60, 50, 40, 30, 20, 15};
  1342. for(int i=0; i<sizeof(compatRates)/sizeof(compatRates[0]); ++i)
  1343. {
  1344. const int compatRate = compatRates[i];
  1345. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("set compress rate: %d", compatRate);
  1346. vector<int> comprressionParams;
  1347. comprressionParams.push_back(CV_IMWRITE_JPEG_QUALITY);
  1348. comprressionParams.push_back(compatRate);
  1349. try
  1350. {
  1351. imwrite(srcFilePath, src, comprressionParams);
  1352. } catch(cv::Exception& ex)
  1353. {
  1354. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("exception converting image to jpeg: %s", ex.what());
  1355. return -1;
  1356. }
  1357. Sleep(50);
  1358. const auto fileSize = GetFileSize(srcFilePath);
  1359. if(fileSize == (DWORD)-1)
  1360. return -1;
  1361. if(fileSize <= aim_size)
  1362. return 0;
  1363. }
  1364. return 1;
  1365. }
  1366. int CDocScannerCap::Resize(LPCTSTR srcFilePath, DWORD dwSrcFileSize, int compressRate)
  1367. {
  1368. const int aim_size = 1*1024*1024;
  1369. if(dwSrcFileSize == -1 || aim_size >= dwSrcFileSize)
  1370. return 0;
  1371. cv::Mat src = cv::imread(srcFilePath);
  1372. if(src.empty())
  1373. return -1;
  1374. float rate = sqrt(aim_size * 1.0f / dwSrcFileSize);
  1375. int width = static_cast<int>(src.cols*rate);
  1376. int height = static_cast<int>(src.rows*rate);
  1377. cv::Mat dest;
  1378. resize(src, dest, cv::Size(width, height));
  1379. vector<int> comprressionParams;
  1380. comprressionParams.push_back(CV_IMWRITE_JPEG_QUALITY);
  1381. comprressionParams.push_back(compressRate);
  1382. imwrite(srcFilePath, dest, comprressionParams);
  1383. FILE* fHandle = fopen(srcFilePath, "rb");
  1384. fseek(fHandle, 0, SEEK_END);
  1385. long fileSize = ftell(fHandle);
  1386. fclose(fHandle);
  1387. return 1;
  1388. }
  1389. LRESULT CALLBACK CameraNotifierProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1390. {
  1391. if (message == WM_DEVICECHANGE) {
  1392. if (DBT_DEVICEARRIVAL != wParam && DBT_DEVICEREMOVECOMPLETE != wParam) {
  1393. return TRUE;
  1394. }
  1395. PDEV_BROADCAST_HDR pdbh = (PDEV_BROADCAST_HDR)lParam;
  1396. if (pdbh->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) {
  1397. return TRUE;
  1398. }
  1399. PDEV_BROADCAST_DEVICEINTERFACE pdbi = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
  1400. if (pdbi->dbcc_classguid == AM_KSCATEGORY_VIDEO) {
  1401. if (DBT_DEVICEARRIVAL == wParam) {
  1402. printf("receive AM_KSCATEGORY_VIDEO change add \n");
  1403. } else if (DBT_DEVICEREMOVECOMPLETE == wParam) {
  1404. printf("receive AM_KSCATEGORY_VIDEO change remove \n");
  1405. }
  1406. }
  1407. return TRUE;
  1408. }
  1409. return DefWindowProc(hWnd, message, wParam, lParam);
  1410. }
  1411. void OnMouseTrace(int event, int x, int y, int flags, void* param /*= NULL*/)
  1412. {
  1413. CDocScannerCap* pCap = reinterpret_cast<CDocScannerCap*>(param);
  1414. if(pCap == NULL) {
  1415. return;
  1416. }
  1417. pCap->MouseClick(event, x, y, flags);
  1418. }