#include "StdAfx.h" #include "SeparateThreadTwainFeeder.h" CSeparateThreadTwainFeeder::CSeparateThreadTwainFeeder(void) :m_current_task_type(STTF_TASK_TYPE_DEFAULT) ,m_connect_task_excute_state(STTF_TASK_EXCUTE_STATE_NOTSTART) ,m_hWnd(NULL) { InitializeCriticalSection(&m_lock); m_img =NULL; } CSeparateThreadTwainFeeder::~CSeparateThreadTwainFeeder(void) { DeleteCriticalSection(&m_lock); } ServiceState CSeparateThreadTwainFeeder::OnStarting( void ) { EnterCriticalSection(&m_lock); if(m_current_task_type == STTF_TASK_TYPE_CONNECT){//扫描仪连接任务 while(m_current_connect_task_count>0){ int nId = m_current_connect_task[m_current_connect_task_first]; LeaveCriticalSection(&m_lock); if(GetDSMState()>3&&nId != getDataSource()->Id){ unloadDS(); loadDS(nId); } if(GetDSMState()<3){ connectDSM(); } if(GetDSMState()<4){ loadDS(nId); } if(m_hWnd!=NULL)PostMessage(m_hWnd,WM_IDENTIFOR_SANNER_CONNECT,nId,GetDSMState()>=4?TRUE:FALSE); EnterCriticalSection(&m_lock); m_current_connect_task_first =(m_current_connect_task_first+1)%MAX_CONNET_TASK_COUNT; m_current_connect_task_count--; if(m_current_connect_task_count==0) { m_connect_task_excute_state = STTF_TASK_EXCUTE_STATE_STOPING; LeaveCriticalSection(&m_lock); return stoping; } } } LeaveCriticalSection(&m_lock); m_img = NULL; pTW_IDENTITY pID = getDataSource(); if(pID==NULL||pID->Id != m_scanner_index){ if(GetDSMState()>4){ disableDS(); } if(GetDSMState()>3){ unloadDS(); } if(GetDSMState()<3){ connectDSM(); } loadDS(m_scanner_index); } TwainApp::enableDS(NULL,FALSE); if(GetDSMState()<=4){ if(m_hwnd != NULL){ IDENTIFOR_ERROR_MSG* msg =new IDENTIFOR_ERROR_MSG; msg->type=1; strcpy(msg->msg,"无法连接到扫描仪,请检测是否连接到扫描仪并打开电源开关."); PostMessage(m_hwnd,WM_IDENTIFOR_ERROR,(WPARAM)msg,0); } return stoping; } int ret =WaitCommand(); if(ret==0) return running; return stoping; } ServiceState CSeparateThreadTwainFeeder::OnRunning( void ) { StartScan(); return stoping; } ServiceState CSeparateThreadTwainFeeder::OnStoping( void ) { EnterCriticalSection(&m_lock); if(m_current_task_type == STTF_TASK_TYPE_CONNECT){ m_connect_task_excute_state = STTF_TASK_EXCUTE_STATE_STOPED; m_current_task_type = STTF_TASK_TYPE_DEFAULT; LeaveCriticalSection(&m_lock); return IService::OnStoping(); } LeaveCriticalSection(&m_lock); m_DSMessage = (TW_UINT16)-1; TwainApp::disableDS(); TwainApp::unloadDS(); return IService::OnStoping(); } /************************************************************************/ /* 等待扫描仪命令 */ /************************************************************************/ int CSeparateThreadTwainFeeder::WaitCommand() { while((TW_UINT16)-1 == m_DSMessage) { MSG Msg; if(!PeekMessage((LPMSG)&Msg, NULL, 0, 0,PM_REMOVE)) { Sleep(1); continue; } if (Msg.message == WM_QUIT) break ; TW_EVENT twEvent = {0}; twEvent.pEvent = (TW_MEMREF)&Msg; twEvent.TWMessage = MSG_NULL; TW_UINT16 twRC = TWRC_NOTDSEVENT; twRC = _DSM_Entry( getAppIdentity(),m_pDataSource,DG_CONTROL,DAT_EVENT, MSG_PROCESSEVENT,(TW_MEMREF)&twEvent); if(!gUSE_CALLBACKS && twRC==TWRC_DSEVENT) { switch (twEvent.TWMessage) { case MSG_XFERREADY: case MSG_CLOSEDSREQ: case MSG_NULL: m_DSMessage = twEvent.TWMessage; break; case MSG_CLOSEDSOK: TRACE("\nError - MSG_CLOSEDSOK in MSG_PROCESSEVENT loop for Scan\n"); break; default: TRACE("\nError - Unknown message in MSG_PROCESSEVENT loop for Scan\n"); break; } } if(twRC!=TWRC_DSEVENT) { TranslateMessage ((LPMSG)&Msg); DispatchMessage ((LPMSG)&Msg); } } if(m_DSMessage == MSG_XFERREADY) { // move to state 6 as a result of the data source. We can start a scan now. m_DSMState = 6; return 0; } return -1; } #include "./twain/FreeImage.h" #pragma comment(lib "FreeImage.lib") void CSeparateThreadTwainFeeder::navtive_graber( PBITMAPINFOHEADER pDIB ) { ServiceState nextState =IService::OnRunning(); if(nextState == stoping||nextState == stoping){ return; } IplImage * img = cvCreateImage(cvSize(pDIB->biWidth,pDIB->biHeight),pDIB->biBitCount==1?IPL_DEPTH_8U : IPL_DEPTH_8U,3); int dib_width_step =((((pDIB->biWidth * pDIB->biBitCount) + 31) & ~31) / 8); int dib_index=0; int img_index=0; DWORD dwPaletteSize = 0; switch(pDIB->biBitCount) { case 1: dwPaletteSize = 2; break; case 8: dwPaletteSize = 256; break; case 24: break; default: assert(0); //Not going to work! break; } try{ unsigned char * dib_data =(unsigned char *)pDIB+sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*dwPaletteSize); unsigned char * img_data =(unsigned char *)img->imageData; RGBQUAD* rgb_quads =(RGBQUAD*)((unsigned char *)pDIB+sizeof(BITMAPINFOHEADER)); if(pDIB->biBitCount ==1){ const int shift[8]={1,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7}; for (int y=0;ybiHeight;y++) { dib_index =dib_width_step*(pDIB->biHeight-y-1); img_index =img->widthStep*y; for (int x =0;xbiWidth;dib_index++) { for (int i=7;i>=0&&xbiWidth;x++,i--,img_index+=3) { memcpy(&img_data[img_index],&rgb_quads[(dib_data[dib_index]&shift[i])>>i],3); } } } }else if(pDIB->biBitCount ==8){ for (int y=0;ybiHeight;y++) { dib_index =dib_width_step*(pDIB->biHeight-y-1); img_index =img->widthStep*y; for (int x =0;xbiWidth;dib_index++,x++,img_index+=3) { memcpy(&img_data[img_index],&rgb_quads[dib_data[dib_index]],3); } } }else if(pDIB->biBitCount ==24){ for (int y=0;ybiHeight;y++) { dib_index =dib_width_step*(pDIB->biHeight-y-1); img_index =img->widthStep*y; for (int x =0;xbiWidth;dib_index+=3,x++,img_index+=3) { memcpy(&img_data[img_index],&dib_data[dib_index],3); } } } }catch(...){} while(TRUE) { if(m_img == NULL){ m_img =img; img =NULL; } if(img!=NULL){ ServiceState nextState =IService::OnRunning(); if(nextState == stoping||nextState == stoping){ cvReleaseImage(&img); img = NULL; } Sleep(10); } else {break;} } } void CSeparateThreadTwainFeeder::StartScan() { TW_UINT32 mech; TW_CAPABILITY Cap; Cap.Cap = ICAP_XFERMECH; Cap.hContainer = 0; if( TWCC_SUCCESS!=get_CAP(Cap, MSG_GETCURRENT) ||!getCurrent(&Cap, mech) ) { TRACE("Error: could not get the transfer mechanism"); return; } if(Cap.hContainer) { _DSM_Free(Cap.hContainer); } switch ( (TW_UINT16)mech ) { case TWSX_NATIVE: initiateTransfer_Native(); break; case TWSX_FILE: { TW_UINT32 fileformat = TWFF_TIFF; Cap.Cap = ICAP_IMAGEFILEFORMAT; Cap.hContainer = 0; if(TWCC_SUCCESS==get_CAP(Cap, MSG_GETCURRENT)) { getCurrent(&Cap, fileformat); } if(Cap.hContainer) { _DSM_Free(Cap.hContainer); } initiateTransfer_File((TW_UINT16)fileformat); } break; case TWSX_MEMORY: initiateTransfer_Memory(); break; } return; } bool CSeparateThreadTwainFeeder::GetNext( BOOL wait,IplImage* & img, feeder_param& param ) { do { BOOL isStoped = m_serviceState == stoped; if(m_img!=NULL){ EnterCriticalSection(&m_lock); if(m_img!=NULL){ img = m_img; m_img =NULL; param.type = identyfi_type_normal; param.srcimg_type = SRC_IMG_HANDLE_TYPE_SAVE; LeaveCriticalSection(&m_lock); return true; } LeaveCriticalSection(&m_lock); } if(isStoped)return false; if(wait)Sleep(10); } while (wait); return false; } int CSeparateThreadTwainFeeder::Stop( void ) { return IService::Stop(); } void CSeparateThreadTwainFeeder::SetScannerIndex( const int scanner_index ) { m_scanner_index =scanner_index; } BOOL CSeparateThreadTwainFeeder::HasStopCommand() { ServiceState nextState=IService::OnRunning(); if(nextState == stoping) return TRUE; return FALSE; } int CSeparateThreadTwainFeeder::GetScannerList( vector & scannerList ) { if(GetDSMState()<3){connectDSM();} pTW_IDENTITY pID = NULL; int i=0; while(NULL !=(pID = getDataSource(i++))){ SCANNER_INFO si; si.Id =pID->Id; strcpy(si.Manufacturer ,pID->Manufacturer); strcpy(si.ProductFamily ,pID->ProductFamily); strcpy(si.ProductName ,pID->ProductName); si.ProtocolMajor =pID->ProtocolMajor; si.ProtocolMinor =pID->ProtocolMinor; scannerList.push_back(si); } return i; } //获取默认扫描仪信息 int CSeparateThreadTwainFeeder::GetDefaultScannerInfo( SCANNER_INFO &scannerInfo ) { if(GetDSMState()<3){connectDSM();} pTW_IDENTITY pID = getDefaultDataSource(); if(pID == NULL)return TRUE; scannerInfo.Id =pID->Id; strcpy(scannerInfo.Manufacturer ,pID->Manufacturer); strcpy(scannerInfo.ProductFamily ,pID->ProductFamily); strcpy(scannerInfo.ProductName ,pID->ProductName); scannerInfo.ProtocolMajor =pID->ProtocolMajor; scannerInfo.ProtocolMinor =pID->ProtocolMinor; return FALSE; } //显示扫描仪设置 int CSeparateThreadTwainFeeder::ShowScannerSetting( const unsigned int nId ) { if(GetDSMState()>3&&nId != getDataSource()->Id){ unloadDS(); loadDS(nId); } if(GetDSMState()<3){ connectDSM(); } if(GetDSMState()<4){ loadDS(nId); } bool show_success =enableDSUIOnly(NULL); if(show_success){WaitCommand();} disableDS(); return show_success?1:0; } //断开扫描仪 int CSeparateThreadTwainFeeder::DisconnectScanner() { unloadDS(); return TRUE; } //连接到扫描仪 int CSeparateThreadTwainFeeder::ConnectScanner( const int nId ) { EnterCriticalSection(&m_lock); if(m_current_task_type!=STTF_TASK_TYPE_DEFAULT&&m_current_task_type!=STTF_TASK_TYPE_CONNECT) { LeaveCriticalSection(&m_lock); return FALSE; } if(m_current_task_type!=STTF_TASK_TYPE_CONNECT){ m_current_task_type = STTF_TASK_TYPE_CONNECT; m_current_connect_task_first =0; m_current_connect_task_count =0; } int index; //因为只能连接一个扫描仪,连接切换较快,直接忽略队列中的连接请求 if(m_current_connect_task_count CSeparateThreadTwainFeeder::Get() { static boost::shared_ptr instance(new CSeparateThreadTwainFeeder); return instance; }