![]() |
wxIScan
|
00001 /*************************************************************** 00002 * Name: wxscan.cpp 00003 * Purpose: wxWidgets wrapper around libsane (for scanner 00004 * access) 00005 * Author: Daniel Nell (daniel.nell@nellresearch.de) 00006 * Created: 2008-05-04 00007 * Copyright: Daniel Nell (www.nellresearch.de) 00008 * License: wxWindows license 00009 **************************************************************/ 00010 00011 // Include headers. 00012 #include "wx_pch.h" 00013 #include "wxscan.h" 00014 00015 00016 #if defined( __UNIX_LIKE__ ) 00017 ////////////////////////////////////////////////////////// 00018 // Class wxScanSane 00019 // 00020 // Standard constructor. 00021 // 00022 wxScanSane::wxScanSane( bool bOnlyLocalDevices ) 00023 { 00024 // Initialize members. 00025 m_bOnlyLocalDevices= bOnlyLocalDevices; 00026 m_nResolution= -1; // Invalid value for resolution. 00027 00028 // Initialize SANE. 00029 m_SaneStatus= ::sane_init( NULL, NULL ); 00030 00031 // Get the device list from SANE subsystem. 00032 SaneGetDevices(); 00033 } 00034 00035 // Virtual destructor. 00036 // 00037 wxScanSane::~wxScanSane() 00038 { 00039 // Close the SANE sub system. 00040 ::sane_exit(); 00041 } 00042 00043 // Get an image from the scanning device. 00044 // 00045 bool wxScanSane::ScanImage( wxImage& oImage ) 00046 { 00047 // Check if there is a proper device index. 00048 if( !IsDeviceAvailable() ) 00049 { 00050 // Log and signal error. 00051 wxLogError( wxString( wxT( "bool wxScan::ScanImage() - " ) ) 00052 + _( "SANE device not available." ) ); 00053 return false; 00054 } 00055 00056 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 3 00057 for( int i= 0; i < m_nDeviceCount; i++ ) 00058 { 00059 if( i != m_nDeviceIndex ) 00060 { 00061 wxLogMessage( wxT( "SANE DEVICE" ) ); 00062 wxLogMessage( wxT( "\tname == " ) + GetDeviceName( i ) ); 00063 wxLogMessage( wxT( "\tvendor == " ) + GetDeviceVendor( i ) ); 00064 wxLogMessage( wxT( "\tmodel == " ) + GetDeviceModel( i ) ); 00065 wxLogMessage( wxT( "\ttype == " ) + GetDeviceType( i ) ); 00066 wxLogMessage( wxT( "============" ) ); 00067 } 00068 } 00069 ::wxSafeYield(); 00070 #endif 00071 00072 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 1 00073 wxLogMessage( wxT( "DEFAULT SANE DEVICE" )); 00074 wxLogMessage( wxT( "\tname == " ) + GetDeviceName( m_nDeviceIndex ) ); 00075 wxLogMessage( wxT( "\tvendor == " ) + GetDeviceVendor( m_nDeviceIndex ) ); 00076 wxLogMessage( wxT( "\tmodel == " ) + GetDeviceModel( m_nDeviceIndex ) ); 00077 wxLogMessage( wxT( "\ttype == " ) + GetDeviceType( m_nDeviceIndex ) ); 00078 wxLogMessage( wxT( "============" ) ); 00079 ::wxSafeYield(); 00080 #endif 00081 00082 // Sane device handle. 00083 SANE_Handle hSaneHandle; 00084 00085 // Open the sane device... 00086 m_SaneStatus= ::sane_open( GetDeviceName( m_nDeviceIndex ).mb_str( wxConvISO8859_1 ), &hSaneHandle ); 00087 if( !IsOk() ) 00088 { 00089 // Log and signal error. 00090 wxLogError( GetSaneStatusString() + wxT( " (SANE)" ) ); 00091 return false; 00092 } 00093 00094 // ... and start scanning. 00095 m_SaneStatus= ::sane_start( hSaneHandle ); 00096 if( !IsOk() ) 00097 { 00098 // Log and signal error. 00099 wxLogError( GetSaneStatusString() + wxT( " (SANE)" ) ); 00100 return false; 00101 } 00102 00103 // Get scanning parameters e. g. width, height, color depth etc. 00104 SANE_Parameters oSaneParameters; 00105 00106 ::sane_get_parameters( hSaneHandle, &oSaneParameters ); 00107 00108 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 1 00109 wxLogMessage( wxT( "SCANNING PARAMETERS" ) ); 00110 wxLogMessage( wxString::Format( wxT( "\tformat = %d" ), oSaneParameters.format ) ); 00111 wxLogMessage( wxString::Format( wxT( "\tlast_frame = %d" ), oSaneParameters.last_frame ) ); 00112 wxLogMessage( wxString::Format( wxT( "\tbytes_per_line = %d" ), oSaneParameters.bytes_per_line ) ); 00113 wxLogMessage( wxString::Format( wxT( "\tpixels_per_line = %d" ), oSaneParameters.pixels_per_line ) ); 00114 wxLogMessage( wxString::Format( wxT( "\tlines = %d" ), oSaneParameters.lines ) ); 00115 wxLogMessage( wxString::Format( wxT( "\tdepth = %d" ), oSaneParameters.depth ) ); 00116 wxLogMessage( wxT( "============" ) ); 00117 ::wxSafeYield(); 00118 #endif 00119 00120 // Check format information. 00121 // 00122 // Note: At the moment we only support RGB/8-bit-per-pixel scans. 00123 if( 00124 !oSaneParameters.last_frame 00125 || ( oSaneParameters.format != SANE_FRAME_RGB ) 00126 || ( oSaneParameters.depth != oSaneParameters.depth ) 00127 ) 00128 { 00129 // Log and signal error. 00130 wxLogError( wxString( wxT( "bool wxScan::ScanImage() - " ) ) 00131 + _( "Formats other than RGB with 8 bit per pixel are not yet supported." ) ); 00132 return false; 00133 } 00134 00135 // Create scan buffer. 00136 int nImageBufferSize= ( oSaneParameters.pixels_per_line * oSaneParameters.lines * 3 + 1 ) * sizeof( SANE_Byte ); 00137 SANE_Byte *pScanBuffer= (SANE_Byte *)malloc( nImageBufferSize ); 00138 00139 if( !pScanBuffer ) 00140 { 00141 // Log and signal error. 00142 wxLogError( wxString( wxT( "bool wxScan::ScanImage() - " ) ) 00143 + _( "Cannot allocate read buffer." ) ); 00144 return false; 00145 } 00146 00147 // Read image from scanner. 00148 SANE_Int nScannedBytes; 00149 SANE_Byte *pScanBufferPtr= pScanBuffer; 00150 00151 do 00152 { 00153 m_SaneStatus= ::sane_read( hSaneHandle, pScanBufferPtr, nImageBufferSize, &nScannedBytes ); 00154 pScanBufferPtr += nScannedBytes * sizeof( SANE_Byte ); 00155 } while( ( m_SaneStatus != SANE_STATUS_EOF ) && ( m_SaneStatus == SANE_STATUS_GOOD ) ) ; 00156 if( ( m_SaneStatus != SANE_STATUS_EOF ) ) 00157 { 00158 // Log, clean up, and signal error. 00159 wxLogError( wxString( wxT( "bool wxScan::ScanImage() - " ) ) 00160 + _( "An error occured while fetching data from scanning device." ) ); 00161 ::sane_cancel( hSaneHandle ); 00162 free( pScanBuffer ); 00163 return false; 00164 } 00165 m_SaneStatus= SANE_STATUS_GOOD; 00166 00167 // Save the image in the result image. 00168 wxImage oNewImage( oSaneParameters.pixels_per_line, oSaneParameters.lines, pScanBuffer ); 00169 00170 oImage= oNewImage; 00171 00172 // Get the image resoltuion; 00173 m_nResolution= -1; 00174 00175 int nOptionCount; 00176 const SANE_Option_Descriptor *oSaneOptionDescriptor; 00177 00178 ::sane_control_option( hSaneHandle, 0, SANE_ACTION_GET_VALUE, &nOptionCount, NULL ); 00179 for( int i= 0; i < nOptionCount; i++ ) 00180 { 00181 oSaneOptionDescriptor= ::sane_get_option_descriptor( hSaneHandle, i ); 00182 00183 wxString strOption( SANE_STRING_TO_WXSTRING( oSaneOptionDescriptor->name ) ); 00184 00185 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 2 00186 wxLogMessage( wxT( "DEVICE OPTION DESCRIPTOR %d" ), i ); 00187 wxLogMessage( strOption + wxString::Format( wxT( "(%d):" ), oSaneOptionDescriptor->size ) ); 00188 wxLogMessage( wxT( "\t" ) + SANE_STRING_TO_WXSTRING( oSaneOptionDescriptor->title ) ); 00189 wxLogMessage( wxT( "\t" ) + SANE_STRING_TO_WXSTRING( oSaneOptionDescriptor->desc ) ); 00190 #endif 00191 if( 0 == strOption.CompareTo( wxT( "resolution" ) ) ) 00192 { 00193 switch( oSaneOptionDescriptor->type ) 00194 { 00195 case SANE_TYPE_INT : { 00196 int nValue; 00197 00198 ::sane_control_option( hSaneHandle, i, SANE_ACTION_GET_VALUE, &nValue, NULL ); 00199 m_nResolution= (int)nValue; 00200 } 00201 break; 00202 case SANE_TYPE_FIXED : { 00203 SANE_Fixed nValue; 00204 00205 ::sane_control_option( hSaneHandle, i, SANE_ACTION_GET_VALUE, &nValue, NULL ); 00206 m_nResolution= (int)nValue; 00207 } 00208 break; 00209 default : { 00210 // [Nothing to do, yet.] 00211 } 00212 } 00213 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 1 00214 wxLogMessage( wxT( "\tresolution == %d DPI" ), m_nResolution ); 00215 #endif 00216 } 00217 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 2 00218 wxLogMessage( wxT( "============" ) ); 00219 #endif 00220 } 00221 00222 if( m_nResolution > 0 ) 00223 { 00224 oImage.SetOption( wxIMAGE_OPTION_RESOLUTIONUNIT, wxIMAGE_RESOLUTION_INCHES ); 00225 oImage.SetOption( wxIMAGE_OPTION_RESOLUTIONX, m_nResolution ); 00226 oImage.SetOption( wxIMAGE_OPTION_RESOLUTIONY, m_nResolution ); 00227 oImage.SetOption( wxIMAGE_OPTION_RESOLUTION, m_nResolution ); 00228 } 00229 00230 // Close the sane device. 00231 ::sane_close( hSaneHandle ); 00232 00233 // Return the state. 00234 return IsOk(); 00235 } 00236 00237 // Select the scanning device by index number. 00238 // 00239 bool wxScanSane::SetDeviceIndex( int nIndex ) 00240 { 00241 int nOldIndex= m_nDeviceIndex; 00242 00243 m_nDeviceIndex= nIndex; 00244 00245 bool nRetCode= IsDeviceAvailable(); 00246 00247 if( !nRetCode ); 00248 { 00249 m_nDeviceIndex= nOldIndex; 00250 } 00251 00252 return nRetCode; 00253 } 00254 00255 // Fill the SANE device list. 00256 // 00257 bool wxScanSane::SaneGetDevices() 00258 { 00259 // Get the device list from sane subsystem... 00260 m_SaneStatus= ::sane_get_devices( &m_ppDeviceList, m_bOnlyLocalDevices ); 00261 if( !IsOk() ) 00262 { 00263 // Log error. 00264 wxLogError( GetSaneStatusString() + wxT( " (SANE)" ) ); 00265 return false ; 00266 } 00267 00268 // ... and count the devices. 00269 for( m_nDeviceCount=0; m_ppDeviceList[m_nDeviceCount]; m_nDeviceCount++ ) 00270 { 00271 } 00272 00273 // Initialize device index (default device); 00274 m_nDeviceIndex= m_nDeviceCount > 0 ? 0 : -1; 00275 00276 // Return the state. 00277 return IsOk(); 00278 } 00279 #endif // __UNIX_LIKE__ 00280 00281 #if defined( __WXMSW__ ) 00282 // Standard constructor. 00283 // 00284 // ... 00285 #endif // __WXMSW__