kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			1680 wiersze
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			1680 wiersze
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
| /*.............................................................................
 | ||
|  * Project : SANE library for Plustek parallelport flatbed scanners.
 | ||
|  *.............................................................................
 | ||
|  */
 | ||
| 
 | ||
| /* @file plustek-pp_image.c
 | ||
|  * @brief functions to convert scanner data into image data
 | ||
|  *
 | ||
|  * based on sources acquired from Plustek Inc.
 | ||
|  * Copyright (C) 1998 Plustek Inc.
 | ||
|  * Copyright (C) 2000-2004 Gerhard Jaeger <gerhard@gjaeger.de>
 | ||
|  * also based on the work done by Rick Bronson
 | ||
|  *
 | ||
|  * History:
 | ||
|  * - 0.30 - initial version
 | ||
|  * - 0.31 - no changes
 | ||
|  * - 0.32 - no changes
 | ||
|  * - 0.33 - no changes
 | ||
|  * - 0.34 - reactivated code in imageP96WaitLineData() to recover from
 | ||
|  *          loosing data
 | ||
|  * - 0.35 - no changes
 | ||
|  * - 0.36 - removed comment
 | ||
|  *        - added wDither exchange to imageP9xSetupScanSettings
 | ||
|  *        - added fnHalftoneDirect1 which provides dithering by using random
 | ||
|  *          thresholds
 | ||
|  *        - removed the swapping behaviour for model OP_600 in
 | ||
|  *          fnP96ColorDirect() according to the Primax 4800 Direct tests
 | ||
|  *        - changes, due to define renaming
 | ||
|  *        - removed _ASIC_96001 specific stuff to invert colors
 | ||
|  * - 0.37 - removed // comments
 | ||
|  *        - corrected output of 12bit/pixel
 | ||
|  * - 0.38 - added P12 stuff
 | ||
|  *        - renamed WaitLineData functions to ReadOneImageLine
 | ||
|  * - 0.39 - fixed a problem in imageP98003ReadOneImageLine, that causes
 | ||
|  *          these I/O timeouts...
 | ||
|  * - 0.40 - no changes
 | ||
|  * - 0.41 - no changes
 | ||
|  * - 0.42 - fixed a problem for the 12bit modes fo ASIC9800x based devices
 | ||
|  *        - changed include names
 | ||
|  * .
 | ||
|  * <hr>
 | ||
|  * This file is part of the SANE package.
 | ||
|  *
 | ||
|  * This program is free software; you can redistribute it and/or
 | ||
|  * modify it under the terms of the GNU General Public License as
 | ||
|  * published by the Free Software Foundation; either version 2 of the
 | ||
|  * License, or (at your option) any later version.
 | ||
|  *
 | ||
|  * This program is distributed in the hope that it will be useful, but
 | ||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | ||
|  * General Public License for more details.
 | ||
|  *
 | ||
|  * You should have received a copy of the GNU General Public License
 | ||
|  * along with this program; if not, write to the Free Software
 | ||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | ||
|  * MA 02111-1307, USA.
 | ||
|  *
 | ||
|  * As a special exception, the authors of SANE give permission for
 | ||
|  * additional uses of the libraries contained in this release of SANE.
 | ||
|  *
 | ||
|  * The exception is that, if you link a SANE library with other files
 | ||
|  * to produce an executable, this does not by itself cause the
 | ||
|  * resulting executable to be covered by the GNU General Public
 | ||
|  * License.  Your use of that executable is in no way restricted on
 | ||
|  * account of linking the SANE library code into it.
 | ||
|  *
 | ||
|  * This exception does not, however, invalidate any other reasons why
 | ||
|  * the executable file might be covered by the GNU General Public
 | ||
|  * License.
 | ||
|  *
 | ||
|  * If you submit changes to SANE to the maintainers to be included in
 | ||
|  * a subsequent release, you agree by submitting the changes that
 | ||
|  * those changes may be distributed with this exception intact.
 | ||
|  *
 | ||
|  * If you write modifications of your own for SANE, it is your choice
 | ||
|  * whether to permit this exception to apply to your modifications.
 | ||
|  * If you do not wish that, delete this exception notice.
 | ||
|  * <hr>
 | ||
|  */
 | ||
| #include "plustek-pp_scan.h"
 | ||
| 
 | ||
| /************************ local definitions **********************************/
 | ||
| 
 | ||
| #define _LINE_TIMEOUT   (_SECOND * 5 )      /* max 5 second per line !  */
 | ||
| 
 | ||
| /*************************** local vars **************************************/
 | ||
| 
 | ||
| static UShort wPreviewScanned = 0;
 | ||
| 
 | ||
| static ExpXStepDef posScan[5] = {{128, 8}, {96, 12},
 | ||
|                                  {96, 24}, {96, 48}, {96, 96}};
 | ||
| static ExpXStepDef negScan[5] = {{128, 8}, {96, 12},
 | ||
|                                  {96, 24}, {96, 48}, {96, 96}};
 | ||
| 
 | ||
| static ExpXStepDef nmlScan[4][5] = {
 | ||
|     {{160, 10}, {96, 12},  {96, 24},  {96, 48},  {96, 96}},     /* EPP */
 | ||
|     {{160, 10}, {128, 16}, {128, 32}, {192, 96}, {192, 96}},    /* SPP */
 | ||
|     {{160, 10}, {96, 12},  {96, 24},  {160, 80}, {160, 160}},   /* BPP */
 | ||
|     {{160, 10}, {96, 12},  {96, 24},  {96, 48},  {96, 96}}      /* ECP */
 | ||
| };
 | ||
| 
 | ||
| static ThreshDef xferSpeed[4] = {
 | ||
|     {0, 3200, 2500}, {0, 1200, 800}, {0, 800, 1250}, {0, 3200, 2500}
 | ||
| };
 | ||
| 
 | ||
| /*************************** local functions *********************************/
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * return the correct DPI-value
 | ||
|  * The ASIC 96001/3 models are limited to an optical resolution of 300 Dpi
 | ||
|  * so it<69>s necessary to scale in X and Y direction (see scale.c)!
 | ||
|  */
 | ||
| static UShort imageGetPhysDPI( pScanData ps, pImgDef pImgInf, Bool fDpiX )
 | ||
