1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_extensions.hxx" 24 #include <cstdarg> 25 #include <math.h> 26 #include <osl/file.h> 27 #include <tools/stream.hxx> 28 #include <sane.hxx> 29 #include <dlfcn.h> 30 #include <stdio.h> 31 #include <unistd.h> 32 #include <sys/time.h> 33 #include <sys/types.h> 34 #include <sal/config.h> 35 36 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL 37 #include <stdarg.h> 38 #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d ); 39 #else 40 #define dump_state( a, b, c, d ) ; 41 #endif 42 inline void dbg_msg( const char* pString, ... ) 43 { 44 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL 45 va_list ap; 46 va_start( ap, pString ); 47 vfprintf( stderr, pString, ap ); 48 va_end( ap ); 49 #else 50 (void)pString; 51 #endif 52 } 53 54 #define FAIL_SHUTDOWN_STATE( x, y, z ) \ 55 if( x != SANE_STATUS_GOOD ) \ 56 { \ 57 dump_state( "%s returned error %d (%s)\n", \ 58 y, x, p_strstatus( x ) ); \ 59 DeInit(); \ 60 return z; \ 61 } 62 63 #define FAIL_STATE( x, y, z ) \ 64 if( x != SANE_STATUS_GOOD ) \ 65 { \ 66 dump_state( "%s returned error %d (%s)\n", \ 67 y, x, p_strstatus( x ) ); \ 68 return z; \ 69 } 70 71 #define DUMP_STATE( x, y ) \ 72 if( x != SANE_STATUS_GOOD ) \ 73 { \ 74 dump_state( "%s returned error %d (%s)\n", \ 75 y, x, p_strstatus( x ) ); \ 76 } 77 78 #define CHECK_STATE( x, y ) \ 79 if( x != SANE_STATUS_GOOD ) \ 80 { \ 81 dump_state( "%s returned error %d (%s)\n", \ 82 y, x, p_strstatus( x ) ); \ 83 } \ 84 else 85 86 int Sane::nRefCount = 0; 87 oslModule Sane::pSaneLib = 0; 88 SANE_Int Sane::nVersion = 0; 89 SANE_Device** Sane::ppDevices = 0; 90 int Sane::nDevices = 0; 91 92 SANE_Status (*Sane::p_init)( SANE_Int*, 93 SANE_Auth_Callback ) = 0; 94 void (*Sane::p_exit)() = 0; 95 SANE_Status (*Sane::p_get_devices)( const SANE_Device***, 96 SANE_Bool ) = 0; 97 SANE_Status (*Sane::p_open)( SANE_String_Const, SANE_Handle ) = 0; 98 void (*Sane::p_close)( SANE_Handle ) = 0; 99 const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)( 100 SANE_Handle, SANE_Int ) = 0; 101 SANE_Status (*Sane::p_control_option)( SANE_Handle, SANE_Int, 102 SANE_Action, void*, 103 SANE_Int* ) = 0; 104 SANE_Status (*Sane::p_get_parameters)( SANE_Handle, 105 SANE_Parameters* ) = 0; 106 SANE_Status (*Sane::p_start)( SANE_Handle ) = 0; 107 SANE_Status (*Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int, 108 SANE_Int* ) = 0; 109 void (*Sane::p_cancel)( SANE_Handle ) = 0; 110 SANE_Status (*Sane::p_set_io_mode)( SANE_Handle, SANE_Bool ) = 0; 111 SANE_Status (*Sane::p_get_select_fd)( SANE_Handle, SANE_Int* ) = 0; 112 SANE_String_Const (*Sane::p_strstatus)( SANE_Status ) = 0; 113 114 static sal_Bool bSaneSymbolLoadFailed = sal_False; 115 116 inline oslGenericFunction Sane::LoadSymbol( const char* pSymbolname ) 117 { 118 oslGenericFunction pFunction = osl_getAsciiFunctionSymbol( pSaneLib, pSymbolname ); 119 if( ! pFunction ) 120 { 121 fprintf( stderr, "Could not load symbol %s\n", 122 pSymbolname ); 123 bSaneSymbolLoadFailed = sal_True; 124 } 125 return pFunction; 126 } 127 128 SANE_Status Sane::ControlOption( int nOption, SANE_Action nAction, 129 void* pData ) 130 { 131 SANE_Status nStatus = SANE_STATUS_GOOD; 132 SANE_Int nInfo = 0; 133 134 nStatus = p_control_option( maHandle, (SANE_Int)nOption, 135 nAction, pData, &nInfo ); 136 DUMP_STATE( nStatus, "sane_control_option" ); 137 #if OSL_DEBUG_LEVEL > 1 138 if( nStatus != SANE_STATUS_GOOD ) 139 { 140 const char* pAction = "Unknown"; 141 switch( nAction ) 142 { 143 case SANE_ACTION_GET_VALUE: 144 pAction = "SANE_ACTION_GET_VALUE";break; 145 case SANE_ACTION_SET_VALUE: 146 pAction = "SANE_ACTION_SET_VALUE";break; 147 case SANE_ACTION_SET_AUTO: 148 pAction = "SANE_ACTION_SET_AUTO";break; 149 } 150 dbg_msg( "Option: \"%s\" action: %s\n", 151 ByteString( GetOptionName( nOption ), gsl_getSystemTextEncoding() ).GetBuffer(), 152 pAction ); 153 } 154 #endif 155 // if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) ) 156 if( nInfo & SANE_INFO_RELOAD_OPTIONS ) 157 ReloadOptions(); 158 return nStatus; 159 } 160 161 Sane::Sane() : 162 mppOptions( 0 ), 163 mnOptions( 0 ), 164 mnDevice( -1 ), 165 maHandle( 0 ) 166 { 167 if( ! nRefCount || ! pSaneLib ) 168 Init(); 169 nRefCount++; 170 }; 171 172 Sane::~Sane() 173 { 174 if( IsOpen() ) 175 Close(); 176 nRefCount--; 177 if( ! nRefCount && pSaneLib ) 178 DeInit(); 179 } 180 181 void Sane::Init() 182 { 183 ::rtl::OUString sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ) ); 184 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY ); 185 if( ! pSaneLib ) 186 { 187 sSaneLibName = ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ".1" ); 188 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY ); 189 } 190 // try reasonable places that might not be in the library search path 191 if( ! pSaneLib ) 192 { 193 ::rtl::OUString sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION ) ); 194 osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData ); 195 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY ); 196 } 197 198 if( pSaneLib ) 199 { 200 bSaneSymbolLoadFailed = sal_False; 201 p_init = (SANE_Status(*)(SANE_Int*, SANE_Auth_Callback )) 202 LoadSymbol( "sane_init" ); 203 p_exit = (void(*)()) 204 LoadSymbol( "sane_exit" ); 205 p_get_devices = (SANE_Status(*)(const SANE_Device***, 206 SANE_Bool )) 207 LoadSymbol( "sane_get_devices" ); 208 p_open = (SANE_Status(*)(SANE_String_Const, SANE_Handle )) 209 LoadSymbol( "sane_open" ); 210 p_close = (void(*)(SANE_Handle)) 211 LoadSymbol( "sane_close" ); 212 p_get_option_descriptor = (const SANE_Option_Descriptor*(*)(SANE_Handle, 213 SANE_Int)) 214 LoadSymbol( "sane_get_option_descriptor" ); 215 p_control_option = (SANE_Status(*)(SANE_Handle, SANE_Int, 216 SANE_Action, void*, SANE_Int*)) 217 LoadSymbol( "sane_control_option" ); 218 p_get_parameters = (SANE_Status(*)(SANE_Handle,SANE_Parameters*)) 219 LoadSymbol( "sane_get_parameters" ); 220 p_start = (SANE_Status(*)(SANE_Handle)) 221 LoadSymbol( "sane_start" ); 222 p_read = (SANE_Status(*)(SANE_Handle, SANE_Byte*, 223 SANE_Int, SANE_Int* )) 224 LoadSymbol( "sane_read" ); 225 p_cancel = (void(*)(SANE_Handle)) 226 LoadSymbol( "sane_cancel" ); 227 p_set_io_mode = (SANE_Status(*)(SANE_Handle, SANE_Bool)) 228 LoadSymbol( "sane_set_io_mode" ); 229 p_get_select_fd = (SANE_Status(*)(SANE_Handle, SANE_Int*)) 230 LoadSymbol( "sane_get_select_fd" ); 231 p_strstatus = (SANE_String_Const(*)(SANE_Status)) 232 LoadSymbol( "sane_strstatus" ); 233 if( bSaneSymbolLoadFailed ) 234 DeInit(); 235 else 236 { 237 SANE_Status nStatus = p_init( &nVersion, 0 ); 238 FAIL_SHUTDOWN_STATE( nStatus, "sane_init", ); 239 nStatus = p_get_devices( (const SANE_Device***)&ppDevices, 240 SANE_FALSE ); 241 FAIL_SHUTDOWN_STATE( nStatus, "sane_get_devices", ); 242 for( nDevices = 0 ; ppDevices[ nDevices ]; nDevices++ ) ; 243 } 244 } 245 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL 246 else 247 fprintf( stderr, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION, 248 dlerror() ); 249 #endif 250 } 251 252 void Sane::DeInit() 253 { 254 if( pSaneLib ) 255 { 256 p_exit(); 257 osl_unloadModule( pSaneLib ); 258 pSaneLib = 0; 259 } 260 } 261 262 void Sane::ReloadDevices() 263 { 264 if( IsOpen() ) 265 Close(); 266 DeInit(); 267 Init(); 268 } 269 270 void Sane::ReloadOptions() 271 { 272 if( ! IsOpen() ) 273 return; 274 275 SANE_Option_Descriptor* pZero = (SANE_Option_Descriptor*) 276 p_get_option_descriptor( maHandle, 0 ); 277 SANE_Word pOptions[2]; 278 SANE_Status nStatus = p_control_option( maHandle, 0, SANE_ACTION_GET_VALUE, 279 (void*)pOptions, NULL ); 280 if( nStatus != SANE_STATUS_GOOD ) 281 fprintf( stderr, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus ) ); 282 283 mnOptions = pOptions[ 0 ]; 284 if( (size_t)pZero->size > sizeof( SANE_Word ) ) 285 fprintf( stderr, "driver returned number of options with larger size than SANE_Word !!!\n" ); 286 if( mppOptions ) 287 delete [] mppOptions; 288 mppOptions = (const SANE_Option_Descriptor**)new SANE_Option_Descriptor*[ mnOptions ]; 289 mppOptions[ 0 ] = (SANE_Option_Descriptor*)pZero; 290 for( int i = 1; i < mnOptions; i++ ) 291 mppOptions[ i ] = (SANE_Option_Descriptor*) 292 p_get_option_descriptor( maHandle, i ); 293 294 CheckConsistency( NULL, sal_True ); 295 296 maReloadOptionsLink.Call( this ); 297 } 298 299 sal_Bool Sane::Open( const char* name ) 300 { 301 int i; 302 303 SANE_Status nStatus = p_open( (SANE_String_Const)name, &maHandle ); 304 FAIL_STATE( nStatus, "sane_open", sal_False ); 305 306 ReloadOptions(); 307 308 if( mnDevice == -1 ) 309 { 310 ByteString aDevice( name ); 311 for( i = 0; i < nDevices; i++ ) 312 { 313 if( aDevice.Equals( ppDevices[i]->name ) ) 314 { 315 mnDevice = i; 316 break; 317 } 318 } 319 } 320 321 return sal_True; 322 } 323 324 sal_Bool Sane::Open( int n ) 325 { 326 if( n >= 0 && n < nDevices ) 327 { 328 mnDevice = n; 329 return Open( (char*)ppDevices[n]->name ); 330 } 331 return sal_False; 332 } 333 334 void Sane::Close() 335 { 336 if( maHandle ) 337 { 338 p_close( maHandle ); 339 delete [] mppOptions; 340 mppOptions = 0; 341 maHandle = 0; 342 mnDevice = -1; 343 } 344 } 345 346 int Sane::GetOptionByName( const char* rName ) 347 { 348 int i; 349 ByteString aOption( rName ); 350 for( i = 0; i < mnOptions; i++ ) 351 { 352 if( mppOptions[i]->name && aOption.Equals( mppOptions[i]->name ) ) 353 return i; 354 } 355 return -1; 356 } 357 358 sal_Bool Sane::GetOptionValue( int n, sal_Bool& rRet ) 359 { 360 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL ) 361 return sal_False; 362 SANE_Word nRet; 363 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, &nRet ); 364 if( nStatus != SANE_STATUS_GOOD ) 365 return sal_False; 366 367 rRet = nRet; 368 return sal_True; 369 } 370 371 sal_Bool Sane::GetOptionValue( int n, ByteString& rRet ) 372 { 373 sal_Bool bSuccess = sal_False; 374 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING ) 375 return sal_False; 376 char* pRet = new char[mppOptions[n]->size+1]; 377 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet ); 378 if( nStatus == SANE_STATUS_GOOD ) 379 { 380 bSuccess = sal_True; 381 rRet = pRet; 382 } 383 delete [] pRet; 384 return bSuccess; 385 } 386 387 sal_Bool Sane::GetOptionValue( int n, double& rRet, int nElement ) 388 { 389 sal_Bool bSuccess = sal_False; 390 391 if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT && 392 mppOptions[n]->type != SANE_TYPE_FIXED ) ) 393 return sal_False; 394 395 SANE_Word* pRet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]; 396 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet ); 397 if( nStatus == SANE_STATUS_GOOD ) 398 { 399 bSuccess = sal_True; 400 if( mppOptions[n]->type == SANE_TYPE_INT ) 401 rRet = (double)pRet[ nElement ]; 402 else 403 rRet = SANE_UNFIX( pRet[nElement] ); 404 } 405 delete [] pRet; 406 return bSuccess; 407 } 408 409 sal_Bool Sane::GetOptionValue( int n, double* pSet ) 410 { 411 if( ! maHandle || ! ( mppOptions[n]->type == SANE_TYPE_FIXED || 412 mppOptions[n]->type == SANE_TYPE_INT ) ) 413 return sal_False; 414 415 SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]; 416 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pFixedSet ); 417 if( nStatus != SANE_STATUS_GOOD ) 418 { 419 delete [] pFixedSet; 420 return sal_False; 421 } 422 for( size_t i = 0; i <mppOptions[n]->size/sizeof(SANE_Word); i++ ) 423 { 424 if( mppOptions[n]->type == SANE_TYPE_FIXED ) 425 pSet[i] = SANE_UNFIX( pFixedSet[i] ); 426 else 427 pSet[i] = (double) pFixedSet[i]; 428 } 429 delete [] pFixedSet; 430 return sal_True; 431 } 432 433 sal_Bool Sane::SetOptionValue( int n, sal_Bool bSet ) 434 { 435 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL ) 436 return sal_False; 437 SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE; 438 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nRet ); 439 if( nStatus != SANE_STATUS_GOOD ) 440 return sal_False; 441 return sal_True; 442 } 443 444 sal_Bool Sane::SetOptionValue( int n, const String& rSet ) 445 { 446 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING ) 447 return sal_False; 448 ByteString aSet( rSet, gsl_getSystemTextEncoding() ); 449 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, (void*)aSet.GetBuffer() ); 450 if( nStatus != SANE_STATUS_GOOD ) 451 return sal_False; 452 return sal_True; 453 } 454 455 sal_Bool Sane::SetOptionValue( int n, double fSet, int nElement ) 456 { 457 sal_Bool bSuccess = sal_False; 458 459 if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT && 460 mppOptions[n]->type != SANE_TYPE_FIXED ) ) 461 return sal_False; 462 463 SANE_Status nStatus; 464 if( mppOptions[n]->size/sizeof(SANE_Word) > 1 ) 465 { 466 SANE_Word* pSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]; 467 nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pSet ); 468 if( nStatus == SANE_STATUS_GOOD ) 469 { 470 pSet[nElement] = mppOptions[n]->type == SANE_TYPE_INT ? 471 (SANE_Word)fSet : SANE_FIX( fSet ); 472 nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pSet ); 473 } 474 delete [] pSet; 475 } 476 else 477 { 478 SANE_Word nSetTo = 479 mppOptions[n]->type == SANE_TYPE_INT ? 480 (SANE_Word)fSet : SANE_FIX( fSet ); 481 482 nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nSetTo ); 483 if( nStatus == SANE_STATUS_GOOD ) 484 bSuccess = sal_True; 485 } 486 return bSuccess; 487 } 488 489 sal_Bool Sane::SetOptionValue( int n, double* pSet ) 490 { 491 if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT && 492 mppOptions[n]->type != SANE_TYPE_FIXED ) ) 493 return sal_False; 494 SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)]; 495 for( size_t i = 0; i < mppOptions[n]->size/sizeof(SANE_Word); i++ ) 496 { 497 if( mppOptions[n]->type == SANE_TYPE_FIXED ) 498 pFixedSet[i] = SANE_FIX( pSet[i] ); 499 else 500 pFixedSet[i] = (SANE_Word)pSet[i]; 501 } 502 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pFixedSet ); 503 delete [] pFixedSet; 504 if( nStatus != SANE_STATUS_GOOD ) 505 return sal_False; 506 return sal_True; 507 } 508 509 enum FrameStyleType { 510 FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated 511 }; 512 513 #define BYTE_BUFFER_SIZE 32768 514 515 static inline sal_uInt8 _ReadValue( FILE* fp, int depth ) 516 { 517 if( depth == 16 ) 518 { 519 sal_uInt16 nWord; 520 // data always come in native byte order ! 521 // 16 bits is not really supported by backends as of now 522 // e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN 523 // against SANE documentation (xscanimage gets the same result 524 // as we do 525 fread( &nWord, 1, 2, fp ); 526 return (sal_uInt8)( nWord / 256 ); 527 } 528 sal_uInt8 nByte; 529 fread( &nByte, 1, 1, fp ); 530 return nByte; 531 } 532 533 sal_Bool Sane::CheckConsistency( const char* pMes, sal_Bool bInit ) 534 { 535 static SANE_Option_Descriptor** pDescArray = NULL; 536 static SANE_Option_Descriptor* pZero = NULL; 537 538 if( bInit ) 539 { 540 pDescArray = (SANE_Option_Descriptor**)mppOptions; 541 if( mppOptions ) 542 pZero = (SANE_Option_Descriptor*)mppOptions[0]; 543 return sal_True; 544 } 545 546 sal_Bool bConsistent = sal_True; 547 548 if( pDescArray != mppOptions ) 549 bConsistent = sal_False; 550 if( pZero != mppOptions[0] ) 551 bConsistent = sal_False; 552 553 if( ! bConsistent ) 554 dbg_msg( "Sane is not consistent. (%s)\n", pMes ); 555 556 return bConsistent; 557 } 558 559 sal_Bool Sane::Start( BitmapTransporter& rBitmap ) 560 { 561 int nStream = 0, nLine = 0, i = 0; 562 SANE_Parameters aParams; 563 FrameStyleType eType = FrameStyle_Gray; 564 sal_Bool bSuccess = sal_True; 565 sal_Bool bWidthSet = sal_False; 566 567 if( ! maHandle ) 568 return sal_False; 569 570 int nWidthMM = 0; 571 int nHeightMM = 0; 572 double fTLx, fTLy, fBRx, fBRy, fResl = 0.0; 573 int nOption; 574 if( ( nOption = GetOptionByName( "tl-x" ) ) != -1 && 575 GetOptionValue( nOption, fTLx, 0 ) && 576 GetOptionUnit( nOption ) == SANE_UNIT_MM ) 577 { 578 if( ( nOption = GetOptionByName( "br-x" ) ) != -1 && 579 GetOptionValue( nOption, fBRx, 0 ) && 580 GetOptionUnit( nOption ) == SANE_UNIT_MM ) 581 { 582 nWidthMM = (int)fabs(fBRx - fTLx); 583 } 584 } 585 if( ( nOption = GetOptionByName( "tl-y" ) ) != -1 && 586 GetOptionValue( nOption, fTLy, 0 ) && 587 GetOptionUnit( nOption ) == SANE_UNIT_MM ) 588 { 589 if( ( nOption = GetOptionByName( "br-y" ) ) != -1 && 590 GetOptionValue( nOption, fBRy, 0 ) && 591 GetOptionUnit( nOption ) == SANE_UNIT_MM ) 592 { 593 nHeightMM = (int)fabs(fBRy - fTLy); 594 } 595 } 596 if( ( nOption = GetOptionByName( "resolution" ) ) != -1 ) 597 GetOptionValue( nOption, fResl ); 598 599 sal_uInt8* pBuffer = NULL; 600 601 SANE_Status nStatus = SANE_STATUS_GOOD; 602 603 rBitmap.lock(); 604 SvMemoryStream& aConverter = rBitmap.getStream(); 605 aConverter.Seek( 0 ); 606 aConverter.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 607 608 // write bitmap stream header 609 aConverter << 'B' << 'M'; 610 aConverter << (sal_uInt32) 0; 611 aConverter << (sal_uInt32) 0; 612 aConverter << (sal_uInt32) 60; 613 614 // write BITMAPINFOHEADER 615 aConverter << (sal_uInt32)40; 616 aConverter << (sal_uInt32)0; // fill in width later 617 aConverter << (sal_uInt32)0; // fill in height later 618 aConverter << (sal_uInt16)1; 619 // create header for 24 bits 620 // correct later if necessary 621 aConverter << (sal_uInt16)24; 622 aConverter << (sal_uInt32)0; 623 aConverter << (sal_uInt32)0; 624 aConverter << (sal_uInt32)0; 625 aConverter << (sal_uInt32)0; 626 aConverter << (sal_uInt32)0; 627 aConverter << (sal_uInt32)0; 628 629 for( nStream=0; nStream < 3 && bSuccess ; nStream++ ) 630 { 631 nStatus = p_start( maHandle ); 632 DUMP_STATE( nStatus, "sane_start" ); 633 CheckConsistency( "sane_start" ); 634 if( nStatus == SANE_STATUS_GOOD ) 635 { 636 nStatus = p_get_parameters( maHandle, &aParams ); 637 DUMP_STATE( nStatus, "sane_get_parameters" ); 638 CheckConsistency( "sane_get_parameters" ); 639 if (nStatus != SANE_STATUS_GOOD || aParams.bytes_per_line == 0) 640 { 641 bSuccess = sal_False; 642 break; 643 } 644 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL 645 const char* ppFormats[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB", 646 "SANE_FRAME_RED", "SANE_FRAME_GREEN", 647 "SANE_FRAME_BLUE", "Unknown !!!" }; 648 fprintf( stderr, "Parameters for frame %d:\n", nStream ); 649 if( aParams.format < 0 || aParams.format > 4 ) 650 aParams.format = (SANE_Frame)5; 651 fprintf( stderr, "format: %s\n", ppFormats[ (int)aParams.format ] ); 652 fprintf( stderr, "last_frame: %s\n", aParams.last_frame ? "TRUE" : "FALSE" ); 653 fprintf( stderr, "depth: %d\n", (int)aParams.depth ); 654 fprintf( stderr, "pixels_per_line: %d\n", (int)aParams.pixels_per_line ); 655 fprintf( stderr, "bytes_per_line: %d\n", (int)aParams.bytes_per_line ); 656 #endif 657 if( ! pBuffer ) 658 { 659 pBuffer = new sal_uInt8[ BYTE_BUFFER_SIZE < 4*aParams.bytes_per_line ? 4*aParams.bytes_per_line : BYTE_BUFFER_SIZE ]; 660 } 661 662 if( aParams.last_frame ) 663 nStream=3; 664 665 switch( aParams.format ) 666 { 667 case SANE_FRAME_GRAY: 668 eType = FrameStyle_Gray; 669 if( aParams.depth == 1 ) 670 eType = FrameStyle_BW; 671 break; 672 case SANE_FRAME_RGB: 673 eType = FrameStyle_RGB; 674 break; 675 case SANE_FRAME_RED: 676 case SANE_FRAME_GREEN: 677 case SANE_FRAME_BLUE: 678 eType = FrameStyle_Separated; 679 break; 680 default: 681 fprintf( stderr, "Warning: unknown frame style !!!\n" ); 682 } 683 684 sal_Bool bSynchronousRead = sal_True; 685 686 // should be fail safe, but ... ?? 687 nStatus = p_set_io_mode( maHandle, SANE_FALSE ); 688 CheckConsistency( "sane_set_io_mode" ); 689 if( nStatus != SANE_STATUS_GOOD ) 690 { 691 bSynchronousRead = sal_False; 692 nStatus = p_set_io_mode( maHandle, SANE_TRUE ); 693 CheckConsistency( "sane_set_io_mode" ); 694 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL 695 if( nStatus != SANE_STATUS_GOOD ) 696 // what ?!? 697 fprintf( stderr, "Sane::Start: driver is confused\n" ); 698 #endif 699 } 700 701 SANE_Int nLen=0; 702 SANE_Int fd = 0; 703 704 if( ! bSynchronousRead ) 705 { 706 nStatus = p_get_select_fd( maHandle, &fd ); 707 DUMP_STATE( nStatus, "sane_get_select_fd" ); 708 CheckConsistency( "sane_get_select_fd" ); 709 if( nStatus != SANE_STATUS_GOOD ) 710 bSynchronousRead = sal_True; 711 } 712 FILE* pFrame = tmpfile(); 713 if( ! pFrame ) 714 { 715 bSuccess = sal_False; 716 break; 717 } 718 do { 719 if( ! bSynchronousRead ) 720 { 721 fd_set fdset; 722 struct timeval tv; 723 724 FD_ZERO( &fdset ); 725 FD_SET( (int)fd, &fdset ); 726 tv.tv_sec = 5; 727 tv.tv_usec = 0; 728 if( select( fd+1, &fdset, NULL, NULL, &tv ) == 0 ) 729 fprintf( stderr, "Timeout on sane_read descriptor\n" ); 730 } 731 nLen = 0; 732 nStatus = p_read( maHandle, pBuffer, BYTE_BUFFER_SIZE, &nLen ); 733 CheckConsistency( "sane_read" ); 734 if( nLen && ( nStatus == SANE_STATUS_GOOD || 735 nStatus == SANE_STATUS_EOF ) ) 736 { 737 fwrite( pBuffer, 1, nLen, pFrame ); 738 } 739 else 740 DUMP_STATE( nStatus, "sane_read" ); 741 } while( nStatus == SANE_STATUS_GOOD ); 742 if( nStatus != SANE_STATUS_EOF ) 743 { 744 fclose( pFrame ); 745 bSuccess = sal_False; 746 break; 747 } 748 749 int nFrameLength = ftell( pFrame ); 750 fseek( pFrame, 0, SEEK_SET ); 751 sal_uInt32 nWidth = (sal_uInt32) aParams.pixels_per_line; 752 sal_uInt32 nHeight = (sal_uInt32) (nFrameLength / aParams.bytes_per_line); 753 if( ! bWidthSet ) 754 { 755 if( ! fResl ) 756 fResl = 300; // if all else fails that's a good guess 757 if( ! nWidthMM ) 758 nWidthMM = (int)(((double)nWidth / fResl) * 25.4); 759 if( ! nHeightMM ) 760 nHeightMM = (int)(((double)nHeight / fResl) * 25.4); 761 #if OSL_DEBUG_LEVEL > 1 762 fprintf( stderr, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", (int)nWidth, (int)nHeight, (int)nWidthMM, (int)nHeightMM, fResl ); 763 #endif 764 765 aConverter.Seek( 18 ); 766 aConverter << (sal_uInt32)nWidth; 767 aConverter << (sal_uInt32)nHeight; 768 aConverter.Seek( 38 ); 769 aConverter << (sal_uInt32)(1000*nWidth/nWidthMM); 770 aConverter << (sal_uInt32)(1000*nHeight/nHeightMM); 771 bWidthSet = sal_True; 772 } 773 aConverter.Seek(60); 774 775 if( eType == FrameStyle_BW ) 776 { 777 aConverter.Seek( 10 ); 778 aConverter << (sal_uInt32)64; 779 aConverter.Seek( 28 ); 780 aConverter << (sal_uInt16) 1; 781 aConverter.Seek( 54 ); 782 // write color table 783 aConverter << (sal_uInt16)0xffff; 784 aConverter << (sal_uInt8)0xff; 785 aConverter << (sal_uInt8)0; 786 aConverter << (sal_uInt32)0; 787 aConverter.Seek( 64 ); 788 } 789 else if( eType == FrameStyle_Gray ) 790 { 791 aConverter.Seek( 10 ); 792 aConverter << (sal_uInt32)1084; 793 aConverter.Seek( 28 ); 794 aConverter << (sal_uInt16) 8; 795 aConverter.Seek( 54 ); 796 // write color table 797 for( nLine = 0; nLine < 256; nLine++ ) 798 { 799 aConverter << (sal_uInt8)nLine; 800 aConverter << (sal_uInt8)nLine; 801 aConverter << (sal_uInt8)nLine; 802 aConverter << (sal_uInt8)0; 803 } 804 aConverter.Seek( 1084 ); 805 } 806 807 for( nLine = nHeight-1; 808 nLine >= 0; nLine-- ) 809 { 810 fseek( pFrame, nLine * aParams.bytes_per_line, SEEK_SET ); 811 if( eType == FrameStyle_BW || 812 ( eType == FrameStyle_Gray && aParams.depth == 8 ) 813 ) 814 { 815 fread( pBuffer, 1, aParams.bytes_per_line, pFrame ); 816 aConverter.Write( pBuffer, aParams.bytes_per_line ); 817 } 818 else if( eType == FrameStyle_Gray ) 819 { 820 for( i = 0; i < (aParams.pixels_per_line); i++ ) 821 { 822 sal_uInt8 nGray = _ReadValue( pFrame, aParams.depth ); 823 aConverter << nGray; 824 } 825 } 826 else if( eType == FrameStyle_RGB ) 827 { 828 for( i = 0; i < (aParams.pixels_per_line); i++ ) 829 { 830 sal_uInt8 nRed, nGreen, nBlue; 831 nRed = _ReadValue( pFrame, aParams.depth ); 832 nGreen = _ReadValue( pFrame, aParams.depth ); 833 nBlue = _ReadValue( pFrame, aParams.depth ); 834 aConverter << nBlue; 835 aConverter << nGreen; 836 aConverter << nRed; 837 } 838 } 839 else if( eType == FrameStyle_Separated ) 840 { 841 for( i = 0; i < (aParams.pixels_per_line); i++ ) 842 { 843 sal_uInt8 nValue = _ReadValue( pFrame, aParams.depth ); 844 switch( aParams.format ) 845 { 846 case SANE_FRAME_RED: 847 aConverter.SeekRel( 2 ); 848 aConverter << nValue; 849 break; 850 case SANE_FRAME_GREEN: 851 aConverter.SeekRel( 1 ); 852 aConverter << nValue; 853 aConverter.SeekRel( 1 ); 854 break; 855 case SANE_FRAME_BLUE: 856 aConverter << nValue; 857 aConverter.SeekRel( 2 ); 858 break; 859 case SANE_FRAME_GRAY: 860 case SANE_FRAME_RGB: 861 break; 862 } 863 } 864 } 865 int nGap = aConverter.Tell() & 3; 866 if( nGap ) 867 aConverter.SeekRel( 4-nGap ); 868 } 869 fclose( pFrame ); // deletes tmpfile 870 if( eType != FrameStyle_Separated ) 871 break; 872 } 873 else 874 bSuccess = sal_False; 875 } 876 // get stream length 877 aConverter.Seek( STREAM_SEEK_TO_END ); 878 int nPos = aConverter.Tell(); 879 880 aConverter.Seek( 2 ); 881 aConverter << (sal_uInt32) nPos+1; 882 aConverter.Seek( 0 ); 883 884 rBitmap.unlock(); 885 886 if( bSuccess ) 887 { 888 // only cancel a successful operation 889 // sane disrupts memory else 890 p_cancel( maHandle ); 891 CheckConsistency( "sane_cancel" ); 892 } 893 if( pBuffer ) 894 delete [] pBuffer; 895 896 ReloadOptions(); 897 898 899 dbg_msg( "Sane::Start returns with %s\n", bSuccess ? "TRUE" : "FALSE" ); 900 901 return bSuccess; 902 } 903 904 int Sane::GetRange( int n, double*& rpDouble ) 905 { 906 if( mppOptions[n]->constraint_type != SANE_CONSTRAINT_RANGE && 907 mppOptions[n]->constraint_type != SANE_CONSTRAINT_WORD_LIST ) 908 { 909 return -1; 910 } 911 912 rpDouble = 0; 913 int nItems, i; 914 sal_Bool bIsFixed = mppOptions[n]->type == SANE_TYPE_FIXED ? sal_True : sal_False; 915 916 dbg_msg( "Sane::GetRange of option %s ", mppOptions[n]->name ); 917 if(mppOptions[n]->constraint_type == SANE_CONSTRAINT_RANGE ) 918 { 919 double fMin, fMax, fQuant; 920 if( bIsFixed ) 921 { 922 fMin = SANE_UNFIX( mppOptions[n]->constraint.range->min ); 923 fMax = SANE_UNFIX( mppOptions[n]->constraint.range->max ); 924 fQuant = SANE_UNFIX( mppOptions[n]->constraint.range->quant ); 925 } 926 else 927 { 928 fMin = (double)mppOptions[n]->constraint.range->min; 929 fMax = (double)mppOptions[n]->constraint.range->max; 930 fQuant = (double)mppOptions[n]->constraint.range->quant; 931 } 932 if( fQuant != 0.0 ) 933 { 934 dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n", 935 fMin, fQuant, fMax ); 936 nItems = (int)((fMax - fMin)/fQuant)+1; 937 rpDouble = new double[ nItems ]; 938 double fValue = fMin; 939 for( i = 0; i < nItems; i++, fValue += fQuant ) 940 rpDouble[i] = fValue; 941 rpDouble[ nItems-1 ] = fMax; 942 return nItems; 943 } 944 else 945 { 946 dbg_msg( "normal range [ %lg %lg ]\n", 947 fMin, fMax ); 948 rpDouble = new double[2]; 949 rpDouble[0] = fMin; 950 rpDouble[1] = fMax; 951 return 0; 952 } 953 } 954 else 955 { 956 nItems = mppOptions[n]->constraint.word_list[0]; 957 rpDouble = new double[nItems]; 958 for( i=0; i<nItems; i++ ) 959 { 960 rpDouble[i] = bIsFixed ? 961 SANE_UNFIX( mppOptions[n]->constraint.word_list[i+1] ) : 962 (double)mppOptions[n]->constraint.word_list[i+1]; 963 } 964 dbg_msg( "wordlist [ %lg ... %lg ]\n", 965 rpDouble[ 0 ], rpDouble[ nItems-1 ] ); 966 return nItems; 967 } 968 } 969 970 static const char *ppUnits[] = { 971 "", 972 "[Pixel]", 973 "[Bit]", 974 "[mm]", 975 "[DPI]", 976 "[%]", 977 "[usec]" 978 }; 979 980 String Sane::GetOptionUnitName( int n ) 981 { 982 String aText; 983 SANE_Unit nUnit = mppOptions[n]->unit; 984 size_t nUnitAsSize = (size_t)nUnit; 985 if (nUnitAsSize >= sizeof(ppUnits)/sizeof(ppUnits[0])) 986 aText = String::CreateFromAscii( "[unknown units]" ); 987 else 988 aText = String( ppUnits[ nUnit ], gsl_getSystemTextEncoding() ); 989 return aText; 990 } 991 992 sal_Bool Sane::ActivateButtonOption( int n ) 993 { 994 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, NULL ); 995 if( nStatus != SANE_STATUS_GOOD ) 996 return sal_False; 997 return sal_True; 998 } 999 1000 /* vim: set noet sw=4 ts=4: */ 1001