├── .gitattributes ├── dll ├── TWAIN.dll └── TWAINDSM.dll ├── interface ├── twain.h ├── DSMInterface.h └── DSMInterface.cpp ├── twaintest_src ├── twain.h ├── InputDlg.cpp ├── InputDlg.h ├── twaintest.h ├── ChildFrm.h ├── twaintestDoc.h ├── ChildFrm.cpp ├── twaintestDoc.cpp ├── twaintestView.h ├── MainFrm.h ├── TwainCpp.h ├── DIB.h ├── twaintestView.cpp ├── twaintest.cpp ├── MainFrm.cpp ├── TwainSpec.txt ├── TwainCpp.cpp └── DIB.cpp ├── usb demo ├── USBTest.cpp └── USBTest.h ├── source └── twain_layout.jpg ├── docs └── TWAIN-2.3-Specification.pdf ├── friendly interface ├── TwainApp.cpp ├── TwainAppCMD.cpp ├── TwainApp_ui.h ├── TwainApp_ui.cpp ├── TwainAppCMD.h └── TwainApp.h ├── Twain_App_OutputErr.cpp └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.h linguist-language=c -------------------------------------------------------------------------------- /dll/TWAIN.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/dll/TWAIN.dll -------------------------------------------------------------------------------- /dll/TWAINDSM.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/dll/TWAINDSM.dll -------------------------------------------------------------------------------- /interface/twain.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/interface/twain.h -------------------------------------------------------------------------------- /twaintest_src/twain.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/twaintest_src/twain.h -------------------------------------------------------------------------------- /usb demo/USBTest.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/usb demo/USBTest.cpp -------------------------------------------------------------------------------- /source/twain_layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/source/twain_layout.jpg -------------------------------------------------------------------------------- /docs/TWAIN-2.3-Specification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/docs/TWAIN-2.3-Specification.pdf -------------------------------------------------------------------------------- /friendly interface/TwainApp.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/friendly interface/TwainApp.cpp -------------------------------------------------------------------------------- /friendly interface/TwainAppCMD.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrlitong/TWAIN-SDK/HEAD/friendly interface/TwainAppCMD.cpp -------------------------------------------------------------------------------- /usb demo/USBTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum ScannerVendor 4 | { 5 | OTHER, 6 | CANON, 7 | PANASONIC, 8 | FUJITSU, 9 | KODAK 10 | }; 11 | 12 | bool CheckScannerVendor(ScannerVendor vendor); 13 | 14 | -------------------------------------------------------------------------------- /Twain_App_OutputErr.cpp: -------------------------------------------------------------------------------- 1 | #include "twain.h" 2 | 3 | #include 4 | 5 | /** 6 | * Display the last windows error messages. 7 | */ 8 | 9 | void printWindowsErrorMessage() 10 | { 11 | 12 | LPVOID lpMsgBuf; 13 | DWORD dw = GetLastError(); 14 | 15 | FormatMessage( 16 | FORMAT_MESSAGE_ALLOCATE_BUFFER | 17 | FORMAT_MESSAGE_FROM_SYSTEM, 18 | NULL, 19 | dw, 20 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 21 | (LPTSTR)&lpMsgBuf, 22 | 0, NULL); 23 | 24 | std::cerr << "Error: id [" << dw << "] msg [" << lpMsgBuf << "]" << std::endl; 25 | 26 | LocalFree(lpMsgBuf); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /twaintest_src/InputDlg.cpp: -------------------------------------------------------------------------------- 1 | // InputDlg.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "twaintest.h" 6 | #include "InputDlg.h" 7 | 8 | #ifdef _DEBUG 9 | #define new DEBUG_NEW 10 | #undef THIS_FILE 11 | static char THIS_FILE[] = __FILE__; 12 | #endif 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | // CInputDlg dialog 16 | 17 | 18 | CInputDlg::CInputDlg(CWnd* pParent /*=NULL*/) 19 | : CDialog(CInputDlg::IDD, pParent) 20 | { 21 | //{{AFX_DATA_INIT(CInputDlg) 22 | m_EditStr = _T(""); 23 | //}}AFX_DATA_INIT 24 | } 25 | 26 | 27 | void CInputDlg::DoDataExchange(CDataExchange* pDX) 28 | { 29 | CDialog::DoDataExchange(pDX); 30 | //{{AFX_DATA_MAP(CInputDlg) 31 | DDX_Text(pDX, IDC_EDIT1, m_EditStr); 32 | //}}AFX_DATA_MAP 33 | } 34 | 35 | 36 | BEGIN_MESSAGE_MAP(CInputDlg, CDialog) 37 | //{{AFX_MSG_MAP(CInputDlg) 38 | // NOTE: the ClassWizard will add message map macros here 39 | //}}AFX_MSG_MAP 40 | END_MESSAGE_MAP() 41 | 42 | ///////////////////////////////////////////////////////////////////////////// 43 | // CInputDlg message handlers 44 | -------------------------------------------------------------------------------- /twaintest_src/InputDlg.h: -------------------------------------------------------------------------------- 1 | #if !defined(AFX_INPUTDLG_H__04EC5F80_7364_11D3_9160_A234B585301E__INCLUDED_) 2 | #define AFX_INPUTDLG_H__04EC5F80_7364_11D3_9160_A234B585301E__INCLUDED_ 3 | 4 | #if _MSC_VER > 1000 5 | #pragma once 6 | #endif // _MSC_VER > 1000 7 | // InputDlg.h : header file 8 | // 9 | 10 | ///////////////////////////////////////////////////////////////////////////// 11 | // CInputDlg dialog 12 | 13 | class CInputDlg : public CDialog 14 | { 15 | // Construction 16 | public: 17 | CInputDlg(CWnd* pParent = NULL); // standard constructor 18 | 19 | // Dialog Data 20 | //{{AFX_DATA(CInputDlg) 21 | enum { IDD = IDD_DIALOG_INPUT }; 22 | CString m_EditStr; 23 | //}}AFX_DATA 24 | 25 | 26 | // Overrides 27 | // ClassWizard generated virtual function overrides 28 | //{{AFX_VIRTUAL(CInputDlg) 29 | protected: 30 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 31 | //}}AFX_VIRTUAL 32 | 33 | // Implementation 34 | protected: 35 | 36 | // Generated message map functions 37 | //{{AFX_MSG(CInputDlg) 38 | // NOTE: the ClassWizard will add member functions here 39 | //}}AFX_MSG 40 | DECLARE_MESSAGE_MAP() 41 | }; 42 | 43 | //{{AFX_INSERT_LOCATION}} 44 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 45 | 46 | #endif // !defined(AFX_INPUTDLG_H__04EC5F80_7364_11D3_9160_A234B585301E__INCLUDED_) 47 | -------------------------------------------------------------------------------- /twaintest_src/twaintest.h: -------------------------------------------------------------------------------- 1 | // twaintest.h : main header file for the TWAINTEST application 2 | // 3 | 4 | #if !defined(AFX_TWAINTEST_H__2C017504_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 5 | #define AFX_TWAINTEST_H__2C017504_4DC7_11D3_915F_E5DF02F24121__INCLUDED_ 6 | 7 | #if _MSC_VER > 1000 8 | #pragma once 9 | #endif // _MSC_VER > 1000 10 | 11 | #ifndef __AFXWIN_H__ 12 | #error include 'stdafx.h' before including this file for PCH 13 | #endif 14 | 15 | #include "resource.h" // main symbols 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // CTwaintestApp: 18 | // See twaintest.cpp for the implementation of this class 19 | // 20 | 21 | class CTwaintestApp : public CWinApp 22 | { 23 | public: 24 | CTwaintestApp(); 25 | ~CTwaintestApp(); 26 | 27 | // Overrides 28 | // ClassWizard generated virtual function overrides 29 | //{{AFX_VIRTUAL(CTwaintestApp) 30 | public: 31 | virtual BOOL InitInstance(); 32 | //}}AFX_VIRTUAL 33 | 34 | // Implementation 35 | //{{AFX_MSG(CTwaintestApp) 36 | afx_msg void OnAppAbout(); 37 | //}}AFX_MSG 38 | DECLARE_MESSAGE_MAP() 39 | 40 | public: 41 | }; 42 | 43 | 44 | ///////////////////////////////////////////////////////////////////////////// 45 | 46 | //{{AFX_INSERT_LOCATION}} 47 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 48 | 49 | #endif // !defined(AFX_TWAINTEST_H__2C017504_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 50 | -------------------------------------------------------------------------------- /twaintest_src/ChildFrm.h: -------------------------------------------------------------------------------- 1 | // ChildFrm.h : interface of the CChildFrame class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #if !defined(AFX_CHILDFRM_H__2C01750A_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 6 | #define AFX_CHILDFRM_H__2C01750A_4DC7_11D3_915F_E5DF02F24121__INCLUDED_ 7 | 8 | #if _MSC_VER > 1000 9 | #pragma once 10 | #endif // _MSC_VER > 1000 11 | 12 | 13 | class CChildFrame : public CMDIChildWnd 14 | { 15 | DECLARE_DYNCREATE(CChildFrame) 16 | public: 17 | CChildFrame(); 18 | 19 | // Attributes 20 | public: 21 | 22 | // Operations 23 | public: 24 | 25 | // Overrides 26 | // ClassWizard generated virtual function overrides 27 | //{{AFX_VIRTUAL(CChildFrame) 28 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs); 29 | //}}AFX_VIRTUAL 30 | 31 | // Implementation 32 | public: 33 | virtual ~CChildFrame(); 34 | #ifdef _DEBUG 35 | virtual void AssertValid() const; 36 | virtual void Dump(CDumpContext& dc) const; 37 | #endif 38 | 39 | // Generated message map functions 40 | protected: 41 | //{{AFX_MSG(CChildFrame) 42 | // NOTE - the ClassWizard will add and remove member functions here. 43 | // DO NOT EDIT what you see in these blocks of generated code! 44 | //}}AFX_MSG 45 | DECLARE_MESSAGE_MAP() 46 | }; 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | 50 | //{{AFX_INSERT_LOCATION}} 51 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 52 | 53 | #endif // !defined(AFX_CHILDFRM_H__2C01750A_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 54 | -------------------------------------------------------------------------------- /twaintest_src/twaintestDoc.h: -------------------------------------------------------------------------------- 1 | // twaintestDoc.h : interface of the CTwaintestDoc class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #if !defined(AFX_TWAINTESTDOC_H__2C01750C_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 6 | #define AFX_TWAINTESTDOC_H__2C01750C_4DC7_11D3_915F_E5DF02F24121__INCLUDED_ 7 | 8 | #if _MSC_VER > 1000 9 | #pragma once 10 | #endif // _MSC_VER > 1000 11 | 12 | #include "dib.h" 13 | 14 | class CTwaintestDoc : public CDocument 15 | { 16 | protected: // create from serialization only 17 | CTwaintestDoc(); 18 | DECLARE_DYNCREATE(CTwaintestDoc) 19 | 20 | // Attributes 21 | public: 22 | 23 | // Operations 24 | public: 25 | 26 | // Overrides 27 | // ClassWizard generated virtual function overrides 28 | //{{AFX_VIRTUAL(CTwaintestDoc) 29 | public: 30 | virtual BOOL OnNewDocument(); 31 | virtual void Serialize(CArchive& ar); 32 | //}}AFX_VIRTUAL 33 | 34 | // Implementation 35 | public: 36 | virtual ~CTwaintestDoc(); 37 | #ifdef _DEBUG 38 | virtual void AssertValid() const; 39 | virtual void Dump(CDumpContext& dc) const; 40 | #endif 41 | 42 | protected: 43 | 44 | // Generated message map functions 45 | protected: 46 | //{{AFX_MSG(CTwaintestDoc) 47 | //}}AFX_MSG 48 | DECLARE_MESSAGE_MAP() 49 | 50 | public: 51 | CDIB m_Dib; 52 | }; 53 | 54 | ///////////////////////////////////////////////////////////////////////////// 55 | 56 | //{{AFX_INSERT_LOCATION}} 57 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 58 | 59 | #endif // !defined(AFX_TWAINTESTDOC_H__2C01750C_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 60 | -------------------------------------------------------------------------------- /twaintest_src/ChildFrm.cpp: -------------------------------------------------------------------------------- 1 | // ChildFrm.cpp : implementation of the CChildFrame class 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "twaintest.h" 6 | 7 | #include "ChildFrm.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // CChildFrame 17 | 18 | IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) 19 | 20 | BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) 21 | //{{AFX_MSG_MAP(CChildFrame) 22 | // NOTE - the ClassWizard will add and remove mapping macros here. 23 | // DO NOT EDIT what you see in these blocks of generated code ! 24 | //}}AFX_MSG_MAP 25 | END_MESSAGE_MAP() 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | // CChildFrame construction/destruction 29 | 30 | CChildFrame::CChildFrame() 31 | { 32 | // TODO: add member initialization code here 33 | 34 | } 35 | 36 | CChildFrame::~CChildFrame() 37 | { 38 | } 39 | 40 | BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) 41 | { 42 | // TODO: Modify the Window class or styles here by modifying 43 | // the CREATESTRUCT cs 44 | 45 | if( !CMDIChildWnd::PreCreateWindow(cs) ) 46 | return FALSE; 47 | 48 | return TRUE; 49 | } 50 | 51 | 52 | 53 | ///////////////////////////////////////////////////////////////////////////// 54 | // CChildFrame diagnostics 55 | 56 | #ifdef _DEBUG 57 | void CChildFrame::AssertValid() const 58 | { 59 | CMDIChildWnd::AssertValid(); 60 | } 61 | 62 | void CChildFrame::Dump(CDumpContext& dc) const 63 | { 64 | CMDIChildWnd::Dump(dc); 65 | } 66 | 67 | #endif //_DEBUG 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | // CChildFrame message handlers 71 | -------------------------------------------------------------------------------- /twaintest_src/twaintestDoc.cpp: -------------------------------------------------------------------------------- 1 | // twaintestDoc.cpp : implementation of the CTwaintestDoc class 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "twaintest.h" 6 | #include "twaintestDoc.h" 7 | #include "Mainfrm.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // CTwaintestDoc 17 | 18 | IMPLEMENT_DYNCREATE(CTwaintestDoc, CDocument) 19 | 20 | BEGIN_MESSAGE_MAP(CTwaintestDoc, CDocument) 21 | //{{AFX_MSG_MAP(CTwaintestDoc) 22 | //}}AFX_MSG_MAP 23 | END_MESSAGE_MAP() 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | // CTwaintestDoc construction/destruction 27 | 28 | CTwaintestDoc::CTwaintestDoc() 29 | { 30 | // TODO: add one-time construction code here 31 | 32 | } 33 | 34 | CTwaintestDoc::~CTwaintestDoc() 35 | { 36 | } 37 | 38 | BOOL CTwaintestDoc::OnNewDocument() 39 | { 40 | if (!CDocument::OnNewDocument()) 41 | return FALSE; 42 | 43 | // TODO: add reinitialization code here 44 | // (SDI documents will reuse this document) 45 | 46 | return TRUE; 47 | } 48 | 49 | 50 | 51 | ///////////////////////////////////////////////////////////////////////////// 52 | // CTwaintestDoc serialization 53 | 54 | void CTwaintestDoc::Serialize(CArchive& ar) 55 | { 56 | if (ar.IsStoring()) 57 | { 58 | // TODO: add storing code here 59 | } 60 | else 61 | { 62 | // TODO: add loading code here 63 | } 64 | } 65 | 66 | ///////////////////////////////////////////////////////////////////////////// 67 | // CTwaintestDoc diagnostics 68 | 69 | #ifdef _DEBUG 70 | void CTwaintestDoc::AssertValid() const 71 | { 72 | CDocument::AssertValid(); 73 | } 74 | 75 | void CTwaintestDoc::Dump(CDumpContext& dc) const 76 | { 77 | CDocument::Dump(dc); 78 | } 79 | #endif //_DEBUG 80 | 81 | ///////////////////////////////////////////////////////////////////////////// 82 | // CTwaintestDoc commands 83 | 84 | -------------------------------------------------------------------------------- /twaintest_src/twaintestView.h: -------------------------------------------------------------------------------- 1 | // twaintestView.h : interface of the CTwaintestView class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #if !defined(AFX_TWAINTESTVIEW_H__2C01750E_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 6 | #define AFX_TWAINTESTVIEW_H__2C01750E_4DC7_11D3_915F_E5DF02F24121__INCLUDED_ 7 | 8 | #if _MSC_VER > 1000 9 | #pragma once 10 | #endif // _MSC_VER > 1000 11 | 12 | 13 | class CTwaintestView : public CScrollView 14 | { 15 | protected: // create from serialization only 16 | CTwaintestView(); 17 | DECLARE_DYNCREATE(CTwaintestView) 18 | 19 | // Attributes 20 | public: 21 | CTwaintestDoc* GetDocument(); 22 | 23 | // Operations 24 | public: 25 | 26 | // Overrides 27 | // ClassWizard generated virtual function overrides 28 | //{{AFX_VIRTUAL(CTwaintestView) 29 | public: 30 | virtual void OnDraw(CDC* pDC); // overridden to draw this view 31 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs); 32 | virtual void OnInitialUpdate(); 33 | protected: 34 | virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); 35 | virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); 36 | virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); 37 | virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); 38 | //}}AFX_VIRTUAL 39 | 40 | // Implementation 41 | public: 42 | virtual ~CTwaintestView(); 43 | #ifdef _DEBUG 44 | virtual void AssertValid() const; 45 | virtual void Dump(CDumpContext& dc) const; 46 | #endif 47 | protected: 48 | 49 | // Generated message map functions 50 | protected: 51 | //{{AFX_MSG(CTwaintestView) 52 | //}}AFX_MSG 53 | DECLARE_MESSAGE_MAP() 54 | }; 55 | 56 | #ifndef _DEBUG // debug version in twaintestView.cpp 57 | inline CTwaintestDoc* CTwaintestView::GetDocument() 58 | { return (CTwaintestDoc*)m_pDocument; } 59 | #endif 60 | 61 | ///////////////////////////////////////////////////////////////////////////// 62 | 63 | //{{AFX_INSERT_LOCATION}} 64 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 65 | 66 | #endif // !defined(AFX_TWAINTESTVIEW_H__2C01750E_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 67 | -------------------------------------------------------------------------------- /twaintest_src/MainFrm.h: -------------------------------------------------------------------------------- 1 | // MainFrm.h : interface of the CMainFrame class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #if !defined(AFX_MAINFRM_H__2C017508_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 6 | #define AFX_MAINFRM_H__2C017508_4DC7_11D3_915F_E5DF02F24121__INCLUDED_ 7 | 8 | #if _MSC_VER > 1000 9 | #pragma once 10 | #endif // _MSC_VER > 1000 11 | 12 | class CTwaintestDoc; 13 | 14 | #include "TwainCpp.h" 15 | 16 | class CMainFrame : public CMDIFrameWnd,public CTwain 17 | { 18 | DECLARE_DYNAMIC(CMainFrame) 19 | public: 20 | CMainFrame(); 21 | void SetAcquireDoc(CTwaintestDoc *pDoc); 22 | void SetImage(HANDLE hBitmap,int bits); 23 | void CopyImage(HANDLE hBitmap,TW_IMAGEINFO& info); 24 | 25 | // Attributes 26 | public: 27 | 28 | // Operations 29 | public: 30 | 31 | // Overrides 32 | // ClassWizard generated virtual function overrides 33 | //{{AFX_VIRTUAL(CMainFrame) 34 | public: 35 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs); 36 | virtual BOOL PreTranslateMessage(MSG* pMsg); 37 | protected: 38 | virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); 39 | //}}AFX_VIRTUAL 40 | 41 | // Implementation 42 | public: 43 | virtual ~CMainFrame(); 44 | #ifdef _DEBUG 45 | virtual void AssertValid() const; 46 | virtual void Dump(CDumpContext& dc) const; 47 | #endif 48 | 49 | protected: // control bar embedded members 50 | CStatusBar m_wndStatusBar; 51 | CToolBar m_wndToolBar; 52 | 53 | // Generated message map functions 54 | protected: 55 | //{{AFX_MSG(CMainFrame) 56 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 57 | afx_msg void OnFileSelectsource(); 58 | afx_msg void OnUpdateFileSelectsource(CCmdUI* pCmdUI); 59 | afx_msg void OnFileAcquire(); 60 | afx_msg void OnUpdateFileAcquire(CCmdUI* pCmdUI); 61 | afx_msg void OnClose(); 62 | //}}AFX_MSG 63 | DECLARE_MESSAGE_MAP() 64 | 65 | public: 66 | CTwaintestDoc *m_pDoc; 67 | }; 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | 71 | //{{AFX_INSERT_LOCATION}} 72 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 73 | 74 | #endif // !defined(AFX_MAINFRM_H__2C017508_4DC7_11D3_915F_E5DF02F24121__INCLUDED_) 75 | -------------------------------------------------------------------------------- /twaintest_src/TwainCpp.h: -------------------------------------------------------------------------------- 1 | #ifndef __TWAINCPP_ 2 | #define __TWAINCPP_ 3 | 4 | #include "Twain.h" 5 | 6 | 7 | #define TWCPP_ANYCOUNT (-1) 8 | #define TWCPP_CANCELTHIS (1) 9 | #define TWCPP_CANCELALL (2) 10 | #define TWCPP_DOTRANSFER (0) 11 | 12 | class CTwain 13 | { 14 | public: 15 | 16 | 17 | CTwain(HWND hWnd = NULL); 18 | virtual ~CTwain(); 19 | BOOL InitTwain(HWND hWnd); 20 | void ReleaseTwain(); 21 | 22 | 23 | /* 24 | This routine must be implemented by the dervied class 25 | After setting the required values in the m_AppId structure, 26 | the derived class should call the parent class implementation 27 | Refer Pg: 51 of the Twain Specification version 1.8 28 | */ 29 | virtual void GetIdentity(); 30 | virtual BOOL SelectSource(); 31 | virtual BOOL OpenSource(TW_IDENTITY *pSource=NULL); 32 | virtual int ShouldTransfer(TW_IMAGEINFO& info) { return TWCPP_DOTRANSFER;}; 33 | 34 | BOOL ProcessMessage(MSG msg); 35 | 36 | BOOL SelectDefaultSource(); 37 | BOOL IsValidDriver() const; 38 | BOOL SourceSelected() const {return m_bSourceSelected;} ; 39 | BOOL DSMOpen() const; 40 | BOOL DSOpen() const; 41 | BOOL SourceEnabled() const { return m_bSourceEnabled;}; 42 | BOOL ModalUI() const { return m_bModalUI; }; 43 | 44 | TW_INT16 GetRC() const { return m_returnCode; }; 45 | TW_STATUS GetStatus() const { return m_Status; }; 46 | 47 | BOOL SetImageCount(TW_INT16 nCount = 1); 48 | BOOL Acquire(int numImages=1); 49 | 50 | protected: 51 | BOOL CallTwainProc(pTW_IDENTITY pOrigin,pTW_IDENTITY pDest, 52 | TW_UINT32 DG,TW_UINT16 DAT,TW_UINT16 MSG, 53 | TW_MEMREF pData); 54 | 55 | void CloseDSM(); 56 | void CloseDS(); 57 | 58 | BOOL GetCapability(TW_CAPABILITY& twCap,TW_UINT16 cap,TW_UINT16 conType=TWON_DONTCARE16); 59 | BOOL GetCapability(TW_UINT16 cap,TW_UINT32& value); 60 | BOOL SetCapability(TW_UINT16 cap,TW_UINT16 value,BOOL sign=FALSE); 61 | BOOL SetCapability(TW_CAPABILITY& twCap); 62 | BOOL EnableSource(BOOL showUI = TRUE); 63 | 64 | BOOL GetImageInfo(TW_IMAGEINFO& info); 65 | 66 | virtual BOOL DisableSource(); 67 | virtual BOOL CanClose() { return TRUE; }; 68 | 69 | void TranslateMessage(TW_EVENT& twEvent); 70 | void TransferImage(); 71 | BOOL EndTransfer(); 72 | void CancelTransfer(); 73 | BOOL ShouldContinue(); 74 | BOOL GetImage(TW_IMAGEINFO& info); 75 | 76 | virtual void CopyImage(HANDLE hBitmap,TW_IMAGEINFO& info)=0; 77 | 78 | protected: 79 | HINSTANCE m_hTwainDLL; 80 | DSMENTRYPROC m_pDSMProc; 81 | 82 | TW_IDENTITY m_AppId; 83 | TW_IDENTITY m_Source; 84 | TW_STATUS m_Status; 85 | TW_INT16 m_returnCode; 86 | HWND m_hMessageWnd; 87 | 88 | BOOL m_bSourceSelected; 89 | BOOL m_bDSMOpen; 90 | BOOL m_bDSOpen; 91 | BOOL m_bSourceEnabled; 92 | BOOL m_bModalUI; 93 | 94 | int m_nImageCount; 95 | }; 96 | 97 | 98 | #endif -------------------------------------------------------------------------------- /twaintest_src/DIB.h: -------------------------------------------------------------------------------- 1 | #ifndef __DIB 2 | #define __DIB 3 | 4 | 5 | 6 | class CDIB 7 | { 8 | public: 9 | enum BitmapType 10 | { 11 | BMP, 12 | GIF, 13 | TIFF 14 | }; 15 | CDIB(HANDLE hDib=NULL,int nBits=8); 16 | virtual ~CDIB(); 17 | CDIB& operator=(CDIB& dib); 18 | BOOL IsValid() { return (m_pVoid && Width() && Height());}; 19 | void UseGamma(float fg,BOOL bUse=TRUE); 20 | BOOL CreateFromHandle(HANDLE hDib,int nBits); 21 | BOOL Create(int width,int height,int bits=24); 22 | BOOL Create(BITMAPINFOHEADER& bmInfo); 23 | BOOL CopyDIB(CDIB& dib); 24 | BOOL OpenDIB(CString& fileName); 25 | BOOL SaveDIB(CString& fileName,BitmapType type); 26 | void ReplaceColor(unsigned char oldColor,unsigned char newColor); 27 | HANDLE GetDIBits(int nStartX=-1,int nStartY=-1,int nCx=-1,int nCy=-1); 28 | CBitmap *GetBitmap(CDC& dc); 29 | CBitmap *GetTempBitmap(CDC& dc); 30 | DWORD GetDIBSize(); 31 | int GetPaletteSize(BITMAPINFOHEADER& bmInfo); 32 | int GetPaletteSize(); 33 | int CountColors(); 34 | int EnumColors(BYTE *colors); 35 | void InitDIB(COLORREF color); 36 | void CopyLine(int source,int dest); 37 | void DestroyDIB(); 38 | void SetPalette(unsigned char *palette); 39 | void SetPalette(RGBQUAD *pRGB); 40 | COLORREF PaletteColor(int index); 41 | void SetPixel(int x,int y,COLORREF color); 42 | void SetPixel8(int x,int y,unsigned char color); 43 | COLORREF GetPixel(int x,int y); 44 | void GetPixel(UINT x,UINT y,int& pixel); 45 | void BitBlt(HDC hDest,int nXDest,int nYDest,int nWidth,int nHeight,int xSrc,int ySrc); 46 | void BitBlt(int nXDest,int nYDest,int nWidth,int nHeight,CDIB& dibSrc,int nSrcX,int nSrcY,BYTE *colors=NULL); 47 | void StretchBlt(HDC hDest,int nXDest,int nYDest,int nDWidth,int nDHeight,int xSrc,int ySrc,int nSWidth,int nSHeight); 48 | void StretchBlt(int nXDest,int nYDest,int nDWidth,int nDHeight,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight); 49 | void ExpandBlt(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight); 50 | void SetFlags(int flag) { m_nFlags = flag; }; 51 | int Height() { return height ; }; 52 | int Width() { return width ; }; 53 | unsigned char *GetLinePtr(int line); 54 | inline int GetBitCount() {return m_pInfo->bmiHeader.biBitCount;}; 55 | BOOL Make8Bit(CDIB& dib); 56 | BOOL SwitchFromOne(CDIB& dib); 57 | BOOL SwitchFromFour(CDIB& dib); 58 | BOOL SwitchFrom24(CDIB& dib); 59 | BOOL SwitchPalette(CDIB& dib); 60 | int ClosestColor(RGBQUAD *pRgb); 61 | LPBITMAPINFO GetBitmapInfo() { return m_pInfo;}; 62 | static unsigned int Distance(RGBQUAD& rgb1,RGBQUAD& rgb2); 63 | protected : 64 | HANDLE DIBHandle(); 65 | BOOL OpenBMP(CString& csFileName); 66 | BOOL OpenGIF(CString& csFileName); 67 | BOOL OpenTIFF(CString& csFileName); 68 | BOOL SaveBMP(CString& csFileName); 69 | BOOL SaveGIF(CString& csFileName); 70 | BOOL SaveTIFF(CString& csFileName); 71 | void CreateGammaCurve(); 72 | void Expand(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight); 73 | unsigned char *m_pBits; 74 | PBITMAPINFO m_pInfo; 75 | RGBQUAD *m_pRGB; 76 | void *m_pVoid; 77 | BYTE **m_pLinePtr; 78 | int height,bytes,width,m_nBits; 79 | int m_nFlags; 80 | BOOL m_bUseGamma; 81 | float m_fGamma; 82 | float m_fOldGamma; 83 | unsigned char Gamma[256]; 84 | RGBQUAD CacheQuad[256]; 85 | char CachePtr[256]; 86 | }; 87 | 88 | 89 | #endif -------------------------------------------------------------------------------- /friendly interface/TwainApp_ui.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright ?2007 TWAIN Working Group: 3 | * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company, 4 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 5 | * Ricoh Corporation, and Xerox Corporation. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the TWAIN Working Group nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | ***************************************************************************/ 31 | 32 | /** 33 | * @file TwainApp_ui.h 34 | * User interface for TWAIN Application 35 | * @author JFL Peripheral Solutions Inc. 36 | * @date April 2007 37 | */ 38 | 39 | 40 | #ifndef __TWAINAPP_UI_H__ 41 | #define __TWAINAPP_UI_H__ 42 | 43 | #pragma once 44 | 45 | #ifdef _WINDOWS 46 | #ifndef __AFXWIN_H__ 47 | #error include 'stdafx.h' before including this file for PCH 48 | #endif 49 | #endif 50 | 51 | #include "mainService.h" 52 | #include "../external/include/twain.h" 53 | #include "../common/Common.h" 54 | #include "../common/CommonTWAIN.h" 55 | 56 | 57 | /** 58 | * Returns an error message that can be used when a type is of an unexpected type. 59 | * @param[in] _unExpected the expected type 60 | * @param[in] _unReceived the received type 61 | * @return the error string 62 | */ 63 | string getErrorString_UnexpectedType(const TW_UINT16 _unExpected, const TW_UINT16 _unReceived); 64 | 65 | /** 66 | * prints the main menu 67 | */ 68 | void printOptions(); 69 | 70 | /** 71 | * prints the main capabilities menu 72 | */ 73 | void printMainCaps(); 74 | 75 | /** 76 | * prints the ICAP_xxxxx menu for type TW_ONEVALUE 77 | * @param[in] _unCap The cap to print 78 | * @param[in] _pCap pointer to the TW_ONEVALUE returned by the source for this cap 79 | */ 80 | void print_ICAP(const TW_UINT16 _unCap, pTW_ONEVALUE _pCap); 81 | 82 | /** 83 | * @overload void print_ICAP(const TW_UINT16 _unCap, pTW_ENUMERATION _pCap) 84 | * prints the ICAP_xxxxx menu for type TW_ENUMERATION 85 | * @param[in] _unCap The cap to print 86 | * @param[in] _pCap pointer to the TW_ENUMERATION returned by the source for this cap 87 | */ 88 | void print_ICAP(const TW_UINT16 _unCap, pTW_ENUMERATION _pCap); 89 | 90 | #endif // __TWAINAPP_UI_H__ 91 | -------------------------------------------------------------------------------- /twaintest_src/twaintestView.cpp: -------------------------------------------------------------------------------- 1 | // twaintestView.cpp : implementation of the CTwaintestView class 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "twaintest.h" 6 | 7 | #include "twaintestDoc.h" 8 | #include "twaintestView.h" 9 | #include "Mainfrm.h" 10 | #include "InputDlg.h" 11 | #include 12 | 13 | #ifdef _DEBUG 14 | #define new DEBUG_NEW 15 | #undef THIS_FILE 16 | static char THIS_FILE[] = __FILE__; 17 | #endif 18 | 19 | 20 | #define DISTANCE(r1,g1,b1,r2,g2,b2) \ 21 | (long) (3L*(long)((r1)-(r2))*(long)((r1)-(r2)) + \ 22 | 4L*(long)((g1)-(g2))*(long)((g1)-(g2)) + \ 23 | 2L*(long)((b1)-(b2))*(long)((b1)-(b2))) 24 | 25 | 26 | void Create24Bit(CDIB& source,CDIB& dest); 27 | ///////////////////////////////////////////////////////////////////////////// 28 | // CTwaintestView 29 | 30 | IMPLEMENT_DYNCREATE(CTwaintestView, CScrollView) 31 | 32 | BEGIN_MESSAGE_MAP(CTwaintestView, CScrollView) 33 | //{{AFX_MSG_MAP(CTwaintestView) 34 | //}}AFX_MSG_MAP 35 | // Standard printing commands 36 | ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint) 37 | ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint) 38 | ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview) 39 | END_MESSAGE_MAP() 40 | 41 | ///////////////////////////////////////////////////////////////////////////// 42 | // CTwaintestView construction/destruction 43 | 44 | CTwaintestView::CTwaintestView() 45 | { 46 | // TODO: add construction code here 47 | } 48 | 49 | CTwaintestView::~CTwaintestView() 50 | { 51 | } 52 | 53 | BOOL CTwaintestView::PreCreateWindow(CREATESTRUCT& cs) 54 | { 55 | // TODO: Modify the Window class or styles here by modifying 56 | // the CREATESTRUCT cs 57 | 58 | return CScrollView::PreCreateWindow(cs); 59 | } 60 | 61 | ///////////////////////////////////////////////////////////////////////////// 62 | // CTwaintestView drawing 63 | 64 | void CTwaintestView::OnDraw(CDC* pDC) 65 | { 66 | CTwaintestDoc* pDoc = GetDocument(); 67 | ASSERT_VALID(pDoc); 68 | if(pDoc->m_Dib.IsValid()) 69 | { 70 | pDoc->m_Dib.BitBlt(pDC->m_hDC,0,0,pDoc->m_Dib.Width(),pDoc->m_Dib.Height(),0,0); 71 | } 72 | // TODO: add draw code for native data here 73 | } 74 | 75 | ///////////////////////////////////////////////////////////////////////////// 76 | // CTwaintestView printing 77 | 78 | BOOL CTwaintestView::OnPreparePrinting(CPrintInfo* pInfo) 79 | { 80 | // default preparation 81 | return DoPreparePrinting(pInfo); 82 | } 83 | 84 | void CTwaintestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 85 | { 86 | // TODO: add extra initialization before printing 87 | } 88 | 89 | void CTwaintestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 90 | { 91 | // TODO: add cleanup after printing 92 | } 93 | 94 | ///////////////////////////////////////////////////////////////////////////// 95 | // CTwaintestView diagnostics 96 | 97 | #ifdef _DEBUG 98 | void CTwaintestView::AssertValid() const 99 | { 100 | CScrollView::AssertValid(); 101 | } 102 | 103 | void CTwaintestView::Dump(CDumpContext& dc) const 104 | { 105 | CScrollView::Dump(dc); 106 | } 107 | 108 | CTwaintestDoc* CTwaintestView::GetDocument() // non-debug version is inline 109 | { 110 | ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTwaintestDoc))); 111 | return (CTwaintestDoc*)m_pDocument; 112 | } 113 | #endif //_DEBUG 114 | 115 | ///////////////////////////////////////////////////////////////////////////// 116 | // CTwaintestView message handlers 117 | 118 | void CTwaintestView::OnInitialUpdate() 119 | { 120 | SetScrollSizes(MM_TEXT,CSize(100,100)); 121 | CScrollView::OnInitialUpdate(); 122 | OnUpdate(NULL,0,NULL); 123 | } 124 | 125 | 126 | 127 | void CTwaintestView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 128 | { 129 | CTwaintestDoc *pDoc = GetDocument(); 130 | CSize size; 131 | size = CSize(pDoc->m_Dib.Width(),pDoc->m_Dib.Height()); 132 | SetScrollSizes(MM_TEXT,size); 133 | } 134 | 135 | -------------------------------------------------------------------------------- /twaintest_src/twaintest.cpp: -------------------------------------------------------------------------------- 1 | // twaintest.cpp : Defines the class behaviors for the application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "twaintest.h" 6 | 7 | #include "MainFrm.h" 8 | #include "ChildFrm.h" 9 | #include "twaintestDoc.h" 10 | #include "twaintestView.h" 11 | #include "twain.h" 12 | 13 | #ifdef _DEBUG 14 | #define new DEBUG_NEW 15 | #undef THIS_FILE 16 | static char THIS_FILE[] = __FILE__; 17 | #endif 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // CTwaintestApp 21 | 22 | BEGIN_MESSAGE_MAP(CTwaintestApp, CWinApp) 23 | //{{AFX_MSG_MAP(CTwaintestApp) 24 | ON_COMMAND(ID_APP_ABOUT, OnAppAbout) 25 | //}}AFX_MSG_MAP 26 | // Standard file based document commands 27 | ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) 28 | ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) 29 | // Standard print setup command 30 | ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) 31 | END_MESSAGE_MAP() 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | // CTwaintestApp construction 35 | 36 | CTwaintestApp::CTwaintestApp() 37 | { 38 | // TODO: add construction code here, 39 | // Place all significant initialization in InitInstance 40 | } 41 | 42 | CTwaintestApp::~CTwaintestApp() 43 | { 44 | // TODO: add construction code here, 45 | // Place all significant initialization in InitInstance 46 | } 47 | 48 | 49 | ///////////////////////////////////////////////////////////////////////////// 50 | // The one and only CTwaintestApp object 51 | 52 | CTwaintestApp theApp; 53 | 54 | ///////////////////////////////////////////////////////////////////////////// 55 | // CTwaintestApp initialization 56 | 57 | BOOL CTwaintestApp::InitInstance() 58 | { 59 | AfxEnableControlContainer(); 60 | 61 | // Standard initialization 62 | // If you are not using these features and wish to reduce the size 63 | // of your final executable, you should remove from the following 64 | // the specific initialization routines you do not need. 65 | 66 | #ifdef _AFXDLL 67 | Enable3dControls(); // Call this when using MFC in a shared DLL 68 | #else 69 | Enable3dControlsStatic(); // Call this when linking to MFC statically 70 | #endif 71 | 72 | // Change the registry key under which our settings are stored. 73 | // TODO: You should modify this string to be something appropriate 74 | // such as the name of your company or organization. 75 | SetRegistryKey(_T("Local AppWizard-Generated Applications")); 76 | 77 | LoadStdProfileSettings(); // Load standard INI file options (including MRU) 78 | 79 | // Register the application's document templates. Document templates 80 | // serve as the connection between documents, frame windows and views. 81 | 82 | CMultiDocTemplate* pDocTemplate; 83 | pDocTemplate = new CMultiDocTemplate( 84 | IDR_TWAINTTYPE, 85 | RUNTIME_CLASS(CTwaintestDoc), 86 | RUNTIME_CLASS(CChildFrame), // custom MDI child frame 87 | RUNTIME_CLASS(CTwaintestView)); 88 | AddDocTemplate(pDocTemplate); 89 | 90 | // create main MDI Frame window 91 | CMainFrame* pMainFrame = new CMainFrame; 92 | if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) 93 | return FALSE; 94 | m_pMainWnd = pMainFrame; 95 | 96 | // Parse command line for standard shell commands, DDE, file open 97 | CCommandLineInfo cmdInfo; 98 | ParseCommandLine(cmdInfo); 99 | 100 | // Dispatch commands specified on the command line 101 | // if (!ProcessShellCommand(cmdInfo)) 102 | // return FALSE; 103 | 104 | // The main window has been initialized, so show and update it. 105 | pMainFrame->ShowWindow(m_nCmdShow); 106 | pMainFrame->UpdateWindow(); 107 | 108 | return TRUE; 109 | } 110 | 111 | 112 | ///////////////////////////////////////////////////////////////////////////// 113 | // CAboutDlg dialog used for App About 114 | 115 | class CAboutDlg : public CDialog 116 | { 117 | public: 118 | CAboutDlg(); 119 | 120 | // Dialog Data 121 | //{{AFX_DATA(CAboutDlg) 122 | enum { IDD = IDD_ABOUTBOX }; 123 | //}}AFX_DATA 124 | 125 | // ClassWizard generated virtual function overrides 126 | //{{AFX_VIRTUAL(CAboutDlg) 127 | protected: 128 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 129 | //}}AFX_VIRTUAL 130 | 131 | // Implementation 132 | protected: 133 | //{{AFX_MSG(CAboutDlg) 134 | // No message handlers 135 | //}}AFX_MSG 136 | DECLARE_MESSAGE_MAP() 137 | }; 138 | 139 | CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 140 | { 141 | //{{AFX_DATA_INIT(CAboutDlg) 142 | //}}AFX_DATA_INIT 143 | } 144 | 145 | void CAboutDlg::DoDataExchange(CDataExchange* pDX) 146 | { 147 | CDialog::DoDataExchange(pDX); 148 | //{{AFX_DATA_MAP(CAboutDlg) 149 | //}}AFX_DATA_MAP 150 | } 151 | 152 | BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 153 | //{{AFX_MSG_MAP(CAboutDlg) 154 | // No message handlers 155 | //}}AFX_MSG_MAP 156 | END_MESSAGE_MAP() 157 | 158 | // App command to run the dialog 159 | void CTwaintestApp::OnAppAbout() 160 | { 161 | CAboutDlg aboutDlg; 162 | aboutDlg.DoModal(); 163 | } 164 | 165 | ///////////////////////////////////////////////////////////////////////////// 166 | // CTwaintestApp message handlers 167 | 168 | 169 | -------------------------------------------------------------------------------- /interface/DSMInterface.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright ?2007 TWAIN Working Group: 3 | * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company, 4 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 5 | * Ricoh Corporation, and Xerox Corporation. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the TWAIN Working Group nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | ***************************************************************************/ 31 | 32 | /** 33 | * @file DSMInterface.h 34 | * Common defines and typedefs used for accessing DSM for TWAIN Applications. 35 | * @author TWAIN Working Group 36 | * @date April 2007 37 | */ 38 | 39 | #ifndef _DSMINTERFACE_H_ 40 | #define _DSMINTERFACE_H_ 41 | 42 | #pragma once 43 | 44 | #ifdef _WINDOWS 45 | #ifndef __AFXWIN_H__ 46 | #error include 'stdafx.h' before including this file for PCH 47 | #endif 48 | #endif 49 | 50 | //#include "main.h" 51 | #include "twain.h" 52 | 53 | /** 54 | * Load the DSM library. 55 | * @param[in] the name of the DSM library to open 56 | * @return true if success. 57 | */ 58 | bool LoadDSMLib(char* _pszLibName); 59 | 60 | /** 61 | * Unload the DSM library. 62 | */ 63 | void unLoadDSMLib(); 64 | 65 | /** 66 | * Initialize and register the entry point into the DSM. 67 | * @param[in] _pOrigin Identifies the source module of the message. This could 68 | * identify an Application, a Source, or the Source Manager. 69 | * 70 | * @param[in] _pDest Identifies the destination module for the message. 71 | * This could identify an application or a data source. 72 | * If this is NULL, the message goes to the Source Manager. 73 | * 74 | * @param[in] _DG The Data Group. 75 | * Example: DG_IMAGE. 76 | * 77 | * @param[in] _DAT The Data Attribute Type. 78 | * Example: DAT_IMAGEMEMXFER. 79 | * 80 | * @param[in] _MSG The message. Messages are interpreted by the destination module 81 | * with respect to the Data Group and the Data Attribute Type. 82 | * Example: MSG_GET. 83 | * 84 | * @param[in,out] _pData A pointer to the data structure or variable identified 85 | * by the Data Attribute Type. 86 | * Example: (TW_MEMREF)&ImageMemXfer 87 | * where ImageMemXfer is a TW_IMAGEMEMXFER structure. 88 | * 89 | * @return a valid TWRC_xxxx return code. 90 | * Example: TWRC_SUCCESS. 91 | */ 92 | TW_UINT16 _DSM_Entry(pTW_IDENTITY _pOrigin, 93 | pTW_IDENTITY _pDest, 94 | TW_UINT32 _DG, 95 | TW_UINT16 _DAT, 96 | TW_UINT16 _MSG, 97 | TW_MEMREF _pData); 98 | 99 | /** 100 | * Allocate global memory 101 | * @param[in] _size of memory to allocate. 102 | * @return TW_HANDLE to the memory allocated. 103 | */ 104 | TW_HANDLE _DSM_Alloc(TW_UINT32 _size); 105 | 106 | /** 107 | * Free previously allocated global memory 108 | * @param[in] _hMemory TW_HANDLE to the memory needing free. 109 | */ 110 | void _DSM_Free(TW_HANDLE _hMemory); 111 | 112 | /** 113 | * Lock global memory from being updated by others. return a pointer to the 114 | * memory so we can update it. 115 | * @param[in] _hMemory TW_HANDLE to the memory to update. 116 | * @return TW_MEMREF pointer to the memory. 117 | */ 118 | TW_MEMREF _DSM_LockMemory(TW_HANDLE _hMemory); 119 | 120 | /** 121 | * Unlock global memory after locking. to allow updating by others. 122 | * @param[in] _hMemory TW_HANDLE to memory returned by _DSM_Alloc 123 | */ 124 | void _DSM_UnlockMemory(TW_HANDLE _hMemory); 125 | 126 | /** 127 | * Not Used. 128 | * @todo Not Implimented 129 | * @param[in] twEvent reference to the TW_EVENT 130 | * @return TW_UINT16 131 | */ 132 | TW_UINT16 HandleEvent(TW_EVENT &twEvent); 133 | 134 | #endif // _DSMINTERFACE_H_ 135 | -------------------------------------------------------------------------------- /twaintest_src/MainFrm.cpp: -------------------------------------------------------------------------------- 1 | // MainFrm.cpp : implementation of the CMainFrame class 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "twaintest.h" 6 | 7 | #include "MainFrm.h" 8 | #include "TwainTestDoc.h" 9 | 10 | #ifdef _DEBUG 11 | #define new DEBUG_NEW 12 | #undef THIS_FILE 13 | static char THIS_FILE[] = __FILE__; 14 | #endif 15 | 16 | 17 | //#define HIWORD(l) ((WORD) (((DWORD) (l) >> 16) & 0xFFFF)) 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // CMainFrame 20 | 21 | IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) 22 | 23 | BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 24 | //{{AFX_MSG_MAP(CMainFrame) 25 | ON_WM_CREATE() 26 | ON_COMMAND(ID_FILE_SELECTSOURCE, OnFileSelectsource) 27 | ON_UPDATE_COMMAND_UI(ID_FILE_SELECTSOURCE, OnUpdateFileSelectsource) 28 | ON_COMMAND(ID_FILE_ACQUIRE, OnFileAcquire) 29 | ON_UPDATE_COMMAND_UI(ID_FILE_ACQUIRE, OnUpdateFileAcquire) 30 | ON_WM_CLOSE() 31 | //}}AFX_MSG_MAP 32 | END_MESSAGE_MAP() 33 | 34 | static UINT indicators[] = 35 | { 36 | ID_SEPARATOR, // status line indicator 37 | ID_INDICATOR_CAPS, 38 | ID_INDICATOR_NUM, 39 | ID_INDICATOR_SCRL, 40 | }; 41 | 42 | ///////////////////////////////////////////////////////////////////////////// 43 | // CMainFrame construction/destruction 44 | 45 | CMainFrame::CMainFrame() 46 | { 47 | // TODO: add member initialization code here 48 | m_pDoc = NULL; 49 | } 50 | 51 | CMainFrame::~CMainFrame() 52 | { 53 | } 54 | 55 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 56 | { 57 | if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) 58 | return -1; 59 | 60 | if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP 61 | | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || 62 | !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) 63 | { 64 | TRACE0("Failed to create toolbar\n"); 65 | return -1; // fail to create 66 | } 67 | 68 | if (!m_wndStatusBar.Create(this) || 69 | !m_wndStatusBar.SetIndicators(indicators, 70 | sizeof(indicators)/sizeof(UINT))) 71 | { 72 | TRACE0("Failed to create status bar\n"); 73 | return -1; // fail to create 74 | } 75 | 76 | // TODO: Delete these three lines if you don't want the toolbar to 77 | // be dockable 78 | m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); 79 | EnableDocking(CBRS_ALIGN_ANY); 80 | DockControlBar(&m_wndToolBar); 81 | 82 | //<<<<<<>>>>>>> 83 | /* Try to load TWAIN now */ 84 | 85 | InitTwain(m_hWnd); 86 | if(!IsValidDriver()) 87 | { 88 | AfxMessageBox("Unable to load Twain Driver."); 89 | } 90 | return 0; 91 | } 92 | 93 | BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 94 | { 95 | if( !CMDIFrameWnd::PreCreateWindow(cs) ) 96 | return FALSE; 97 | // TODO: Modify the Window class or styles here by modifying 98 | // the CREATESTRUCT cs 99 | 100 | return TRUE; 101 | } 102 | 103 | ///////////////////////////////////////////////////////////////////////////// 104 | // CMainFrame diagnostics 105 | 106 | #ifdef _DEBUG 107 | void CMainFrame::AssertValid() const 108 | { 109 | CMDIFrameWnd::AssertValid(); 110 | } 111 | 112 | void CMainFrame::Dump(CDumpContext& dc) const 113 | { 114 | CMDIFrameWnd::Dump(dc); 115 | } 116 | 117 | #endif //_DEBUG 118 | 119 | ///////////////////////////////////////////////////////////////////////////// 120 | // CMainFrame message handlers 121 | 122 | 123 | BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 124 | { 125 | //<<<<<<>>>>>>> 126 | ProcessMessage(*pMsg); 127 | return CMDIFrameWnd::PreTranslateMessage(pMsg); 128 | } 129 | 130 | 131 | void CMainFrame::SetAcquireDoc(CTwaintestDoc *pDoc) 132 | { 133 | m_pDoc = pDoc; 134 | } 135 | 136 | 137 | BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) 138 | { 139 | return CMDIFrameWnd::OnCommand(wParam, lParam); 140 | } 141 | 142 | static unsigned char masktable[] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; 143 | 144 | void Create24Bit(CDIB& source,CDIB& dest) 145 | { 146 | int pal; 147 | dest.Create(source.Width(),source.Height(),24); 148 | pal = source.GetPaletteSize(); 149 | BYTE palet[768]; 150 | for(int i=0; i < pal; i++) 151 | { 152 | COLORREF col = source.PaletteColor(i); 153 | palet[i*3+2] = GetRValue(col); 154 | palet[i*3+1] = GetGValue(col); 155 | palet[i*3+0] = GetBValue(col); 156 | } 157 | int j; 158 | BYTE *src,*dst,*ptr; 159 | for(i=0; i < source.Height(); i++) 160 | { 161 | src = source.GetLinePtr(i); 162 | dst = dest.GetLinePtr(i); 163 | ptr = dst; 164 | int index; 165 | for(j=0; j < source.Width(); j++,ptr+=3) 166 | { 167 | switch(pal) 168 | { 169 | case 2: 170 | if(src[j>>3] & masktable[j&7]) 171 | { 172 | index = 1; 173 | } 174 | else 175 | { 176 | index = 0; 177 | } 178 | break; 179 | case 16: 180 | if(j & 1) 181 | { 182 | index = src[j>>1] & 0x0f; 183 | } 184 | else 185 | { 186 | index = (src[j>>1] >> 4) & 0x0f; 187 | } 188 | break; 189 | case 256: 190 | index = src[j]; 191 | break; 192 | } 193 | ASSERT(index < pal); 194 | memcpy(ptr,palet+index*3,3); 195 | } 196 | index = (ptr - dst)/3; 197 | ASSERT(index <= source.Width()); 198 | } 199 | 200 | } 201 | 202 | void CMainFrame::SetImage(HANDLE hBitmap,int bits) 203 | { 204 | CWinApp *pApp = AfxGetApp(); 205 | POSITION pos = pApp->GetFirstDocTemplatePosition(); 206 | CMultiDocTemplate *pTemplate = (CMultiDocTemplate *)pApp->GetNextDocTemplate(pos); 207 | CTwaintestDoc *pDoc = (CTwaintestDoc *)pTemplate->OpenDocumentFile(NULL); 208 | if(pDoc) 209 | { 210 | CDIB dib; 211 | dib.CreateFromHandle(hBitmap,bits); 212 | if(bits == 24) pDoc->m_Dib = dib; 213 | else Create24Bit(dib,pDoc->m_Dib); 214 | pDoc->UpdateAllViews(NULL); 215 | } 216 | } 217 | 218 | //<<<<<<>>>>>>> 219 | void CMainFrame::CopyImage(HANDLE hBitmap,TW_IMAGEINFO& info) 220 | { 221 | SetImage(hBitmap,info.BitsPerPixel); 222 | } 223 | 224 | void CMainFrame::OnFileSelectsource() 225 | { 226 | // TODO: Add your command handler code here 227 | SelectSource(); 228 | } 229 | 230 | void CMainFrame::OnUpdateFileSelectsource(CCmdUI* pCmdUI) 231 | { 232 | pCmdUI->Enable(IsValidDriver()); 233 | } 234 | 235 | void CMainFrame::OnFileAcquire() 236 | { 237 | Acquire(TWCPP_ANYCOUNT); 238 | } 239 | 240 | void CMainFrame::OnUpdateFileAcquire(CCmdUI* pCmdUI) 241 | { 242 | pCmdUI->Enable(SourceSelected()); 243 | } 244 | 245 | 246 | 247 | void CMainFrame::OnClose() 248 | { 249 | ReleaseTwain(); 250 | CMDIFrameWnd::OnClose(); 251 | } 252 | -------------------------------------------------------------------------------- /interface/DSMInterface.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright ?2007 TWAIN Working Group: 3 | * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company, 4 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 5 | * Ricoh Corporation, and Xerox Corporation. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the TWAIN Working Group nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | ***************************************************************************/ 31 | 32 | /** 33 | * @file DSMInterface.cpp 34 | * Common defines and typedefs used for accessing DSM for Twain Applications. 35 | * @author TWAIN Working Group 36 | * @date October 2007 37 | */ 38 | 39 | #ifdef _WINDOWS 40 | #include "stdafx.h" 41 | #endif 42 | #include "CommonTWAIN.h" 43 | #include "DSMInterface.h" 44 | 45 | #include 46 | using namespace std; 47 | 48 | // On Windows the official TWAINDSM.dll is signed. this function can verify the signature. 49 | #ifdef TWH_CMP_MSC 50 | /** 51 | * verify the embedded signature in the DSM. 52 | * @param[in] pwszSourceFile the path to the DSM to verify. 53 | */ 54 | BOOL VerifyEmbeddedSignature(LPCWSTR pwszSourceFile); 55 | #endif 56 | 57 | #ifdef TWH_CMP_MSC 58 | HMODULE 59 | #else 60 | void* 61 | #endif 62 | gpDSM = 0; /**< global pointer to the DSM library */ 63 | 64 | DSMENTRYPROC gpDSM_Entry = 0; /**< global pointer to the DSM entry point */ 65 | 66 | TW_ENTRYPOINT g_DSM_Entry = { 0 }; /**< global pointer to the TWAIN entry point structure */ 67 | 68 | 69 | #ifdef TWH_CMP_GNU 70 | #include 71 | #endif 72 | 73 | 74 | TW_UINT16 _DSM_Entry(pTW_IDENTITY _pOrigin, 75 | pTW_IDENTITY _pDest, 76 | TW_UINT32 _DG, 77 | TW_UINT16 _DAT, 78 | TW_UINT16 _MSG, 79 | TW_MEMREF _pData) 80 | { 81 | TW_UINT16 ret = TWRC_FAILURE; 82 | 83 | if ((0 == gpDSM) && !LoadDSMLib(kTWAIN_DSM_DIR kTWAIN_DSM_DLL_NAME)) 84 | { 85 | cerr << "Could not load the DSM: " << kTWAIN_DSM_DIR kTWAIN_DSM_DLL_NAME << endl; 86 | return 0; /*< return 0. @todo are we sure of this return? */ 87 | } 88 | 89 | if (0 != gpDSM_Entry) 90 | { 91 | ret = gpDSM_Entry(_pOrigin, _pDest, _DG, _DAT, _MSG, _pData); 92 | } 93 | 94 | return ret; 95 | } 96 | 97 | ///////////////////////////////////////////////////////////////////////////// 98 | bool LoadDSMLib(char* _pszLibName) 99 | { 100 | // check if already opened 101 | if (0 != gpDSM) 102 | { 103 | return true; 104 | } 105 | #ifdef TWH_CMP_GNU 106 | char *error; 107 | #endif //TWH_CMP_GNU 108 | 109 | if ((gpDSM = LOADLIBRARY(_pszLibName)) != 0) 110 | { 111 | // On Windows the official TWAINDSM.dll is signed. this function can verify the signature. 112 | #ifdef TWH_CMP_MSC 113 | WCHAR szPath[MAX_PATH]; 114 | if (GetModuleFileNameW(gpDSM, szPath, MAX_PATH)) 115 | { 116 | if (!VerifyEmbeddedSignature(szPath)) 117 | { 118 | // Only continue using the DSM from trusted distributor 119 | unLoadDSMLib(); 120 | return false; 121 | } 122 | } 123 | #endif //TWH_CMP_MSC 124 | 125 | if ((gpDSM_Entry = (DSMENTRYPROC)LOADFUNCTION(gpDSM, "DSM_Entry")) == 0) 126 | { 127 | #ifdef TWH_CMP_MSC // dlsym returning NULL is not an error on Unix 128 | cerr << "Error - Could not find DSM_Entry function in DSM: " << _pszLibName << endl; 129 | return false; 130 | #endif //TWH_CMP_MSC 131 | } 132 | #ifdef TWH_CMP_GNU 133 | if ((error = dlerror()) != 0) 134 | { 135 | cerr << "App - dlsym: " << error << endl; 136 | return false; 137 | } 138 | #endif //TWH_CMP_GNU 139 | } 140 | else 141 | { 142 | cerr << "Error - Could not load DSM: " << _pszLibName << endl; 143 | #ifdef TWH_CMP_GNU 144 | cerr << "App - dlopen: " << dlerror() << endl; 145 | #endif //TWH_CMP_GNU 146 | return false; 147 | } 148 | 149 | #ifdef TWH_CMP_GNU 150 | 151 | #endif 152 | 153 | return true; 154 | } 155 | 156 | ///////////////////////////////////////////////////////////////////////////// 157 | void unLoadDSMLib() 158 | { 159 | if (gpDSM) 160 | { 161 | UNLOADLIBRARY(gpDSM); 162 | gpDSM = 0; 163 | gpDSM_Entry = 0; 164 | } 165 | } 166 | 167 | ////////////////////////////////////////////////////////////////////////////// 168 | // The following functions are defined in the DSM2, 169 | // For backwards compatibiltiy on windows call the default function 170 | TW_HANDLE _DSM_Alloc(TW_UINT32 _size) 171 | { 172 | if (g_DSM_Entry.DSM_MemAllocate) 173 | { 174 | return g_DSM_Entry.DSM_MemAllocate(_size); 175 | } 176 | 177 | #ifdef TWH_CMP_MSC 178 | return ::GlobalAlloc(GPTR, _size); 179 | #endif 180 | 181 | return 0; 182 | } 183 | 184 | ////////////////////////////////////////////////////////////////////////////// 185 | void _DSM_Free(TW_HANDLE _hMemory) 186 | { 187 | if (g_DSM_Entry.DSM_MemFree) 188 | { 189 | return g_DSM_Entry.DSM_MemFree(_hMemory); 190 | } 191 | 192 | #ifdef TWH_CMP_MSC 193 | ::GlobalFree(_hMemory); 194 | #endif 195 | 196 | return; 197 | } 198 | 199 | ////////////////////////////////////////////////////////////////////////////// 200 | TW_MEMREF _DSM_LockMemory(TW_HANDLE _hMemory) 201 | { 202 | if (g_DSM_Entry.DSM_MemLock) 203 | { 204 | return g_DSM_Entry.DSM_MemLock(_hMemory); 205 | } 206 | 207 | #ifdef TWH_CMP_MSC 208 | return (TW_MEMREF)::GlobalLock(_hMemory); 209 | #endif 210 | 211 | return 0; 212 | } 213 | 214 | ////////////////////////////////////////////////////////////////////////////// 215 | void _DSM_UnlockMemory(TW_HANDLE _hMemory) 216 | { 217 | if (g_DSM_Entry.DSM_MemUnlock) 218 | { 219 | return g_DSM_Entry.DSM_MemUnlock(_hMemory); 220 | } 221 | 222 | #ifdef TWH_CMP_MSC 223 | ::GlobalUnlock(_hMemory); 224 | #endif 225 | 226 | return; 227 | } 228 | 229 | ////////////////////////////////////////////////////////////////////////////// 230 | -------------------------------------------------------------------------------- /twaintest_src/TwainSpec.txt: -------------------------------------------------------------------------------- 1 | One of my applications needed some scanner support. I thought it might be a good idea 2 | to get into TWAIN and try it out. Well, here are the results. 3 | 4 | 5 | Firstly, this is NOT a complete implementation of the TWAIN specification. I have followed 6 | version 1.8 and have used just the basic functionality to get an image from a scanner, 7 | actually , multiple images too can be acquired one after another. By the way - it will work 8 | with didigtal cameras too - anything which exports a TWAIN interface is supported. 9 | 10 | 11 | Well, lets delve a little further into it. Before we do that though, I would have to mention 12 | that I will not be able to tell you all about TWAIN here. You can download the specification 13 | at http://www.twain.org. They also have a sample Twain source, if you do not have a scanner 14 | and wish to try out TWAIN. 15 | 16 | For our purposes here, the important things are the Data Source Manager (DSM) and the Data 17 | Source (DS) itself. The DS is the actual scanner or digital camera or any other source 18 | which implements TWAIN. The DSM is the module that provides us an interface to the DSM. 19 | And yes, this is a very simplistic view of TWAIN ( I shudder to think of what the TWAIN 20 | designers would make of my description ). 21 | 22 | Now for the class itself. First, the header Twain.h has to be included. I've called my 23 | class, rather unimaginatively CTwain. Now this class requires the TWAIN_32.DLL module 24 | to be loaded. The way I have handled it is by keeping a static Module handle and incrementing 25 | and decrementing the reference count. When the interface is released for the last time, 26 | the module is unloaded. 27 | 28 | Mostly, the class is quite independant of everything else. What it does require though, 29 | is a handle to window to which the DSM can send messages. These messages are not meant 30 | for the application itself but for Twain implementor, in this case CTwain. This window 31 | handle can be passed either to the constructor, or if as is more likely, if the window isn`t 32 | ready yet, in a call to InitTwain. 33 | 34 | The CTwain class is an abstract class as it has one pure virtual method. So to use this 35 | class you will have to derive from CTwain. 36 | 37 | I will now explain the important methods - the ones which will let you start scanning . 38 | 39 | 40 | CTwain(HWND hWnd= NULL) -- Constructor 41 | 42 | The hwnd is optional. If a non Null value is given, the Twain interface is initialized 43 | using this handle. 44 | 45 | 46 | ~CTwain() -- Destructor 47 | 48 | 49 | 50 | InitTwain(HWND hWnd) -- Initializes TWAIN 51 | 52 | This is called by the constructor if the handle passed to the constructor is not null. 53 | Else, it can be called later . Loads the Twain Dll and initializes it. 54 | 55 | 56 | ReleaseTwain() -- Releases Twain interface 57 | 58 | NOTE : If TWAIN has been initialized, this must be called before the window handle passed 59 | to it is destroyed. Not doing so will result in resource and memory leaks. 60 | 61 | 62 | GetIdentity() -- Identitifies application 63 | 64 | This is called by InitTwain to initialize the TW_IDENTITY structure. Please refer to 65 | twain.h for the structure memnbers and to CTwain::GetIdentity for an example as to 66 | how to fill these members. As for now, you need not implement this as long as the 67 | default behaviour suits you. 68 | 69 | 70 | IsValidDriver() -- Returns true if the Driver was loaded successfully 71 | 72 | 73 | 74 | SourceSelected() -- Returns true if a source was selected successfully 75 | 76 | 77 | 78 | SourceEnabled() -- Returns true if a source is enabled 79 | 80 | In TWAIN parlance, a source being enabled means a scan is in progress. 81 | 82 | 83 | SelectDefaultSource() -- Selects the default source for the current machine 84 | 85 | 86 | 87 | SelectSource() -- Shows the Select Source Dialog box and allows the user to select one 88 | 89 | 90 | 91 | 92 | Acquire(int numImages=1) -- Starts image acquisition 93 | 94 | This does not necessarily mean the scanning process is started. All it actually 95 | means is that the Source has been enabled and typically a Scanning parameters 96 | dialog box has been opened. Scanning typically starts from there. 97 | numImages is the number of images that the application can handle or 98 | TWCPP_ANYCOUNT for any number. 99 | 100 | 101 | ProcessMessage(MSG msg) -- Processes messages from Twain 102 | 103 | This should be called from the message loop of the window which is intially 104 | passed to the class. 105 | NOTE : All messages can be passed to this routine. It ignores all Non-Twain messages 106 | and will not act on them unless the source is enabled - so it is not a performance 107 | botte-neck either. 108 | 109 | 110 | ShouldTransfer(TW_IMAGEINFO& info) 111 | 112 | This is called every time an image is to be scanned. It should return one of 113 | the following values : 114 | TWCPP_CANCELTHIS : Cancel this image transfer 115 | TWCPP_CANCELALL : Abort all transfers 116 | TWCPP_DOTRANSFER : Continue with transfer 117 | 118 | The default implementation returns TWCPP_DOTRANSFER. 119 | 120 | 121 | CopyImage(HANDLE hBitmap,TW_IMAGEINFO& info) 122 | 123 | This is a pure virtual method which will get called everytime an image is 124 | transferred from TWAIN. How the image is to be used is upto the 125 | application. 126 | 127 | 128 | Well - these are the routines you would typically use . You can probably do a lot more 129 | too, but the TWAIN specification can probably help you a lot more there than I can. 130 | 131 | Now for the demo application. 132 | 133 | What I have done is used mutiple inheritance with regard to CMainFrame. I figured that would 134 | be the simplest way to handle things. So CMainFrame is derived from CTwain. InitTwain is 135 | called from the OnCreate member of CMainFrame. Though the destructor would automatically 136 | be called when the window closes, the window handle would not be valid at that time. So 137 | I call ReleaseTwain from the OnDestroy member function of CMainFrame. 138 | 139 | The two additions to the File Menu are 140 | Select Source 141 | Acquire 142 | 143 | Select Source shows the default dialog which lists the TWAIN sources available. 144 | Acquire starts the actual acquisition process. 145 | 146 | CTwain::ProcessMessage is called from the PreTranslateMessage member of CMainFrame. 147 | 148 | Also CMainFrame implements CopyImage. This in turn calls CMainFrame::SetImage which 149 | creates a new document along with a frame and assigns the bitmap scanned to that document. 150 | So as new images are scanned new documents are created. 151 | 152 | I guess thats it as far as explanations go. I will now very briefly just go through the 153 | steps required to start scanning . 154 | 155 | First , create a class derived from CTwain. Implement CopyImage to handle bitmaps. 156 | Bitmaps are sent as a handle to a Device Independant Bitmap . In the demo app , 157 | this is handled with a class -CDIB . 158 | 159 | Now in the pretranslate member of the window`s class, 160 | insert this line : 161 | ProcessMessage(*pMsg); 162 | 163 | Add the two menu items - Select Source and Acquire as done in CMainFrame in the demo app. 164 | 165 | And well - you`re done. Thats it - the only thing you really have to work on is CopyImage. 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /friendly interface/TwainApp_ui.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright ?2007 TWAIN Working Group: 3 | * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company, 4 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 5 | * Ricoh Corporation, and Xerox Corporation. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the TWAIN Working Group nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | ***************************************************************************/ 31 | 32 | /** 33 | * @file TwainApp_ui.cpp 34 | * User interface for TWAIN Application 35 | * @author JFL Peripheral Solutions Inc. 36 | * @date October 2006 37 | */ 38 | 39 | #ifdef _WINDOWS 40 | #include "stdafx.h" 41 | #endif 42 | 43 | #include 44 | #include 45 | using namespace std; 46 | 47 | #include "TwainApp_ui.h" 48 | #include "TwainString.h" 49 | 50 | 51 | ////////////////////////////////////////////////////////////////////////////// 52 | string getErrorString_UnexpectedType(const TW_UINT16 _unReceived) 53 | { 54 | ostringstream errMsg; 55 | 56 | errMsg 57 | << "The type is an unexpected value. " 58 | << " got " << convertTWTY_toString(_unReceived); 59 | 60 | return errMsg.str(); 61 | } 62 | 63 | ////////////////////////////////////////////////////////////////////////////// 64 | void printOptions() 65 | { 66 | cout 67 | << "\n" 68 | << "Please enter an option\n" 69 | << "----------------------\n" 70 | << "q - quit\n" 71 | << "h - help\n" 72 | << "cdsm - connect to the dsm\n" 73 | << "xdsm - disconnect from the dsm\n" 74 | << "lds - list data sources available\n" 75 | << "pds# - print identity structure for data source with id#. ex: pds2\n" 76 | << "cds# - connect to data source with id#. ex: cds2\n" 77 | << "xds - disconnect from data source\n" 78 | /* << "caps - negotiate capabilities\n" */ 79 | << "init - init default setting" 80 | << "scan - start the scan\n" 81 | << endl; 82 | return; 83 | } 84 | 85 | ////////////////////////////////////////////////////////////////////////////// 86 | void printMainCaps() 87 | { 88 | cout 89 | << "\n" 90 | << "Capabilites\n" 91 | << "-----------\n" 92 | << "q - done negotiating, go back to main menu\n" 93 | << "h - help\n" 94 | << "1 - ICAP_XFERMECH\n" 95 | << "2 - ICAP_PIXELTYPE\n" 96 | << "3 - ICAP_BITDEPTH\n" 97 | << "4 - ICAP_XRESOLUTION\n" 98 | << "5 - ICAP_YRESOLUTION\n" 99 | << "6 - ICAP_FRAMES\n" 100 | << "7 - ICAP_UNITS\n" 101 | << endl; 102 | return; 103 | } 104 | 105 | ////////////////////////////////////////////////////////////////////////////// 106 | void print_ICAP(const TW_UINT16 _unCap, pTW_ONEVALUE _pCap) 107 | { 108 | if (0 == _pCap) 109 | { 110 | return; 111 | } 112 | 113 | cout 114 | << "\n" 115 | << convertCAP_toString(_unCap) << "\n" 116 | << "--------------\n" 117 | << "Showing supported types. * indicates current setting.\n\n" 118 | << "q - done\n"; 119 | 120 | switch (_pCap->ItemType) 121 | { 122 | case TWTY_FIX32: 123 | { 124 | pTW_FIX32 pFix32 = (pTW_FIX32)&_pCap->Item; 125 | cout << "1 - " << pFix32->Whole << "." << pFix32->Frac << "*\n" << endl; 126 | } 127 | break; 128 | 129 | case TWTY_FRAME: 130 | { 131 | pTW_FRAME pframe = (pTW_FRAME)&_pCap->Item; 132 | 133 | cout 134 | << "1 - Frame Data:*\n" 135 | << "\tLeft,\tTop,\tRight,\tBottom\n" 136 | << "\t" << FIX32ToFloat(pframe->Left) << ",\t" 137 | << FIX32ToFloat(pframe->Top) << ",\t" 138 | << FIX32ToFloat(pframe->Right) << ",\t" 139 | << FIX32ToFloat(pframe->Bottom) << "\n" 140 | << "\n" 141 | << endl; 142 | } 143 | break; 144 | 145 | case TWTY_INT8: 146 | case TWTY_INT16: 147 | case TWTY_INT32: 148 | case TWTY_UINT8: 149 | case TWTY_UINT16: 150 | case TWTY_UINT32: 151 | case TWTY_BOOL: 152 | { 153 | cout << "1 - " << convertCAP_Item_toString(_unCap, _pCap->Item, _pCap->ItemType) << "*" << endl; 154 | } 155 | break; 156 | 157 | case TWTY_STR32: 158 | { 159 | cout << "1 - " << (pTW_STR32)&_pCap->ItemType << "*" << endl; 160 | } 161 | break; 162 | 163 | case TWTY_STR64: 164 | { 165 | cout << "1 - " << (pTW_STR64)&_pCap->ItemType << "*" << endl; 166 | } 167 | break; 168 | 169 | case TWTY_STR128: 170 | { 171 | cout << "1 - " << (pTW_STR128)&_pCap->ItemType << "*" << endl; 172 | } 173 | break; 174 | 175 | case TWTY_STR255: 176 | { 177 | cout << "1 - " << (pTW_STR255)&_pCap->ItemType << "*" << endl; 178 | } 179 | break; 180 | 181 | default: 182 | { 183 | cerr << getErrorString_UnexpectedType(_pCap->ItemType) << endl; 184 | } 185 | break; 186 | 187 | } 188 | return; 189 | } 190 | 191 | ////////////////////////////////////////////////////////////////////////////// 192 | void print_ICAP(const TW_UINT16 _unCap, pTW_ENUMERATION _pCap) 193 | { 194 | if (0 == _pCap) 195 | { 196 | return; 197 | } 198 | 199 | cout 200 | << "\n" 201 | << convertCAP_toString(_unCap) << "\n" 202 | << "--------------\n" 203 | << "Showing supported types. * indicates current setting.\n\n" 204 | << "q - done\n"; 205 | 206 | for (TW_UINT32 x = 0; x < _pCap->NumItems; ++x) 207 | { 208 | switch (_pCap->ItemType) 209 | { 210 | case TWTY_UINT32: 211 | { 212 | cout << x << " - " << convertCAP_Item_toString(_unCap, ((pTW_UINT32)(&_pCap->ItemList))[x], _pCap->ItemType); 213 | } 214 | break; 215 | 216 | case TWTY_INT32: 217 | { 218 | cout << x << " - " << convertCAP_Item_toString(_unCap, ((pTW_INT32)(&_pCap->ItemList))[x], _pCap->ItemType); 219 | } 220 | break; 221 | 222 | case TWTY_UINT16: 223 | { 224 | cout << x << " - " << convertCAP_Item_toString(_unCap, ((pTW_UINT16)(&_pCap->ItemList))[x], _pCap->ItemType); 225 | } 226 | break; 227 | 228 | case TWTY_INT16: 229 | { 230 | cout << x << " - " << convertCAP_Item_toString(_unCap, ((pTW_INT16)(&_pCap->ItemList))[x], _pCap->ItemType); 231 | } 232 | break; 233 | 234 | case TWTY_UINT8: 235 | { 236 | cout << x << " - " << convertCAP_Item_toString(_unCap, ((pTW_UINT8)(&_pCap->ItemList))[x], _pCap->ItemType); 237 | } 238 | break; 239 | 240 | case TWTY_INT8: 241 | { 242 | cout << x << " - " << convertCAP_Item_toString(_unCap, ((pTW_INT8)(&_pCap->ItemList))[x], _pCap->ItemType); 243 | } 244 | break; 245 | 246 | case TWTY_FIX32: 247 | { 248 | cout << x << " - " << ((pTW_FIX32)(&_pCap->ItemList))[x].Whole << "." << (int)((((pTW_FIX32)(&_pCap->ItemList))[x].Frac / 65536.0 + .0005) * 1000); 249 | } 250 | break; 251 | 252 | case TWTY_FRAME: 253 | { 254 | pTW_FRAME pframe = &((pTW_FRAME)(&_pCap->ItemList))[x]; 255 | cout << x << " - Frame Data:\n" 256 | << "\tLeft,\tTop,\tRight,\tBottom\n" 257 | << "\t" << FIX32ToFloat(pframe->Left) << ",\t" 258 | << FIX32ToFloat(pframe->Top) << ",\t" 259 | << FIX32ToFloat(pframe->Right) << ",\t" 260 | << FIX32ToFloat(pframe->Bottom); 261 | } 262 | break; 263 | 264 | case TWTY_STR32: 265 | { 266 | cout << "1 - " << &((pTW_STR32)(&_pCap->ItemList))[x]; 267 | } 268 | break; 269 | 270 | case TWTY_STR64: 271 | { 272 | cout << "1 - " << &((pTW_STR64)(&_pCap->ItemList))[x]; 273 | } 274 | break; 275 | 276 | case TWTY_STR128: 277 | { 278 | cout << "1 - " << &((pTW_STR128)(&_pCap->ItemList))[x]; 279 | } 280 | break; 281 | 282 | case TWTY_STR255: 283 | { 284 | cout << "1 - " << &((pTW_STR255)(&_pCap->ItemList))[x]; 285 | } 286 | break; 287 | 288 | 289 | default: 290 | { 291 | cerr << getErrorString_UnexpectedType(_pCap->ItemType) << endl; 292 | } 293 | break; 294 | } 295 | 296 | if (x == _pCap->CurrentIndex) 297 | { 298 | cout << "*"; 299 | } 300 | 301 | cout << "\n"; 302 | } 303 | 304 | cout << endl; 305 | return; 306 | } 307 | ////////////////////////////////////////////////////////////////////////////// 308 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TWAIN protocol introduction 2 | ==== 3 | 4 | > TWAIN(full name:Technology Without An Interesting Name)is an applications programming interface (API) and communications protocol that regulates communication between software and digital imaging devices, such as image scanners and digital cameras. 5 | TWAIN is not a hardware-level protocol; it requires a driver called Data Source for each device. 6 | > - Provide multiple-platform support 7 | > - Maintain and distribute a no-charge developer's toolkit 8 | > - Ensure ease of implementation 9 | > - Encourage widespread adoption 10 | > - Open Source Data Source Manager 11 | > - Multiple images format support 12 | > 13 | TWAIN is not a hardware-level protocol. It requires a driver (mysteriously called a Data Source or DS) for each imaging device. When a device is advertised as TWAIN Compatible this simply means the device has a TWAIN DS (driver) available for it. 14 | 15 | TWAIN is available at this time (March 2007) on all 32-bit Intel versions of Microsoft Windows and on Apple OS X. Note that Dosadi does not support Apple products or OS X development. 16 | The TWAIN Manager or DSM is provided for free by the TWAIN Working Group - it acts as liason and coordinator between TWAIN applications and Data Sources. 17 | 18 | The DSM has minimal user interface - just the Select Source dialog. All user interaction outside of the Application is handled by the Data Source. 19 | 20 | Each Data Source is basically a high-level device driver, provided by the device manufacturer. The TWAIN Working Group does not enforce compliance with the TWAIN standard. TWAIN compliance and compliance testing are voluntary, and left up to application and DS developers. 21 | 22 | The TWAIN manager and the Data Source are DLLs, so they load into the application's memory space and run essentially as subroutines of the application. The DSM uses interprocess communication to coordinate with other instances of itself when more than one application uses TWAIN. 23 | 24 | Much simplified, the steps of an application using TWAIN are: 25 | 26 | 1. Open a device and have a conversation with the device (actually the DS) about the capabilities and settings of the device. There is a huge list of capabilities, every device implements a different set. But for example, most devices can list the resolutions they support, and most will allow an application to select a resolution for subsequent images. 27 | 28 | 2. Enable a device -which in TWAIN terms means 'give the device permission to deliver images.' Most scanners when enabled display their user interface and allow the user to adjust scan settings, eventually hitting a scan button to actually start the scan. 29 | 30 | The application can request that a DS not display a user interface, but some devices ignore the request and show their dialog anyway. This is a common cause of surprise and frustration for TWAIN application developers. 31 | 32 | 3. Once a device is enabled, the application waits for a notification from the DS that an image is ready. While it waits, the application must somehow ensure that any messages posted to it are routed through TWAIN. Unless this is done correctly, the application will never receive the image-ready notification, and the device's user interface may not work correctly. 33 | 34 | 4. The application accepts the image from the DS. 35 | 36 | TWAIN defines three modes of image transfer: 37 | Native - on Windows this is a DIB (Device Independent Bitmap) in memory. Note that Windows has two kinds of bitmaps! 38 | Memory - strips or blocks of pixels in a series of memory buffers. 39 | File - the DS writes the image out directly to a file. [A DS is not required to support this mode.] 40 | 41 | 5. If appropriate, the application may transfer multiple images until it chooses to stop, or until the DS signals that no more images are available. 42 | 43 | 6. The application normally then disables the DS and closes it - in symmetry with the open/enable steps we started with. 44 | 45 | EZTWAIN 46 | EZTwain sits between the application and the TWAIN DSM, hiding the complexity of the TWAIN API from the rest of the application. With EZTwain, TWAIN is still needed - all the TWAIN parts play their usual roles. To the application, EZTWAIN presents a simplified version of the TWAIN API, plus additional features that are useful to scanning applications, such as image file loading and saving. EZTWAIN relieves the application of the chore of routing all windows messages through TWAIN as needed, and of waiting for and reacting to the image-ready notification. 47 | > [https://zh.wikipedia.org/wiki/TWAIN](https://zh.wikipedia.org/wiki/TWAIN "https://zh.wikipedia.org/wiki/TWAIN") 48 | 49 | ## TWAIN Stucture 50 | 51 | ### Layout 52 | ![](https://github.com/mrlitong/TWAIN-SDK/blob/master/source/twain_layout.jpg) 53 | 54 | ### Application 55 | TODO 56 | 57 | ### Source Manager 58 | 59 | In this figure, we can see that Source Manager plays a very important role as a bridge between Application and Source. Through the unified entry function DSM_Entry(), we can transfer messages between Application and Source to achieve the purpose of communication. The communication between the Source Manager and the Source is done through DS_Entry(). The developer doesn't have to worry about how this function is called. 60 | Source Manager can automatically detect the installed image device on the user's computer and can load the device as needed. 61 | 62 | ### Source 63 | TWAIN core module, a dll file provided by the device manufacturer, this dll and TWAIN interface remain unified, but ** different manufacturers are not exactly the same **. Developers need to perform logical judgments and other verifications at the Application layer. This component is dedicated to solving this problem. 64 | 65 | ## TWAIN-SDK 66 | 67 | TWAIN-SDK provides a unified developer interface for applications that supports the following scanner models: 68 | - Canon CR-1XX series 3XX series,6XX series,D12XX series,FS27XX series,FB63XX series 69 | - Panasonic KV-S50XX series,KV-S20XX series 70 | - Kodak i30XX series,i26XX series 71 | - Fujitsu 72 | - UNISLAN 73 | - Epson 74 | 75 | Developers do not need to care about hardware differences or interface differences between different scanners. 76 | 77 | ## **Guide** 78 | 79 | ### 1.Get TWAIN pointer based on OS 80 | 81 | ```C 82 | DSMENTRYPROC lpDSM_Entry; //* DSM_Entry pointer 83 | HMODULE hDSMDLL; //* Twain_32.Dll handle 84 | 85 | if ((hDSMDLL = LoadLibrary("TWAIN_32.DLL")) != NULL) 86 | { 87 | if ( (lpDSM_Entry =(DSMENTRYPROC) GetProcAddress(hDSMDLL,MAKEINTRESOURCE(1)))!=NULL) 88 | } 89 | // All below operation based on this pointer. 90 | ``` 91 | 92 | ### 2. Open Source Manager 93 | 94 | ```C 95 | int CTwain::OpenSourceManager(void) 96 | { 97 | TW_UINT16 rc; 98 | //... 99 | //hPWnd is the handler of the parent's windows of Source. 100 | rc = (*lpDSM_Entry) ( 101 | &AppID, 102 | NULL, 103 | DG_CONTROL,DAT_PARENT,MSG_OPENDSM, (TW_MEMREF) & (*hPWnd) 104 | ) ; 105 | 106 | switch (rc) // Check if Source Manager is prepared. 107 | { 108 | case TWRC_SUCCESS: // done! 109 | //... 110 | case TWRC_CANCEL: 111 | //... 112 | } 113 | //... 114 | } 115 | ``` 116 | 117 | ### 3.Open Source 118 | 119 | ```C 120 | int CTwain::OpenSource(void) 121 | { 122 | TW_UINT16 rc; 123 | rc = (*lpDSM_Entry) (&AppID,NULL, 124 | DG_CONTROL,DAT_IDENTITY,MSG_OPENDS, 125 | (TW_MEMREF) &SourceID); 126 | switch (rc) 127 | { 128 | case TWRC_SUCCESS: // done! 129 | //... 130 | } 131 | //... 132 | } 133 | ``` 134 | 135 | ### 4. Handle event of Source 136 | 137 | ```C 138 | int CTwain::DealSourceMsg(MSG *pMSG) 139 | { 140 | TW_UINT16 rc = TWRC_NOTDSEVENT; 141 | TW_EVENT twEvent; 142 | twEvent.pEvent = (TW_MEMREF) pMSG; 143 | rc = (*lpDSM_Entry) (&AppID,&SourceID, 144 | DG_CONTROL,DAT_EVENT,MSG_PROCESSEVENT, 145 | (TW_MEMREF) &twEvent); 146 | switch (twEvent.TWMessage) 147 | { 148 | case MSG_XFERREADY: //iStatus=6 149 | iStatus=6; 150 | GetBmpInfo(); 151 | DoNativeTransfer(); 152 | case MSG_CLOSEDSREQ: //close 153 | case MSG_CLOSEDSOK: 154 | case MSG_NULL: 155 | } 156 | . . . 157 | } 158 | ``` 159 | 160 | ### 5.Data transport 161 | 162 | ```C 163 | int CTwain::DoNativeTransfer(void) 164 | { 165 | TW_UINT32 hBitMap = NULL; // Pointing to address of image data. 166 | TW_UINT16 rc; 167 | HANDLE hbm_acq = NULL; 168 | rc = (*lpDSM_Entry)(&AppID,&SourceID, 169 | DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET, 170 | (TW_MEMREF)&hBitMap); 171 | switch (rc) 172 | { 173 | case TWRC_XFERDONE: 174 | hbm_acq = (HBITMAP)hBitMap; 175 | SendMessage(*hPWnd, PM_XFERDONE, (WPARAM)hbm_acq, 0); 176 | iStatus = 7; 177 | break; 178 | case TWRC_CANCEL: 179 | case TWRC_FAILURE: 180 | } 181 | //... 182 | } 183 | ``` 184 | 185 | ### 6.Handle image data 186 | 187 | ```C 188 | LRESULT CTwainAppView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 189 | { 190 | if (message==PM_XFERDONE) // Recieve PM_XFERDONE message 191 | { 192 | HBITMAP hBmp=FixUp(HANDLE(wParam)); // image transform handling 193 | Bitmap *pBm=0; // GDI+ object 194 | pBmp=pBm->FromHBITMAP(hBmp,hDibPal); 195 | Invalidate(); 196 | //... 197 | } 198 | return CView::WindowProc(message, wParam, lParam); 199 | } 200 | ``` 201 | -------------------------------------------------------------------------------- /friendly interface/TwainAppCMD.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright ?2007 TWAIN Working Group: 3 | * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company, 4 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 5 | * Ricoh Corporation, and Xerox Corporation. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the TWAIN Working Group nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | ***************************************************************************/ 31 | 32 | /** 33 | * @file TwainAppCMD.h 34 | * TWAIN CMD Application. 35 | * A TWAIN Application communicates with the DSM to acquire images. 36 | * The goal of the application is to acquire data from a Source. 37 | * However, applications cannot contact the Source directly. All requests for 38 | * data, capability information, error information, etc. must be handled 39 | * Through the Source Manager. 40 | * @author JFL Peripheral Solutions Inc. 41 | * @date April 2007 42 | */ 43 | 44 | #ifndef __TWAINAPPCMD_H__ 45 | #define __TWAINAPPCMD_H__ 46 | 47 | #pragma once 48 | 49 | #ifdef _WINDOWS 50 | #ifndef __AFXWIN_H__ 51 | #error include 'stdafx.h' before including this file for PCH 52 | #endif 53 | #endif 54 | 55 | #include "TwainApp.h" 56 | 57 | #ifndef TWH_CMP_MSC 58 | typedef void* HWND; 59 | #endif 60 | 61 | using namespace std; 62 | 63 | #ifdef TWNDS_OS_LINUX 64 | #include 65 | #endif 66 | 67 | 68 | 69 | /** 70 | * The Main Application Class. 71 | */ 72 | class TwainAppCMD : public TwainApp 73 | { 74 | public: 75 | /** 76 | * Constructor for the main application. 77 | * Initialize the application. 78 | * @param[in] parent handle to Window 79 | */ 80 | TwainAppCMD(HWND parent = NULL); 81 | 82 | /** 83 | * Deconstructor for the main application TwainAppCMD. 84 | * Clean up any alocated memory. 85 | */ 86 | ~TwainAppCMD(); 87 | 88 | /** 89 | * Fills an identity structure with this applications identity details. 90 | * Initialize the Apps identity so the DSM can uniquely identify it. 91 | * @param[out] _identity a structure that will get filled with Applications details 92 | */ 93 | virtual void fillIdentity(TW_IDENTITY& _identity); 94 | 95 | /** 96 | * Override so we can Initilize 97 | * @param[in] _dsID the ID of the datasource to load 98 | */ 99 | int loadDS(bool isRedPaper = false); 100 | /** 101 | * @param[in] _dsID, if -1, then try using default data source; 102 | * otherwise use specified data source 103 | */ 104 | int tryLoadDS(TW_INT32 _dsID); 105 | 106 | /** 107 | * Override so we can Initilize 108 | * @param[in] _dsID the ID of the datasource to load 109 | */ 110 | //virtual int beforeLoadDS(const TW_INT32 _dsID); 111 | 112 | /** 113 | * Unloads the currently loaded datasource. If successful moves the 114 | * app to state 3. 115 | */ 116 | virtual void unloadDS(); 117 | 118 | /** 119 | * Print a list of Data Sources. Prints to stdout a quick list of the 120 | * Data Sources the app knows about. 121 | */ 122 | void printAvailableDataSources(); 123 | 124 | /** 125 | * Prints an identity structure that uniquely identifies an Application 126 | * or Data Source out in detail to stdout. 127 | * @param[in] _ident the TW_IDENTITY structure to print 128 | */ 129 | void printIdentStruct(const TW_IDENTITY& _ident); 130 | 131 | /** 132 | * Goes through the list of known identity structures and prints the one 133 | * with an ID that matches the passed in id. 134 | * @param[in] _identityID The ID of the identity structure to print 135 | */ 136 | void printIdentityStruct(const TW_UINT32 _identityID); 137 | 138 | /** 139 | * Initialize default capabilities. 140 | * Negotiates the default capabilities with the currently opened data source. 141 | */ 142 | void initCaps(); 143 | /** 144 | * Free allocated capabilities. 145 | */ 146 | void uninitCaps(); 147 | /** 148 | * Tries to starts the scanning process. Must be in state 6 to start. 149 | * If successfully finishes scan moves app to state 5. 150 | */ 151 | void startScan(); 152 | 153 | void InitCanon(); 154 | void InitPanasonic(); 155 | 156 | void InitKodak(); 157 | void InitFujitsu(); 158 | 159 | void InitScanner(const std::string& scannerName); 160 | 161 | 162 | TW_INT16 ResetAll(); 163 | 164 | 165 | /** 166 | * Sets the set_CAP_DUPLEX capability 167 | * @param[in] _duplex the value to set 168 | */ 169 | void set_CAP_DUPLEX(const TW_INT16 _duplex); 170 | 171 | 172 | 173 | /** 174 | * Sets the CAP_XFERCOUNT capability 175 | * @param[in] _count the value to set 176 | */ 177 | void set_CAP_XFERCOUNT(const TW_INT16 _count); 178 | 179 | /** 180 | * Sets the ICAP_UNITS capability 181 | * @param[in] _val the value to set 182 | */ 183 | void set_ICAP_UNITS(const TW_UINT16 _val); 184 | 185 | /** 186 | * Sets the ICAP_PIXELTYPE capability 187 | * @param[in] _pt the value to set 188 | */ 189 | void set_ICAP_PIXELTYPE(const TW_UINT16 _pt); 190 | 191 | /** 192 | * Sets the ICAP_RESOLUTION specified in _Cap 193 | * @param[in] _Cap the RESOLUTION cap to set, either ICAP_XRESOLUTION or ICAP_YRESOLUTION 194 | * @param[in] _pVal the value to set the cap to. 195 | */ 196 | void set_ICAP_RESOLUTION(const TW_UINT16 _Cap, const pTW_FIX32 _pVal); 197 | 198 | /** 199 | * Sets the ICAP_XFERMECH capability 200 | * @param[in] _mech the mechanism to use. (TWSX_NATIVE, TWSX_FILE, TWSX_MEMORY) 201 | */ 202 | void set_ICAP_XFERMECH(const TW_UINT16 _mech); 203 | 204 | /** 205 | * Sets the ICAP_IMAGEFILEFORMAT capability 206 | * @param[in] _fileformat the compression to use. (TWFF_TIFF, TWFF_PICT, TWFF_BMP, TWFF_XBM, TWFF_JFIF, TWFF_FPX, TWFF_TIFFMULTI, TWFF_PNG, TWFF_SPIFF, TWFF_EXIF) 207 | */ 208 | void set_ICAP_IMAGEFILEFORMAT(const TW_UINT16 _fileformat); 209 | 210 | /** 211 | * Sets the ICAP_COMPRESSION capability 212 | * @param[in] _comp the compression to use. (TWCP_NONE, TWCP_PACKBITS, TWCP_GROUP4, TWCP_JPEG, ...) 213 | */ 214 | void set_ICAP_COMPRESSION(const TW_UINT16 _comp); 215 | 216 | /** 217 | * Sets the ICAP_FRAMES capability 218 | * @param[in] _pFrame the frame data to set 219 | */ 220 | void set_ICAP_FRAMES(const pTW_FRAME _pFrame); 221 | 222 | /** 223 | * Sets the ICAP_BITDEPTH capability using a TW_ENUMERATION struct. 224 | * @param[in] _nVal the bit depth to set 225 | */ 226 | void set_ICAP_BITDEPTH(const TW_UINT16 _nVal); 227 | 228 | /** 229 | * Gets the current setting for the ICAP_UNITS cap 230 | * @param[out] _val set to the caps value 231 | * @return true on succes 232 | */ 233 | bool getICAP_UNITS(TW_UINT16& _val); 234 | 235 | /** 236 | * Gets the current setting for the CAP_XFERCOUNT cap 237 | * @param[out] _val set to the caps value 238 | * @return true on succes 239 | */ 240 | bool getCAP_XFERCOUNT(TW_INT16& _val); 241 | 242 | /** 243 | * Gets the current setting for the ICAP_XFERMECH cap 244 | * @param[out] _val a TW_UINT16 holding the current transfer method (TWSX_NATIVE, etc...) 245 | * @return true on succes 246 | */ 247 | bool getICAP_XFERMECH(TW_UINT16& _val); 248 | 249 | /** 250 | * Gets the current setting for the ICAP_IMAGEFILEFORMAT cap 251 | * @param[out] _val a TW_UINT16 holding the current compression method (TWFF_TIFF, TWFF_PICT, TWFF_BMP, TWFF_XBM, TWFF_JFIF, TWFF_FPX, TWFF_TIFFMULTI, TWFF_PNG, TWFF_SPIFF, TWFF_EXIF) 252 | * @return true on succes 253 | */ 254 | bool getICAP_IMAGEFILEFORMAT(TW_UINT16& _val); 255 | 256 | /** 257 | * Gets the current setting for the ICAP_COMPRESSION cap 258 | * @param[out] _val a TW_UINT16 holding the current compression method (TWCP_NONE, TWCP_PACKBITS, TWCP_GROUP4, TWCP_JPEG, ...) 259 | * @return true on succes 260 | */ 261 | bool getICAP_COMPRESSION(TW_UINT16& _val); 262 | 263 | /** 264 | * Gets the current setting for the ICAP_PIXELTYPE cap 265 | * @param[out] _val a TW_UINT16 holding the current pixel type (TWPT_BW, etc...) 266 | * @return true on succes 267 | */ 268 | bool getICAP_PIXELTYPE(TW_UINT16& _val); 269 | 270 | /** 271 | * Gets the current setting for the ICAP_BITDEPTH cap 272 | * @param[out] _val a TW_UINT16 holding the current bit depth 273 | * @return true on succes 274 | */ 275 | bool getICAP_BITDEPTH(TW_UINT16& _val); 276 | 277 | /** 278 | * Gets the current setting for the ICAP_XRESOLUTION cap 279 | * @param[out] _xres a TW_FIX32 holding the current x resolution 280 | * @return true on succes 281 | */ 282 | bool getICAP_XRESOLUTION(TW_FIX32& _xres); 283 | 284 | /** 285 | * Gets the current setting for the ICAP_YRESOLUTION cap 286 | * @param[out] _yres a TW_FIX32 holding the current y resolution 287 | * @return true on succes 288 | */ 289 | bool getICAP_YRESOLUTION(TW_FIX32& _yres); 290 | 291 | 292 | //////////////// 293 | // CAPABILITIES 294 | 295 | TW_CAPABILITY m_CAP_XFERCOUNT; /**< Number of images the application is willing to accept this session. */ 296 | TW_CAPABILITY m_ICAP_XFERMECH; /**< Transfer mechanism - used to learn options and set-up for upcoming transfer. */ 297 | TW_CAPABILITY m_ICAP_IMAGEFILEFORMAT; /**< File format saved when using File Xfer Mechanism. */ 298 | TW_CAPABILITY m_ICAP_COMPRESSION; /**< Compression method used for upcoming transfer. */ 299 | TW_CAPABILITY m_ICAP_UNITS; /**< Unit of measure (inches, centimeters, etc). */ 300 | TW_CAPABILITY m_ICAP_PIXELTYPE; /**< The type of pixel data (B/W, gray, color, etc). */ 301 | TW_CAPABILITY m_ICAP_BITDEPTH; /**< Pixel bit depth for Current value of ICAP_PIXELTYPE. */ 302 | TW_CAPABILITY m_ICAP_XRESOLUTION; /**< Current/Available optical resolutions for x-axis. */ 303 | TW_CAPABILITY m_ICAP_YRESOLUTION; /**< Current/Available optical resolutions for y-axis */ 304 | TW_CAPABILITY m_ICAP_FRAMES; /**< Size and location of frames on page. */ 305 | 306 | #ifdef TWNDS_OS_LINUX 307 | sem_t m_TwainEvent; 308 | #endif 309 | 310 | public: 311 | 312 | // check if canon or panasonic scanner is connected, if yes, set to default scanner. 313 | int CheckCanonPanasonic(); 314 | 315 | //Function : Get scanner information like "serial number",or "vender",or"config",etc. 316 | //Notice : "Current" means the current connecting scanner driver,you should make sure that 317 | // DS is already opened and got by your application. 318 | static std::string GetCurrentScannerInfo(); 319 | 320 | private: 321 | std::string mCurrentScannerType; 322 | 323 | }; 324 | 325 | #endif // __TWAINAPPCMD_H__ 326 | -------------------------------------------------------------------------------- /twaintest_src/TwainCpp.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "twaincpp.h" 3 | 4 | /* 5 | Constructor: 6 | Parameters : HWND 7 | Window to subclass 8 | 9 | */ 10 | CTwain::CTwain(HWND hWnd) 11 | { 12 | m_hTwainDLL = NULL; 13 | m_pDSMProc = NULL; 14 | m_bSourceSelected = FALSE; 15 | m_bDSOpen = m_bDSMOpen = FALSE; 16 | m_bSourceEnabled = FALSE; 17 | m_bModalUI = TRUE; 18 | m_nImageCount = TWCPP_ANYCOUNT; 19 | if(hWnd) 20 | { 21 | InitTwain(hWnd); 22 | } 23 | } 24 | 25 | CTwain::~CTwain() 26 | { 27 | ReleaseTwain(); 28 | } 29 | 30 | /* 31 | Initializes TWAIN interface . Is already called from the constructor. 32 | It should be called again if ReleaseTwain is called. 33 | 34 | hWnd is the window which has to subclassed in order to recieve 35 | Twain messaged. Normally - this would be your main application window. 36 | 37 | */ 38 | BOOL CTwain::InitTwain(HWND hWnd) 39 | { 40 | char libName[512]; 41 | if(IsValidDriver()) 42 | { 43 | return TRUE; 44 | } 45 | memset(&m_AppId,0,sizeof(m_AppId)); 46 | if(!IsWindow(hWnd)) 47 | { 48 | return FALSE; 49 | } 50 | m_hMessageWnd = hWnd; 51 | strcpy(libName,"TWAIN_32.DLL"); 52 | 53 | m_hTwainDLL = LoadLibrary(libName); 54 | if(m_hTwainDLL != NULL) 55 | { 56 | if(!(m_pDSMProc = (DSMENTRYPROC)GetProcAddress(m_hTwainDLL,MAKEINTRESOURCE(1)))) 57 | { 58 | FreeLibrary(m_hTwainDLL); 59 | m_hTwainDLL = NULL; 60 | } 61 | } 62 | if(IsValidDriver()) 63 | { 64 | GetIdentity(); 65 | m_bDSMOpen= CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&m_hMessageWnd); 66 | return TRUE; 67 | } 68 | else 69 | { 70 | return FALSE; 71 | } 72 | } 73 | 74 | /* 75 | Releases the twain interface . Need not be called unless you 76 | want to specifically shut it down. 77 | */ 78 | void CTwain::ReleaseTwain() 79 | { 80 | if(IsValidDriver()) 81 | { 82 | CloseDSM(); 83 | FreeLibrary(m_hTwainDLL); 84 | m_hTwainDLL = NULL; 85 | m_pDSMProc = NULL; 86 | } 87 | } 88 | 89 | /* 90 | Returns true if a valid driver has been loaded 91 | */ 92 | BOOL CTwain::IsValidDriver() const 93 | { 94 | return (m_hTwainDLL && m_pDSMProc); 95 | } 96 | 97 | /* 98 | Entry point into Twain. For a complete description of this 99 | routine please refer to the Twain specification 1.8 100 | */ 101 | BOOL CTwain::CallTwainProc(pTW_IDENTITY pOrigin,pTW_IDENTITY pDest, 102 | TW_UINT32 DG,TW_UINT16 DAT,TW_UINT16 MSG, 103 | TW_MEMREF pData) 104 | { 105 | if(IsValidDriver()) 106 | { 107 | USHORT ret_val; 108 | ret_val = (*m_pDSMProc)(pOrigin,pDest,DG,DAT,MSG,pData); 109 | m_returnCode = ret_val; 110 | if(ret_val != TWRC_SUCCESS) 111 | { 112 | (*m_pDSMProc)(pOrigin,pDest,DG_CONTROL,DAT_STATUS,MSG_GET,&m_Status); 113 | } 114 | return (ret_val == TWRC_SUCCESS); 115 | } 116 | else 117 | { 118 | m_returnCode = TWRC_FAILURE; 119 | return FALSE; 120 | } 121 | } 122 | 123 | /* 124 | This function should ideally be overridden in the derived class . If only a 125 | few fields need to be updated , call CTawin::GetIdentity first in your 126 | derived class 127 | */ 128 | void CTwain::GetIdentity() 129 | { 130 | // Expects all the fields in m_AppId to be set except for the id field. 131 | m_AppId.Id = 0; // Initialize to 0 (Source Manager 132 | // will assign real value) 133 | m_AppId.Version.MajorNum = 3; //Your app's version number 134 | m_AppId.Version.MinorNum = 5; 135 | m_AppId.Version.Language = TWLG_USA; 136 | m_AppId.Version.Country = TWCY_USA; 137 | strcpy (m_AppId.Version.Info, "3.5"); 138 | m_AppId.ProtocolMajor = TWON_PROTOCOLMAJOR; 139 | m_AppId.ProtocolMinor = TWON_PROTOCOLMINOR; 140 | m_AppId.SupportedGroups = DG_IMAGE | DG_CONTROL; 141 | strcpy (m_AppId.Manufacturer, "MICSS"); 142 | strcpy (m_AppId.ProductFamily, "Generic"); 143 | strcpy (m_AppId.ProductName, "Twain Test"); 144 | 145 | } 146 | 147 | 148 | /* 149 | Called to display a dialog box to select the Twain source to use. 150 | This can be overridden if a list of all sources is available 151 | to the application. These sources can be enumerated by Twain. 152 | it is not yet supportted by CTwain. 153 | */ 154 | BOOL CTwain::SelectSource() 155 | { 156 | memset(&m_Source,0,sizeof(m_Source)); 157 | if(!SourceSelected()) 158 | { 159 | SelectDefaultSource(); 160 | } 161 | if(CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_USERSELECT,&m_Source)) 162 | { 163 | m_bSourceSelected = TRUE; 164 | } 165 | return m_bSourceSelected; 166 | } 167 | 168 | /* 169 | Called to select the default source 170 | */ 171 | BOOL CTwain::SelectDefaultSource() 172 | { 173 | m_bSourceSelected = CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_GETDEFAULT,&m_Source); 174 | return m_bSourceSelected; 175 | } 176 | 177 | /* 178 | Closes the Data Source 179 | */ 180 | void CTwain::CloseDS() 181 | { 182 | if(DSOpen()) 183 | { 184 | DisableSource(); 185 | CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&m_Source); 186 | m_bDSOpen = FALSE; 187 | } 188 | } 189 | 190 | /* 191 | Closes the Data Source Manager 192 | */ 193 | void CTwain::CloseDSM() 194 | { 195 | if(DSMOpen()) 196 | { 197 | CloseDS(); 198 | CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_PARENT,MSG_CLOSEDSM,(TW_MEMREF)&m_hMessageWnd); 199 | m_bDSMOpen = FALSE; 200 | } 201 | } 202 | 203 | /* 204 | Returns true if the Data Source Manager is Open 205 | */ 206 | BOOL CTwain::DSMOpen() const 207 | { 208 | return IsValidDriver() && m_bDSMOpen; 209 | } 210 | 211 | /* 212 | Returns true if the Data Source is Open 213 | */ 214 | BOOL CTwain::DSOpen() const 215 | { 216 | return IsValidDriver() && DSMOpen() && m_bDSOpen; 217 | } 218 | 219 | /* 220 | Opens a Data Source supplied as the input parameter 221 | */ 222 | BOOL CTwain::OpenSource(TW_IDENTITY *pSource) 223 | { 224 | if(pSource) 225 | { 226 | m_Source = *pSource; 227 | } 228 | if(DSMOpen()) 229 | { 230 | if(!SourceSelected()) 231 | { 232 | SelectDefaultSource(); 233 | } 234 | m_bDSOpen = CallTwainProc(&m_AppId,NULL,DG_CONTROL,DAT_IDENTITY,MSG_OPENDS,(TW_MEMREF)&m_Source); 235 | } 236 | return DSOpen(); 237 | } 238 | 239 | /* 240 | Should be called from the main message loop of the application. Can always be called, 241 | it will not process the message unless a scan is in progress. 242 | */ 243 | BOOL CTwain::ProcessMessage(MSG msg) 244 | { 245 | if(SourceEnabled()) 246 | { 247 | TW_EVENT twEvent; 248 | twEvent.pEvent = (TW_MEMREF)&msg; 249 | twEvent.TWMessage = MSG_NULL; 250 | 251 | CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_EVENT,MSG_PROCESSEVENT,(TW_MEMREF)&twEvent); 252 | if(GetRC() != TWRC_NOTDSEVENT) 253 | { 254 | TranslateMessage(twEvent); 255 | } 256 | return FALSE; 257 | 258 | } 259 | return FALSE; 260 | } 261 | 262 | /* 263 | Queries the capability of the Twain Data Source 264 | */ 265 | BOOL CTwain::GetCapability(TW_CAPABILITY& twCap,TW_UINT16 cap,TW_UINT16 conType) 266 | { 267 | if(DSOpen()) 268 | { 269 | twCap.Cap = cap; 270 | twCap.ConType = conType; 271 | twCap.hContainer = NULL; 272 | 273 | if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_GET,(TW_MEMREF)&twCap)) 274 | { 275 | return TRUE; 276 | } 277 | } 278 | return FALSE; 279 | } 280 | 281 | /* 282 | Queries the capability of the Twain Data Source 283 | */ 284 | BOOL CTwain::GetCapability(TW_UINT16 cap,TW_UINT32& value) 285 | { 286 | TW_CAPABILITY twCap; 287 | if(GetCapability(twCap,cap)) 288 | { 289 | pTW_ONEVALUE pVal; 290 | pVal = (pTW_ONEVALUE )GlobalLock(twCap.hContainer); 291 | if(pVal) 292 | { 293 | value = pVal->Item; 294 | GlobalUnlock(pVal); 295 | GlobalFree(twCap.hContainer); 296 | return TRUE; 297 | } 298 | } 299 | return FALSE; 300 | } 301 | 302 | 303 | /* 304 | Sets the capability of the Twain Data Source 305 | */ 306 | BOOL CTwain::SetCapability(TW_UINT16 cap,TW_UINT16 value,BOOL sign) 307 | { 308 | if(DSOpen()) 309 | { 310 | TW_CAPABILITY twCap; 311 | pTW_ONEVALUE pVal; 312 | BOOL ret_value = FALSE; 313 | 314 | twCap.Cap = cap; 315 | twCap.ConType = TWON_ONEVALUE; 316 | 317 | twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE)); 318 | if(twCap.hContainer) 319 | { 320 | pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer); 321 | pVal->ItemType = sign ? TWTY_INT16 : TWTY_UINT16; 322 | pVal->Item = (TW_UINT32)value; 323 | GlobalUnlock(twCap.hContainer); 324 | ret_value = SetCapability(twCap); 325 | GlobalFree(twCap.hContainer); 326 | } 327 | return ret_value; 328 | } 329 | return FALSE; 330 | } 331 | 332 | /* 333 | Sets the capability of the Twain Data Source 334 | */ 335 | BOOL CTwain::SetCapability(TW_CAPABILITY& cap) 336 | { 337 | if(DSOpen()) 338 | { 339 | return CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_CAPABILITY,MSG_SET,(TW_MEMREF)&cap); 340 | } 341 | return FALSE; 342 | } 343 | 344 | /* 345 | Sets the number of images which can be accpeted by the application at one time 346 | */ 347 | BOOL CTwain::SetImageCount(TW_INT16 nCount) 348 | { 349 | if(SetCapability(CAP_XFERCOUNT,(TW_UINT16)nCount,TRUE)) 350 | { 351 | m_nImageCount = nCount; 352 | return TRUE; 353 | } 354 | else 355 | { 356 | if(GetRC() == TWRC_CHECKSTATUS) 357 | { 358 | TW_UINT32 count; 359 | if(GetCapability(CAP_XFERCOUNT,count)) 360 | { 361 | nCount = (TW_INT16)count; 362 | if(SetCapability(CAP_XFERCOUNT,nCount)) 363 | { 364 | m_nImageCount = nCount; 365 | return TRUE; 366 | } 367 | } 368 | } 369 | } 370 | return FALSE; 371 | } 372 | 373 | /* 374 | Called to enable the Twain Acquire Dialog. This too can be 375 | overridden but is a helluva job . 376 | */ 377 | BOOL CTwain::EnableSource(BOOL showUI) 378 | { 379 | if(DSOpen() && !SourceEnabled()) 380 | { 381 | TW_USERINTERFACE twUI; 382 | twUI.ShowUI = showUI; 383 | twUI.hParent = (TW_HANDLE)m_hMessageWnd; 384 | if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_ENABLEDS,(TW_MEMREF)&twUI)) 385 | { 386 | m_bSourceEnabled = TRUE; 387 | m_bModalUI = twUI.ModalUI; 388 | } 389 | else 390 | { 391 | m_bSourceEnabled = FALSE; 392 | m_bModalUI = TRUE; 393 | } 394 | return m_bSourceEnabled; 395 | } 396 | return FALSE; 397 | } 398 | 399 | /* 400 | Called to acquire images from the source. parameter numImages i the 401 | numberof images that you an handle concurrently 402 | */ 403 | BOOL CTwain::Acquire(int numImages) 404 | { 405 | if(DSOpen() || OpenSource()) 406 | { 407 | if(SetImageCount(numImages)) 408 | { 409 | if(EnableSource()) 410 | { 411 | return TRUE; 412 | } 413 | } 414 | } 415 | return FALSE; 416 | } 417 | 418 | /* 419 | Called to disable the source. 420 | */ 421 | BOOL CTwain::DisableSource() 422 | { 423 | if(SourceEnabled()) 424 | { 425 | TW_USERINTERFACE twUI; 426 | if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_USERINTERFACE,MSG_DISABLEDS,&twUI)) 427 | { 428 | m_bSourceEnabled = FALSE; 429 | return TRUE; 430 | } 431 | } 432 | return FALSE; 433 | } 434 | 435 | /* 436 | Called by ProcessMessage to Translate a TWAIN message 437 | */ 438 | void CTwain::TranslateMessage(TW_EVENT& twEvent) 439 | { 440 | switch(twEvent.TWMessage) 441 | { 442 | case MSG_XFERREADY: 443 | TransferImage(); 444 | break; 445 | case MSG_CLOSEDSREQ: 446 | if(CanClose()) 447 | { 448 | CloseDS(); 449 | } 450 | break; 451 | } 452 | } 453 | 454 | /* 455 | Gets Imageinfo for an image which is about to be transferred. 456 | */ 457 | BOOL CTwain::GetImageInfo(TW_IMAGEINFO& info) 458 | { 459 | if(SourceEnabled()) 460 | { 461 | return CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGEINFO,MSG_GET,(TW_MEMREF)&info); 462 | } 463 | return FALSE; 464 | } 465 | 466 | /* 467 | Trasnfers the image or cancels the transfer depending on the state of the 468 | TWAIN system 469 | */ 470 | void CTwain::TransferImage() 471 | { 472 | TW_IMAGEINFO info; 473 | BOOL bContinue=TRUE; 474 | while(bContinue) 475 | { 476 | if(GetImageInfo(info)) 477 | { 478 | int permission; 479 | permission = ShouldTransfer(info); 480 | switch(permission) 481 | { 482 | case TWCPP_CANCELTHIS: 483 | bContinue=EndTransfer(); 484 | break; 485 | case TWCPP_CANCELALL: 486 | CancelTransfer(); 487 | bContinue=FALSE; 488 | break; 489 | case TWCPP_DOTRANSFER: 490 | bContinue=GetImage(info); 491 | break; 492 | } 493 | } 494 | } 495 | } 496 | 497 | /* 498 | Ends the current transfer. 499 | Returns TRUE if the more images are pending 500 | */ 501 | BOOL CTwain::EndTransfer() 502 | { 503 | TW_PENDINGXFERS twPend; 504 | if(CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_ENDXFER,(TW_MEMREF)&twPend)) 505 | { 506 | return twPend.Count != 0; 507 | } 508 | return FALSE; 509 | } 510 | 511 | /* 512 | Aborts all transfers 513 | */ 514 | void CTwain::CancelTransfer() 515 | { 516 | TW_PENDINGXFERS twPend; 517 | CallTwainProc(&m_AppId,&m_Source,DG_CONTROL,DAT_PENDINGXFERS,MSG_RESET,(TW_MEMREF)&twPend); 518 | } 519 | 520 | /* 521 | Calls TWAIN to actually get the image 522 | */ 523 | BOOL CTwain::GetImage(TW_IMAGEINFO& info) 524 | { 525 | HANDLE hBitmap; 526 | CallTwainProc(&m_AppId,&m_Source,DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET,&hBitmap); 527 | switch(m_returnCode) 528 | { 529 | case TWRC_XFERDONE: 530 | CopyImage(hBitmap,info); 531 | break; 532 | case TWRC_CANCEL: 533 | break; 534 | case TWRC_FAILURE: 535 | CancelTransfer(); 536 | return FALSE; 537 | 538 | } 539 | GlobalFree(hBitmap); 540 | return EndTransfer(); 541 | } 542 | 543 | -------------------------------------------------------------------------------- /friendly interface/TwainApp.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright ?2007 TWAIN Working Group: 3 | * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company, 4 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 5 | * Ricoh Corporation, and Xerox Corporation. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * * Neither the name of the TWAIN Working Group nor the 16 | * names of its contributors may be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY 20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | ***************************************************************************/ 31 | 32 | /** 33 | * @file TwainApp.h 34 | * TWAIN Application. 35 | * A TWAIN Application communicates with the DSM to acquire images. 36 | * The goal of the application is to acquire data from a Source. 37 | * However, applications cannot contact the Source directly. All requests for 38 | * data, capability information, error information, etc. must be handled 39 | * Through the Source Manager. 40 | * @author JFL Peripheral Solutions Inc. 41 | * @date April 2007 42 | */ 43 | 44 | /*! \mainpage TWAIN Application 45 | * 46 | * The goal of the application is to acquire data from a Source. 47 | * However, applications cannot contact the Source directly. All requests for 48 | * data, capability information, error information, etc. must be handled 49 | * Through the Source Manager. 50 | * 51 | * 52 | * 53 | * 54 | * 55 | * 56 | * 57 | * 58 | * Copyright ?2007 TWAIN Working Group: Adobe Systems Incorporated, 59 | * AnyDoc Software Inc., Eastman Kodak Company, 60 | * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc., 61 | * Ricoh Corporation, and Xerox Corporation. 62 | * All rights reserved. 63 | */ 64 | #ifndef _TWAINAPP_H_ 65 | #define _TWAINAPP_H_ 66 | 67 | #pragma once 68 | 69 | #ifdef _WINDOWS 70 | #ifndef __AFXWIN_H__ 71 | #error include 'stdafx.h' before including this file for PCH 72 | #endif 73 | #endif 74 | 75 | #include 76 | #include 77 | #include 78 | 79 | #include "CommonTWAIN.h" 80 | #include "FreeImage.h" 81 | #include "DSMInterface.h" 82 | #include "MsgType.h" 83 | #include "../config/Configuration.h" 84 | #include "../utils/Queue.h" 85 | 86 | 87 | #ifndef TWH_CMP_MSC 88 | typedef void* HWND; 89 | #endif 90 | 91 | using namespace std; 92 | 93 | typedef std::function PostScanCallback; 94 | 95 | 96 | /** 97 | * Determine if two TW_FIX32 variables are equal. 98 | * @param[in] _fix1 First TW_FIX32 99 | * @param[in] _fix2 Second TW_FIX32 100 | * @return bool TRUE if equal 101 | */ 102 | bool operator== (const TW_FIX32& _fix1, const TW_FIX32& _fix2); 103 | 104 | /** 105 | * Output CMD messages. In CMD app used for prompt. In GUI app used by debugger 106 | * @param[in] pStr the message to display 107 | * @param[in] ... additional varibles 108 | */ 109 | void PrintCMDMessage(const char* const pStr, ...); 110 | 111 | /** 112 | * The Main Application Class. 113 | */ 114 | class ScanManager; 115 | class TwainApp 116 | { 117 | public: 118 | /** 119 | * Constructor for the main application. 120 | * Initialize the application. 121 | * @param[in] parent handle to Window 122 | */ 123 | TwainApp(HWND parent = NULL); 124 | 125 | /** 126 | * Deconstructor for the main application TwainApp. 127 | * Clean up any alocated memory. 128 | */ 129 | ~TwainApp(); 130 | 131 | 132 | TW_UINT16 DSM_Entry(TW_UINT32 _DG, 133 | TW_UINT16 _DAT, 134 | TW_UINT16 _MSG, 135 | TW_MEMREF _pData); 136 | /** 137 | * Print out error message and condition code from DS. Looks up the 138 | * condition code using the _pdestID and prints it after the _errorMsg. 139 | * If _errorMsg is empty, a default message is displayed. 140 | * @param[in] _pdestID the destination to get the condition code. 0 is DSM 141 | * anything else is a source. 142 | * @param[in] _errorMsg the error message to display. If empty a standard message 143 | * is displayed 144 | * @return a valid TWCC_xxxx condition code 145 | */ 146 | TW_INT16 printError(pTW_IDENTITY _pdestID = 0, const string& _errorMsg = ""); 147 | 148 | /** 149 | * Retrieves the condition code from the DSM. 150 | * @param[in] _pdestID a pointer to the source to query, or 0 for the DSM 151 | * @param[out] _cc this will be set to the condition code 152 | * @return a valid TWRC_xxxx return code 153 | */ 154 | TW_UINT16 getTWCC(pTW_IDENTITY _pdestID, TW_INT16& _cc); 155 | 156 | /** 157 | * Fills an identity structure with this applications identity details. 158 | * Initialize the Apps identity so the DSM can uniquely identify it. 159 | * @param[out] _identity a structure that will get filled with Applications details 160 | */ 161 | virtual void fillIdentity(TW_IDENTITY& _identity); 162 | 163 | /** 164 | * Exit application clean up everything. 165 | */ 166 | void exit(bool unloadDSM = false); 167 | 168 | /** 169 | * Try to connect to the DSM. Set the App to correct state. 170 | * m_DSMState is set to state 3 if successful. 171 | */ 172 | int connectDSM(); 173 | 174 | /** 175 | * Try to disconnect from the DSM. Set the App to correct state. 176 | * m_DSMState is set to state 2 if successful. 177 | */ 178 | void disconnectDSM(); 179 | 180 | /** 181 | * Queries the DSM for all available Data Sources. Discover all Data 182 | * Sources available and build a list of DS and store them in m_DataSources. 183 | */ 184 | int getSources(); 185 | 186 | /** 187 | * Try to load a Data Source. Loads the data source with the ID passed in. 188 | * To open a Data Source the DSM must be in state 3 (Open). If successful 189 | * moves the app to state 4 190 | * @param[in] _dsID the ID of the datasource to load, -1 to open the default 191 | * @param[in] DSMCallback 192 | */ 193 | //virtual int loadDS(const TW_INT32 _dsID); 194 | virtual int loadDS(); 195 | 196 | TW_INT32 _dsID; 197 | 198 | /** 199 | * Unloads the currently loaded datasource. If successful moves the 200 | * app to state 3. 201 | */ 202 | virtual void unloadDS(); 203 | 204 | /** 205 | * Request the acquisition of data from the currently opened source. If 206 | * successful moves app to state 5. 207 | * @param[in] hWnd the handle to the window 208 | * @param[in] bShowUI true to show UI false to enable without UI 209 | * @return true if successfully enabled DS. 210 | */ 211 | virtual bool enableDS(TW_HANDLE hWnd, BOOL bShowUI); 212 | 213 | /** 214 | * Show the DS GUI so the user can modify current settings. 215 | * successful moves app to state 5. 216 | * @param[in] hWnd the handle to the window 217 | * @return true if successfully enabled DS. 218 | */ 219 | virtual bool enableDSUIOnly(TW_HANDLE hWnd); 220 | 221 | /** 222 | * Tries to disable the sources UI. If successful moves app to state 4 223 | */ 224 | virtual void disableDS(); 225 | 226 | /** 227 | * Starts the scanning process using native mode. Data will be transfered 228 | * in native mode. 229 | */ 230 | void initiateTransfer_Native(); 231 | 232 | /** 233 | * Starts the scanning process using file mode. Data will be transfered 234 | * via a file. 235 | */ 236 | void initiateTransfer_File(TW_UINT16 fileformat = TWFF_TIFF); 237 | 238 | /** 239 | * Starts the scanning process using the memory strip mode. Data will be transfered 240 | * in memory using a buffer. 241 | */ 242 | void initiateTransfer_Memory(); 243 | 244 | /* 245 | * the ability to abort scan 246 | */ 247 | void setScanEnabled(bool bShouldScan) { 248 | std::unique_lock lock(this->mScanMutex); 249 | this->mShouldScan = bShouldScan; 250 | } 251 | 252 | bool shouldContinueScan() { 253 | std::unique_lock lock(this->mScanMutex); 254 | return mShouldScan; 255 | } 256 | 257 | /** 258 | * Abort the scanning process. 259 | * @return a valid TWRC_xxxx return code. 260 | */ 261 | TW_UINT16 DoAbortXfer(); 262 | 263 | /** 264 | * Try to sets a OneValue Capability of any of the TW_INT or TW_UINT types to the value passed 265 | * @param[in] Cap the capability to update to set 266 | * @param[in] _value the value to set 267 | * @param[in] _type the TWAIN Type to set 268 | * @return a valid TWRC_xxxx return code. 269 | */ 270 | TW_UINT16 set_CapabilityOneValue(TW_UINT16 Cap, const int _value, TW_UINT16 _type); 271 | 272 | /** 273 | * Try to sets a OneValue Capability of type TW_FIX32 to the value passed 274 | * @param[in] Cap the capability to update to set 275 | * @param[in] _pValue the value to set 276 | * @return a valid TWRC_xxxx return code. 277 | */ 278 | TW_UINT16 set_CapabilityOneValue(TW_UINT16 Cap, const pTW_FIX32 _pValue); 279 | 280 | /** 281 | * Try to sets a OneValue Capability of type TW_FRAME to the value passed 282 | * @param[in] Cap the capability to update to set 283 | * @param[in] _pValue the value to set 284 | * @return a valid TWRC_xxxx return code. 285 | */ 286 | TW_UINT16 set_CapabilityOneValue(TW_UINT16 Cap, const pTW_FRAME _pValue); 287 | 288 | /** 289 | * Try to sets an Array Capability of any of the TW_INT or TW_UINT types to the values passed 290 | * @param[in] Cap the capability to update to set 291 | * @param[in] _pValues pointer to the array of values to set 292 | * @param[in] Count the number of items in the array 293 | * @param[in] -type the type of items to set 294 | * @return a valid TWRC_xxxx return code. 295 | */ 296 | TW_UINT16 set_CapabilityArray(TW_UINT16 Cap, const int * _pValues, int Count, TW_UINT16 _type); 297 | 298 | /** 299 | * Gets the capability. 300 | * @param[in,out] _cap the capability struct to fill. _cap.Cap needs to be 301 | * @param[in] _msg one of MSG_GET, MSG_GETCURRENT, MSG_GETDEFAULT, or MSG_RESET 302 | * filled with the capability to retrieve. 303 | * @return a valid TWCC_xxxx condition code 304 | */ 305 | TW_INT16 get_CAP(TW_CAPABILITY& _cap, TW_UINT16 _msg = MSG_GET); 306 | 307 | /** 308 | * Query Support messages of the capability. 309 | * @param[in] _cap the capability id to lookup. 310 | * @param[out] _QS the Query Support of the cap 311 | * @return a valid TWRC_xxxx return code 312 | */ 313 | TW_INT16 QuerySupport_CAP(TW_UINT16 _cap, TW_UINT32 &_QS); 314 | 315 | /** 316 | * Get the lable for a capability. 317 | * @param[in] _cap the capability id to lookup. 318 | * @param[out] sLable the Lable if returned 319 | * @return a valid TWRC_xxxx return code 320 | */ 321 | TW_INT16 GetLabel(TW_UINT16 _cap, string &sLable); 322 | 323 | /** 324 | * Get the help or description for a capability. 325 | * @param[in] _cap the capability id to lookup. 326 | * @param[out] sDescription the Description or help if returned 327 | * @return a valid TWRC_xxxx return code 328 | */ 329 | TW_INT16 GetHelp(TW_UINT16 _cap, string &sHelp); 330 | 331 | /** 332 | * Returns a pointer to the applications identity structure. 333 | * @return a TW_IDENTITY pointer to the applications identity struct. 334 | */ 335 | pTW_IDENTITY getAppIdentity(); 336 | 337 | /** 338 | * Returns a pointer to the currently opened data source. 339 | * @param[in] _index the DS index to return 340 | * @return a TW_IDENTITY pointer to the opened data source 341 | * if nothing open then return NULL. 342 | */ 343 | pTW_IDENTITY getDataSource(TW_INT16 _index = -1) const; 344 | 345 | /** 346 | * Set the default data source. 347 | * @param[in] _index the DS index to set as default 348 | * @return a TW_IDENTITY pointer of the default. 349 | */ 350 | pTW_IDENTITY setDefaultDataSource(unsigned int _index); 351 | //pTW_IDENTITY setDefaultDataSource(pTW_IDENTITY pDs); 352 | /** 353 | * Returns a pointer to the default data source. 354 | * @return a TW_IDENTITY pointer to the default. 355 | */ 356 | pTW_IDENTITY getDefaultDataSource(); 357 | /** 358 | * Display the Select Source Dialog and returns a pointer to the selected data source. 359 | * @return a TW_IDENTITY pointer. NULL if no source selected. 360 | */ 361 | pTW_IDENTITY selectDefaultDataSource(void); 362 | 363 | /** 364 | * Gets the imageinfo of the currently transfered image 365 | * @return pointer to the image info 366 | */ 367 | pTW_IMAGEINFO getIMAGEINFO() { return &m_ImageInfo; } 368 | 369 | /** 370 | * Gets the extended image info of the currently transfered image 371 | * @return pointer to the extended image info 372 | */ 373 | string getEXIMAGEINFO(){ return m_strExImageInfo; } 374 | 375 | /** 376 | * retrieve the imageinfo for the current image 377 | * @return true on succes 378 | */ 379 | bool updateIMAGEINFO(); 380 | 381 | /** 382 | * retrieve the extended image info for the current image 383 | * @return true on succes 384 | */ 385 | virtual void updateEXTIMAGEINFO(); 386 | 387 | 388 | 389 | int m_DSMState; /**< The current TWAIN state of the dsm (2-7) */ 390 | TW_UINT16 m_DSMessage; /**< Statis to indicate if we are waiting for DS */ 391 | 392 | protected: 393 | /** 394 | * Create a DIB of the dimention set by m_ImageInfo and bitdepth of 395 | * data source. 396 | * @return the DIB created on succes or 0 if failed. 397 | */ 398 | FIBITMAP* createDIB(); 399 | 400 | HWND m_Parent; /**< Handle to Window to recieve window messages. */ 401 | TW_IDENTITY m_MyInfo; /**< Identity structure with this applications identity details */ 402 | pTW_IDENTITY m_pDataSource; /**< Pointer of Identity structure to current loaded data souce */ 403 | vector m_DataSources; /**< Store a list of available data sources located by DSM */ 404 | size_t m_DsIndex; /**< ds index in m_DataSources */ 405 | 406 | TW_IMAGEINFO m_ImageInfo; /**< Detailed image info retrieved from the DS */ 407 | pTW_EXTIMAGEINFO m_pExtImageInfo; /**< Detailed extended image info retrieved from the DS */ 408 | TW_UINT16 m_nXferNum; /**< Keep track of the number of images attempted to transfer - used when saving file to disk*/ 409 | string m_strExImageInfo; /**< Extended image info retrieved from the DS */ 410 | TW_UINT16 m_nGetLableSupported; /**< Remember if MSG_GETLABLE is supported */ 411 | TW_UINT16 m_nGetHelpSupported; /**< Remember if MSG_GETHELP is supported */ 412 | string m_strSavePath; /**< The Path to save the files to */ 413 | 414 | TW_USERINTERFACE m_ui; /**< Coordinates UI between application and data source. */ 415 | DriverConfig* m_pDriverConfig; /* configuration for current ds */ 416 | 417 | bool mShouldScan; 418 | std::mutex mScanMutex; // used to protect state 419 | 420 | public: 421 | void SetSavePath(const std::string&); 422 | std::string getSavePath() { return m_strSavePath; } 423 | 424 | void SetRootPath(string rootPath); 425 | void setWriteOutputImageMsgCallbackQueue(BlockQueue *pWritedImageQueue) { 426 | this->mpWritedImageQueue = pWritedImageQueue; 427 | } 428 | 429 | void RegisterPostScanCallback(PostScanCallback fnPScan) { 430 | this->mPostScanCallbck = fnPScan; 431 | } 432 | 433 | int SaveImageFiles(vector& v); 434 | 435 | int SaveTWCC(pTW_IDENTITY pId, TW_INT16& _cc); 436 | int UploadTWCC(pTW_IDENTITY pId, TW_INT16& _cc); 437 | 438 | 439 | //Funcation : Get serial number of current connecting scanner. 440 | //Notice : Make sure you have already get DS,or return value will be a null string. 441 | // Multiple devices may all report the same serial number! 442 | // See more details at:TWAIN WORKING GROUP 443 | //Author : litongtongxue@gmail.com 444 | string GetSerialNumber(); 445 | 446 | 447 | 448 | 449 | 450 | 451 | //static DWORD WINAPI SaveImageFileWorker(LPVOID pM); 452 | // //root path to save images. 453 | private: 454 | PostScanCallback mPostScanCallbck; 455 | 456 | string m_examId; 457 | string m_schoolId; 458 | int m_batchNo; 459 | string m_strRootPath; 460 | 461 | // inner queue, image has been scanned but not saved as bmp format, 462 | // will be saved by another thread 463 | //BlockQueue mPendingSaveImageQueue; 464 | 465 | // callback queue, image has been saved as bmp file, 466 | // will inform another thread that such image is ready to 467 | // be recognized/uploaded 468 | BlockQueue* mpWritedImageQueue; 469 | 470 | protected: 471 | string m_serialNumber; 472 | vector m_imageFiles; 473 | }; 474 | 475 | #endif // _TWAINAPP_H_ 476 | -------------------------------------------------------------------------------- /twaintest_src/DIB.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "math.h" 3 | #include "DIB.h" 4 | 5 | #define BIG_DISTANCE 10000000L 6 | 7 | #define DIST(r1,g1,b1,r2,g2,b2) \ 8 | (long) (3L*(long)((r1)-(r2))*(long)((r1)-(r2)) + \ 9 | 4L*(long)((g1)-(g2))*(long)((g1)-(g2)) + \ 10 | 2L*(long)((b1)-(b2))*(long)((b1)-(b2))) 11 | 12 | 13 | static unsigned char masktable[] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; 14 | 15 | 16 | 17 | CDIB::CDIB(HANDLE hDib,int nBits) 18 | { 19 | m_pVoid = NULL; 20 | m_pLinePtr = NULL; 21 | m_bUseGamma=FALSE; 22 | width=height=0; 23 | if(hDib) 24 | { 25 | CreateFromHandle(hDib,nBits); 26 | } 27 | } 28 | 29 | CDIB::~CDIB() 30 | { 31 | DestroyDIB(); 32 | } 33 | 34 | void CDIB::DestroyDIB() 35 | { 36 | if(m_pVoid) free(m_pVoid); 37 | m_pVoid = NULL; 38 | if(m_pLinePtr) free(m_pLinePtr); 39 | m_pLinePtr = NULL; 40 | } 41 | 42 | 43 | BOOL CDIB::Create(int width,int height,int bits) 44 | { 45 | /* 46 | Free existing image 47 | */ 48 | DestroyDIB(); 49 | // ASSERT(bits == 24 || bits == 8); 50 | 51 | BITMAPINFOHEADER bmInfo; 52 | 53 | memset(&bmInfo,0,sizeof(BITMAPINFOHEADER)); 54 | bmInfo.biSize = sizeof(BITMAPINFOHEADER); 55 | bmInfo.biWidth = width; 56 | bmInfo.biHeight = height; 57 | bmInfo.biPlanes = 1; 58 | bmInfo.biBitCount = bits; 59 | bmInfo.biCompression = BI_RGB; 60 | return Create(bmInfo); 61 | } 62 | 63 | BOOL CDIB::Create(BITMAPINFOHEADER& bmInfo) 64 | { 65 | bytes = (bmInfo.biBitCount*bmInfo.biWidth)>>3; 66 | height = bmInfo.biHeight; 67 | width = bmInfo.biWidth; 68 | // bmInfo.biHeight *= -1; 69 | while(bytes%4) bytes++; 70 | 71 | int size; 72 | size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(bmInfo) + bytes*height; 73 | m_pVoid = (void *)malloc(size); 74 | if(!m_pVoid) return FALSE; 75 | 76 | m_pInfo = (PBITMAPINFO )m_pVoid; 77 | memcpy((void *)&m_pInfo->bmiHeader,(void *)&bmInfo,sizeof(BITMAPINFOHEADER)); 78 | m_pRGB = (RGBQUAD *)((unsigned char *)m_pVoid + sizeof(BITMAPINFOHEADER)) ; 79 | m_pBits = (unsigned char *)(m_pVoid) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(); 80 | 81 | int i; 82 | BYTE **ptr; 83 | m_pLinePtr = (BYTE **)malloc(sizeof(BYTE *)*height); 84 | if(!m_pLinePtr) return FALSE; 85 | for(i=0,ptr=m_pLinePtr; i < height; i++,ptr++) 86 | { 87 | //*ptr = (int)(m_pBits)+(i*bytes); 88 | //*ptr = (int)GetLinePtr(i); 89 | *ptr = m_pBits + (height-i-1)*bytes; 90 | } 91 | m_nFlags = 0; 92 | return TRUE; 93 | } 94 | 95 | void CDIB::SetPalette(unsigned char *palette) 96 | { 97 | int i,size; 98 | RGBQUAD *rgb; 99 | if(!palette) return; 100 | size = GetPaletteSize(); 101 | for(i=0,rgb = m_pRGB; i < size; i++,rgb++,palette+=3) 102 | { 103 | if(m_bUseGamma) 104 | { 105 | rgb->rgbRed = Gamma[palette[0]]; 106 | rgb->rgbGreen = Gamma[palette[1]]; 107 | rgb->rgbBlue = Gamma[palette[2]]; 108 | } 109 | else 110 | { 111 | rgb->rgbRed = palette[0]; 112 | rgb->rgbGreen = palette[1]; 113 | rgb->rgbBlue = palette[2]; 114 | } 115 | rgb->rgbReserved = (BYTE)0; 116 | } 117 | } 118 | 119 | void CDIB::SetPalette(RGBQUAD *pRGB) 120 | { 121 | int size; 122 | if(!pRGB) return; 123 | size = GetPaletteSize(); 124 | memcpy(m_pRGB,pRGB,size*sizeof(RGBQUAD)); 125 | } 126 | 127 | 128 | int CDIB::GetPaletteSize() 129 | { 130 | return GetPaletteSize(m_pInfo->bmiHeader); 131 | } 132 | 133 | 134 | int CDIB::GetPaletteSize(BITMAPINFOHEADER& bmInfo) 135 | { 136 | switch(bmInfo.biBitCount) 137 | { 138 | case 1: 139 | return 2; 140 | case 4: 141 | return 16; 142 | case 8: 143 | return 256; 144 | default: 145 | return 0; 146 | } 147 | } 148 | 149 | 150 | void CDIB::SetPixel(int x,int y,COLORREF color) 151 | { 152 | unsigned char *ptr; 153 | ASSERT(x >= 0 && y >=0); 154 | ASSERT(x < width && y < height); 155 | 156 | // ptr = m_pBits + (y*bytes) + x * 3; 157 | ptr = (unsigned char *)m_pLinePtr[y]; 158 | ptr += x*3; 159 | *ptr++ = (unsigned char)GetBValue(color); 160 | *ptr++ = (unsigned char)GetGValue(color); 161 | *ptr++ = (unsigned char)GetRValue(color); 162 | } 163 | 164 | void CDIB::SetPixel8(int x,int y,unsigned char color) 165 | { 166 | unsigned char *ptr,*aptr; 167 | ASSERT(x >= 0 && y >=0); 168 | ASSERT(x < width && y < height); 169 | 170 | // ptr = m_pBits + (y*bytes) + x ; 171 | // ptr = (unsigned char *)m_pLinePtr[y] ; 172 | ptr = GetLinePtr(y); 173 | aptr = ptr; 174 | ptr += x; 175 | *ptr = color; 176 | } 177 | 178 | 179 | COLORREF CDIB::GetPixel(int x,int y) 180 | { 181 | unsigned char *ptr; 182 | COLORREF color; 183 | if(x < 0 || y < 0) return 0; 184 | if(x >= width || y >= height) return 0; 185 | 186 | // ptr = m_pBits + (y*bytes) + x * 3; 187 | ptr = GetLinePtr(y); 188 | ptr += (x*3); 189 | color = RGB(*(ptr+2),*(ptr+1),*ptr); 190 | return color; 191 | } 192 | 193 | CBitmap *CDIB::GetTempBitmap(CDC& dc) 194 | { 195 | HBITMAP hBitmap; 196 | CBitmap *temp; 197 | ASSERT(m_pVoid != NULL); 198 | hBitmap = CreateDIBitmap(dc.m_hDC, 199 | (PBITMAPINFOHEADER)m_pInfo, 200 | CBM_INIT, 201 | (const void *)m_pBits, 202 | m_pInfo, 203 | DIB_RGB_COLORS); 204 | 205 | if(hBitmap == NULL) return NULL; 206 | temp = CBitmap::FromHandle(hBitmap); 207 | return temp; 208 | } 209 | 210 | CBitmap *CDIB::GetBitmap(CDC& dc) 211 | { 212 | HBITMAP hBitmap; 213 | CBitmap *temp; 214 | ASSERT(m_pVoid != NULL); 215 | hBitmap = CreateDIBitmap(dc.m_hDC, 216 | (PBITMAPINFOHEADER)m_pInfo, 217 | CBM_INIT, 218 | (const void *)m_pBits, 219 | m_pInfo, 220 | DIB_RGB_COLORS); 221 | 222 | if(hBitmap == NULL) return NULL; 223 | temp = CBitmap::FromHandle(hBitmap); 224 | if(temp) 225 | { 226 | BITMAP bmp; 227 | LPVOID lpVoid; 228 | temp->GetBitmap(&bmp); 229 | lpVoid = malloc(bmp.bmWidthBytes*bmp.bmHeight); 230 | if(!lpVoid) return NULL; 231 | temp->GetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,lpVoid); 232 | CBitmap *newBmp = new CBitmap; 233 | newBmp->CreateBitmapIndirect(&bmp); 234 | newBmp->SetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,lpVoid); 235 | free(lpVoid); 236 | return newBmp; 237 | } 238 | else return NULL; 239 | 240 | } 241 | 242 | void CDIB::CopyLine(int source,int dest) 243 | { 244 | unsigned char *src,*dst; 245 | ASSERT(source <= height && source >= 0); 246 | ASSERT(dest <= height && dest >= 0); 247 | if(source == dest) return; 248 | src = GetLinePtr(source); 249 | dst = GetLinePtr(dest); 250 | memcpy(dst,src,bytes); 251 | } 252 | 253 | void CDIB::InitDIB(COLORREF color) 254 | { 255 | int i,j; 256 | unsigned char *ptr; 257 | 258 | if(m_pInfo->bmiHeader.biBitCount == 24) 259 | { 260 | unsigned char col[3]; 261 | col[0]=GetBValue(color); 262 | col[1]=GetGValue(color); 263 | col[2]=GetRValue(color); 264 | for(i=0,ptr = m_pBits; i < height; i++) 265 | { 266 | ptr = m_pBits + i*bytes; 267 | for(j=0; j < width ; j++,ptr+=3) 268 | { 269 | memcpy(ptr,col,3); 270 | } 271 | } 272 | } 273 | else 274 | { 275 | for(i=0,ptr = m_pBits; i < height; i++,ptr+=bytes) 276 | { 277 | memset(ptr,(BYTE)color,bytes); 278 | } 279 | } 280 | } 281 | 282 | 283 | void CDIB::BitBlt(HDC hDest,int nXDest,int nYDest,int nWidth,int nHeight,int xSrc,int ySrc) 284 | { 285 | SetDIBitsToDevice(hDest,nXDest,nYDest,nWidth,nHeight,xSrc,Height()-ySrc-nHeight,0,Height(),m_pBits,m_pInfo,DIB_RGB_COLORS); 286 | } 287 | 288 | void CDIB::StretchBlt(HDC hDest,int nXDest,int nYDest,int nDWidth,int nDHeight,int xSrc,int ySrc,int nSWidth,int nSHeight) 289 | { 290 | int err; 291 | err = StretchDIBits(hDest,nXDest,nYDest,nDWidth,nDHeight,xSrc,ySrc,nSWidth,nSHeight,m_pBits,(CONST BITMAPINFO * )&m_pInfo->bmiHeader,DIB_RGB_COLORS,SRCCOPY); 292 | } 293 | 294 | void CDIB::ExpandBlt(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight) 295 | { 296 | SetPalette(dibSrc.m_pRGB); 297 | 298 | nSWidth = xSrc+nSWidth > dibSrc.width ? dibSrc.width-xSrc : nSWidth; 299 | nSHeight = ySrc+nSHeight > dibSrc.height? dibSrc.height-ySrc : nSHeight; 300 | 301 | Expand(nXDest,nYDest,xRatio,yRatio,dibSrc,xSrc,ySrc,nSWidth,nSHeight); 302 | } 303 | 304 | void CDIB::Expand(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight) 305 | { 306 | int xNum,yNum,xErr,yErr; 307 | int nDWidth,nDHeight; 308 | 309 | nDWidth = nSWidth*xRatio; 310 | nDHeight = nSHeight*yRatio; 311 | 312 | nDWidth = nXDest+nDWidth > width ? width-nXDest : nDWidth ; 313 | nDHeight = nYDest+nDHeight > height ? height-nYDest : nDHeight; 314 | 315 | xNum = nDWidth/xRatio; 316 | yNum = nDHeight/yRatio; 317 | xErr = nDWidth%xRatio; 318 | yErr = nDHeight%yRatio; 319 | 320 | unsigned char *buffer,*srcPtr,*destPtr,*ptr; 321 | int i,j,k; 322 | 323 | buffer = (unsigned char *)malloc(nDWidth+20); 324 | if(!buffer) return; 325 | 326 | for(i=0; i < yNum; i++,ySrc++) 327 | { 328 | srcPtr = dibSrc.GetLinePtr(ySrc) + xSrc; 329 | ptr = buffer; 330 | for(j=0; j < xNum; j++,ptr+=xRatio) 331 | { 332 | memset(ptr,*(srcPtr+j),xRatio); 333 | k=*(srcPtr+j); 334 | } 335 | memset(ptr,(unsigned char)k,xErr); 336 | for(j=0; j < yRatio ; j++,nYDest++) 337 | { 338 | destPtr = GetLinePtr(nYDest) + nXDest; 339 | memcpy(destPtr,buffer,nDWidth); 340 | } 341 | } 342 | for(j=0; j < yErr; j++,nYDest++) 343 | { 344 | destPtr = GetLinePtr(nYDest) + nXDest; 345 | memcpy(destPtr,buffer,nDWidth); 346 | } 347 | free(buffer); 348 | } 349 | 350 | void CDIB::StretchBlt(int nXDest,int nYDest,int nDWidth,int nDHeight,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight) 351 | { 352 | SetPalette(dibSrc.m_pRGB); 353 | nDWidth = nXDest+nDWidth > width ? width-nXDest : nDWidth ; 354 | nDHeight = nYDest+nDHeight > height ? height-nYDest : nDHeight; 355 | 356 | nSWidth = xSrc+nSWidth > dibSrc.width ? dibSrc.width-xSrc : nSWidth; 357 | nSHeight = ySrc+nSHeight > dibSrc.height? dibSrc.height-ySrc : nSHeight; 358 | 359 | int xDiv,yDiv; 360 | int xMod,yMod; 361 | 362 | xDiv = nDWidth/nSWidth; 363 | xMod = nDWidth%nSWidth; 364 | 365 | yDiv = nDHeight/nSHeight; 366 | yMod = nDHeight%nSHeight; 367 | 368 | if(!xMod && !yMod && xDiv > 0 && yDiv > 0) 369 | { 370 | ExpandBlt(nXDest,nYDest,xDiv,yDiv,dibSrc,xSrc,ySrc,nSWidth,nSHeight); 371 | return; 372 | } 373 | 374 | unsigned char *tempPtr,*srcPix,*destPix,*q; 375 | tempPtr = (unsigned char *)malloc(nDWidth+20); 376 | int i,j,k,l,x,y,m; 377 | int xErr,yErr; 378 | for(i=yErr=m=0; i < nSHeight; i++) 379 | { 380 | srcPix = dibSrc.GetLinePtr(i+ySrc) + xSrc; 381 | q = tempPtr; 382 | for(j=l=xErr=0; j < nSWidth; j++,srcPix++) 383 | { 384 | k = xDiv; 385 | xErr += xMod; 386 | if(xErr >= nSWidth) 387 | { 388 | k++; 389 | xErr%=nSWidth; 390 | } 391 | x=0; 392 | while(l < nDWidth && x < k) 393 | { 394 | *q++ = *srcPix; 395 | l++; 396 | x++; 397 | } 398 | } 399 | while(l < nDWidth) 400 | { 401 | *q++=*srcPix; 402 | l++; 403 | } 404 | k= yDiv; 405 | yErr += yMod; 406 | if(yErr >= nSHeight) 407 | { 408 | k++; 409 | yErr%=nSHeight; 410 | } 411 | y=0; 412 | while(m < nDHeight && y < k) 413 | { 414 | destPix = GetLinePtr(m+nYDest) + nXDest; 415 | memcpy(destPix,tempPtr,nDWidth); 416 | m++; 417 | y++; 418 | } 419 | } 420 | while(m < nDHeight ) 421 | { 422 | destPix = GetLinePtr(m+nYDest) + nXDest; 423 | memcpy(destPix,tempPtr,nDWidth); 424 | m++; 425 | } 426 | free(tempPtr); 427 | } 428 | 429 | void CDIB::BitBlt(int nXDest,int nYDest,int nWidth,int nHeight,CDIB& dibSrc,int nSrcX,int nSrcY,BYTE *colors) 430 | { 431 | SetPalette(dibSrc.m_pRGB); 432 | if(nXDest < 0) 433 | { 434 | nSrcX -= nXDest; 435 | nWidth += nXDest; 436 | nXDest=0; 437 | } 438 | if(nYDest < 0) 439 | { 440 | nSrcY -= nYDest; 441 | nHeight += nYDest; 442 | nYDest=0; 443 | } 444 | if(nSrcX < 0) 445 | { 446 | nXDest -= nSrcX; 447 | nWidth += nSrcX; 448 | nSrcX=0; 449 | } 450 | if(nSrcY < 0) 451 | { 452 | nYDest -= nSrcY; 453 | nHeight += nSrcY; 454 | nSrcY=0; 455 | } 456 | nWidth = nXDest+nWidth > width ? width-nXDest : nWidth ; 457 | nHeight = nYDest+nHeight > height ? height-nYDest : nHeight; 458 | 459 | nWidth = nSrcX+nWidth > dibSrc.width ? dibSrc.width-nSrcX : nWidth; 460 | nHeight = nSrcY+nHeight > dibSrc.height? dibSrc.height-nSrcY : nHeight; 461 | 462 | nWidth = __max(0,nWidth); 463 | nHeight = __max(0,nHeight); 464 | int i,k,l,j; 465 | unsigned char *srcPtr,*destPtr; 466 | if(!colors) 467 | { 468 | for(i=0,k=nSrcY,l=nYDest; i < nHeight; i++,k++,l++) 469 | { 470 | if(k < 0 || l < 0) 471 | { 472 | continue; 473 | } 474 | else 475 | { 476 | srcPtr = dibSrc.GetLinePtr(k); 477 | destPtr = GetLinePtr(l); 478 | memcpy(destPtr+nXDest,srcPtr+nSrcX,nWidth); 479 | } 480 | } 481 | } 482 | else 483 | { 484 | for(i=0,k=nSrcY,l=nYDest; i < nHeight; i++,k++,l++) 485 | { 486 | if(k < 0 || l < 0) 487 | { 488 | continue; 489 | } 490 | else 491 | { 492 | srcPtr = dibSrc.GetLinePtr(k)+nXDest; 493 | destPtr = GetLinePtr(l)+nSrcX; 494 | for(j=0; j < nWidth; j++,srcPtr++,destPtr++) 495 | { 496 | if(colors[*srcPtr]) *destPtr=*srcPtr; 497 | } 498 | } 499 | } 500 | } 501 | } 502 | 503 | unsigned char *CDIB::GetLinePtr(int line) 504 | { 505 | /*unsigned char *ptr; 506 | ptr = m_pBits + (height-line-1)*bytes; 507 | return ptr;*/ 508 | return m_pLinePtr[line]; 509 | } 510 | 511 | BOOL CDIB::CopyDIB(CDIB& dib) 512 | { 513 | if(Create(dib.m_pInfo->bmiHeader)) 514 | { 515 | SetPalette(dib.m_pRGB); 516 | memcpy(m_pBits,dib.m_pBits,height*bytes); 517 | return TRUE; 518 | } 519 | return FALSE; 520 | } 521 | 522 | void CDIB::ReplaceColor(unsigned char oldColor,unsigned char newColor) 523 | { 524 | int i,j; 525 | unsigned char *ptr; 526 | for(i=0; i < height; i++) 527 | { 528 | ptr = GetLinePtr(i); 529 | for(j=0; j < width; j++) 530 | { 531 | if(ptr[j] == oldColor) ptr[j] = newColor; 532 | } 533 | } 534 | } 535 | 536 | 537 | CDIB& CDIB::operator=(CDIB& dib) 538 | { 539 | CopyDIB(dib); 540 | return *this; 541 | } 542 | 543 | HANDLE CDIB::GetDIBits(int nStartX,int nStartY,int nCx,int nCy) 544 | { 545 | if(nStartX == -1) 546 | { 547 | nStartX = nStartY=0; 548 | nCx = width; 549 | nCy = height; 550 | CDIB dib; 551 | dib.Create(nCx,nCy,8); 552 | dib.BitBlt(0,0,nCx,nCy,*this,0,0); 553 | dib.SetPalette(m_pRGB); 554 | return dib.DIBHandle(); 555 | } 556 | return DIBHandle(); 557 | } 558 | 559 | DWORD CDIB::GetDIBSize() 560 | { 561 | return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height; 562 | } 563 | 564 | HANDLE CDIB::DIBHandle() 565 | { 566 | int nSize; 567 | HANDLE hMem; 568 | nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height; 569 | hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,nSize); 570 | if(hMem == NULL) return NULL; 571 | UCHAR *lpVoid,*pBits; 572 | LPBITMAPINFOHEADER pHead; 573 | RGBQUAD *pRgb; 574 | lpVoid = (UCHAR *)GlobalLock(hMem); 575 | pHead = (LPBITMAPINFOHEADER )lpVoid; 576 | memcpy(pHead,&m_pInfo->bmiHeader,sizeof(BITMAPINFOHEADER)); 577 | pRgb = (RGBQUAD *)(lpVoid + sizeof(BITMAPINFOHEADER) ); 578 | memcpy(pRgb,m_pRGB,sizeof(RGBQUAD)*GetPaletteSize()); 579 | pBits = lpVoid + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(); 580 | memcpy(pBits,m_pBits,height*bytes); 581 | GlobalUnlock(lpVoid); 582 | return hMem; 583 | } 584 | 585 | BOOL CDIB::CreateFromHandle(HANDLE hMem,int bits) 586 | { 587 | DestroyDIB(); 588 | UCHAR *lpVoid,*pBits; 589 | LPBITMAPINFOHEADER pHead; 590 | RGBQUAD *pRgb; 591 | lpVoid = (UCHAR *)GlobalLock(hMem); 592 | pHead = (LPBITMAPINFOHEADER )lpVoid; 593 | width = pHead->biWidth; 594 | height = pHead->biHeight; 595 | m_nBits = pHead->biBitCount; 596 | if(pHead->biCompression != BI_RGB) 597 | { 598 | GlobalUnlock(lpVoid); 599 | return FALSE; 600 | } 601 | if(pHead->biBitCount >= 15) 602 | { 603 | if(pHead->biBitCount != 24) 604 | { 605 | GlobalUnlock(lpVoid); 606 | return FALSE; 607 | } 608 | } 609 | if(!Create(*pHead)) 610 | { 611 | GlobalUnlock(lpVoid); 612 | return FALSE; 613 | } 614 | pRgb = (RGBQUAD *)(lpVoid + sizeof(BITMAPINFOHEADER) ); 615 | memcpy(m_pRGB,pRgb,sizeof(RGBQUAD)*GetPaletteSize()); 616 | pBits = lpVoid + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(); 617 | memcpy(m_pBits,pBits,height*bytes); 618 | GlobalUnlock(lpVoid); 619 | return TRUE; 620 | } 621 | 622 | void CDIB::UseGamma(float fg,BOOL bUse) 623 | { 624 | m_bUseGamma = bUse; 625 | m_fOldGamma = m_fGamma; 626 | m_fGamma = fg; 627 | CreateGammaCurve(); 628 | } 629 | 630 | 631 | void CDIB::CreateGammaCurve() 632 | { 633 | int i; 634 | for(i=0;i<256;++i) 635 | { 636 | Gamma[i]=(int)(255 * pow((double)i/255,m_fGamma) + (double)0.5); 637 | } 638 | } 639 | 640 | 641 | 642 | void CDIB::GetPixel(UINT x,UINT y,int& pixel) 643 | { 644 | ASSERT(x < (UINT)Width()); 645 | ASSERT(y < (UINT)Height()); 646 | if(x >= (UINT)Width()) return; 647 | if(y >= (UINT)Height()) return; 648 | pixel=(GetLinePtr(y))[x]; 649 | } 650 | 651 | BOOL CDIB::Make8Bit(CDIB& dib) 652 | { 653 | int nBits; 654 | ASSERT(Width() == dib.Width()); 655 | ASSERT(Height() == dib.Height()); 656 | nBits = dib.GetBitCount(); 657 | switch(nBits) 658 | { 659 | case 1: 660 | return SwitchFromOne(dib); 661 | break; 662 | case 4: 663 | return SwitchFromFour(dib); 664 | break; 665 | case 8: 666 | return SwitchPalette(dib); 667 | break; 668 | case 24: 669 | return SwitchFrom24(dib); 670 | break; 671 | default: 672 | return FALSE; 673 | } 674 | return FALSE; 675 | } 676 | 677 | /* 678 | BOOL CDIB::SwitchFrom24(CDIB& dib) 679 | { 680 | int i,j,w,h; 681 | unsigned char *sPtr,*dPtr; 682 | w = Width(); 683 | h = Height(); 684 | memset(CachePtr,0,sizeof(CachePtr)); 685 | for(i=0; i < h; i++) 686 | { 687 | dPtr = GetLinePtr(i); 688 | sPtr = dib.GetLinePtr(i); 689 | for(j=0 ; j < w; j++,dPtr++,sPtr+=3) 690 | { 691 | *dPtr = ClosestColor((RGBQUAD *)sPtr); 692 | } 693 | } 694 | return TRUE; 695 | } 696 | */ 697 | 698 | 699 | BOOL CDIB::SwitchFromOne(CDIB& dib) 700 | { 701 | int i,n,j,w,h; 702 | unsigned char *sPtr,*dPtr; 703 | unsigned char cols[2]; 704 | w = Width(); 705 | h = Height(); 706 | memset(CachePtr,0,sizeof(CachePtr)); 707 | cols[0]=ClosestColor(dib.m_pRGB); 708 | cols[1]=ClosestColor(dib.m_pRGB+1); 709 | for(i=0; i < h; i++) 710 | { 711 | dPtr = GetLinePtr(i); 712 | sPtr = dib.GetLinePtr(i); 713 | for(j=0 ; j < w; j++,dPtr++) 714 | { 715 | if(!(sPtr[j>>3] & masktable[j&7])) *dPtr = cols[0]; 716 | else *dPtr = cols[1]; 717 | } 718 | } 719 | return TRUE; 720 | } 721 | 722 | BOOL CDIB::SwitchFromFour(CDIB& dib) 723 | { 724 | int i,n,j,w,h; 725 | unsigned char *sPtr,*dPtr; 726 | unsigned char cols[16]; 727 | w = Width(); 728 | h = Height(); 729 | memset(CachePtr,0,sizeof(CachePtr)); 730 | for(i=0; i < 16; i++) 731 | { 732 | cols[i]=ClosestColor(dib.m_pRGB+i); 733 | } 734 | for(i=0; i < h; i++) 735 | { 736 | dPtr = GetLinePtr(i); 737 | sPtr = dib.GetLinePtr(i); 738 | for(j=0 ; j < w; j++,dPtr++) 739 | { 740 | if(!(j&1)) n = (*sPtr & 0xf0)>>4; 741 | else 742 | { 743 | n = *sPtr & 0x0f; 744 | sPtr++; 745 | } 746 | *dPtr = cols[n]; 747 | } 748 | } 749 | return TRUE; 750 | } 751 | 752 | BOOL CDIB::SwitchPalette(CDIB& dib) 753 | { 754 | int i,j,w,h; 755 | unsigned char *sPtr,*dPtr; 756 | unsigned char cols[256]; 757 | w = Width(); 758 | h = Height(); 759 | memset(CachePtr,0,sizeof(CachePtr)); 760 | for(i=0; i < 256; i++) 761 | { 762 | cols[i]=ClosestColor(dib.m_pRGB+i); 763 | } 764 | for(i=0; i < h; i++) 765 | { 766 | dPtr = GetLinePtr(i); 767 | sPtr = dib.GetLinePtr(i); 768 | for(j=0 ; j < w; j++,sPtr++,dPtr++) 769 | { 770 | *dPtr = cols[*sPtr]; 771 | } 772 | } 773 | return TRUE; 774 | } 775 | 776 | 777 | int CDIB::ClosestColor(RGBQUAD *pRgb) 778 | { 779 | unsigned int dist=BIG_DISTANCE,i,d,c; 780 | RGBQUAD *pQuad=m_pRGB; 781 | int pSize=GetPaletteSize(); 782 | for(i=0; i < pSize;i++) 783 | { 784 | if(CachePtr[i]) 785 | { 786 | if(!memcmp((void *)&CacheQuad[i],(void *)pRgb,3)) 787 | { 788 | return i; 789 | } 790 | } 791 | } 792 | for(i=0; i < pSize; i++,pQuad++) 793 | { 794 | d = Distance(*pRgb,*pQuad); 795 | if(!d) 796 | { 797 | CacheQuad[i]=*pRgb; 798 | CachePtr[i]=1; 799 | return i; 800 | } 801 | if(dist > d) 802 | { 803 | c = i; 804 | dist = d; 805 | } 806 | } 807 | CacheQuad[c]=*pRgb; 808 | CachePtr[c]=1; 809 | return c; 810 | } 811 | 812 | unsigned int CDIB::Distance(RGBQUAD& rgb1,RGBQUAD& rgb2) 813 | { 814 | unsigned int d; 815 | d = 3*(unsigned)((rgb1.rgbRed)-(rgb2.rgbRed))*(unsigned)((rgb1.rgbRed)-(rgb2.rgbRed)); 816 | d += 4*(unsigned)((rgb1.rgbGreen)-(rgb2.rgbGreen))*(unsigned)((rgb1.rgbGreen)-(rgb2.rgbGreen)) ; 817 | d += 2*(unsigned)((rgb1.rgbBlue)-(rgb2.rgbBlue))*(unsigned)((rgb1.rgbBlue)-(rgb2.rgbBlue)); 818 | return d; 819 | } 820 | 821 | BOOL CDIB::OpenDIB(CString& csFileName) 822 | { 823 | CFile file; 824 | if(!file.Open(csFileName,CFile::modeRead | CFile::typeBinary)) 825 | { 826 | return FALSE; 827 | } 828 | file.Close(); 829 | if(OpenBMP(csFileName)) return TRUE; 830 | return FALSE; 831 | } 832 | 833 | 834 | 835 | BOOL CDIB::SaveDIB(CString& csFileName,BitmapType type) 836 | { 837 | CFile file; 838 | if(!file.Open(csFileName,CFile::modeCreate | CFile::typeBinary)) 839 | { 840 | return FALSE; 841 | } 842 | file.Close(); 843 | switch(type) 844 | { 845 | case BMP: 846 | return SaveBMP(csFileName); 847 | default: 848 | return FALSE; 849 | } 850 | return FALSE; 851 | } 852 | 853 | BOOL CDIB::SaveBMP(CString& csFileName) 854 | { 855 | BITMAPFILEHEADER bFile; 856 | CFile file; 857 | if(!file.Open(csFileName,CFile::modeWrite | CFile::typeBinary)) 858 | { 859 | return FALSE; 860 | } 861 | ::ZeroMemory(&bFile,sizeof(bFile)); 862 | memcpy((void *)&bFile.bfType,"BM",2); 863 | bFile.bfSize = GetDIBSize() + sizeof(bFile); 864 | bFile.bfOffBits = sizeof(BITMAPINFOHEADER) + GetPaletteSize()*sizeof(RGBQUAD) + sizeof(BITMAPFILEHEADER); 865 | file.Write(&bFile,sizeof(bFile)); 866 | file.Write(m_pVoid,GetDIBSize()); 867 | file.Close(); 868 | return TRUE; 869 | 870 | } 871 | 872 | BOOL CDIB::OpenBMP(CString& csFileName) 873 | { 874 | BITMAPFILEHEADER bFile; 875 | BITMAPINFOHEADER head; 876 | CFile file; 877 | if(!file.Open(csFileName,CFile::modeRead | CFile::typeBinary)) 878 | { 879 | return FALSE; 880 | } 881 | file.Read(&bFile,sizeof(bFile)); 882 | if(memcmp((void *)&bFile.bfType,"BM",2)) 883 | { 884 | file.Close(); 885 | return FALSE; 886 | } 887 | file.Read(&head,sizeof(head)); 888 | if(!Create(head)) 889 | { 890 | file.Close(); 891 | return FALSE; 892 | } 893 | file.Read(m_pRGB,sizeof(RGBQUAD)*GetPaletteSize()); 894 | file.Seek(bFile.bfOffBits,CFile::begin); 895 | file.Read(m_pBits,height*bytes); 896 | file.Close(); 897 | return TRUE; 898 | 899 | } 900 | 901 | 902 | int CDIB::CountColors() 903 | { 904 | ASSERT(GetBitCount()==8); 905 | BYTE colors[256],*ptr; 906 | int nNum=0,i,j,w,d; 907 | w = Width(); 908 | d = Height(); 909 | memset(colors,0,256); 910 | for(i=0; i < d; i++) 911 | { 912 | ptr = GetLinePtr(i); 913 | for(j=0; j < w; j++,ptr++) 914 | { 915 | if(!colors[*ptr]) 916 | { 917 | colors[*ptr]=1; 918 | nNum++; 919 | } 920 | } 921 | } 922 | return nNum; 923 | } 924 | 925 | int CDIB::EnumColors(BYTE *array) 926 | { 927 | ASSERT(GetBitCount()==8); 928 | BYTE *ptr; 929 | int nNum=0,i,j,w,d; 930 | w = Width(); 931 | d = Height(); 932 | memset(array,0,256); 933 | for(i=0; i < d; i++) 934 | { 935 | ptr = GetLinePtr(i); 936 | for(j=0; j < w; j++,ptr++) 937 | { 938 | if(!array[*ptr]) 939 | { 940 | array[*ptr]=1; 941 | nNum++; 942 | } 943 | } 944 | } 945 | return nNum; 946 | } 947 | 948 | COLORREF CDIB::PaletteColor(int nIndex) 949 | { 950 | ASSERT(nIndex < 256); 951 | RGBQUAD *pRGB= m_pRGB+nIndex; 952 | return RGB(pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue); 953 | } 954 | 955 | BOOL CDIB::SwitchFrom24(CDIB& dib) 956 | { 957 | int i,j,w,h,c; 958 | unsigned char *sPtr,*dPtr; 959 | BYTE *index_ptr=NULL; 960 | RGBQUAD rgb; 961 | w = Width(); 962 | h = Height(); 963 | index_ptr = (BYTE *)malloc(0x7FFF+1); 964 | if(!index_ptr) return FALSE; 965 | memset(CachePtr,0,sizeof(CachePtr)); 966 | for(i=0; i <= 0x7FFF; i++) 967 | { 968 | rgb.rgbRed = (((i & 0x7C00)>>10) << 3) | 0x07; 969 | rgb.rgbGreen = (((i & 0x3e0)>>5) << 3) | 0x07; 970 | rgb.rgbBlue = ((i & 0x1F)<<3) | 0x07; 971 | index_ptr[i] = ClosestColor(&rgb); 972 | } 973 | for(i=0; i < h; i++) 974 | { 975 | dPtr = GetLinePtr(i); 976 | sPtr = dib.GetLinePtr(i); 977 | for(j=0 ; j < w; j++,dPtr++,sPtr+=3) 978 | { 979 | c = (*sPtr >> 3) | ((*(sPtr+1) >> 3) << 5) | ((*(sPtr+2) >> 3) << 10); 980 | *dPtr = index_ptr[c]; 981 | } 982 | } 983 | free(index_ptr); 984 | return TRUE; 985 | } 986 | --------------------------------------------------------------------------------