| {
 | ||
| 	if( _IS_ASIC98(ps->sCaps.AsicID)) {
 | ||
| 
 | ||
| 	    if (fDpiX) {
 | ||
| 
 | ||
| 			if (pImgInf->xyDpi.x > ps->LensInf.rDpiX.wPhyMax)
 | ||
| 	    		return ps->LensInf.rDpiX.wPhyMax;
 | ||
| 			else
 | ||
| 	    		return pImgInf->xyDpi.x;
 | ||
| 
 | ||
| 	    } else {
 | ||
| 			if (pImgInf->xyDpi.y > ps->LensInf.rDpiY.wPhyMax)
 | ||
| 	    		return ps->LensInf.rDpiY.wPhyMax;
 | ||
| 			else
 | ||
| 	    		return pImgInf->xyDpi.y;
 | ||
| 	    }
 | ||
| 	} else {
 | ||
| 
 | ||
| 	    if (fDpiX) {
 | ||
| 
 | ||
| 			if (pImgInf->wDataType >= COLOR_TRUE24) {
 | ||
| 	    		if (pImgInf->xyDpi.x > ps->LensInf.rDpiX.wPhyMax)
 | ||
| 					return ps->LensInf.rDpiX.wPhyMax;
 | ||
| 			    else
 | ||
| 					return pImgInf->xyDpi.x;
 | ||
| 			} else {
 | ||
| 	    		if (pImgInf->xyDpi.x > (ps->LensInf.rDpiX.wPhyMax * 2))
 | ||
| 					return (ps->LensInf.rDpiX.wPhyMax * 2);
 | ||
| 			    else
 | ||
| 					return pImgInf->xyDpi.x;
 | ||
| 			}
 | ||
|     	} else {
 | ||
| 
 | ||
| 			if (pImgInf->wDataType >= COLOR_TRUE24 ) {
 | ||
| 	    		if (pImgInf->xyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2))
 | ||
| 					return (ps->LensInf.rDpiY.wPhyMax / 2);
 | ||
| 			    else
 | ||
| 					return pImgInf->xyDpi.y;
 | ||
| 			} else {
 | ||
| 	    		if (pImgInf->xyDpi.y > ps->LensInf.rDpiY.wPhyMax)
 | ||
| 					return ps->LensInf.rDpiY.wPhyMax;
 | ||
| 			    else
 | ||
| 					return pImgInf->xyDpi.y;
 | ||
| 			}
 | ||
| 	    }
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /*****************************************************************************
 | ||
|  *			Sampling stuff for ASIC 98003      						         *
 | ||
|  *****************************************************************************/
 | ||
| 
 | ||
| static Bool fnEveryLines( pScanData ps )
 | ||
| {
 | ||
| 	_VAR_NOT_USED( ps );
 | ||
|     return _TRUE;
 | ||
| }
 | ||
| 
 | ||
| static Bool fnSampleLines( pScanData ps )
 | ||
| {
 | ||
|     ps->DataInf.wYSum += ps->DataInf.xyAppDpi.y;
 | ||
| 
 | ||
|     if( ps->DataInf.wYSum >= ps->DataInf.xyPhyDpi.y ) {
 | ||
| 
 | ||
|         ps->DataInf.wYSum -= ps->DataInf.xyPhyDpi.y;
 | ||
|     	return	_TRUE;
 | ||
|     }
 | ||
| 
 | ||
| 	return _FALSE;
 | ||
| }
 | ||
| 
 | ||
| static Bool fnSamplePreview( pScanData ps )
 | ||
| {
 | ||
|     ps->DataInf.wYSum += wPreviewScanned;
 | ||
|     if( ps->DataInf.wYSum >= 150 ) {
 | ||
| 
 | ||
|         ps->DataInf.wYSum -= 150;
 | ||
|     	return	_TRUE;
 | ||
|     }
 | ||
| 
 | ||
| 	return _FALSE;
 | ||
| }
 | ||
| 
 | ||
| /*****************************************************************************
 | ||
|  *			Data Processing Routines			     						 *
 | ||
|  *****************************************************************************/
 | ||
| 
 | ||
| static Bool fnReadToDriver( pScanData ps )
 | ||
| {
 | ||
|     ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
 | ||
|     IOReadScannerImageData( ps, ps->Scan.BufPut.blue.bp,
 | ||
| 							ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
| 	ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
 | ||
|     IOReadScannerImageData( ps, ps->Scan.BufPut.green.bp,
 | ||
| 							ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
|     if( ps->Scan.gd_gk.wGreenKeep )
 | ||
| 		ps->Scan.gd_gk.wGreenKeep--;
 | ||
|     else {
 | ||
| 		ps->Scan.BufPut.green.bp += ps->DataInf.dwAsicBytesPerPlane;
 | ||
| 
 | ||
| 		if( ps->Scan.BufPut.green.bp >= ps->Scan.BufEnd.green.bp )
 | ||
| 		    ps->Scan.BufPut.green.bp = ps->Scan.BufBegin.green.bp;
 | ||
|     }
 | ||
| 
 | ||
|     ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
 | ||
|     IOReadScannerImageData( ps, ps->Scan.BufPut.red.bp,
 | ||
| 							ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
|     ps->Scan.BufPut.red.bp += ps->DataInf.dwAsicBytesPerPlane;
 | ||
|     if( ps->Scan.BufPut.red.bp >= ps->Scan.BufEnd.red.bp )
 | ||
| 		ps->Scan.BufPut.red.bp = ps->Scan.BufBegin.red.bp;
 | ||
| 
 | ||
|     if( ps->Scan.bd_rk.wRedKeep ) {
 | ||
| 		ps->Scan.bd_rk.wRedKeep--;
 | ||
| 		return _FALSE;
 | ||
| 
 | ||
|     } else {
 | ||
| 
 | ||
| 		ps->Scan.BufData.green.bp = ps->Scan.BufGet.green.bp;
 | ||
| 
 | ||
| 		if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) {
 | ||
| 		    ps->Scan.BufData.red.bp  = ps->Scan.BufGet.blue.bp;
 | ||
| 		    ps->Scan.BufData.blue.bp = ps->Scan.BufGet.red.bp;
 | ||
| 		} else {
 | ||
| 		    ps->Scan.BufData.red.bp = ps->Scan.BufGet.red.bp;
 | ||
| 		    ps->Scan.BufData.blue.bp = ps->Scan.BufGet.blue.bp;
 | ||
| 		}
 | ||
| 
 | ||
| 		ps->Scan.BufGet.red.bp   += ps->DataInf.dwAsicBytesPerPlane;
 | ||
| 		ps->Scan.BufGet.green.bp += ps->DataInf.dwAsicBytesPerPlane;
 | ||
| 
 | ||
| 		if( ps->Scan.BufGet.red.bp >= ps->Scan.BufEnd.red.bp )
 | ||
| 		    ps->Scan.BufGet.red.bp = ps->Scan.BufBegin.red.bp;
 | ||
| 
 | ||
| 		if( ps->Scan.BufGet.green.bp >= ps->Scan.BufEnd.green.bp )
 | ||
| 		    ps->Scan.BufGet.green.bp = ps->Scan.BufBegin.green.bp;
 | ||
| 
 | ||
| 		return _TRUE;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static Bool fnReadOutScanner( pScanData ps )
 | ||
| {
 | ||
|     if( ps->Scan.bd_rk.wBlueDiscard ) {
 | ||
| 
 | ||
|         ps->Scan.bd_rk.wBlueDiscard--;
 | ||
|     	ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
 | ||
| 
 | ||
| 	    IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf,
 | ||
|                                     ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
|     	if( ps->Scan.gd_gk.wGreenDiscard ) {
 | ||
|             ps->Scan.gd_gk.wGreenDiscard--;
 | ||
| 
 | ||
| 	        ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
 | ||
|     	    IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf,
 | ||
|                                         ps->DataInf.dwAsicBytesPerPlane);
 | ||
|     	}
 | ||
| 	    return _FALSE;
 | ||
| 
 | ||
|     } else {
 | ||
|         IOReadColorData( ps, ps->Bufs.b1.pReadBuf,
 | ||
|                              ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 	    return _TRUE;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * Interpolates the gray data by using averaged the continuous pixels
 | ||
|  */	
 | ||
| static void fnP96GrayDirect( pScanData ps, pVoid pBuf, pVoid pImg, ULong bl )
 | ||
| {
 | ||
| 	pUChar src, dest;
 | ||
| 
 | ||
| 	src  = (pUChar)pImg;
 | ||
| 	dest = (pUChar)pBuf;
 | ||
| 	
 | ||
|     for (; bl; bl--, src++, dest++ )
 | ||
| 		*dest = ps->pbMapRed [*src];
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *	This routine used in the condition:
 | ||
|  *	1) The data type is B/W or GrayScale.
 | ||
|  *	2) The required horizontal resolution doesn't exceed the optic spec.
 | ||
|  *	3) The required vertical resolution exceeds the optic spec.
 | ||
|  *	So, the vertcal lines have to average with previous line to smooth the
 | ||
|  *	image.
 | ||
|  */
 | ||
| static void fnDataDirect( pScanData ps, pVoid pBuf, pVoid pImg, ULong bl )
 | ||
| {
 | ||
| 	_VAR_NOT_USED( ps );
 | ||
| 	memcpy( pBuf, pImg, bl );
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * According to dither matrix to convert the input gray scale data into
 | ||
|  * one-bit data.
 | ||
|  */
 | ||
| static void fnHalftoneDirect0( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
 | ||
| {
 | ||
| 	pUChar pDither, src, dest;
 | ||
| 	ULong  dw;
 | ||
| 
 | ||
| 	src  = (pUChar)pImg;
 | ||
| 	dest = (pUChar)pb;
 | ||
|    
 | ||
| 	pDither = &ps->a_bDitherPattern[ps->dwDitherIndex];
 | ||
| 
 | ||
|     for( ; bL; bL--, dest++, pDither -= 8 ) {
 | ||
| 
 | ||
| 		for( dw = 8; dw; dw--, src++, pDither++ ) {
 | ||
| 
 | ||
| 		    if( *src < *pDither ) {
 | ||
| 				*dest = (*dest << 1) | 0x01;
 | ||
| 			} else {
 | ||
| 				*dest <<= 1;
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	ps->dwDitherIndex = (ps->dwDitherIndex + 8) & 0x3f;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * use random generator to make halftoning
 | ||
|  */
 | ||
| static void fnHalftoneDirect1( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
 | ||
| {
 | ||
| 	pUChar src, dest;
 | ||
|     UChar  threshold;
 | ||
|     ULong  dw;
 | ||
| 
 | ||
| 	_VAR_NOT_USED( ps );
 | ||
| 	src  = (pUChar)pImg;
 | ||
| 	dest = (pUChar)pb;
 | ||
| 
 | ||
| 	for (; bL; bL--, dest++ ) {
 | ||
| 
 | ||
| 		for (dw = 8; dw; dw--, src++ ) {
 | ||
| 
 | ||
| 		    threshold = (UChar)MiscLongRand();
 | ||
| 
 | ||
| 		    if (*src < threshold ) {
 | ||
| 				*dest = (*dest << 1) | 0x01;
 | ||
| 			} else {
 | ||
| 				*dest <<= 1;
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * Merges the color planes to pixels style without enlarge operation.
 | ||
|  */
 | ||
| static void fnP98ColorDirect( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
 | ||
| {
 | ||
| 	pUChar      src;
 | ||
| 	pRGBByteDef dest;
 | ||
| 	
 | ||
| 	src  = (pUChar)pImg;
 | ||
| 	dest = (pRGBByteDef)pb;
 | ||
| 	
 | ||
| 	for ( bL = ps->DataInf.dwAsicPixelsPerPlane; bL; bL--, src++, dest++) {
 | ||
| 
 | ||
| 		dest->Red   = *src;
 | ||
| 		dest->Green = src[ps->DataInf.dwAsicPixelsPerPlane];
 | ||
| 		dest->Blue  = src[ps->DataInf.dwAsicPixelsPerPlane*2];
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| static void fnP96ColorDirect( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
 | ||
| {
 | ||
| 	pUChar      src;
 | ||
| 	pRGBByteDef dest;
 | ||
| 
 | ||
| 	src  = (pUChar)pImg;
 | ||
| 	dest = (pRGBByteDef)pb;
 | ||
| 		
 | ||
| 	for ( bL = ps->DataInf.dwAsicPixelsPerPlane; bL; bL--, dest++, src++) {
 | ||
| 
 | ||
| 			dest->Red  =ps->pbMapRed[*src];
 | ||
| 			dest->Green=ps->pbMapGreen[src[ps->DataInf.dwAsicPixelsPerPlane]];
 | ||
| 			dest->Blue =ps->pbMapBlue[src[ps->DataInf.dwAsicPixelsPerPlane*2]];
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * Merges the color planes to pixels style without enlarge operation.
 | ||
|  * The scanner returns the pixel data in Motorola-Format, so we have to swap
 | ||
|  */
 | ||
| static void fnP98Color48( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
 | ||
| {
 | ||
| 	pUShort       src;
 | ||
| 	pRGBUShortDef dest;
 | ||
| 	
 | ||
| 	register ULong i;
 | ||
| 
 | ||
| 	_VAR_NOT_USED( bL );
 | ||
| 	src  = (pUShort)pImg;
 | ||
| 	dest = (pRGBUShortDef)pb;
 | ||
| 	
 | ||
| 	for ( i = ps->DataInf.dwAsicPixelsPerPlane; i;	i--, src++, dest++) {
 | ||
| 
 | ||
| 		dest->Red   = *src;
 | ||
| 		dest->Green = src[ps->DataInf.dwAsicPixelsPerPlane];
 | ||
| 		dest->Blue  = src[ps->DataInf.dwAsicPixelsPerPlane * 2];
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * prepare for scanning
 | ||
|  */
 | ||
| static int imageP98SetupScanSettings( pScanData ps, pScanInfo pInf )
 | ||
| {
 | ||
| 	UShort brightness;
 | ||
| 	ULong  xAdjust;
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "imageP98SetupScanSettings()\n" );
 | ||
| 
 | ||
| 	xAdjust = pInf->ImgDef.crArea.x + pInf->ImgDef.crArea.cx;
 | ||
| 
 | ||
|     ps->DataInf.dwScanFlag = pInf->ImgDef.dwFlag;
 | ||
|     ps->DataInf.dwVxdFlag  = 0;
 | ||
|     ps->DataInf.crImage    = pInf->ImgDef.crArea;
 | ||
| 
 | ||
|     /* AdjustOriginXByLens
 | ||
|      * [NOTE]
 | ||
|      *	Here we just simply adjust it to double (600 DPI is two times of
 | ||
|      *	300 DPI), but if this model is a multi-lens scanner, we should adjust
 | ||
|      *	it according to different lens.
 | ||
| 	 */
 | ||
|     ps->DataInf.crImage.x <<= 1;
 | ||
| 
 | ||
|     ps->DataInf.xyAppDpi 	 = pInf->ImgDef.xyDpi;
 | ||
|     ps->DataInf.siBrightness = pInf->siBrightness;
 | ||
|     ps->DataInf.wDither      = pInf->wDither;
 | ||
|     ps->DataInf.wAppDataType = pInf->ImgDef.wDataType;
 | ||
| 
 | ||
|     ps->GetImageInfo( ps, &pInf->ImgDef );
 | ||
| 
 | ||
|     if (ps->DataInf.dwVxdFlag & _VF_DATATOUSERBUFFER) {
 | ||
| 		ps->Scan.DataProcess = fnDataDirect;
 | ||
| 	}
 | ||
|     if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
 | ||
| 		ps->Scan.lBufferAdjust = -(Long)ps->DataInf.dwAppBytesPerLine;
 | ||
| 	} else {
 | ||
| 		ps->Scan.lBufferAdjust = (Long)ps->DataInf.dwAppBytesPerLine;
 | ||
| 	}
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "Scan settings:\n" );
 | ||
| 	DBG( DBG_LOW, "ImageInfo: (x=%u,y=%u,dx=%u,dy=%u)\n",
 | ||
| 			 ps->DataInf.crImage.x,  ps->DataInf.crImage.y,
 | ||
| 			 ps->DataInf.crImage.cx, ps->DataInf.crImage.cy );
 | ||
| 
 | ||
|     /*
 | ||
| 	 * SetBwBrightness
 | ||
|      * [NOTE]
 | ||
|      *
 | ||
|      *	 0                   _DEF_BW_THRESHOLD					   255
 | ||
|      *	 +-------------------------+--------------------------------+
 | ||
|      *	 |<------- Black --------->|<----------- White ------------>|
 | ||
|      *	 So, if user wish to make image darker, the threshold value should be
 | ||
|      *	 higher than _defBwThreshold, otherwise it should lower than the
 | ||
|      *	 _DefBwThreshold.
 | ||
|      *	 Darker = _DefBwThreshold + White * Input / 127;
 | ||
|      *		  Input < 0, and White = 255 - _DefBwThreshold, so
 | ||
|      *		= _DefBwThreshold - (255 - _DefBwThreshold) * Input / 127;
 | ||
|      *	 The brighter is the same idea.
 | ||
| 	 *
 | ||
|  	 * CHECK: it seems that the brightness only works for the binary mode !
 | ||
| 	 */
 | ||
| 	if( ps->DataInf.wPhyDataType != COLOR_BW ) {/* if not line art 			*/
 | ||
| 		ps->wBrightness = pInf->siBrightness;   /* use internal tables for 	*/
 | ||
| 		ps->wContrast   = pInf->siContrast;		/* brightness and contrast	*/
 | ||
| 
 | ||
| 		pInf->siBrightness = 0;				/* don't use asic for threshold */
 | ||
|     }
 | ||
| 
 | ||
| /* CHECK: We have now two methods for setting the brightness...
 | ||
| */
 | ||
| 	DBG( DBG_LOW, "brightness = %i\n", pInf->siBrightness );
 | ||
| 
 | ||
|     if (ps->DataInf.siBrightness < 0) {
 | ||
| 		brightness = (UShort)(_DEF_BW_THRESHOLD -
 | ||
| 			       (255 - _DEF_BW_THRESHOLD) * ps->DataInf.siBrightness /127);
 | ||
| 	} else {
 | ||
| 		brightness = (UShort)(_DEF_BW_THRESHOLD -
 | ||
| 					       _DEF_BW_THRESHOLD * ps->DataInf.siBrightness /127);
 | ||
| 	}
 | ||
|     ps->AsicReg.RD_ThresholdControl = brightness;
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "1. brightness = %i\n", brightness );
 | ||
| 
 | ||
|     if( ps->DataInf.siBrightness >= 0 ) {
 | ||
| 	    brightness = (short)((long)(-(255 - _DEF_BW_THRESHOLD) *
 | ||
| 						 ps->DataInf.siBrightness) / 127 + _DEF_BW_THRESHOLD);
 | ||
| 	} else {
 | ||
| 	    brightness = (short)((long)(_DEF_BW_THRESHOLD *
 | ||
|  						  ps->DataInf.siBrightness) / 127 + _DEF_BW_THRESHOLD);
 | ||
| 	}
 | ||
| 
 | ||
| 	brightness = (brightness ^ 0xff) & 0xff;
 | ||
| 
 | ||
| 	if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
 | ||
| 	    ps->AsicReg.RD_ThresholdControl = brightness;
 | ||
| 		DBG( DBG_LOW, "2. brightness = %i\n", brightness );
 | ||
| 	}
 | ||
| 
 | ||
| 	ps->DataInf.pCurrentBuffer = ps->pScanBuffer1;
 | ||
| 
 | ||
| 	return _OK;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static void imageP98DoCopyBuffer( pScanData ps, pUChar pImage )
 | ||
| {
 | ||
| 	memcpy( ps->pFilterBuf, pImage, ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
| 	ps->pFilterBuf += 5120;
 | ||
|     if (ps->pFilterBuf >= ps->pEndBuf)
 | ||
| 		ps->pFilterBuf = ps->pProcessingBuf;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static Bool imageP98CopyToFilterBuffer( pScanData ps, pUChar pImage )
 | ||
| {
 | ||
|     if (ps->fDoFilter) {
 | ||
| 
 | ||
| 		if (ps->fFilterFirstLine) {
 | ||
| 
 | ||
| 		    imageP98DoCopyBuffer( ps, pImage );
 | ||
| 		    imageP98DoCopyBuffer( ps, pImage );
 | ||
| 		    ps->dwLinesFilter--;
 | ||
| 		    return _FALSE;
 | ||
| 	} else {
 | ||
| 
 | ||
| 		    imageP98DoCopyBuffer( ps, pImage );
 | ||
| 		    if ((ps->dwLinesFilter--) == 0)
 | ||
| 				imageP98DoCopyBuffer( ps, pImage);
 | ||
| 		}
 | ||
|     }
 | ||
|     return _TRUE;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static void imageP98UnSharpCompare( pScanData ps, Byte Center,
 | ||
| 								 Byte Neighbour, pLong pdwNewValue )
 | ||
| {
 | ||
|     Byte b;
 | ||
| 
 | ||
|     b = (Center >= Neighbour) ? Center - Neighbour : Neighbour - Center ;
 | ||
| 
 | ||
|     if (b > ps->bOffsetFilter) {
 | ||
| 
 | ||
| 		*pdwNewValue -= (Long)Neighbour;
 | ||
| 		ps->dwDivFilter--;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static void imageP98DoFilter( pScanData ps, pUChar pPut )
 | ||
| {
 | ||
| 	ULong dw;
 | ||
|     Long  dwNewValue;
 | ||
| 
 | ||
|     if (ps->fDoFilter && (ps->DataInf.xyAppDpi.x) >= 600UL) {
 | ||
| 
 | ||
| 		/* DoUnsharpMask(); */
 | ||
| 		for (dw = 0; dw < ps->DataInf.dwAsicBytesPerPlane - 2; dw++, pPut++) {
 | ||
| 
 | ||
| 			ps->dwDivFilter = ps->dwMul;
 | ||
| 
 | ||
| 		    dwNewValue = ((ULong)ps->pGet2[dw+1]) * ps->dwMul;
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw+1], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw+2], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet2[dw], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet2[dw+2], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw+1], &dwNewValue);
 | ||
| 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw+2], &dwNewValue);
 | ||
| 
 | ||
|     	    if( dwNewValue > 0 ) {
 | ||
| 				if((dwNewValue /= ps->dwDivFilter) < 255) {
 | ||
| 		    		*pPut = (Byte) dwNewValue;
 | ||
| 				} else {
 | ||
| 				    *pPut = 255;
 | ||
| 				}
 | ||
| 		    } else {
 | ||
| 				*pPut = 0;
 | ||
| 			}
 | ||
| 		}
 | ||
| 		pPut = ps->pGet1;
 | ||
| 		ps->pGet1 = ps->pGet2;
 | ||
| 		ps->pGet2 = ps->pGet3;
 | ||
| 		ps->pGet3 = pPut;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static Bool imageP98DataIsReady( pScanData ps )
 | ||
| {
 | ||
| 	Byte b;
 | ||
| 
 | ||
| 	ps->Scan.fMotorBackward = _FALSE;
 | ||
| 	ps->bMoveDataOutFlag    = _DataAfterRefreshState;
 | ||
| 
 | ||
|     b = (ps->DataInf.wPhyDataType >= COLOR_TRUE24) ?
 | ||
| 											_BLUE_DATA_READY : _GREEN_DATA_READY;
 | ||
|     while( _TRUE ) {
 | ||
| 
 | ||
| 		ps->dwColorRunIndex ++;
 | ||
| 
 | ||
| 		if(ps->pColorRunTable[ps->dwColorRunIndex] & b)
 | ||
| 	    	break;
 | ||
|     }
 | ||
| 
 | ||
|     if (b == _GREEN_DATA_READY) {
 | ||
| 
 | ||
| 		ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
 | ||
| 		IOReadScannerImageData( ps, ps->DataInf.pCurrentBuffer,
 | ||
| 			 	    		        ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
| 		imageP98CopyToFilterBuffer( ps, ps->DataInf.pCurrentBuffer );
 | ||
|     } else  {
 | ||
| 
 | ||
| 		/* ReadColorImageData() */
 | ||
| 		if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) {
 | ||
| 
 | ||
| 			ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
 | ||
| 			IOReadScannerImageData( ps, ps->pScanBuffer1 +
 | ||
| 				         			    ps->DataInf.dwAsicBytesPerPlane * 2,
 | ||
| 									    ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
| 			ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
 | ||
| 			IOReadScannerImageData( ps, ps->pScanBuffer1 +
 | ||
| 										ps->DataInf.dwAsicBytesPerPlane,
 | ||
| 										ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
| 			ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
 | ||
| 			IOReadScannerImageData( ps, ps->pScanBuffer1,
 | ||
| 				 					    ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 		} else {
 | ||
| 
 | ||
|             IOReadColorData( ps, ps->pScanBuffer1,
 | ||
|                                  ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 		}
 | ||
|     }
 | ||
| 
 | ||
| 	if (ps->fFilterFirstLine) {
 | ||
| 		ps->fFilterFirstLine = _FALSE;
 | ||
| 	    return _TRUE;
 | ||
| 	}
 | ||
| 
 | ||
| 	imageP98DoFilter( ps, ps->DataInf.pCurrentBuffer );
 | ||
| 
 | ||
|     (*ps->Scan.DataProcess)( ps, ps->Scan.bp.pMonoBuf,
 | ||
|                              ps->DataInf.pCurrentBuffer,
 | ||
|                              ps->DataInf.dwAppPhyBytesPerLine );
 | ||
| 
 | ||
|     return _TRUE;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * here we wait for one data-line
 | ||
|  */
 | ||
| static Bool imageP98001ReadOneImageLine( pScanData ps )
 | ||
| {
 | ||
| 	ULong    dwFifoCounter;
 | ||
| 	TimerDef timer;
 | ||
| 
 | ||
| 	MiscStartTimer( &timer, _LINE_TIMEOUT );
 | ||
|     do {
 | ||
| 
 | ||
| 		ps->Scan.bNowScanState = IOGetScanState( ps, _FALSE );
 | ||
| 		dwFifoCounter = IOReadFifoLength( ps );
 | ||
| 
 | ||
| 		if (!(ps->Scan.bNowScanState & _SCANSTATE_STOP) &&
 | ||
| 								    (dwFifoCounter < ps->dwMaxReadFifoData)) {
 | ||
| 
 | ||
| 		    if( ps->Scan.bOldScanState != ps->Scan.bNowScanState )
 | ||
| 				ps->UpdateDataCurrentReadLine( ps );
 | ||
| 
 | ||
| 		    if( dwFifoCounter >= ps->Scan.dwMinReadFifo )
 | ||
| 				return imageP98DataIsReady( ps );
 | ||
| 
 | ||
| 		} else {	/* ScanStateIsStop */
 | ||
| 
 | ||
| 		    if (dwFifoCounter >= ps->dwSizeMustProcess)
 | ||
| 				return imageP98DataIsReady( ps );
 | ||
| 
 | ||
| 			ps->UpdateDataCurrentReadLine( ps );
 | ||
| 
 | ||
| 		    if( dwFifoCounter >= ps->Scan.dwMinReadFifo )
 | ||
| 				return imageP98DataIsReady( ps );
 | ||
| 		}
 | ||
| 
 | ||
| 		_DODELAY(10);			     /* delay 10 ms */
 | ||
| 
 | ||
|     } while (!MiscCheckTimer( &timer ));
 | ||
| 
 | ||
| 	DBG( DBG_HIGH, "Timeout - Scanner malfunction !!\n" );
 | ||
| 	MotorToHomePosition(ps);
 | ||
| 
 | ||
| 	/* timed out, scanner malfunction */
 | ||
|     return _FALSE;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * calculate the image properties according to the scanmode
 | ||
|  */
 | ||
| static void imageP98GetInfo( pScanData ps, pImgDef pImgInf )
 | ||
| {
 | ||
| 	DBG( DBG_LOW, "imageP98GetInfo()\n" );
 | ||
| 
 | ||
| 	ps->DataInf.xyPhyDpi.x = imageGetPhysDPI( ps, pImgInf, _TRUE  );
 | ||
| 	ps->DataInf.xyPhyDpi.y = imageGetPhysDPI( ps, pImgInf, _FALSE );
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "xyPhyDpi.x = %u, xyPhyDpi.y = %u\n",
 | ||
| 		 ps->DataInf.xyPhyDpi.x, ps->DataInf.xyPhyDpi.y );
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "crArea.x = %u, crArea.y = %u\n",
 | ||
| 		 pImgInf->crArea.x, pImgInf->crArea.y );
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "crArea.cx = %u, crArea.cy = %u\n",
 | ||
| 		 pImgInf->crArea.cx, pImgInf->crArea.cy );
 | ||
| 
 | ||
| 	ps->DataInf.XYRatio = (double)ps->DataInf.xyPhyDpi.y/
 | ||
| 						  (double)ps->DataInf.xyPhyDpi.x;
 | ||
| 
 | ||
| 	ps->DataInf.dwAppLinesPerArea = (ULong)pImgInf->crArea.cy *
 | ||
| 									  pImgInf->xyDpi.y / _MEASURE_BASE;
 | ||
| 
 | ||
|     ps->DataInf.dwAppPixelsPerLine = (ULong)pImgInf->crArea.cx *
 | ||
| 									   pImgInf->xyDpi.x / _MEASURE_BASE;
 | ||
| 
 | ||
| 	ps->DataInf.dwPhysBytesPerLine = (ULong)pImgInf->crArea.cx *
 | ||
| 									   ps->DataInf.xyPhyDpi.x / _MEASURE_BASE;
 | ||
| 
 | ||
|     if( pImgInf->wDataType <= COLOR_HALFTONE ) {
 | ||
| 		ps->DataInf.dwAsicPixelsPerPlane = (ps->DataInf.dwAppPixelsPerLine+7UL)&
 | ||
| 											 0xfffffff8UL;
 | ||
| 		ps->DataInf.dwAppPhyBytesPerLine =
 | ||
| 		ps->DataInf.dwAppBytesPerLine 	 =
 | ||
| 		ps->DataInf.dwAsicBytesPerLine   =
 | ||
| 		ps->DataInf.dwAsicBytesPerPlane  = ps->DataInf.dwAsicPixelsPerPlane>>3;
 | ||
|     } else {
 | ||
| 		ps->DataInf.dwAsicBytesPerPlane  =
 | ||
| 		ps->DataInf.dwAsicPixelsPerPlane = ps->DataInf.dwAppPixelsPerLine;
 | ||
| 	}
 | ||
| 
 | ||
|     if( COLOR_TRUE48 == pImgInf->wDataType ) {
 | ||
| 		ps->DataInf.dwAsicBytesPerPlane *= 2;
 | ||
| 	}
 | ||
| 
 | ||
|     switch( pImgInf->wDataType ) {
 | ||
| 
 | ||
| 	case COLOR_BW:
 | ||
| 	    ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER;
 | ||
| 	    ps->DataInf.wPhyDataType = COLOR_BW;
 | ||
|         ps->Shade.bIntermediate  = _ScanMode_Mono;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_HALFTONE:
 | ||
| 		if( ps->DataInf.wDither == 2 ) {
 | ||
|             ps->Scan.DataProcess = fnHalftoneDirect1;
 | ||
| 		} else {
 | ||
|             ps->Scan.DataProcess = fnHalftoneDirect0;
 | ||
| 		}
 | ||
| /*
 | ||
|  * CHANGE: it seems, that we have to use the same settings as for 256GRAY
 | ||
|  */
 | ||
| 		ps->DataInf.dwAsicBytesPerPlane =
 | ||
| 		ps->DataInf.dwAsicPixelsPerPlane = ps->DataInf.dwAppPixelsPerLine;
 | ||
| 	    ps->DataInf.wPhyDataType = COLOR_256GRAY;
 | ||
|         ps->Shade.bIntermediate  = _ScanMode_Mono;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_256GRAY:
 | ||
| 	    ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER;
 | ||
| 	    ps->DataInf.dwAsicBytesPerLine =
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine;
 | ||
| 	    ps->DataInf.wPhyDataType = COLOR_256GRAY;
 | ||
|         ps->Shade.bIntermediate  = _ScanMode_Mono;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_TRUE24:
 | ||
|         ps->Scan.DataProcess = fnP98ColorDirect;
 | ||
| 	    ps->DataInf.dwAsicBytesPerLine =
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 3;
 | ||
| 	    ps->DataInf.wPhyDataType = COLOR_TRUE24;
 | ||
|         ps->Shade.bIntermediate  = _ScanMode_Color;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_TRUE48:
 | ||
|         ps->Scan.DataProcess = fnP98Color48;
 | ||
| 	    ps->DataInf.dwAsicBytesPerLine =
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 6;
 | ||
| 	    ps->DataInf.wPhyDataType = COLOR_TRUE48;
 | ||
|         ps->Shade.bIntermediate  = _ScanMode_Color;
 | ||
| 	    break;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     if (pImgInf->dwFlag & SCANDEF_BoundaryDWORD) {
 | ||
| 		ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 3) &
 | ||
| 									      0xfffffffc;
 | ||
| 	} else {
 | ||
| 		if (pImgInf->dwFlag & SCANDEF_BoundaryWORD) {
 | ||
| 		    ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 1) &
 | ||
| 											  0xfffffffe;
 | ||
| 		} else {
 | ||
| 		    ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine;
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "AppLinesPerArea    = %lu\n", ps->DataInf.dwAppLinesPerArea    );
 | ||
| 	DBG( DBG_LOW, "AppPixelsPerLine   = %lu\n", ps->DataInf.dwAppPixelsPerLine   );
 | ||
| 	DBG( DBG_LOW, "AppPhyBytesPerLine = %lu\n", ps->DataInf.dwAppPhyBytesPerLine );
 | ||
| 	DBG( DBG_LOW, "AppBytesPerLine    = %lu\n", ps->DataInf.dwAppBytesPerLine    );
 | ||
| 	DBG( DBG_LOW, "AsicPixelsPerPlane = %lu\n", ps->DataInf.dwAsicPixelsPerPlane );
 | ||
| 	DBG( DBG_LOW, "AsicBytesPerPlane  = %lu\n", ps->DataInf.dwAsicBytesPerPlane  );
 | ||
| 	DBG( DBG_LOW, "AsicBytesPerLine   = %lu\n", ps->DataInf.dwAsicBytesPerLine   );
 | ||
| 	DBG( DBG_LOW, "Physical Bytes     = %lu\n", ps->DataInf.dwPhysBytesPerLine   );
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static void imageP96GetInfo( pScanData ps, pImgDef pImgInf )
 | ||
| {
 | ||
| 	DBG( DBG_LOW, "imageP96GetInfo()\n" );
 | ||
| 
 | ||
| 	ps->DataInf.xyPhyDpi.x = imageGetPhysDPI( ps, pImgInf, _TRUE  );
 | ||
| 	ps->DataInf.xyPhyDpi.y = imageGetPhysDPI( ps, pImgInf, _FALSE );
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "xyPhyDpi.x = %u, xyPhyDpi.y = %u\n",
 | ||
| 		 ps->DataInf.xyPhyDpi.x, ps->DataInf.xyPhyDpi.y );
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "crArea.x = %u, crArea.y = %u\n",
 | ||
| 		 pImgInf->crArea.x, pImgInf->crArea.y );
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "crArea.cx = %u, crArea.cy = %u\n",
 | ||
| 		 pImgInf->crArea.cx, pImgInf->crArea.cy );
 | ||
| 
 | ||
| 	ps->DataInf.XYRatio = (double)ps->DataInf.xyPhyDpi.y/
 | ||
| 						  (double)ps->DataInf.xyPhyDpi.x;
 | ||
| 
 | ||
| 	DBG( DBG_LOW, "xyDpi.x = %u, xyDpi.y = %u\n",
 | ||
| 					 pImgInf->xyDpi.x, pImgInf->xyDpi.y );
 | ||
| 
 | ||
| 	ps->DataInf.dwAppLinesPerArea = (ULong)pImgInf->crArea.cy *
 | ||
| 					  					   pImgInf->xyDpi.y / _MEASURE_BASE;
 | ||
|     ps->DataInf.dwAsicBytesPerPlane  =
 | ||
| 	ps->DataInf.dwAsicPixelsPerPlane = (ULong)ps->DataInf.xyPhyDpi.x *
 | ||
| 				 					       pImgInf->crArea.cx / _MEASURE_BASE;
 | ||
| 
 | ||
|     ps->DataInf.dwAppPixelsPerLine = (ULong)pImgInf->crArea.cx *
 | ||
| 										    pImgInf->xyDpi.x / _MEASURE_BASE;
 | ||
| 
 | ||
| 	ps->DataInf.dwPhysBytesPerLine = (ULong)pImgInf->crArea.cx *
 | ||
| 									   ps->DataInf.xyPhyDpi.x / _MEASURE_BASE;
 | ||
| 
 | ||
|     ps->DataInf.wPhyDataType = ps->DataInf.wAppDataType;
 | ||
| 
 | ||
|     switch( pImgInf->wDataType ) {
 | ||
| 
 | ||
| 	case COLOR_BW:
 | ||
| 	    ps->DataInf.dwAsicBytesPerPlane =
 | ||
| 								 (ps->DataInf.dwAsicPixelsPerPlane + 7) >> 3;
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine =
 | ||
| 									 (ps->DataInf.dwAppPixelsPerLine + 7) >> 3;
 | ||
| 	    ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER;
 | ||
|         ps->Scan.DataProcess = fnDataDirect;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_HALFTONE:
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine =
 | ||
| 								 (ps->DataInf.dwAsicPixelsPerPlane + 7) >> 3;
 | ||
| 		if( ps->DataInf.wDither == 2 ) {
 | ||
|             ps->Scan.DataProcess = fnHalftoneDirect1;
 | ||
| 		} else {
 | ||
|             ps->Scan.DataProcess = fnHalftoneDirect0;
 | ||
| 		}
 | ||
| 	    ps->DataInf.wPhyDataType = COLOR_256GRAY;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_256GRAY:
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine;
 | ||
|         ps->Scan.DataProcess = fnP96GrayDirect;
 | ||
| 	    break;
 | ||
| 
 | ||
| 	case COLOR_TRUE24:
 | ||
| #ifdef _A3I_EN
 | ||
|         ps->Scan.DataProcess = fnP98ColorDirect;
 | ||
| #else
 | ||
|         ps->Scan.DataProcess = fnP96ColorDirect;
 | ||
| #endif
 | ||
| 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 3;
 | ||
|     }
 | ||
| 
 | ||
|     if( pImgInf->dwFlag & SCANDEF_BoundaryDWORD ) {
 | ||
| 		ps->DataInf.dwAppBytesPerLine =
 | ||
| 							(ps->DataInf.dwAppPhyBytesPerLine + 3) & 0xfffffffc;
 | ||
| 	} else {
 | ||
| 		if ( pImgInf->dwFlag & SCANDEF_BoundaryWORD ) {
 | ||
| 		    ps->DataInf.dwAppBytesPerLine =
 | ||
| 							(ps->DataInf.dwAppPhyBytesPerLine + 1) & 0xfffffffe;
 | ||
| 		} else {
 | ||
| 	    	ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine;
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
|     if (ps->DataInf.wPhyDataType == COLOR_TRUE24)
 | ||
| 		ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane * 3;
 | ||
|     else
 | ||
| 		ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane;
 | ||
| 
 | ||
| /* WORK: AsicBytesPerLine only used for ASIC_98001 based scanners - try to remove
 | ||
| **		 that, also try to remove redundant info
 | ||
| */
 | ||
| 	DBG( DBG_LOW, "AppLinesPerArea    = %lu\n", ps->DataInf.dwAppLinesPerArea    );
 | ||
| 	DBG( DBG_LOW, "AppPixelsPerLine   = %lu\n", ps->DataInf.dwAppPixelsPerLine   );
 | ||
| 	DBG( DBG_LOW, "AppPhyBytesPerLine = %lu\n", ps->DataInf.dwAppPhyBytesPerLine );
 | ||
| 	DBG( DBG_LOW, "AppBytesPerLine    = %lu\n", ps->DataInf.dwAppBytesPerLine    );
 | ||
| 	DBG( DBG_LOW, "AsicPixelsPerPlane = %lu\n", ps->DataInf.dwAsicPixelsPerPlane );
 | ||
| 	DBG( DBG_LOW, "AsicBytesPerPlane  = %lu\n", ps->DataInf.dwAsicBytesPerPlane  );
 | ||
| 	DBG( DBG_LOW, "AsicBytesPerLine   = %lu\n", ps->DataInf.dwAsicBytesPerLine   );
 | ||
| 	DBG( DBG_LOW, "Physical Bytes     = %lu\n", ps->DataInf.dwPhysBytesPerLine   );
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * here we wait for one data-line
 | ||
|  */
 | ||
| static Bool imageP96ReadOneImageLine( pScanData ps )
 | ||
| {
 | ||
|     Bool     result = _FALSE;
 | ||
| 	Byte	 bData, bFifoCount;
 | ||
|     TimerDef timer;
 | ||
| 
 | ||
| 	MiscStartTimer( &timer, _LINE_TIMEOUT);
 | ||
|     do {
 | ||
| 
 | ||
| 		bFifoCount = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
 | ||
| 
 | ||
| /* CHECK ps->bMoveDataOutFlag will never be set to _DataFromStopState !!!*/
 | ||
| #if 1
 | ||
| 		if ((bFifoCount < ps->bMinReadFifo) &&
 | ||
| 					            (ps->bMoveDataOutFlag == _DataFromStopState)) {
 | ||
| 
 | ||
| 		    bData = IOGetScanState( ps, _FALSE);
 | ||
| 
 | ||
| 		    if (!(bData & _SCANSTATE_STOP)) {
 | ||
| 				if (bData < ps->bCurrentLineCount)
 | ||
| 				    bData += _NUMBER_OF_SCANSTEPS;
 | ||
| 				if ((bData - ps->bCurrentLineCount) < _SCANSTATE_BYTES)
 | ||
| 				    continue;
 | ||
| 		    }
 | ||
| 	
 | ||
| 		    ps->bMoveDataOutFlag = _DataAfterRefreshState;
 | ||
| 		}
 | ||
| #endif
 | ||
| 
 | ||
| /*
 | ||
| // HEINER:A3I
 | ||
| //		if( ps->bMoveDataOutFlag != _DataFromStopState )
 | ||
| //	    	ps->UpdateDataCurrentReadLine( ps );
 | ||
| */
 | ||
| 		if( bFifoCount >= ps->bMinReadFifo ) {
 | ||
| 
 | ||
| 		    /* data is ready */
 | ||
| 		    for (; !(*ps->pCurrentColorRunTable &
 | ||
| 				(ps->RedDataReady | ps->GreenDataReady | _BLUE_DATA_READY));
 | ||
| 												 ps->pCurrentColorRunTable++);
 | ||
| 
 | ||
| #ifdef DEBUG			
 | ||
| 			if( ps->pCurrentColorRunTable >
 | ||
| 							(ps->pColorRunTable+ps->BufferForColorRunTable))
 | ||
| 				DBG( DBG_LOW, "WARNING: pCurrentColorRunTab>pColorRunTable\n");
 | ||
| #endif
 | ||
| 
 | ||
| 		    if (ps->DataInf.wPhyDataType == COLOR_TRUE24) {
 | ||
| 
 | ||
| 				/* read color planes (either R/G/B or R/B/G sequence that
 | ||
| 				 * depends on COLOR CCD, see below
 | ||
| 				 */
 | ||
| 				if (*ps->pCurrentColorRunTable & ps->b1stColor) {
 | ||
| 				    *ps->pCurrentColorRunTable &= ps->b1stMask;
 | ||
| 				    IOReadScannerImageData (ps, ps->pPutBufR,
 | ||
| 						  					    ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 				    ps->pPutBufR += ps->BufferSizePerModel;
 | ||
| 					if (ps->pPutBufR == ps->pEndBufR)
 | ||
| 						ps->pPutBufR = ps->pPrescan16;
 | ||
| 				} else
 | ||
| 					if (*ps->pCurrentColorRunTable & ps->b2ndColor) {
 | ||
| 						*ps->pCurrentColorRunTable &= ps->b2ndMask;
 | ||
| 						IOReadScannerImageData( ps, ps->pPutBufG,
 | ||
| 										        ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 						ps->pPutBufG += ps->BufferSizePerModel;
 | ||
| 						if (ps->pPutBufG == ps->pEndBufG)
 | ||
| 						    ps->pPutBufG = ps->pPrescan8;
 | ||
| 		    	} else {
 | ||
| 					*ps->pCurrentColorRunTable &= ps->b3rdMask;
 | ||
| 					ps->pCurrentColorRunTable++;    /* processed this step */
 | ||
| 
 | ||
| 					/* according to CCD type & image placement method to
 | ||
| 					 * read third color into corresponding location.
 | ||
| 					 * SONY CCD: Red, Green and Blue.
 | ||
| 					 * TOSHIBA CCD: Red, Blue and Green.
 | ||
| 					 * SCANDEF_BmpStyle: Blue, Green and Red, Otherwise
 | ||
| 					 *  Red, Green and Blue.
 | ||
| 					 */
 | ||
| 					if (ps->b3rdColor & ps->GreenDataReady) {
 | ||
| 					    /* Green always in middle */
 | ||
| 					    IOReadScannerImageData (ps,
 | ||
|                                                  ps->DataInf.pCurrentBuffer +
 | ||
| 											  ps->DataInf.dwAsicBytesPerPlane,
 | ||
| 											  ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 					} else {
 | ||
| 					    /* Blue depends the request style from caller */
 | ||
| 					    if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
 | ||
| 							/* BMP style, blue is the first one */
 | ||
| 							IOReadScannerImageData (ps,
 | ||
|                                                    ps->DataInf.pCurrentBuffer,
 | ||
| 											  ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 						} else {
 | ||
| 							/* Blue is the last one */
 | ||
| 							IOReadScannerImageData (ps, ps->DataInf.pCurrentBuffer +
 | ||
| 											ps->DataInf.dwAsicBytesPerPlane * 2,
 | ||
| 											  ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 						}
 | ||
| 					}
 | ||
| 
 | ||
| 					/* reassemble 3 color lines for separated RGB value */
 | ||
|     				if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
 | ||
| 					    /* BMP style, red is last one */
 | ||
| 					    memcpy( ps->DataInf.pCurrentBuffer +
 | ||
| 								ps->DataInf.dwAsicBytesPerPlane * 2,
 | ||
| 								ps->pGetBufR, ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 					} else {
 | ||
| 					    /* Red is first one */
 | ||
| 					    memcpy( ps->DataInf.pCurrentBuffer,
 | ||
| 		 					    ps->pGetBufR, ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 					}
 | ||
| 
 | ||
| 					if (ps->b2ndColor & ps->GreenDataReady) {
 | ||
| 					    /* Green always in middle */
 | ||
| 						memcpy( ps->DataInf.pCurrentBuffer +
 | ||
| 							   ps->DataInf.dwAsicBytesPerPlane,
 | ||
| 							   ps->pGetBufG, ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 					} else {
 | ||
| 				    	/* Blue depends the request style from caller */
 | ||
| 					    if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
 | ||
| 							/* BMP style, blue is the first one */
 | ||
| 							memcpy( ps->DataInf.pCurrentBuffer,
 | ||
| 							        ps->pGetBufG,
 | ||
| 							        ps->DataInf.dwAsicBytesPerPlane);
 | ||
| 						} else {
 | ||
| 							/* BMP style, blue is the last one */
 | ||
| 							memcpy( ps->DataInf.pCurrentBuffer +
 | ||
| 							        ps->DataInf.dwAsicBytesPerPlane * 2,
 | ||
| 							        ps->pGetBufG,
 | ||
| 							        ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 						}
 | ||
| 					}
 | ||
| 
 | ||
| 					/* Adjust the get pointers */
 | ||
| 					ps->pGetBufR += ps->BufferSizePerModel;
 | ||
| 					ps->pGetBufG += ps->BufferSizePerModel;
 | ||
| 					if (ps->pGetBufR == ps->pEndBufR)
 | ||
| 					    ps->pGetBufR = ps->pPrescan16;
 | ||
| 
 | ||
| 					if (ps->pGetBufG == ps->pEndBufG)
 | ||
| 					    ps->pGetBufG = ps->pPrescan8;
 | ||
| 
 | ||
|     				result = _TRUE; /* Line data in buffer */
 | ||
|                     break;
 | ||
| 			    }
 | ||
| 
 | ||
| 				/* reset timer for new 10-second interval */
 | ||
| 				MiscStartTimer( &timer, (10 * _SECOND));
 | ||
| 
 | ||
| 		    } else  {
 | ||
| 				/* Gray Image */
 | ||
| 				*ps->pCurrentColorRunTable &= 0xf0; /* leave high nibble for debug  */
 | ||
| 				ps->pCurrentColorRunTable++;		/* this step has been processed */
 | ||
| 				IOReadScannerImageData( ps, ps->DataInf.pCurrentBuffer,
 | ||
| 									        ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
| 				result = _TRUE;
 | ||
|                 break;
 | ||
| 		    }
 | ||
| 		}
 | ||
| 
 | ||
| /* HEINER:A3I */
 | ||
| 		if( ps->bMoveDataOutFlag != _DataFromStopState )
 | ||
| 	    	ps->UpdateDataCurrentReadLine( ps );
 | ||
| 
 | ||
|     } while (!MiscCheckTimer( &timer));
 | ||
| 
 | ||
|     if( _TRUE == result ) {
 | ||
|         (*ps->Scan.DataProcess)( ps, ps->Scan.bp.pMonoBuf,
 | ||
|                                  ps->DataInf.pCurrentBuffer,
 | ||
|                                  ps->DataInf.dwAppPhyBytesPerLine );
 | ||
|         return _TRUE;
 | ||
|     }
 | ||
| 
 | ||
| 	DBG( DBG_HIGH, "Timeout - Scanner malfunction !!\n" );
 | ||
| 	MotorToHomePosition(ps);
 | ||
| 
 | ||
|     return _FALSE;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * prepare for scanning
 | ||
|  */
 | ||
| static int imageP96SetupScanSettings( pScanData ps, pScanInfo pInf )
 | ||
| {
 | ||
| 	DBG( DBG_LOW, "imageSetupP96ScanSettings()\n" );
 | ||
| 
 | ||
| 	ps->DataInf.dwVxdFlag = 0;
 | ||
| 	if (pInf->ImgDef.dwFlag & SCANDEF_BuildBwMap)
 | ||
| 		ps->DataInf.dwVxdFlag |= _VF_BUILDMAP;
 | ||
| 
 | ||
|     ps->DataInf.dwScanFlag = pInf->ImgDef.dwFlag;
 | ||
| 
 | ||
|     ps->DataInf.crImage = pInf->ImgDef.crArea;
 | ||
| 
 | ||
| 	/* scale according to DPI */
 | ||
|     ps->DataInf.crImage.x  *= ps->PhysicalDpi / _MEASURE_BASE;
 | ||
|     ps->DataInf.crImage.cx *= ps->PhysicalDpi / _MEASURE_BASE;
 | ||
| 
 | ||
|     if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
 | ||
| 		ps->DataInf.crImage.x += _Transparency48OriginOffsetX;
 | ||
| 		ps->DataInf.crImage.y += _Transparency48OriginOffsetY;
 | ||
|     }
 | ||
| 
 | ||
|     ps->DataInf.xyAppDpi     = pInf->ImgDef.xyDpi;
 | ||
|     ps->DataInf.wAppDataType = pInf->ImgDef.wDataType;
 | ||
|     ps->DataInf.wDither      = pInf->wDither;
 | ||
| 
 | ||
|     ps->GetImageInfo( ps, &pInf->ImgDef );
 | ||
| 
 | ||
| 	/* try to get brightness to work */
 | ||
| 	if (ps->DataInf.wPhyDataType != COLOR_BW) { /* if not line art 			*/
 | ||
| 		ps->wBrightness = pInf->siBrightness;   /* use internal tables for 	*/
 | ||
| 		ps->wContrast   = pInf->siContrast;		/* brightness and contrast	*/
 | ||
| 
 | ||
| 		pInf->siBrightness = 0;				/* don't use asic for threshold */
 | ||
|     }
 | ||
|     ps->DataInf.siBrightness = pInf->siBrightness;
 | ||
| 
 | ||
|     if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle)
 | ||
| 		ps->Scan.lBufferAdjust = -(Long)ps->DataInf.dwAppBytesPerLine;
 | ||
|     else
 | ||
| 		ps->Scan.lBufferAdjust = (Long)ps->DataInf.dwAppBytesPerLine;
 | ||
| 
 | ||
|     if (ps->DataInf.siBrightness < 0)
 | ||
| 		ps->DataInf.siBrightness = 255 - (_DEF_BW_THRESHOLD *
 | ||
| 							ps->DataInf.siBrightness / 127 + _DEF_BW_THRESHOLD);
 | ||
|     else
 | ||
| 		ps->DataInf.siBrightness = 255 - ((255 - _DEF_BW_THRESHOLD) *
 | ||
| 							 ps->DataInf.siBrightness / 127 + _DEF_BW_THRESHOLD);
 | ||
| 
 | ||
|     ps->AsicReg.RD_ThresholdControl = (Byte)ps->DataInf.siBrightness;
 | ||
| 
 | ||
|     ps->DataInf.pCurrentBuffer = ps->pScanBuffer1;
 | ||
| 
 | ||
| 	return _OK;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static Bool imageP98003DataIsReady( pScanData ps )
 | ||
| {
 | ||
| 	pUChar pb;
 | ||
| 
 | ||
|     if( ps->Scan.bDiscardAll ) {
 | ||
|     	ps->Scan.bDiscardAll--;
 | ||
| 
 | ||
|     	if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
 | ||
|     	    ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
 | ||
|     	    IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf,
 | ||
|                                         ps->DataInf.dwAsicBytesPerPlane );
 | ||
|     	} else {
 | ||
|             IOReadColorData( ps, ps->Bufs.b1.pReadBuf,
 | ||
|                                  ps->DataInf.dwAsicBytesPerPlane );
 | ||
|         }
 | ||
| 	    return _FALSE;
 | ||
|     }
 | ||
| 
 | ||
|    	if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
 | ||
| 
 | ||
|     	ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
 | ||
| 		pb = ps->Scan.bp.pMonoBuf;
 | ||
| 
 | ||
| 		/* use a larger buffer during halftone reads...*/
 | ||
| 		if( ps->DataInf.wAppDataType == COLOR_HALFTONE )
 | ||
| 			pb = ps->Scan.BufPut.red.bp;
 | ||
| 
 | ||
| 	    IOReadScannerImageData( ps, pb, ps->DataInf.dwAsicBytesPerPlane );
 | ||
| 
 | ||
|     } else {
 | ||
|     	if( !ps->Scan.DataRead( ps )) {
 | ||
|     	    return _FALSE;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     if( ps->Scan.DoSample( ps )) {
 | ||
| 
 | ||
|     	if( ps->Scan.dwLinesToRead == 1 &&
 | ||
|            !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP))
 | ||
| 	        IORegisterToScanner( ps, ps->RegRefreshScanState );
 | ||
| 
 | ||
| 		/* direct is done here without copying...*/
 | ||
| 		if( fnDataDirect != ps->Scan.DataProcess ) {
 | ||
| 			(*ps->Scan.DataProcess)(ps, (pVoid)(ps->Scan.bp.pMonoBuf ),
 | ||
|                                         (pVoid)(ps->Scan.BufPut.red.bp),
 | ||
|                                         ps->DataInf.dwAppPhyBytesPerLine);
 | ||
| 		}
 | ||
|     	return _TRUE;
 | ||
|     }
 | ||
| 
 | ||
|     return _FALSE;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static Bool imageP98003ReadOneImageLine( pScanData ps )
 | ||
| {
 | ||
|     Byte     b, state;
 | ||
| 	TimerDef timer, t2;
 | ||
| 
 | ||
| 	MiscStartTimer( &timer, _LINE_TIMEOUT );
 | ||
| 	MiscStartTimer( &t2, _SECOND*2 );
 | ||
|     do {
 | ||
| 
 | ||
|         state = IOGetScanState( ps, _TRUE );
 | ||
|         ps->Scan.bNowScanState = (state & _SCANSTATE_MASK);
 | ||
| 
 | ||
|     	if( state & _SCANSTATE_STOP ) {
 | ||
| 
 | ||
| 	        MotorP98003ModuleForwardBackward( ps );
 | ||
| 
 | ||
|     	    if( IOReadFifoLength( ps ) >= ps->Scan.dwMinReadFifo )
 | ||
| 	        	if( imageP98003DataIsReady( ps ))
 | ||
| 		            return _TRUE;
 | ||
|     	} else {
 | ||
| 
 | ||
|     	    ps->Scan.bModuleState = _MotorInNormalState;
 | ||
|     	    b = ps->Scan.bNowScanState - ps->Scan.bOldScanState;
 | ||
| 
 | ||
|     	    if((char) b < 0)
 | ||
|         		b += _NUMBER_OF_SCANSTEPS;
 | ||
| 
 | ||
|     	    if( b >= ps->Scan.bRefresh ) {
 | ||
|         		IORegisterToScanner( ps, ps->RegRefreshScanState );
 | ||
| 
 | ||
|                 ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE );
 | ||
|                 ps->Scan.bOldScanState &= _SCANSTATE_MASK;
 | ||
|     	    }
 | ||
| 
 | ||
| 	        if( IOReadFifoLength( ps ) >= ps->Scan.dwMaxReadFifo ) {
 | ||
|             	if( imageP98003DataIsReady( ps ))
 | ||
| 	                return _TRUE;
 | ||
|     	    } else {
 | ||
| 
 | ||
|         	    b = ps->Scan.bNowScanState - ps->Scan.bOldScanState;
 | ||
| 
 | ||
|     	        if((char) b < 0)
 | ||
|         	    	b += _NUMBER_OF_SCANSTEPS;
 | ||
| 
 | ||
|         	    if( b >= ps->Scan.bRefresh ) {
 | ||
|             		IORegisterToScanner( ps, ps->RegRefreshScanState );
 | ||
| 
 | ||
|                     ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE );
 | ||
|                     ps->Scan.bOldScanState &= _SCANSTATE_MASK;
 | ||
|         	    }
 | ||
| 
 | ||
|         	    if( IOReadFifoLength( ps ) >= ps->Scan.dwMinReadFifo ) {
 | ||
|                 	if( imageP98003DataIsReady( ps ))
 | ||
| 	                    return _TRUE;
 | ||
|                 }
 | ||
|         	}
 | ||
|         }
 | ||
| 		_DODELAY(5);			     /* delay 5 ms */
 | ||
| 
 | ||
|     } while( !MiscCheckTimer( &timer ));
 | ||
| 
 | ||
| #ifdef __KERNEL__    
 | ||
| 	_PRINT(
 | ||
| #else
 | ||
| 	DBG( DBG_HIGH,
 | ||
| #endif
 | ||
| 	"Timeout - Scanner malfunction !!\n" );
 | ||
| 	MotorToHomePosition(ps);
 | ||
| 
 | ||
| 	/* timed out, scanner malfunction */
 | ||
|     return _FALSE;
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  *
 | ||
|  */
 | ||
| static void imageP98003SetupScanStateVariables( pScanData ps, ULong index )
 | ||
| {
 | ||
|     DataType var;
 | ||
| 
 | ||
|     ps->Scan.dpiIdx = index;
 | ||
| 
 | ||
|     if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
 | ||
| 
 | ||
|         if(((ps->IO.portMode == _PORT_BIDI) ||
 | ||
|             (ps->IO.portMode == _PORT_SPP)) &&
 | ||
|             (ps->DataInf.wPhyDataType > COLOR_TRUE24) &&
 | ||
|                                              (ps->DataInf.xyAppDpi.y >= 600)) {
 | ||
| 
 | ||
|        		ps->Shade.wExposure = nmlScan[ps->IO.portMode][index].exposureTime;
 | ||
| 	        ps->Shade.wXStep    = nmlScan[ps->IO.portMode][index].xStepTime;
 | ||
|    	    } else {
 | ||
| 		    ps->Shade.wExposure = nmlScan[_PORT_EPP][index].exposureTime;
 | ||
|     		ps->Shade.wXStep    = nmlScan[_PORT_EPP][index].xStepTime;
 | ||
| 	    }
 | ||
| 
 | ||
| 	    if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) {
 | ||
|     	    ps->Shade.wExposure >>= 1;
 | ||
| 	        ps->Shade.wXStep    >>= 1;
 | ||
|     	}
 | ||
|     } else {
 | ||
|     	if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) {
 | ||
|     	    ps->Shade.wExposure = posScan[index].exposureTime;
 | ||
| 	        ps->Shade.wXStep    = posScan[index].xStepTime;
 | ||
|     	} else {
 | ||
|     	    ps->Shade.wExposure = ps->Scan.negScan[index].exposureTime;
 | ||
| 	        ps->Shade.wXStep    = ps->Scan.negScan[index].xStepTime;
 | ||
|     	}
 | ||
|     }
 | ||
| 
 | ||
|     ps->Scan.dwInterlace = 0;
 | ||
|     ps->Scan.dwInterval  = 1;
 | ||
| 
 | ||
|     if( ps->DataInf.wPhyDataType == COLOR_BW )
 | ||
| 	    var.dwValue = xferSpeed[ps->IO.portMode].thresholdBW;
 | ||
| 	else {
 | ||
|         if( ps->DataInf.wPhyDataType == COLOR_256GRAY )
 | ||
|     		var.dwValue = xferSpeed[ps->IO.portMode].thresholdGray;
 | ||
| 	    else
 | ||
| 		    var.dwValue = xferSpeed[ps->IO.portMode].thresholdColor;
 | ||
|     }
 | ||
| 
 | ||
|     /* for small size/descreen */
 | ||
|     if((ps->DataInf.xyAppDpi.y >= 300) && var.dwValue &&
 | ||
|        (ps->DataInf.dwAsicBytesPerPlane <= var.dwValue)) {
 | ||
|     	ps->Scan.dwInterval <<= 1;
 | ||
|     }
 | ||
| 
 | ||
|     if( var.dwValue && ps->DataInf.dwAsicBytesPerPlane > var.dwValue ) {
 | ||
|     	if((var.dwValue << 1) > ps->DataInf.dwAsicBytesPerPlane)
 | ||
| 	        ps->Scan.dwInterval <<= 1;			
 | ||
|     	else
 | ||
|         	if((var.dwValue << 2) > ps->DataInf.dwAsicBytesPerPlane)
 | ||
| 		        ps->Scan.dwInterval <<= 2;
 | ||
|     	    else
 | ||
| 	        	ps->Scan.dwInterval <<= 3;
 | ||
|     }
 | ||
| 
 | ||
|     /* 48 bit/600 dpi/Bpp mode will scan failed */
 | ||
|     if(((ps->IO.portMode == _PORT_BIDI) ||
 | ||
|         (ps->IO.portMode == _PORT_SPP)) &&
 | ||
|         (ps->DataInf.wPhyDataType > COLOR_TRUE24) &&
 | ||
|                                              (ps->DataInf.xyAppDpi.y >= 600)) {
 | ||
|     	ps->Scan.dwInterval <<= 1;
 | ||
|     }
 | ||
| 
 | ||
|     if( ps->DataInf.wPhyDataType >= COLOR_TRUE24 ) {
 | ||
| 
 | ||
|     	if( ps->DataInf.xyPhyDpi.y > 75U ) { 
 | ||
|     	    if( ps->Device.f0_8_16 ) {
 | ||
| 	        	ps->Scan.gd_gk.wGreenDiscard = ps->DataInf.xyPhyDpi.y / 75U;
 | ||
|     	    } else {
 | ||
| 	        	ps->Scan.gd_gk.wGreenDiscard = ps->DataInf.xyPhyDpi.y / 150U;
 | ||
| 	        }
 | ||
|     	} else {
 | ||
|            	ps->Scan.gd_gk.wGreenDiscard = 1;
 | ||
| 		}
 | ||
| 
 | ||
|        	ps->Scan.bd_rk.wBlueDiscard = ps->Scan.gd_gk.wGreenDiscard << 1;
 | ||
|     } else {
 | ||
|        	ps->Scan.bd_rk.wBlueDiscard = ps->Scan.gd_gk.wGreenDiscard = 0;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /*.............................................................................
 | ||
|  * PrepareScanningVariables() !!!
 | ||
|  */
 | ||
| static int imageP98003SetupScanSettings( pScanData ps, pScanInfo pInf )
 | ||
| {
 | ||
| 	DBG( DBG_LOW, "imageP98003SetupScanSettings()\n" );
 | ||
| 
 | ||
|     /* call the one for ASIC 98001 first */
 | ||
|     imageP98SetupScanSettings( ps, pInf );
 | ||
| 
 | ||
|     if( !(ps->DataInf.dwScanFlag & SCANDEF_TPA )) {
 | ||
| 
 | ||
|         ps->Scan.dwScanOrigin = ps->Device.lUpNormal * 4 + _RFT_SCANNING_ORG;
 | ||
| 
 | ||
|     } else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency) {
 | ||
| 
 | ||
| 	    ps->Scan.dwScanOrigin = ps->Device.lUpPositive * 4 +
 | ||
|             							   _POS_SCANNING_ORG;
 | ||
| 	} else {
 | ||
| 	    ps->Scan.dwScanOrigin = ps->Device.lUpNegative * 4 +
 | ||
|             							   _NEG_SCANNING_ORG;
 | ||
|     }
 | ||
|     ps->Scan.dwScanOrigin += ps->Device.dwModelOriginY;
 | ||
| 
 | ||
|     /* ------- Setup CCD Offset variables ------- */
 | ||
|     if( ps->DataInf.xyAppDpi.y <= 75 ) {
 | ||
| 
 | ||
|     	if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) {
 | ||
| 
 | ||
|             ps->Scan.bDiscardAll   = 0;
 | ||
|     	    ps->DataInf.xyPhyDpi.y = 150;
 | ||
|             ps->Shade.bIntermediate |= _ScanMode_AverageOut;
 | ||
|     	    imageP98003SetupScanStateVariables( ps, 1 );
 | ||
| 	        ps->Scan.gd_gk.wGreenDiscard = 0;
 | ||
| 
 | ||
| 	        if( ps->DataInf.xyAppDpi.y >= 38 )
 | ||
|         		ps->Scan.bd_rk.wBlueDiscard = 1;
 | ||
| 	        else
 | ||
|         		ps->Scan.bd_rk.wBlueDiscard = 0;
 | ||
| 
 | ||
| 	        if( ps->DataInf.wPhyDataType >= COLOR_256GRAY ) {
 | ||
|         		ps->Shade.wXStep    = 6;
 | ||
| 		        ps->Shade.wExposure = 8 * ps->Shade.wXStep;
 | ||
|     	    }
 | ||
| 	    } else {
 | ||
|     	    if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA) &&
 | ||
|                 (ps->DataInf.xyAppDpi.y <= 50) &&
 | ||
| 				(ps->DataInf.wPhyDataType >= COLOR_TRUE24)) {
 | ||
|         		ps->Shade.bIntermediate |= _ScanMode_AverageOut;
 | ||
|             }
 | ||
| 
 | ||
|     	    if((ps->DataInf.wPhyDataType<COLOR_TRUE24) || ps->Device.f0_8_16 ||
 | ||
|            			         (ps->Shade.bIntermediate & _ScanMode_AverageOut)) {
 | ||
| 
 | ||
|         		ps->Scan.bDiscardAll   = 1;
 | ||
|         		ps->DataInf.xyPhyDpi.y = 75;
 | ||
| 		        imageP98003SetupScanStateVariables( ps, 0 );
 | ||
|     	    } else {
 | ||
|         		ps->Scan.bDiscardAll   = 2;
 | ||
|         		ps->DataInf.xyPhyDpi.y = 150;
 | ||
| 		        imageP98003SetupScanStateVariables( ps, 1 );
 | ||
|     	    }
 | ||
|     	}
 | ||
|     } else {
 | ||
|     	if( ps->DataInf.xyAppDpi.y <= 150 ) {
 | ||
| 
 | ||
|     	    ps->Scan.bDiscardAll   = 2;
 | ||
| 	        ps->DataInf.xyPhyDpi.y = 150;
 | ||
| 	        imageP98003SetupScanStateVariables( ps, 1 );
 | ||
| 
 | ||
|     	} else if( ps->DataInf.xyAppDpi.y <= 300 ) {
 | ||
| 
 | ||
|     	    ps->Scan.bDiscardAll   = 4;
 | ||
| 	        ps->DataInf.xyPhyDpi.y = 300;
 | ||
| 	        imageP98003SetupScanStateVariables( ps, 2 );
 | ||
| 
 | ||
| 	    } else if( ps->DataInf.xyAppDpi.y <= 600 ) {
 | ||
| 
 | ||
|     	    ps->Scan.bDiscardAll   = 8;
 | ||
| 	        ps->DataInf.xyPhyDpi.y = 600;
 | ||
|             imageP98003SetupScanStateVariables( ps, 3 );
 | ||
| 
 | ||
| 		} else {
 | ||
| 
 | ||
|     	    ps->Scan.bDiscardAll   = 16;
 | ||
| 	        ps->DataInf.xyPhyDpi.y = 1200;
 | ||
| 	        imageP98003SetupScanStateVariables( ps, 4 );
 | ||
| 		}
 | ||
|     }
 | ||
| 
 | ||
|     /* ------- Lines have to sample or not? ------- */
 | ||
|     if( ps->DataInf.xyAppDpi.y == ps->DataInf.xyPhyDpi.y ) {
 | ||
| 		DBG( DBG_LOW, "Sample every line\n" );
 | ||
|     	ps->Scan.DoSample = fnEveryLines;
 | ||
|     } else {
 | ||
|     	if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) {
 | ||
| 
 | ||
| 			DBG( DBG_LOW, "Sample preview\n" );
 | ||
|             ps->Scan.DoSample = fnSamplePreview;
 | ||
| 	        ps->DataInf.wYSum = 150;
 | ||
| 
 | ||
| 	        if( ps->DataInf.xyAppDpi.y >= 38 )
 | ||
|         		wPreviewScanned = ps->DataInf.xyAppDpi.y * 2;
 | ||
|     	    else if( ps->DataInf.xyAppDpi.y >= 19 )
 | ||
| 		            wPreviewScanned = ps->DataInf.xyAppDpi.y * 4;
 | ||
|         		else
 | ||
|             		wPreviewScanned = ps->DataInf.xyAppDpi.y * 8;
 | ||
|     	} else {
 | ||
| 
 | ||
| 			DBG( DBG_LOW, "Sample lines (%u - %u)...\n",
 | ||
| 						  ps->DataInf.xyPhyDpi.y, ps->DataInf.xyAppDpi.y );
 | ||
|             ps->Scan.DoSample = fnSampleLines;
 | ||
| 	        ps->DataInf.wYSum = ps->DataInf.xyPhyDpi.y - ps->DataInf.xyAppDpi.y;
 | ||
|     	}
 | ||
|     }
 | ||
| 
 | ||
|     /*
 | ||
|      * now assign the buffer pointers for image aquisition
 | ||
|      */
 | ||
| 	ps->Scan.p48BitBuf.pb = NULL;
 | ||
| 
 | ||
|     if( ps->DataInf.wPhyDataType >= COLOR_TRUE24 ) {
 | ||
| 
 | ||
|         ULong r,g,b;
 | ||
| 
 | ||
|         r = (ULong)_SIZE_REDFIFO /
 | ||
| 			ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep;
 | ||
|         g = (ULong)_SIZE_GREENFIFO /
 | ||
| 			ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep;
 | ||
| 
 | ||
|     	if((int)r < 16 || (int)g < 16) {
 | ||
| 
 | ||
|     	    b = (ULong)(ps->Scan.bd_rk.wRedKeep +
 | ||
| 						ps->Scan.gd_gk.wGreenKeep + 2U) *
 | ||
| 			            ps->DataInf.dwAsicBytesPerPlane;
 | ||
| 
 | ||
| 			DBG( DBG_LOW, "48Bit buffer request: len=%lu bytes, available=%lu\n",
 | ||
| 						  b, ps->TotalBufferRequire );
 | ||
| 
 | ||
| 			if( b > ps->TotalBufferRequire )
 | ||
| 				return _E_NORESOURCE;
 | ||
| 
 | ||
| 			ps->Scan.p48BitBuf.pb = ps->Bufs.b1.pReadBuf;
 | ||
| 		}
 | ||
|     }	
 | ||
| 
 | ||
|     if( ps->Scan.p48BitBuf.pb ){
 | ||
|     	ps->Scan.DataRead          = fnReadToDriver;
 | ||
| 	    ps->Scan.BufGet.red.bp     =
 | ||
|     	ps->Scan.BufPut.red.bp     =
 | ||
| 	    ps->Scan.BufBegin.red.bp   = ps->Scan.p48BitBuf.pb;
 | ||
|     	ps->Scan.BufEnd.red.bp     =
 | ||
| 	    ps->Scan.BufBegin.green.bp =
 | ||
|     	ps->Scan.BufGet.green.bp   =
 | ||
| 	    ps->Scan.BufPut.green.bp   = ps->Scan.p48BitBuf.pb +
 | ||
| 	                			     ps->DataInf.dwAsicBytesPerLine *
 | ||
|                                      (ps->Scan.bd_rk.wRedKeep + 1U);
 | ||
| 
 | ||
|     	ps->Scan.BufEnd.green.bp = ps->Scan.BufBegin.green.bp +
 | ||
| 	                			   ps->DataInf.dwAsicBytesPerLine *
 | ||
|                 				   (ps->Scan.gd_gk.wGreenKeep + 1U);
 | ||
|         ps->Scan.BufPut.blue.bp =
 | ||
|     	ps->Scan.BufGet.blue.bp = ps->Bufs.b1.pReadBuf +
 | ||
|                                   ps->DataInf.dwAsicBytesPerLine * 2;
 | ||
|     } else {
 | ||
|     	ps->Scan.DataRead         = fnReadOutScanner;
 | ||
|     	ps->Scan.BufPut.red.bp    = ps->Bufs.b1.pReadBuf;
 | ||
|     	ps->Scan.BufData.green.bp =
 | ||
| 	    ps->Scan.BufPut.green.bp  = ps->Scan.BufPut.red.bp +
 | ||
|                 			        ps->DataInf.dwAsicBytesPerLine;
 | ||
|     	ps->Scan.BufPut.blue.bp   = ps->Scan.BufPut.green.bp +
 | ||
|                 			        ps->DataInf.dwAsicBytesPerLine;
 | ||
| 
 | ||
|         if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) {
 | ||
|     	    ps->Scan.BufData.red.bp  = ps->Scan.BufPut.blue.bp;
 | ||
| 	        ps->Scan.BufData.blue.bp = ps->Scan.BufPut.red.bp;
 | ||
|     	} else {
 | ||
|     	    ps->Scan.BufData.red.bp  = ps->Scan.BufPut.red.bp;
 | ||
| 	        ps->Scan.BufData.blue.bp = ps->Scan.BufPut.blue.bp;
 | ||
|     	}
 | ||
|     }
 | ||
| 
 | ||
| /* CHECK: maybe remove this stuff */
 | ||
| 	if( ps->DataInf.dwScanFlag & SCANDEF_Transparency) {
 | ||
| 	    posScan[1].exposureTime = 96;
 | ||
| 	    posScan[1].xStepTime    = 12;
 | ||
| 	    posScan[2].exposureTime = 96;
 | ||
| 	    posScan[2].xStepTime    = 24;
 | ||
| 	    posScan[3].exposureTime = 96;
 | ||
| 	    posScan[3].xStepTime    = 48;
 | ||
| 	    posScan[4].exposureTime = 96;
 | ||
| 	    posScan[4].xStepTime    = 96;
 | ||
| 
 | ||
| 	    /* Reset shading Exposure Time & xStep Time */
 | ||
| 	    ps->Shade.wExposure = posScan[ps->Scan.dpiIdx].exposureTime;
 | ||
| 	    ps->Shade.wXStep    = posScan[ps->Scan.dpiIdx].xStepTime;
 | ||
| 	}
 | ||
| 	else if( ps->DataInf.dwScanFlag & SCANDEF_Negative) {
 | ||
|         ps->Scan.negScan[1].exposureTime = 96;
 | ||
|         ps->Scan.negScan[1].xStepTime    = 12;
 | ||
|         ps->Scan.negScan[2].exposureTime = 96;
 | ||
|         ps->Scan.negScan[2].xStepTime    = 24;
 | ||
|         ps->Scan.negScan[3].exposureTime = 96;
 | ||
|         ps->Scan.negScan[3].xStepTime    = 48;
 | ||
|         ps->Scan.negScan[4].exposureTime = 96;
 | ||
|         ps->Scan.negScan[4].xStepTime    = 96;
 | ||
| 
 | ||
| 	    /* Reset shading Exposure Time & xStep Time */
 | ||
|     	ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime;
 | ||
| 		ps->Shade.wXStep    = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime;
 | ||
|     }
 | ||
| 
 | ||
| 	return _OK;
 | ||
| }
 | ||
| 
 | ||
| /************************ exported functions *********************************/
 | ||
| 
 | ||
| /**
 | ||
|  */
 | ||
| _LOC int ImageInitialize( pScanData ps )
 | ||
| {
 | ||
| 	DBG( DBG_HIGH, "ImageInitialize()\n" );
 | ||
| 
 | ||
| 	if( NULL == ps )
 | ||
| 		return _E_NULLPTR;
 | ||
| 
 | ||
|     ps->Scan.dpiIdx  = 0;
 | ||
|     ps->Scan.negScan = negScan;
 | ||
| 
 | ||
| 	/*
 | ||
| 	 * depending on the asic, we set some functions
 | ||
| 	 */
 | ||
| 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
 | ||
| 
 | ||
| 		ps->GetImageInfo 	  = imageP98GetInfo;
 | ||
| 		ps->SetupScanSettings = imageP98SetupScanSettings;
 | ||
| 		ps->ReadOneImageLine  = imageP98001ReadOneImageLine;
 | ||
| 
 | ||
|     } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
 | ||
| 
 | ||
| 		ps->GetImageInfo 	  = imageP98GetInfo;
 | ||
| 		ps->SetupScanSettings = imageP98003SetupScanSettings;
 | ||
| 		ps->ReadOneImageLine  = imageP98003ReadOneImageLine;
 | ||
| 
 | ||
| 	} else if( _IS_ASIC96(ps->sCaps.AsicID)) {
 | ||
| 
 | ||
| 		ps->GetImageInfo 	  = imageP96GetInfo;
 | ||
| 		ps->SetupScanSettings = imageP96SetupScanSettings;
 | ||
| 		ps->ReadOneImageLine  = imageP96ReadOneImageLine;
 | ||
| 
 | ||
| 	} else {
 | ||
| 
 | ||
| 		DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
 | ||
| 		return _E_NOSUPP;
 | ||
| 	}
 | ||
| 	return _OK;
 | ||
| }
 | ||
| 
 | ||
| /* END PLUSTEK-PP_IMAGE.C ...................................................*/
 |