1/* @file u12_image.c 2 * @brief functions to convert scanner data into image data 3 * 4 * based on sources acquired from Plustek Inc. 5 * Copyright (c) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de> 6 * 7 * History: 8 * - 0.01 - initial version 9 * - 0.02 - fixed fnColor42() to return 16bit values instead of 10 * only 12bit (this is the maximum the scanner can) 11 * - added scaling function u12image_ScaleX() 12 * . 13 * <hr> 14 * This file is part of the SANE package. 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of the 19 * License, or (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, but 22 * WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 * General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program. If not, see <https://www.gnu.org/licenses/>. 28 * 29 * As a special exception, the authors of SANE give permission for 30 * additional uses of the libraries contained in this release of SANE. 31 * 32 * The exception is that, if you link a SANE library with other files 33 * to produce an executable, this does not by itself cause the 34 * resulting executable to be covered by the GNU General Public 35 * License. Your use of that executable is in no way restricted on 36 * account of linking the SANE library code into it. 37 * 38 * This exception does not, however, invalidate any other reasons why 39 * the executable file might be covered by the GNU General Public 40 * License. 41 * 42 * If you submit changes to SANE to the maintainers to be included in 43 * a subsequent release, you agree by submitting the changes that 44 * those changes may be distributed with this exception intact. 45 * 46 * If you write modifications of your own for SANE, it is your choice 47 * whether to permit this exception to apply to your modifications. 48 * If you do not wish that, delete this exception notice. 49 * <hr> 50 */ 51 52/*************************** local vars **************************************/ 53 54static u_short wPreviewScanned = 0; 55 56static ExpXStepDef negScan[5] = { 57 {128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96} 58}; 59 60static ExpXStepDef posScan[5] = { 61 {128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96} 62}; 63 64static ExpXStepDef nmlScan[5] = { 65 {160, 10}, {96, 12}, {96, 24}, {96, 48}, {96, 96}, 66}; 67 68/*************************** local functions *********************************/ 69 70/** 71 */ 72static SANE_Bool fnReadToDriver( U12_Device *dev ) 73{ 74 dev->regs.RD_ModeControl = _ModeFifoBSel; 75 u12io_ReadMonoData( dev, dev->scan.BufPut.blue.bp, 76 dev->DataInf.dwAsicBytesPerPlane ); 77 78 dev->regs.RD_ModeControl = _ModeFifoGSel; 79 u12io_ReadMonoData( dev, dev->scan.BufPut.green.bp, 80 dev->DataInf.dwAsicBytesPerPlane ); 81 82 if( dev->scan.gd_gk.wGreenKeep ) 83 dev->scan.gd_gk.wGreenKeep--; 84 else { 85 dev->scan.BufPut.green.bp += dev->DataInf.dwAsicBytesPerPlane; 86 87 if( dev->scan.BufPut.green.bp >= dev->scan.BufEnd.green.bp ) 88 dev->scan.BufPut.green.bp = dev->scan.BufBegin.green.bp; 89 } 90 91 dev->regs.RD_ModeControl = _ModeFifoRSel; 92 u12io_ReadMonoData( dev, dev->scan.BufPut.red.bp, 93 dev->DataInf.dwAsicBytesPerPlane ); 94 95 dev->scan.BufPut.red.bp += dev->DataInf.dwAsicBytesPerPlane; 96 if( dev->scan.BufPut.red.bp >= dev->scan.BufEnd.red.bp ) 97 dev->scan.BufPut.red.bp = dev->scan.BufBegin.red.bp; 98 99 if( dev->scan.bd_rk.wRedKeep ) { 100 dev->scan.bd_rk.wRedKeep--; 101 return SANE_FALSE; 102 103 } else { 104 105 dev->scan.BufData.green.bp = dev->scan.BufGet.green.bp; 106 dev->scan.BufData.red.bp = dev->scan.BufGet.red.bp; 107 dev->scan.BufData.blue.bp = dev->scan.BufGet.blue.bp; 108 109 dev->scan.BufGet.red.bp += dev->DataInf.dwAsicBytesPerPlane; 110 dev->scan.BufGet.green.bp += dev->DataInf.dwAsicBytesPerPlane; 111 112 if( dev->scan.BufGet.red.bp >= dev->scan.BufEnd.red.bp ) 113 dev->scan.BufGet.red.bp = dev->scan.BufBegin.red.bp; 114 115 if( dev->scan.BufGet.green.bp >= dev->scan.BufEnd.green.bp ) 116 dev->scan.BufGet.green.bp = dev->scan.BufBegin.green.bp; 117 118 return SANE_TRUE; 119 } 120} 121 122/** 123 */ 124static SANE_Bool fnReadOutScanner( U12_Device *dev ) 125{ 126 if( dev->scan.bd_rk.wBlueDiscard ) { 127 128 dev->scan.bd_rk.wBlueDiscard--; 129 dev->regs.RD_ModeControl = _ModeFifoBSel; 130 131 u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf, 132 dev->DataInf.dwAsicBytesPerPlane ); 133 134 if( dev->scan.gd_gk.wGreenDiscard ) { 135 dev->scan.gd_gk.wGreenDiscard--; 136 137 dev->regs.RD_ModeControl = _ModeFifoGSel; 138 u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf, 139 dev->DataInf.dwAsicBytesPerPlane ); 140 } 141 return SANE_FALSE; 142 143 } else { 144 u12io_ReadColorData( dev, dev->bufs.b1.pReadBuf, 145 dev->DataInf.dwAsicBytesPerPlane ); 146 return SANE_TRUE; 147 } 148} 149 150/** some sampling functions 151 */ 152static SANE_Bool fnEveryLine( U12_Device *dev ) 153{ 154 _VAR_NOT_USED( dev ); 155 return SANE_TRUE; 156} 157 158static SANE_Bool fnSampleLines( U12_Device *dev ) 159{ 160 dev->DataInf.wYSum += dev->DataInf.xyAppDpi.y; 161 162 if( dev->DataInf.wYSum >= dev->DataInf.xyPhyDpi.y ) { 163 dev->DataInf.wYSum -= dev->DataInf.xyPhyDpi.y; 164 return SANE_TRUE; 165 } 166 return SANE_FALSE; 167} 168 169static SANE_Bool fnSamplePreview( U12_Device *dev ) 170{ 171 dev->DataInf.wYSum += wPreviewScanned; 172 if( dev->DataInf.wYSum >= 150 ) { 173 174 dev->DataInf.wYSum -= 150; 175 return SANE_TRUE; 176 } 177 178 return SANE_FALSE; 179} 180 181/** this function is used when 182 * - the data type is B/W or GrayScale. 183 * - the required horizontal resolution doesn't exceed the optic spec. 184 * - the required vertical resolution exceeds the optic spec. 185 */ 186static void fnDataDirect( U12_Device *dev, void *src, void *dest, u_long len ) 187{ 188 _VAR_NOT_USED( dev ); 189 memcpy( dest, src, len ); 190} 191 192/** merges the color planes to pixels style without enlarge operation. 193 */ 194static void fnColorDirect( U12_Device *dev, void *pb, void *img, u_long len ) 195{ 196 SANE_Byte *src; 197 RGBByteDef *dest; 198 199 src = (SANE_Byte*)img; 200 dest = (RGBByteDef*)pb; 201 202 for ( len = dev->DataInf.dwAsicPixelsPerPlane; len; len--, src++, dest++) { 203 204 dest->Red = *src; 205 dest->Green = src[dev->DataInf.dwAsicPixelsPerPlane]; 206 dest->Blue = src[dev->DataInf.dwAsicPixelsPerPlane*2]; 207 } 208} 209 210/** merges the color planes to pixels style without enlarge operation. 211 * The scanner returns the pixel data in Motorola-Format, so we have to swap 212 * (at least on x86) 213 */ 214static void fnColor42( U12_Device *dev, void *pb, void *img, u_long len ) 215{ 216 u_short *src; 217 RGBUShortDef *dest; 218 219 register u_long i; 220 221 _VAR_NOT_USED( len ); 222 src = (u_short*)img; 223 dest = (RGBUShortDef*)pb; 224 225 for ( i = dev->DataInf.dwAsicPixelsPerPlane; i; i--, src++, dest++) { 226 227 dest->Red = (*src) << 4; 228 dest->Green = (src[dev->DataInf.dwAsicPixelsPerPlane]) << 4; 229 dest->Blue = (src[dev->DataInf.dwAsicPixelsPerPlane * 2]) << 4; 230 } 231} 232 233/** 234 */ 235static void u12image_SetupScanStateVariables( U12_Device *dev, u_long index ) 236{ 237 DataType var; 238 239 DBG( _DBG_INFO, "u12image_SetupScanStateVariables(%lu)\n", index ); 240 dev->scan.dpiIdx = index; 241 242 if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) { 243 244 dev->shade.wExposure = nmlScan[index].exposureTime; 245 dev->shade.wXStep = nmlScan[index].xStepTime; 246 247 if( dev->shade.intermediate & _ScanMode_AverageOut ) { 248 dev->shade.wExposure >>= 1; 249 dev->shade.wXStep >>= 1; 250 } 251 } else { 252 if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency ) { 253 dev->shade.wExposure = posScan[index].exposureTime; 254 dev->shade.wXStep = posScan[index].xStepTime; 255 } else { 256 dev->shade.wExposure = dev->scan.negScan[index].exposureTime; 257 dev->shade.wXStep = dev->scan.negScan[index].xStepTime; 258 } 259 } 260 dev->scan.dwInterval = 1; 261 262 if( dev->DataInf.wPhyDataType == COLOR_BW ) 263 var.dwValue = 0; 264 else { 265 if( dev->DataInf.wPhyDataType == COLOR_256GRAY ) 266 var.dwValue = 2500; 267 else 268 var.dwValue = 3200; 269 } 270 271 /* for small size/descreen */ 272 if((dev->DataInf.xyAppDpi.y >= 300) && var.dwValue && 273 (dev->DataInf.dwAsicBytesPerPlane <= var.dwValue)) { 274 dev->scan.dwInterval <<= 1; 275 } 276 277 if( var.dwValue && dev->DataInf.dwAsicBytesPerPlane > var.dwValue ) { 278 if((var.dwValue << 1) > dev->DataInf.dwAsicBytesPerPlane) 279 dev->scan.dwInterval <<= 1; 280 else 281 if((var.dwValue << 2) > dev->DataInf.dwAsicBytesPerPlane) 282 dev->scan.dwInterval <<= 2; 283 else 284 dev->scan.dwInterval <<= 3; 285 } 286 287 if( dev->DataInf.wPhyDataType >= COLOR_TRUE24 ) { 288 289 if( dev->DataInf.xyPhyDpi.y > 75U ) { 290 if( dev->f0_8_16 ) { 291 dev->scan.gd_gk.wGreenDiscard = dev->DataInf.xyPhyDpi.y / 75U; 292 } else { 293 dev->scan.gd_gk.wGreenDiscard = dev->DataInf.xyPhyDpi.y / 150U; 294 } 295 } else { 296 dev->scan.gd_gk.wGreenDiscard = 1; 297 } 298 299 dev->scan.bd_rk.wBlueDiscard = dev->scan.gd_gk.wGreenDiscard << 1; 300 } else { 301 dev->scan.bd_rk.wBlueDiscard = dev->scan.gd_gk.wGreenDiscard = 0; 302 } 303} 304 305/** limit the resolution 306 */ 307static u_short 308u12image_GetPhysDPI( U12_Device *dev, ImgDef *img, SANE_Bool fDpiX ) 309{ 310 if( fDpiX ) { 311 312 if( img->xyDpi.x > dev->dpi_max_x ) 313 return dev->dpi_max_x; 314 else 315 return img->xyDpi.x; 316 317 } else { 318 319 if( img->xyDpi.y > dev->dpi_max_y ) 320 return dev->dpi_max_y; 321 else 322 return img->xyDpi.y; 323 } 324} 325 326/** calculate the image properties according to the scanmode 327 * set all internally needed information 328 */ 329static void u12image_GetImageInfo( U12_Device *dev, ImgDef *image ) 330{ 331 DBG( _DBG_INFO, "u12image_GetImageInfo()\n" ); 332 333 dev->DataInf.xyPhyDpi.x = u12image_GetPhysDPI(dev, image, SANE_TRUE ); 334 dev->DataInf.xyPhyDpi.y = u12image_GetPhysDPI(dev, image, SANE_FALSE); 335 336 DBG( _DBG_INFO, "* xyPhyDpi.x = %u, xyPhyDpi.y = %u\n", 337 dev->DataInf.xyPhyDpi.x, dev->DataInf.xyPhyDpi.y ); 338 339 DBG( _DBG_INFO, "* crArea.x = %u, crArea.y = %u\n", 340 image->crArea.x, image->crArea.y ); 341 342 DBG( _DBG_INFO, "* crArea.cx = %u, crArea.cy = %u\n", 343 image->crArea.cx, image->crArea.cy ); 344 345 dev->DataInf.xyRatio = (double)dev->DataInf.xyPhyDpi.y/ 346 (double)dev->DataInf.xyPhyDpi.x; 347 348 dev->DataInf.dwAppLinesPerArea = (u_long)image->crArea.cy * 349 image->xyDpi.y / _MEASURE_BASE; 350 351 dev->DataInf.dwAppPixelsPerLine = (u_long)image->crArea.cx * 352 image->xyDpi.x / _MEASURE_BASE; 353 354 dev->DataInf.dwPhysBytesPerLine = (u_long)image->crArea.cx * 355 dev->DataInf.xyPhyDpi.x / _MEASURE_BASE; 356 357 if( image->wDataType <= COLOR_BW ) { 358 dev->DataInf.dwAsicPixelsPerPlane = 359 (dev->DataInf.dwAppPixelsPerLine+7UL) & 0xfffffff8UL; 360 dev->DataInf.dwAppPhyBytesPerLine = 361 dev->DataInf.dwAppBytesPerLine = 362 dev->DataInf.dwAsicBytesPerLine = 363 dev->DataInf.dwAsicBytesPerPlane = dev->DataInf.dwAsicPixelsPerPlane>>3; 364 } else { 365 dev->DataInf.dwAsicBytesPerPlane = 366 dev->DataInf.dwAsicPixelsPerPlane = dev->DataInf.dwAppPixelsPerLine; 367 } 368 369 if( COLOR_TRUE42 == image->wDataType ) { 370 dev->DataInf.dwAsicBytesPerPlane *= 2; 371 } 372 373 switch( image->wDataType ) { 374 375 case COLOR_BW: 376 dev->scan.DataProcess = fnDataDirect; 377 dev->DataInf.wPhyDataType = COLOR_BW; 378 dev->shade.intermediate = _ScanMode_Mono; 379 break; 380 381 case COLOR_256GRAY: 382 dev->scan.DataProcess = fnDataDirect; 383 dev->DataInf.dwAsicBytesPerLine = 384 dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine; 385 dev->DataInf.wPhyDataType = COLOR_256GRAY; 386 dev->shade.intermediate = _ScanMode_Mono; 387 break; 388 389 case COLOR_TRUE24: 390 dev->scan.DataProcess = fnColorDirect; 391 dev->DataInf.dwAsicBytesPerLine = 392 dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine * 3; 393 dev->DataInf.wPhyDataType = COLOR_TRUE24; 394 dev->shade.intermediate = _ScanMode_Color; 395 break; 396 397 case COLOR_TRUE42: 398 dev->scan.DataProcess = fnColor42; 399 dev->DataInf.dwAsicBytesPerLine = 400 dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine * 6; 401 dev->DataInf.wPhyDataType = COLOR_TRUE42; 402 dev->shade.intermediate = _ScanMode_Color; 403 break; 404 } 405 406 /* raus mit einem von beiden!!!!*/ 407 dev->DataInf.dwAppBytesPerLine = dev->DataInf.dwAppPhyBytesPerLine; 408 409 DBG( _DBG_INFO, "AppLinesPerArea = %lu\n", dev->DataInf.dwAppLinesPerArea ); 410 DBG( _DBG_INFO, "AppPixelsPerLine = %lu\n", dev->DataInf.dwAppPixelsPerLine ); 411 DBG( _DBG_INFO, "AppPhyBytesPerLine = %lu\n", dev->DataInf.dwAppPhyBytesPerLine ); 412 DBG( _DBG_INFO, "AppBytesPerLine = %lu\n", dev->DataInf.dwAppBytesPerLine ); 413 DBG( _DBG_INFO, "AsicPixelsPerPlane = %lu\n", dev->DataInf.dwAsicPixelsPerPlane ); 414 DBG( _DBG_INFO, "AsicBytesPerPlane = %lu\n", dev->DataInf.dwAsicBytesPerPlane ); 415 DBG( _DBG_INFO, "AsicBytesPerLine = %lu\n", dev->DataInf.dwAsicBytesPerLine ); 416 DBG( _DBG_INFO, "Physical Bytes = %lu\n", dev->DataInf.dwPhysBytesPerLine ); 417} 418 419/** 420 */ 421static int imageSetupScanSettings( U12_Device *dev, ImgDef *img ) 422{ 423 u_short brightness; 424 425 DBG( _DBG_INFO, "imageSetupScanSettings()\n" ); 426 427 dev->DataInf.dwScanFlag = img->dwFlag; 428 dev->DataInf.crImage = img->crArea; 429 430 DBG( _DBG_INFO,"* DataInf.dwScanFlag = 0x%08lx\n",dev->DataInf.dwScanFlag); 431 432 dev->DataInf.crImage.x <<= 1; 433 434 dev->DataInf.xyAppDpi = img->xyDpi; 435 dev->DataInf.wAppDataType = img->wDataType; 436 437 u12image_GetImageInfo( dev, img ); 438 439 dev->scan.lBufferAdjust = (long)dev->DataInf.dwAppBytesPerLine; 440 441 DBG( _DBG_INFO, "* Scan settings:\n" ); 442 DBG( _DBG_INFO, "* ImageInfo: (x=%u,y=%u,dx=%u,dy=%u)\n", 443 dev->DataInf.crImage.x, dev->DataInf.crImage.y, 444 dev->DataInf.crImage.cx, dev->DataInf.crImage.cy ); 445 446 /* 447 * 0 _DEF_BW_THRESHOLD 255 448 * +-------------------------+--------------------------------+ 449 * |<------- Black --------->|<----------- White ------------>| 450 * So, if user wish to make image darker, the threshold value should be 451 * higher than _defBwThreshold, otherwise it should lower than the 452 * _DefBwThreshold. 453 * Darker = _DEF_BW_THRESHOLD + White * Input / 127; 454 * Input < 0, and White = 255 - _DEF_BW_THRESHOLD, so 455 * = _DEF_BW_THRESHOLD - (255 - _DEF_BW_THRESHOLD) * Input / 127; 456 * The brighter is the same idea. 457 */ 458 459/* CHECK: We have now two methods for setting the brightness... 460*/ 461 DBG( _DBG_INFO, "* brightness = %i\n", dev->DataInf.siBrightness ); 462 if ( dev->DataInf.siBrightness < 0) { 463 brightness = (u_short)(_DEF_BW_THRESHOLD - 464 (255 - _DEF_BW_THRESHOLD) * dev->DataInf.siBrightness /127); 465 } else { 466 brightness = (u_short)(_DEF_BW_THRESHOLD - 467 _DEF_BW_THRESHOLD * dev->DataInf.siBrightness /127); 468 } 469 470 dev->regs.RD_ThresholdControl = brightness; 471 DBG( _DBG_INFO, "* RD_ThresholdControl = %i\n", brightness ); 472 return 0; 473} 474 475/** PrepareScanningVariables() !!! 476 */ 477static SANE_Status u12image_SetupScanSettings( U12_Device *dev, ImgDef *img ) 478{ 479 DBG( _DBG_INFO, "u12image_SetupScanSettings()\n" ); 480 481 wPreviewScanned = 0; 482 dev->scan.dpiIdx = 0; 483 dev->scan.negScan = negScan; 484 485 imageSetupScanSettings( dev, img ); 486 487 if( !(dev->DataInf.dwScanFlag & _SCANDEF_TPA )) { 488 489 dev->scan.dwScanOrigin = dev->adj.upNormal * 4 + _RFT_SCANNING_ORG; 490 491 } else if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency) { 492 493 dev->scan.dwScanOrigin = dev->adj.upPositive * 4 + _POS_SCANNING_ORG; 494 } else { 495 dev->scan.dwScanOrigin = dev->adj.upNegative * 4 + _NEG_SCANNING_ORG; 496 } 497 dev->scan.dwScanOrigin += 64 /*dev->dwModelOriginY*/; 498 499 if( dev->DataInf.xyAppDpi.y <= 75 ) { 500 501 if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) { 502 503 dev->scan.bDiscardAll = 0; 504 dev->DataInf.xyPhyDpi.y = 150; 505 dev->shade.intermediate |= _ScanMode_AverageOut; 506 u12image_SetupScanStateVariables( dev, 1 ); 507 dev->scan.gd_gk.wGreenDiscard = 0; 508 509 if( dev->DataInf.xyAppDpi.y >= 38 ) 510 dev->scan.bd_rk.wBlueDiscard = 1; 511 else 512 dev->scan.bd_rk.wBlueDiscard = 0; 513 514 if( dev->DataInf.wPhyDataType >= COLOR_256GRAY ) { 515 dev->shade.wXStep = 6; 516 dev->shade.wExposure = 8 * dev->shade.wXStep; 517 } 518 } else { 519 if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA) && 520 (dev->DataInf.xyAppDpi.y <= 50) && 521 (dev->DataInf.wPhyDataType >= COLOR_TRUE24)) { 522 dev->shade.intermediate |= _ScanMode_AverageOut; 523 } 524 525 if((dev->DataInf.wPhyDataType<COLOR_TRUE24) || dev->f0_8_16 || 526 (dev->shade.intermediate & _ScanMode_AverageOut)) { 527 528 dev->scan.bDiscardAll = 1; 529 dev->DataInf.xyPhyDpi.y = 75; 530 u12image_SetupScanStateVariables( dev, 0 ); 531 } else { 532 dev->scan.bDiscardAll = 2; 533 dev->DataInf.xyPhyDpi.y = 150; 534 u12image_SetupScanStateVariables( dev, 1 ); 535 } 536 } 537 } else { 538 if( dev->DataInf.xyAppDpi.y <= 150 ) { 539 540 dev->scan.bDiscardAll = 2; 541 dev->DataInf.xyPhyDpi.y = 150; 542 u12image_SetupScanStateVariables( dev, 1 ); 543 544 } else if( dev->DataInf.xyAppDpi.y <= 300 ) { 545 546 dev->scan.bDiscardAll = 4; 547 dev->DataInf.xyPhyDpi.y = 300; 548 u12image_SetupScanStateVariables( dev, 2 ); 549 550 } else if( dev->DataInf.xyAppDpi.y <= 600 ) { 551 552 dev->scan.bDiscardAll = 8; 553 dev->DataInf.xyPhyDpi.y = 600; 554 u12image_SetupScanStateVariables( dev, 3 ); 555 556 } else { 557 558 dev->scan.bDiscardAll = 16; 559 dev->DataInf.xyPhyDpi.y = 1200; 560 u12image_SetupScanStateVariables( dev, 4 ); 561 } 562 } 563 564 /* ------- lines to sample or not? ------- */ 565 if( dev->DataInf.xyAppDpi.y == dev->DataInf.xyPhyDpi.y ) { 566 DBG( _DBG_INFO, "* Sample every line\n" ); 567 dev->scan.DoSample = fnEveryLine; 568 } else { 569 if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) { 570 571 DBG( _DBG_INFO, "* Sample preview\n" ); 572 dev->scan.DoSample = fnSamplePreview; 573 dev->DataInf.wYSum = 150; 574 575 if( dev->DataInf.xyAppDpi.y >= 38 ) 576 wPreviewScanned = dev->DataInf.xyAppDpi.y * 2; 577 else if( dev->DataInf.xyAppDpi.y >= 19 ) 578 wPreviewScanned = dev->DataInf.xyAppDpi.y * 4; 579 else 580 wPreviewScanned = dev->DataInf.xyAppDpi.y * 8; 581 } else { 582 583 DBG( _DBG_INFO, "* Sample lines (%u - %u)...\n", 584 dev->DataInf.xyPhyDpi.y, dev->DataInf.xyAppDpi.y ); 585 dev->scan.DoSample = fnSampleLines; 586 dev->DataInf.wYSum = dev->DataInf.xyPhyDpi.y - dev->DataInf.xyAppDpi.y; 587 } 588 } 589 590 /* now assign the buffer pointers for image acquisition 591 */ 592 dev->scan.p48BitBuf.pb = NULL; 593 594 if( dev->DataInf.wPhyDataType >= COLOR_TRUE24 ) { 595 596 u_long r, g, b; 597 598 r = (u_long)_SIZE_REDFIFO / 599 dev->DataInf.dwAsicBytesPerPlane - dev->scan.bd_rk.wRedKeep; 600 g = (u_long)_SIZE_GREENFIFO / 601 dev->DataInf.dwAsicBytesPerPlane - dev->scan.gd_gk.wGreenKeep; 602 603 if((int)r < 16 || (int)g < 16) { 604 605 b = (u_long)(dev->scan.bd_rk.wRedKeep + 606 dev->scan.gd_gk.wGreenKeep + 2U) * 607 dev->DataInf.dwAsicBytesPerPlane; 608 609 DBG( _DBG_INFO, "48Bit buffer request: " 610 "len=%lu bytes, available=%lu\n", b, _SIZE_TOTAL_BUF_TPA ); 611 612 if( b > _SIZE_TOTAL_BUF_TPA ) { 613 DBG( _DBG_ERROR, "Not that much FIFO memory available!\n" ); 614 return SANE_STATUS_NO_MEM; 615 } 616 617 dev->scan.p48BitBuf.pb = dev->bufs.b1.pReadBuf; 618 } 619 } 620 621 if( dev->scan.p48BitBuf.pb ){ 622 dev->scan.DataRead = fnReadToDriver; 623 dev->scan.BufGet.red.bp = 624 dev->scan.BufPut.red.bp = 625 dev->scan.BufBegin.red.bp = dev->scan.p48BitBuf.pb; 626 dev->scan.BufEnd.red.bp = 627 dev->scan.BufBegin.green.bp = 628 dev->scan.BufGet.green.bp = 629 dev->scan.BufPut.green.bp = dev->scan.p48BitBuf.pb + 630 dev->DataInf.dwAsicBytesPerLine * 631 (dev->scan.bd_rk.wRedKeep + 1U); 632 633 dev->scan.BufEnd.green.bp = dev->scan.BufBegin.green.bp + 634 dev->DataInf.dwAsicBytesPerLine * 635 (dev->scan.gd_gk.wGreenKeep + 1U); 636 dev->scan.BufPut.blue.bp = 637 dev->scan.BufGet.blue.bp = dev->bufs.b1.pReadBuf + 638 dev->DataInf.dwAsicBytesPerLine * 2; 639 } else { 640 dev->scan.DataRead = fnReadOutScanner; 641 dev->scan.BufPut.red.bp = dev->bufs.b1.pReadBuf; 642 dev->scan.BufData.green.bp = 643 dev->scan.BufPut.green.bp = dev->scan.BufPut.red.bp + 644 dev->DataInf.dwAsicBytesPerLine; 645 dev->scan.BufPut.blue.bp = dev->scan.BufPut.green.bp + 646 dev->DataInf.dwAsicBytesPerLine; 647 648 dev->scan.BufData.red.bp = dev->scan.BufPut.red.bp; 649 dev->scan.BufData.blue.bp = dev->scan.BufPut.blue.bp; 650 } 651 652/* CHECK: maybe remove this stuff */ 653#if 0 654 if( ps->DataInf.dwScanFlag & _SCANDEF_Transparency) { 655 posScan[1].exposureTime = 96; 656 posScan[1].xStepTime = 12; 657 posScan[2].exposureTime = 96; 658 posScan[2].xStepTime = 24; 659 posScan[3].exposureTime = 96; 660 posScan[3].xStepTime = 48; 661 posScan[4].exposureTime = 96; 662 posScan[4].xStepTime = 96; 663 664 /* Reset shading Exposure Time & xStep Time */ 665 ps->Shade.wExposure = posScan[ps->Scan.dpiIdx].exposureTime; 666 ps->Shade.wXStep = posScan[ps->Scan.dpiIdx].xStepTime; 667 } 668 else if( ps->DataInf.dwScanFlag & _SCANDEF_Negative) { 669 ps->Scan.negScan[1].exposureTime = 96; 670 ps->Scan.negScan[1].xStepTime = 12; 671 ps->Scan.negScan[2].exposureTime = 96; 672 ps->Scan.negScan[2].xStepTime = 24; 673 ps->Scan.negScan[3].exposureTime = 96; 674 ps->Scan.negScan[3].xStepTime = 48; 675 ps->Scan.negScan[4].exposureTime = 96; 676 ps->Scan.negScan[4].xStepTime = 96; 677 678 /* Reset shading Exposure Time & xStep Time */ 679 ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime; 680 ps->Shade.wXStep = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime; 681 } 682#endif 683 return SANE_STATUS_GOOD; 684} 685 686/** 687 */ 688static SANE_Bool u12image_DataIsReady( U12_Device *dev, void* buf ) 689{ 690 DBG( _DBG_READ, "* DataIsReady()\n" ); 691 692 if( dev->scan.bDiscardAll ) { 693 dev->scan.bDiscardAll--; 694 695 if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { 696 dev->regs.RD_ModeControl = _ModeFifoGSel; 697 u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf, 698 dev->DataInf.dwAsicBytesPerPlane ); 699 } else { 700 u12io_ReadColorData( dev, dev->bufs.b1.pReadBuf, 701 dev->DataInf.dwAsicBytesPerPlane ); 702 } 703 return SANE_FALSE; 704 } 705 706 if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { 707 708 dev->regs.RD_ModeControl = _ModeFifoGSel; 709 u12io_ReadMonoData( dev, buf, dev->DataInf.dwAsicBytesPerPlane ); 710 711 } else { 712 713 if( !dev->scan.DataRead( dev )) { 714 return SANE_FALSE; 715 } 716 } 717 718 if( dev->scan.DoSample( dev )) { 719 720 /* direct is done here without copying...*/ 721 if( fnDataDirect != dev->scan.DataProcess ) { 722 (*dev->scan.DataProcess)(dev, buf, (void*)(dev->scan.BufPut.red.bp), 723 dev->DataInf.dwAppPhyBytesPerLine); 724 } 725 return SANE_TRUE; 726 } 727 return SANE_FALSE; 728} 729 730/** 731 */ 732static SANE_Status u12image_ReadOneImageLine( U12_Device *dev, void* buf ) 733{ 734 SANE_Byte b, state; 735 TimerDef timer, t2; 736 737 DBG( _DBG_READ, "u12image_ReadOneImageLine()\n" ); 738 739 u12io_StartTimer( &timer, _LINE_TIMEOUT ); 740 u12io_StartTimer( &t2, _SECOND*2 ); 741 do { 742 743 state = u12io_GetScanState( dev ); 744 dev->scan.bNowScanState = (state & _SCANSTATE_MASK); 745 746 if( state & _SCANSTATE_STOP ) { 747 748 DBG( _DBG_READ, "* SCANSTATE_STOP\n" ); 749 u12motor_ModuleForwardBackward( dev ); 750 751 if( u12io_GetFifoLength( dev ) >= dev->scan.dwMinReadFifo ) 752 if( u12image_DataIsReady( dev, buf )) 753 return SANE_STATUS_GOOD; 754 755 } else { 756 757 dev->scan.bModuleState = _MotorInNormalState; 758 b = dev->scan.bNowScanState - dev->scan.oldScanState; 759 760 if((char) b < 0) 761 b += _NUMBER_OF_SCANSTEPS; 762 763 if( b >= dev->scan.bRefresh ) { 764 765 u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); 766 dev->scan.oldScanState = u12io_GetScanState( dev ); 767 dev->scan.oldScanState &= _SCANSTATE_MASK; 768 } 769 770 if( u12io_GetFifoLength( dev ) >= dev->scan.dwMaxReadFifo ) { 771 772 if( u12image_DataIsReady( dev, buf )) 773 return SANE_STATUS_GOOD; 774 } 775 else { 776 777 b = dev->scan.bNowScanState - dev->scan.oldScanState; 778 779 if((char) b < 0) 780 b += _NUMBER_OF_SCANSTEPS; 781 782 if( b >= dev->scan.bRefresh ) { 783 784 u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); 785 dev->scan.oldScanState = u12io_GetScanState( dev ); 786 dev->scan.oldScanState &= _SCANSTATE_MASK; 787 } 788 789 if( u12io_GetFifoLength( dev ) >= dev->scan.dwMinReadFifo ) { 790 if( u12image_DataIsReady( dev, buf )) 791 return SANE_STATUS_GOOD; 792 } 793 } 794 } 795 796 } while( !u12io_CheckTimer( &timer )); 797 798 DBG( _DBG_ERROR, "Timeout - Scanner malfunction !!\n" ); 799 u12motor_ToHomePosition( dev, SANE_TRUE ); 800 801 /* timed out, scanner malfunction */ 802 return SANE_STATUS_IO_ERROR; 803} 804 805/** 806 */ 807static void u12image_PrepareScaling( U12_Device *dev ) 808{ 809 int step; 810 double ratio; 811 812 dev->scaleBuf = NULL; 813 DBG( _DBG_INFO, "APP-DPIX=%u, MAX-DPIX=%u\n", 814 dev->DataInf.xyAppDpi.x, dev->dpi_max_x ); 815 816 if( dev->DataInf.xyAppDpi.x > dev->dpi_max_x ) { 817 818 dev->scaleBuf = malloc( dev->DataInf.dwAppBytesPerLine ); 819 820 ratio = (double)dev->DataInf.xyAppDpi.x/(double)dev->dpi_max_x; 821 dev->scaleIzoom = (int)(1.0/ratio * 1000); 822 823 switch( dev->DataInf.wAppDataType ) { 824 825 case COLOR_BW : step = 0; break; 826 case COLOR_256GRAY : step = 1; break; 827 case COLOR_TRUE24 : step = 3; break; 828 case COLOR_TRUE42 : step = 6; break; 829 default : step = 99; break; 830 } 831 dev->scaleStep = step; 832 833 DBG( _DBG_INFO, "u12image_PrepareScaling: izoom=%i, step=%u\n", 834 dev->scaleIzoom, step ); 835 } else { 836 837 DBG( _DBG_INFO, "u12image_PrepareScaling: DISABLED\n" ); 838 } 839} 840 841/** scaling picture data in x-direction, using a DDA algorithm 842 * (digital differential analyzer). 843 */ 844static void u12image_ScaleX( U12_Device *dev, SANE_Byte *ib, SANE_Byte *ob ) 845{ 846 SANE_Byte tmp; 847 int ddax; 848 u_long i, j, x; 849 850 /* when not supported, only copy the data */ 851 if( 99 == dev->scaleStep ) { 852 memcpy( ob, ib, dev->DataInf.dwAppBytesPerLine ); 853 return; 854 } 855 856 /* now scale... */ 857 if( 0 == dev->scaleStep ) { 858 859 /* binary scaling */ 860 ddax = 0; 861 x = 0; 862 memset( ob, 0, dev->DataInf.dwAppBytesPerLine ); 863 864 for( i = 0; i < dev->DataInf.dwPhysBytesPerLine*8; i++ ) { 865 866 ddax -= 1000; 867 868 while( ddax < 0 ) { 869 870 tmp = ib[(i>>3)]; 871 872 if((x>>3) < dev->DataInf.dwAppBytesPerLine ) { 873 if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7)))) 874 ob[x>>3] |= (1 << ((~(x & 0x7))&0x7)); 875 } 876 x++; 877 ddax += dev->scaleIzoom; 878 } 879 } 880 881 } else { 882 883 /* color and gray scaling */ 884 ddax = 0; 885 x = 0; 886 for( i = 0; i < dev->DataInf.dwPhysBytesPerLine*dev->scaleStep; 887 i+=dev->scaleStep ) { 888 889 ddax -= 1000; 890 891 while( ddax < 0 ) { 892 893 for( j = 0; j < (u_long)dev->scaleStep; j++ ) { 894 895 if((x+j) < dev->DataInf.dwAppBytesPerLine ) { 896 ob[x+j] = ib[i+j]; 897 } 898 } 899 x += dev->scaleStep; 900 ddax += dev->scaleIzoom; 901 } 902 } 903 } 904} 905 906/* END U12_IMAGE.C ..........................................................*/ 907