1 /* @file plustek-pp_image.c
2  * @brief functions to convert scanner data into image data
3  *
4  * based on sources acquired from Plustek Inc.
5  * Copyright (C) 1998 Plustek Inc.
6  * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de>
7  * also based on the work done by Rick Bronson
8  *
9  * History:
10  * - 0.30 - initial version
11  * - 0.31 - no changes
12  * - 0.32 - no changes
13  * - 0.33 - no changes
14  * - 0.34 - reactivated code in imageP96WaitLineData() to recover from
15  *          losing data
16  * - 0.35 - no changes
17  * - 0.36 - removed comment
18  *        - added wDither exchange to imageP9xSetupScanSettings
19  *        - added fnHalftoneDirect1 which provides dithering by using random
20  *          thresholds
21  *        - removed the swapping behaviour for model OP_600 in
22  *          fnP96ColorDirect() according to the Primax 4800 Direct tests
23  *        - changes, due to define renaming
24  *        - removed _ASIC_96001 specific stuff to invert colors
25  * - 0.37 - removed // comments
26  *        - corrected output of 12bit/pixel
27  * - 0.38 - added P12 stuff
28  *        - renamed WaitLineData functions to ReadOneImageLine
29  * - 0.39 - fixed a problem in imageP98003ReadOneImageLine, that causes
30  *          these I/O timeouts...
31  * - 0.40 - no changes
32  * - 0.41 - no changes
33  * - 0.42 - fixed a problem for the 12bit modes for ASIC9800x based devices
34  *        - changed include names
35  * - 0.43 - removed floating point stuff
36  *        - cleanup
37  * - 0.44 - fix format string issues, as Long types default to int32_t
38  *          now
39  * .
40  * <hr>
41  * This file is part of the SANE package.
42  *
43  * This program is free software; you can redistribute it and/or
44  * modify it under the terms of the GNU General Public License as
45  * published by the Free Software Foundation; either version 2 of the
46  * License, or (at your option) any later version.
47  *
48  * This program is distributed in the hope that it will be useful, but
49  * WITHOUT ANY WARRANTY; without even the implied warranty of
50  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
51  * General Public License for more details.
52  *
53  * You should have received a copy of the GNU General Public License
54  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
55  *
56  * As a special exception, the authors of SANE give permission for
57  * additional uses of the libraries contained in this release of SANE.
58  *
59  * The exception is that, if you link a SANE library with other files
60  * to produce an executable, this does not by itself cause the
61  * resulting executable to be covered by the GNU General Public
62  * License.  Your use of that executable is in no way restricted on
63  * account of linking the SANE library code into it.
64  *
65  * This exception does not, however, invalidate any other reasons why
66  * the executable file might be covered by the GNU General Public
67  * License.
68  *
69  * If you submit changes to SANE to the maintainers to be included in
70  * a subsequent release, you agree by submitting the changes that
71  * those changes may be distributed with this exception intact.
72  *
73  * If you write modifications of your own for SANE, it is your choice
74  * whether to permit this exception to apply to your modifications.
75  * If you do not wish that, delete this exception notice.
76  * <hr>
77  */
78 #include "plustek-pp_scan.h"
79 
80 /************************ local definitions **********************************/
81 
82 #define _LINE_TIMEOUT   (_SECOND * 5 )      /* max 5 second per line !  */
83 
84 /*************************** local vars **************************************/
85 
86 static UShort wPreviewScanned = 0;
87 
88 static ExpXStepDef posScan[5] = {{128, 8}, {96, 12},
89                                  {96, 24}, {96, 48}, {96, 96}};
90 static ExpXStepDef negScan[5] = {{128, 8}, {96, 12},
91                                  {96, 24}, {96, 48}, {96, 96}};
92 
93 static ExpXStepDef nmlScan[4][5] = {
94     {{160, 10}, {96, 12},  {96, 24},  {96, 48},  {96, 96}},     /* EPP */
95     {{160, 10}, {128, 16}, {128, 32}, {192, 96}, {192, 96}},    /* SPP */
96     {{160, 10}, {96, 12},  {96, 24},  {160, 80}, {160, 160}},   /* BPP */
97     {{160, 10}, {96, 12},  {96, 24},  {96, 48},  {96, 96}}      /* ECP */
98 };
99 
100 static ThreshDef xferSpeed[4] = {
101     {0, 3200, 2500}, {0, 1200, 800}, {0, 800, 1250}, {0, 3200, 2500}
102 };
103 
104 /*************************** local functions *********************************/
105 
106 /** return the correct DPI-value
107  * The ASIC 96001/3 models are limited to an optical resolution of 300 Dpi
108  * so it´s necessary to scale in X and Y direction (see scale.c)!
109  */
imageGetPhysDPI(pScanData ps,pImgDef pImgInf,Bool fDpiX)110 static UShort imageGetPhysDPI( pScanData ps, pImgDef pImgInf, Bool fDpiX )
111 {
112 	if( _IS_ASIC98(ps->sCaps.AsicID)) {
113 
114 	    if (fDpiX) {
115 
116 			if (pImgInf->xyDpi.x > ps->LensInf.rDpiX.wPhyMax)
117 	    		return ps->LensInf.rDpiX.wPhyMax;
118 			else
119 	    		return pImgInf->xyDpi.x;
120 
121 	    } else {
122 			if (pImgInf->xyDpi.y > ps->LensInf.rDpiY.wPhyMax)
123 	    		return ps->LensInf.rDpiY.wPhyMax;
124 			else
125 	    		return pImgInf->xyDpi.y;
126 	    }
127 	} else {
128 
129 	    if (fDpiX) {
130 
131 			if (pImgInf->wDataType >= COLOR_TRUE24) {
132 	    		if (pImgInf->xyDpi.x > ps->LensInf.rDpiX.wPhyMax)
133 					return ps->LensInf.rDpiX.wPhyMax;
134 			    else
135 					return pImgInf->xyDpi.x;
136 			} else {
137 	    		if (pImgInf->xyDpi.x > (ps->LensInf.rDpiX.wPhyMax * 2))
138 					return (ps->LensInf.rDpiX.wPhyMax * 2);
139 			    else
140 					return pImgInf->xyDpi.x;
141 			}
142     	} else {
143 
144 			if (pImgInf->wDataType >= COLOR_TRUE24 ) {
145 	    		if (pImgInf->xyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2))
146 					return (ps->LensInf.rDpiY.wPhyMax / 2);
147 			    else
148 					return pImgInf->xyDpi.y;
149 			} else {
150 	    		if (pImgInf->xyDpi.y > ps->LensInf.rDpiY.wPhyMax)
151 					return ps->LensInf.rDpiY.wPhyMax;
152 			    else
153 					return pImgInf->xyDpi.y;
154 			}
155 	    }
156 	}
157 }
158 
159 /*****************************************************************************
160  *			Sampling stuff for ASIC 98003      						         *
161  *****************************************************************************/
162 
fnEveryLines(pScanData ps)163 static Bool fnEveryLines( pScanData ps )
164 {
165 	_VAR_NOT_USED( ps );
166     return _TRUE;
167 }
168 
fnSampleLines(pScanData ps)169 static Bool fnSampleLines( pScanData ps )
170 {
171     ps->DataInf.wYSum += ps->DataInf.xyAppDpi.y;
172 
173     if( ps->DataInf.wYSum >= ps->DataInf.xyPhyDpi.y ) {
174 
175         ps->DataInf.wYSum -= ps->DataInf.xyPhyDpi.y;
176     	return	_TRUE;
177     }
178 
179 	return _FALSE;
180 }
181 
fnSamplePreview(pScanData ps)182 static Bool fnSamplePreview( pScanData ps )
183 {
184     ps->DataInf.wYSum += wPreviewScanned;
185     if( ps->DataInf.wYSum >= 150 ) {
186 
187         ps->DataInf.wYSum -= 150;
188     	return	_TRUE;
189     }
190 
191 	return _FALSE;
192 }
193 
194 /*****************************************************************************
195  *			Data Processing Routines			     						 *
196  *****************************************************************************/
197 
fnReadToDriver(pScanData ps)198 static Bool fnReadToDriver( pScanData ps )
199 {
200     ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
201     IOReadScannerImageData( ps, ps->Scan.BufPut.blue.bp,
202 							ps->DataInf.dwAsicBytesPerPlane );
203 
204 	ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
205     IOReadScannerImageData( ps, ps->Scan.BufPut.green.bp,
206 							ps->DataInf.dwAsicBytesPerPlane );
207 
208     if( ps->Scan.gd_gk.wGreenKeep )
209 		ps->Scan.gd_gk.wGreenKeep--;
210     else {
211 		ps->Scan.BufPut.green.bp += ps->DataInf.dwAsicBytesPerPlane;
212 
213 		if( ps->Scan.BufPut.green.bp >= ps->Scan.BufEnd.green.bp )
214 		    ps->Scan.BufPut.green.bp = ps->Scan.BufBegin.green.bp;
215     }
216 
217     ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
218     IOReadScannerImageData( ps, ps->Scan.BufPut.red.bp,
219 							ps->DataInf.dwAsicBytesPerPlane );
220 
221     ps->Scan.BufPut.red.bp += ps->DataInf.dwAsicBytesPerPlane;
222     if( ps->Scan.BufPut.red.bp >= ps->Scan.BufEnd.red.bp )
223 		ps->Scan.BufPut.red.bp = ps->Scan.BufBegin.red.bp;
224 
225     if( ps->Scan.bd_rk.wRedKeep ) {
226 		ps->Scan.bd_rk.wRedKeep--;
227 		return _FALSE;
228 
229     } else {
230 
231 		ps->Scan.BufData.green.bp = ps->Scan.BufGet.green.bp;
232 
233 		if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) {
234 		    ps->Scan.BufData.red.bp  = ps->Scan.BufGet.blue.bp;
235 		    ps->Scan.BufData.blue.bp = ps->Scan.BufGet.red.bp;
236 		} else {
237 		    ps->Scan.BufData.red.bp = ps->Scan.BufGet.red.bp;
238 		    ps->Scan.BufData.blue.bp = ps->Scan.BufGet.blue.bp;
239 		}
240 
241 		ps->Scan.BufGet.red.bp   += ps->DataInf.dwAsicBytesPerPlane;
242 		ps->Scan.BufGet.green.bp += ps->DataInf.dwAsicBytesPerPlane;
243 
244 		if( ps->Scan.BufGet.red.bp >= ps->Scan.BufEnd.red.bp )
245 		    ps->Scan.BufGet.red.bp = ps->Scan.BufBegin.red.bp;
246 
247 		if( ps->Scan.BufGet.green.bp >= ps->Scan.BufEnd.green.bp )
248 		    ps->Scan.BufGet.green.bp = ps->Scan.BufBegin.green.bp;
249 
250 		return _TRUE;
251     }
252 }
253 
fnReadOutScanner(pScanData ps)254 static Bool fnReadOutScanner( pScanData ps )
255 {
256     if( ps->Scan.bd_rk.wBlueDiscard ) {
257 
258         ps->Scan.bd_rk.wBlueDiscard--;
259     	ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
260 
261 	    IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf,
262                                     ps->DataInf.dwAsicBytesPerPlane );
263 
264     	if( ps->Scan.gd_gk.wGreenDiscard ) {
265             ps->Scan.gd_gk.wGreenDiscard--;
266 
267 	        ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
268     	    IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf,
269                                         ps->DataInf.dwAsicBytesPerPlane);
270     	}
271 	    return _FALSE;
272 
273     } else {
274         IOReadColorData( ps, ps->Bufs.b1.pReadBuf,
275                              ps->DataInf.dwAsicBytesPerPlane );
276 	    return _TRUE;
277     }
278 }
279 
280 /** Interpolates the gray data by using averaged the continuous pixels
281  */
fnP96GrayDirect(pScanData ps,pVoid pBuf,pVoid pImg,ULong bl)282 static void fnP96GrayDirect( pScanData ps, pVoid pBuf, pVoid pImg, ULong bl )
283 {
284 	pUChar src, dest;
285 
286 	src  = (pUChar)pImg;
287 	dest = (pUChar)pBuf;
288 
289     for (; bl; bl--, src++, dest++ )
290 		*dest = ps->pbMapRed [*src];
291 }
292 
293 /** This routine used in the condition:
294  * 1) The data type is B/W or GrayScale.
295  * 2) The required horizontal resolution doesn't exceed the optic spec.
296  * 3) The required vertical resolution exceeds the optic spec.
297  * So, the vertcal lines have to average with previous line to smooth the
298  * image.
299  */
fnDataDirect(pScanData ps,pVoid pBuf,pVoid pImg,ULong bl)300 static void fnDataDirect( pScanData ps, pVoid pBuf, pVoid pImg, ULong bl )
301 {
302 	_VAR_NOT_USED( ps );
303 	memcpy( pBuf, pImg, bl );
304 }
305 
306 /** According to dither matrix to convert the input gray scale data into
307  * one-bit data.
308  */
fnHalftoneDirect0(pScanData ps,pVoid pb,pVoid pImg,ULong bL)309 static void fnHalftoneDirect0( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
310 {
311 	pUChar pDither, src, dest;
312 	ULong  dw;
313 
314 	src  = (pUChar)pImg;
315 	dest = (pUChar)pb;
316 
317 	pDither = &ps->a_bDitherPattern[ps->dwDitherIndex];
318 
319     for( ; bL; bL--, dest++, pDither -= 8 ) {
320 
321 		for( dw = 8; dw; dw--, src++, pDither++ ) {
322 
323 		    if( *src < *pDither ) {
324 				*dest = (*dest << 1) | 0x01;
325 			} else {
326 				*dest <<= 1;
327 			}
328 		}
329 	}
330 	ps->dwDitherIndex = (ps->dwDitherIndex + 8) & 0x3f;
331 }
332 
333 /** use random generator to make halftoning
334  */
fnHalftoneDirect1(pScanData ps,pVoid pb,pVoid pImg,ULong bL)335 static void fnHalftoneDirect1( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
336 {
337 	pUChar src, dest;
338     UChar  threshold;
339     ULong  dw;
340 
341 	_VAR_NOT_USED( ps );
342 	src  = (pUChar)pImg;
343 	dest = (pUChar)pb;
344 
345 	for (; bL; bL--, dest++ ) {
346 
347 		for (dw = 8; dw; dw--, src++ ) {
348 
349 		    threshold = (UChar)MiscLongRand();
350 
351 		    if (*src < threshold ) {
352 				*dest = (*dest << 1) | 0x01;
353 			} else {
354 				*dest <<= 1;
355 			}
356 		}
357 	}
358 }
359 
360 /** Merges the color planes to pixels style without enlarge operation.
361  */
fnP98ColorDirect(pScanData ps,pVoid pb,pVoid pImg,ULong bL)362 static void fnP98ColorDirect( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
363 {
364 	pUChar      src;
365 	pRGBByteDef dest;
366 
367 	src  = (pUChar)pImg;
368 	dest = (pRGBByteDef)pb;
369 
370 	for ( bL = ps->DataInf.dwAsicPixelsPerPlane; bL; bL--, src++, dest++) {
371 
372 		dest->Red   = *src;
373 		dest->Green = src[ps->DataInf.dwAsicPixelsPerPlane];
374 		dest->Blue  = src[ps->DataInf.dwAsicPixelsPerPlane*2];
375 	}
376 }
377 
fnP96ColorDirect(pScanData ps,pVoid pb,pVoid pImg,ULong bL)378 static void fnP96ColorDirect( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
379 {
380 	pUChar      src;
381 	pRGBByteDef dest;
382 
383 	src  = (pUChar)pImg;
384 	dest = (pRGBByteDef)pb;
385 
386 	for ( bL = ps->DataInf.dwAsicPixelsPerPlane; bL; bL--, dest++, src++) {
387 
388 			dest->Red  =ps->pbMapRed[*src];
389 			dest->Green=ps->pbMapGreen[src[ps->DataInf.dwAsicPixelsPerPlane]];
390 			dest->Blue =ps->pbMapBlue[src[ps->DataInf.dwAsicPixelsPerPlane*2]];
391     }
392 }
393 
394 /** Merges the color planes to pixels style without enlarge operation.
395  * The scanner returns the pixel data in Motorola-Format, so we have to swap
396  */
fnP98Color48(pScanData ps,pVoid pb,pVoid pImg,ULong bL)397 static void fnP98Color48( pScanData ps, pVoid pb, pVoid pImg, ULong bL )
398 {
399 	pUShort       src;
400 	pRGBUShortDef dest;
401 
402 	register ULong i;
403 
404 	_VAR_NOT_USED( bL );
405 	src  = (pUShort)pImg;
406 	dest = (pRGBUShortDef)pb;
407 
408 	for ( i = ps->DataInf.dwAsicPixelsPerPlane; i;	i--, src++, dest++) {
409 
410 		dest->Red   = *src;
411 		dest->Green = src[ps->DataInf.dwAsicPixelsPerPlane];
412 		dest->Blue  = src[ps->DataInf.dwAsicPixelsPerPlane * 2];
413     }
414 }
415 
416 /** prepare for scanning
417  */
imageP98SetupScanSettings(pScanData ps,pScanInfo pInf)418 static int imageP98SetupScanSettings( pScanData ps, pScanInfo pInf )
419 {
420 	UShort brightness;
421 
422 	DBG( DBG_LOW, "imageP98SetupScanSettings()\n" );
423 
424     ps->DataInf.dwScanFlag = pInf->ImgDef.dwFlag;
425     ps->DataInf.dwVxdFlag  = 0;
426     ps->DataInf.crImage    = pInf->ImgDef.crArea;
427 
428     /* AdjustOriginXByLens
429      * [NOTE]
430      *	Here we just simply adjust it to double (600 DPI is two times of
431      *	300 DPI), but if this model is a multi-lens scanner, we should adjust
432      *	it according to different lens.
433 	 */
434     ps->DataInf.crImage.x <<= 1;
435 
436     ps->DataInf.xyAppDpi 	 = pInf->ImgDef.xyDpi;
437     ps->DataInf.siBrightness = pInf->siBrightness;
438     ps->DataInf.wDither      = pInf->wDither;
439     ps->DataInf.wAppDataType = pInf->ImgDef.wDataType;
440 
441     ps->GetImageInfo( ps, &pInf->ImgDef );
442 
443     if (ps->DataInf.dwVxdFlag & _VF_DATATOUSERBUFFER) {
444 		ps->Scan.DataProcess = fnDataDirect;
445 	}
446     if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
447 		ps->Scan.lBufferAdjust = -(Long)ps->DataInf.dwAppBytesPerLine;
448 	} else {
449 		ps->Scan.lBufferAdjust = (Long)ps->DataInf.dwAppBytesPerLine;
450 	}
451 
452 	DBG( DBG_LOW, "Scan settings:\n" );
453 	DBG( DBG_LOW, "ImageInfo: (x=%u,y=%u,dx=%u,dy=%u)\n",
454 			 ps->DataInf.crImage.x,  ps->DataInf.crImage.y,
455 			 ps->DataInf.crImage.cx, ps->DataInf.crImage.cy );
456 
457     /*
458 	 * SetBwBrightness
459      * [NOTE]
460      *
461      *	 0                   _DEF_BW_THRESHOLD					   255
462      *	 +-------------------------+--------------------------------+
463      *	 |<------- Black --------->|<----------- White ------------>|
464      *	 So, if user wish to make image darker, the threshold value should be
465      *	 higher than _defBwThreshold, otherwise it should lower than the
466      *	 _DefBwThreshold.
467      *	 Darker = _DefBwThreshold + White * Input / 127;
468      *		  Input < 0, and White = 255 - _DefBwThreshold, so
469      *		= _DefBwThreshold - (255 - _DefBwThreshold) * Input / 127;
470      *	 The brighter is the same idea.
471 	 *
472  	 * CHECK: it seems that the brightness only works for the binary mode !
473 	 */
474 	if( ps->DataInf.wPhyDataType != COLOR_BW ) {/* if not line art 			*/
475 		ps->wBrightness = pInf->siBrightness;   /* use internal tables for 	*/
476 		ps->wContrast   = pInf->siContrast;		/* brightness and contrast	*/
477 
478 		pInf->siBrightness = 0;				/* don't use asic for threshold */
479     }
480 
481 /* CHECK: We have now two methods for setting the brightness...
482 */
483 	DBG( DBG_LOW, "brightness = %i\n", pInf->siBrightness );
484 
485     if (ps->DataInf.siBrightness < 0) {
486 		brightness = (UShort)(_DEF_BW_THRESHOLD -
487 			       (255 - _DEF_BW_THRESHOLD) * ps->DataInf.siBrightness /127);
488 	} else {
489 		brightness = (UShort)(_DEF_BW_THRESHOLD -
490 					       _DEF_BW_THRESHOLD * ps->DataInf.siBrightness /127);
491 	}
492     ps->AsicReg.RD_ThresholdControl = brightness;
493 
494 	DBG( DBG_LOW, "1. brightness = %i\n", brightness );
495 
496     if( ps->DataInf.siBrightness >= 0 ) {
497 	    brightness = (short)((long)(-(255 - _DEF_BW_THRESHOLD) *
498 						 ps->DataInf.siBrightness) / 127 + _DEF_BW_THRESHOLD);
499 	} else {
500 	    brightness = (short)((long)(_DEF_BW_THRESHOLD *
501  						  ps->DataInf.siBrightness) / 127 + _DEF_BW_THRESHOLD);
502 	}
503 
504 	brightness = (brightness ^ 0xff) & 0xff;
505 
506 	if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
507 	    ps->AsicReg.RD_ThresholdControl = brightness;
508 		DBG( DBG_LOW, "2. brightness = %i\n", brightness );
509 	}
510 
511 	ps->DataInf.pCurrentBuffer = ps->pScanBuffer1;
512 
513 	return _OK;
514 }
515 
516 /**
517  */
imageP98DoCopyBuffer(pScanData ps,pUChar pImage)518 static void imageP98DoCopyBuffer( pScanData ps, pUChar pImage )
519 {
520 	memcpy( ps->pFilterBuf, pImage, ps->DataInf.dwAsicBytesPerPlane );
521 
522 	ps->pFilterBuf += 5120;
523     if (ps->pFilterBuf >= ps->pEndBuf)
524 		ps->pFilterBuf = ps->pProcessingBuf;
525 }
526 
527 /**
528  */
imageP98CopyToFilterBuffer(pScanData ps,pUChar pImage)529 static Bool imageP98CopyToFilterBuffer( pScanData ps, pUChar pImage )
530 {
531     if (ps->fDoFilter) {
532 
533 		if (ps->fFilterFirstLine) {
534 
535 		    imageP98DoCopyBuffer( ps, pImage );
536 		    imageP98DoCopyBuffer( ps, pImage );
537 		    ps->dwLinesFilter--;
538 		    return _FALSE;
539 	} else {
540 
541 		    imageP98DoCopyBuffer( ps, pImage );
542 		    if ((ps->dwLinesFilter--) == 0)
543 				imageP98DoCopyBuffer( ps, pImage);
544 		}
545     }
546     return _TRUE;
547 }
548 
549 /**
550  */
imageP98UnSharpCompare(pScanData ps,Byte Center,Byte Neighbour,pLong pdwNewValue)551 static void imageP98UnSharpCompare( pScanData ps, Byte Center,
552                                     Byte Neighbour, pLong pdwNewValue )
553 {
554     Byte b;
555 
556     b = (Center >= Neighbour) ? Center - Neighbour : Neighbour - Center ;
557 
558     if (b > ps->bOffsetFilter) {
559 
560 		*pdwNewValue -= (Long)Neighbour;
561 		ps->dwDivFilter--;
562     }
563 }
564 
565 /**
566  */
imageP98DoFilter(pScanData ps,pUChar pPut)567 static void imageP98DoFilter( pScanData ps, pUChar pPut )
568 {
569 	ULong dw;
570     Long  dwNewValue;
571 
572     if (ps->fDoFilter && (ps->DataInf.xyAppDpi.x) >= 600UL) {
573 
574 		/* DoUnsharpMask(); */
575 		for (dw = 0; dw < ps->DataInf.dwAsicBytesPerPlane - 2; dw++, pPut++) {
576 
577 			ps->dwDivFilter = ps->dwMul;
578 
579 		    dwNewValue = ((ULong)ps->pGet2[dw+1]) * ps->dwMul;
580 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw], &dwNewValue);
581 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw+1], &dwNewValue);
582 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw+2], &dwNewValue);
583 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet2[dw], &dwNewValue);
584 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet2[dw+2], &dwNewValue);
585 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw], &dwNewValue);
586 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw+1], &dwNewValue);
587 			imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw+2], &dwNewValue);
588 
589     	    if( dwNewValue > 0 ) {
590 				if((dwNewValue /= ps->dwDivFilter) < 255) {
591 		    		*pPut = (Byte) dwNewValue;
592 				} else {
593 				    *pPut = 255;
594 				}
595 		    } else {
596 				*pPut = 0;
597 			}
598 		}
599 		pPut = ps->pGet1;
600 		ps->pGet1 = ps->pGet2;
601 		ps->pGet2 = ps->pGet3;
602 		ps->pGet3 = pPut;
603     }
604 }
605 
606 /**
607  */
imageP98DataIsReady(pScanData ps)608 static Bool imageP98DataIsReady( pScanData ps )
609 {
610 	Byte b;
611 
612 	ps->Scan.fMotorBackward = _FALSE;
613 	ps->bMoveDataOutFlag    = _DataAfterRefreshState;
614 
615     b = (ps->DataInf.wPhyDataType >= COLOR_TRUE24) ?
616 	                                      _BLUE_DATA_READY : _GREEN_DATA_READY;
617     while( _TRUE ) {
618 
619 		ps->dwColorRunIndex ++;
620 
621 		if(ps->pColorRunTable[ps->dwColorRunIndex] & b)
622 	    	break;
623     }
624 
625     if (b == _GREEN_DATA_READY) {
626 
627 		ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
628 		IOReadScannerImageData( ps, ps->DataInf.pCurrentBuffer,
629 			 	    		        ps->DataInf.dwAsicBytesPerPlane );
630 
631 		imageP98CopyToFilterBuffer( ps, ps->DataInf.pCurrentBuffer );
632     } else  {
633 
634 		/* ReadColorImageData() */
635 		if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) {
636 
637 			ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
638 			IOReadScannerImageData( ps, ps->pScanBuffer1 +
639 				         			    ps->DataInf.dwAsicBytesPerPlane * 2,
640 									    ps->DataInf.dwAsicBytesPerPlane );
641 
642 			ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
643 			IOReadScannerImageData( ps, ps->pScanBuffer1 +
644 										ps->DataInf.dwAsicBytesPerPlane,
645 										ps->DataInf.dwAsicBytesPerPlane );
646 
647 			ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
648 			IOReadScannerImageData( ps, ps->pScanBuffer1,
649 				 					    ps->DataInf.dwAsicBytesPerPlane );
650 		} else {
651 
652             IOReadColorData( ps, ps->pScanBuffer1,
653                                  ps->DataInf.dwAsicBytesPerPlane );
654 		}
655     }
656 
657 	if (ps->fFilterFirstLine) {
658 		ps->fFilterFirstLine = _FALSE;
659 	    return _TRUE;
660 	}
661 
662 	imageP98DoFilter( ps, ps->DataInf.pCurrentBuffer );
663 
664     (*ps->Scan.DataProcess)( ps, ps->Scan.bp.pMonoBuf,
665                              ps->DataInf.pCurrentBuffer,
666                              ps->DataInf.dwAppPhyBytesPerLine );
667 
668     return _TRUE;
669 }
670 
671 /** here we wait for one data-line
672  */
imageP98001ReadOneImageLine(pScanData ps)673 static Bool imageP98001ReadOneImageLine( pScanData ps )
674 {
675 	ULong    dwFifoCounter;
676 	TimerDef timer;
677 
678 	MiscStartTimer( &timer, _LINE_TIMEOUT );
679     do {
680 
681 		ps->Scan.bNowScanState = IOGetScanState( ps, _FALSE );
682 		dwFifoCounter = IOReadFifoLength( ps );
683 
684 		if (!(ps->Scan.bNowScanState & _SCANSTATE_STOP) &&
685 								    (dwFifoCounter < ps->dwMaxReadFifoData)) {
686 
687 		    if( ps->Scan.bOldScanState != ps->Scan.bNowScanState )
688 				ps->UpdateDataCurrentReadLine( ps );
689 
690 		    if( dwFifoCounter >= ps->Scan.dwMinReadFifo )
691 				return imageP98DataIsReady( ps );
692 
693 		} else {	/* ScanStateIsStop */
694 
695 		    if (dwFifoCounter >= ps->dwSizeMustProcess)
696 				return imageP98DataIsReady( ps );
697 
698 			ps->UpdateDataCurrentReadLine( ps );
699 
700 		    if( dwFifoCounter >= ps->Scan.dwMinReadFifo )
701 				return imageP98DataIsReady( ps );
702 		}
703 
704 		_DODELAY(10);			     /* delay 10 ms */
705 
706     } while (!MiscCheckTimer( &timer ));
707 
708 	DBG( DBG_HIGH, "Timeout - Scanner malfunction !!\n" );
709 	MotorToHomePosition(ps);
710 
711 	/* timed out, scanner malfunction */
712     return _FALSE;
713 }
714 
715 /** calculate the image properties according to the scanmode
716  */
imageP98GetInfo(pScanData ps,pImgDef pImgInf)717 static void imageP98GetInfo( pScanData ps, pImgDef pImgInf )
718 {
719 	DBG( DBG_LOW, "imageP98GetInfo()\n" );
720 
721 	ps->DataInf.xyPhyDpi.x = imageGetPhysDPI( ps, pImgInf, _TRUE  );
722 	ps->DataInf.xyPhyDpi.y = imageGetPhysDPI( ps, pImgInf, _FALSE );
723 
724 	DBG( DBG_LOW, "xyPhyDpi.x = %u, xyPhyDpi.y = %u\n",
725 		 ps->DataInf.xyPhyDpi.x, ps->DataInf.xyPhyDpi.y );
726 
727 	DBG( DBG_LOW, "crArea.x = %u, crArea.y = %u\n",
728 		 pImgInf->crArea.x, pImgInf->crArea.y );
729 
730 	DBG( DBG_LOW, "crArea.cx = %u, crArea.cy = %u\n",
731 		 pImgInf->crArea.cx, pImgInf->crArea.cy );
732 
733 	ps->DataInf.XYRatio = 1000 * ps->DataInf.xyPhyDpi.y/ps->DataInf.xyPhyDpi.x;
734 	DBG( DBG_LOW, "xyDpi.x = %u, xyDpi.y = %u, XYRatio = %u\n",
735 	               pImgInf->xyDpi.x, pImgInf->xyDpi.y, ps->DataInf.XYRatio );
736 
737 	ps->DataInf.dwAppLinesPerArea = (ULong)pImgInf->crArea.cy *
738 									  pImgInf->xyDpi.y / _MEASURE_BASE;
739 
740     ps->DataInf.dwAppPixelsPerLine = (ULong)pImgInf->crArea.cx *
741 									   pImgInf->xyDpi.x / _MEASURE_BASE;
742 
743 	ps->DataInf.dwPhysBytesPerLine = (ULong)pImgInf->crArea.cx *
744 									   ps->DataInf.xyPhyDpi.x / _MEASURE_BASE;
745 
746     if( pImgInf->wDataType <= COLOR_HALFTONE ) {
747 		ps->DataInf.dwAsicPixelsPerPlane = (ps->DataInf.dwAppPixelsPerLine+7UL)&
748 											 0xfffffff8UL;
749 		ps->DataInf.dwAppPhyBytesPerLine =
750 		ps->DataInf.dwAppBytesPerLine 	 =
751 		ps->DataInf.dwAsicBytesPerLine   =
752 		ps->DataInf.dwAsicBytesPerPlane  = ps->DataInf.dwAsicPixelsPerPlane>>3;
753     } else {
754 		ps->DataInf.dwAsicBytesPerPlane  =
755 		ps->DataInf.dwAsicPixelsPerPlane = ps->DataInf.dwAppPixelsPerLine;
756 	}
757 
758     if( COLOR_TRUE48 == pImgInf->wDataType ) {
759 		ps->DataInf.dwAsicBytesPerPlane *= 2;
760 	}
761 
762     switch( pImgInf->wDataType ) {
763 
764 	case COLOR_BW:
765 	    ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER;
766 	    ps->DataInf.wPhyDataType = COLOR_BW;
767         ps->Shade.bIntermediate  = _ScanMode_Mono;
768 	    break;
769 
770 	case COLOR_HALFTONE:
771 		if( ps->DataInf.wDither == 2 ) {
772             ps->Scan.DataProcess = fnHalftoneDirect1;
773 		} else {
774             ps->Scan.DataProcess = fnHalftoneDirect0;
775 		}
776 /*
777  * CHANGE: it seems, that we have to use the same settings as for 256GRAY
778  */
779 		ps->DataInf.dwAsicBytesPerPlane =
780 		ps->DataInf.dwAsicPixelsPerPlane = ps->DataInf.dwAppPixelsPerLine;
781 	    ps->DataInf.wPhyDataType = COLOR_256GRAY;
782         ps->Shade.bIntermediate  = _ScanMode_Mono;
783 	    break;
784 
785 	case COLOR_256GRAY:
786 	    ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER;
787 	    ps->DataInf.dwAsicBytesPerLine =
788 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine;
789 	    ps->DataInf.wPhyDataType = COLOR_256GRAY;
790         ps->Shade.bIntermediate  = _ScanMode_Mono;
791 	    break;
792 
793 	case COLOR_TRUE24:
794         ps->Scan.DataProcess = fnP98ColorDirect;
795 	    ps->DataInf.dwAsicBytesPerLine =
796 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 3;
797 	    ps->DataInf.wPhyDataType = COLOR_TRUE24;
798         ps->Shade.bIntermediate  = _ScanMode_Color;
799 	    break;
800 
801 	case COLOR_TRUE48:
802         ps->Scan.DataProcess = fnP98Color48;
803 	    ps->DataInf.dwAsicBytesPerLine =
804 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 6;
805 	    ps->DataInf.wPhyDataType = COLOR_TRUE48;
806         ps->Shade.bIntermediate  = _ScanMode_Color;
807 	    break;
808 
809     }
810 
811     if (pImgInf->dwFlag & SCANDEF_BoundaryDWORD) {
812 		ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 3) &
813 									      0xfffffffc;
814 	} else {
815 		if (pImgInf->dwFlag & SCANDEF_BoundaryWORD) {
816 		    ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 1) &
817 											  0xfffffffe;
818 		} else {
819 		    ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine;
820 		}
821 	}
822 
823 	DBG( DBG_LOW, "AppLinesPerArea    = %u\n", ps->DataInf.dwAppLinesPerArea    );
824 	DBG( DBG_LOW, "AppPixelsPerLine   = %u\n", ps->DataInf.dwAppPixelsPerLine   );
825 	DBG( DBG_LOW, "AppPhyBytesPerLine = %u\n", ps->DataInf.dwAppPhyBytesPerLine );
826 	DBG( DBG_LOW, "AppBytesPerLine    = %u\n", ps->DataInf.dwAppBytesPerLine    );
827 	DBG( DBG_LOW, "AsicPixelsPerPlane = %u\n", ps->DataInf.dwAsicPixelsPerPlane );
828 	DBG( DBG_LOW, "AsicBytesPerPlane  = %u\n", ps->DataInf.dwAsicBytesPerPlane  );
829 	DBG( DBG_LOW, "AsicBytesPerLine   = %u\n", ps->DataInf.dwAsicBytesPerLine   );
830 	DBG( DBG_LOW, "Physical Bytes     = %u\n", ps->DataInf.dwPhysBytesPerLine   );
831 }
832 
833 /**
834  */
imageP96GetInfo(pScanData ps,pImgDef pImgInf)835 static void imageP96GetInfo( pScanData ps, pImgDef pImgInf )
836 {
837 	DBG( DBG_LOW, "imageP96GetInfo()\n" );
838 
839 	ps->DataInf.xyPhyDpi.x = imageGetPhysDPI( ps, pImgInf, _TRUE  );
840 	ps->DataInf.xyPhyDpi.y = imageGetPhysDPI( ps, pImgInf, _FALSE );
841 
842 	DBG( DBG_LOW, "xyPhyDpi.x = %u, xyPhyDpi.y = %u\n",
843 		 ps->DataInf.xyPhyDpi.x, ps->DataInf.xyPhyDpi.y );
844 
845 	DBG( DBG_LOW, "crArea.x = %u, crArea.y = %u\n",
846 		 pImgInf->crArea.x, pImgInf->crArea.y );
847 
848 	DBG( DBG_LOW, "crArea.cx = %u, crArea.cy = %u\n",
849 		 pImgInf->crArea.cx, pImgInf->crArea.cy );
850 
851 	ps->DataInf.XYRatio = 1000 * ps->DataInf.xyPhyDpi.y/ps->DataInf.xyPhyDpi.x;
852 	DBG( DBG_LOW, "xyDpi.x = %u, xyDpi.y = %u, XYRatio = %u\n",
853 	               pImgInf->xyDpi.x, pImgInf->xyDpi.y, ps->DataInf.XYRatio );
854 
855 	ps->DataInf.dwAppLinesPerArea = (ULong)pImgInf->crArea.cy *
856 					  					   pImgInf->xyDpi.y / _MEASURE_BASE;
857     ps->DataInf.dwAsicBytesPerPlane  =
858 	ps->DataInf.dwAsicPixelsPerPlane = (ULong)ps->DataInf.xyPhyDpi.x *
859 				 					       pImgInf->crArea.cx / _MEASURE_BASE;
860 
861     ps->DataInf.dwAppPixelsPerLine = (ULong)pImgInf->crArea.cx *
862 										    pImgInf->xyDpi.x / _MEASURE_BASE;
863 
864 	ps->DataInf.dwPhysBytesPerLine = (ULong)pImgInf->crArea.cx *
865 									   ps->DataInf.xyPhyDpi.x / _MEASURE_BASE;
866 
867     ps->DataInf.wPhyDataType = ps->DataInf.wAppDataType;
868 
869     switch( pImgInf->wDataType ) {
870 
871 	case COLOR_BW:
872 	    ps->DataInf.dwAsicBytesPerPlane =
873 								 (ps->DataInf.dwAsicPixelsPerPlane + 7) >> 3;
874 	    ps->DataInf.dwAppPhyBytesPerLine =
875 									 (ps->DataInf.dwAppPixelsPerLine + 7) >> 3;
876 	    ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER;
877         ps->Scan.DataProcess = fnDataDirect;
878 	    break;
879 
880 	case COLOR_HALFTONE:
881 	    ps->DataInf.dwAppPhyBytesPerLine =
882 								 (ps->DataInf.dwAsicPixelsPerPlane + 7) >> 3;
883 		if( ps->DataInf.wDither == 2 ) {
884             ps->Scan.DataProcess = fnHalftoneDirect1;
885 		} else {
886             ps->Scan.DataProcess = fnHalftoneDirect0;
887 		}
888 	    ps->DataInf.wPhyDataType = COLOR_256GRAY;
889 	    break;
890 
891 	case COLOR_256GRAY:
892 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine;
893         ps->Scan.DataProcess = fnP96GrayDirect;
894 	    break;
895 
896 	case COLOR_TRUE24:
897 #ifdef _A3I_EN
898         ps->Scan.DataProcess = fnP98ColorDirect;
899 #else
900         ps->Scan.DataProcess = fnP96ColorDirect;
901 #endif
902 	    ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 3;
903     }
904 
905     if( pImgInf->dwFlag & SCANDEF_BoundaryDWORD ) {
906 		ps->DataInf.dwAppBytesPerLine =
907 							(ps->DataInf.dwAppPhyBytesPerLine + 3) & 0xfffffffc;
908 	} else {
909 		if ( pImgInf->dwFlag & SCANDEF_BoundaryWORD ) {
910 		    ps->DataInf.dwAppBytesPerLine =
911 							(ps->DataInf.dwAppPhyBytesPerLine + 1) & 0xfffffffe;
912 		} else {
913 	    	ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine;
914 		}
915 	}
916 
917     if (ps->DataInf.wPhyDataType == COLOR_TRUE24)
918 		ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane * 3;
919     else
920 		ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane;
921 
922 /* WORK: AsicBytesPerLine only used for ASIC_98001 based scanners - try to remove
923 **		 that, also try to remove redundant info
924 */
925 	DBG( DBG_LOW, "AppLinesPerArea    = %u\n", ps->DataInf.dwAppLinesPerArea    );
926 	DBG( DBG_LOW, "AppPixelsPerLine   = %u\n", ps->DataInf.dwAppPixelsPerLine   );
927 	DBG( DBG_LOW, "AppPhyBytesPerLine = %u\n", ps->DataInf.dwAppPhyBytesPerLine );
928 	DBG( DBG_LOW, "AppBytesPerLine    = %u\n", ps->DataInf.dwAppBytesPerLine    );
929 	DBG( DBG_LOW, "AsicPixelsPerPlane = %u\n", ps->DataInf.dwAsicPixelsPerPlane );
930 	DBG( DBG_LOW, "AsicBytesPerPlane  = %u\n", ps->DataInf.dwAsicBytesPerPlane  );
931 	DBG( DBG_LOW, "AsicBytesPerLine   = %u\n", ps->DataInf.dwAsicBytesPerLine   );
932 	DBG( DBG_LOW, "Physical Bytes     = %u\n", ps->DataInf.dwPhysBytesPerLine   );
933 }
934 
935 /** here we wait for one data-line
936  */
imageP96ReadOneImageLine(pScanData ps)937 static Bool imageP96ReadOneImageLine( pScanData ps )
938 {
939     Bool     result = _FALSE;
940 	Byte	 bData, bFifoCount;
941     TimerDef timer;
942 
943 	MiscStartTimer( &timer, _LINE_TIMEOUT);
944     do {
945 
946 		bFifoCount = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
947 
948 /* CHECK ps->bMoveDataOutFlag will never be set to _DataFromStopState !!!*/
949 #if 1
950 		if ((bFifoCount < ps->bMinReadFifo) &&
951 					            (ps->bMoveDataOutFlag == _DataFromStopState)) {
952 
953 		    bData = IOGetScanState( ps, _FALSE);
954 
955 		    if (!(bData & _SCANSTATE_STOP)) {
956 				if (bData < ps->bCurrentLineCount)
957 				    bData += _NUMBER_OF_SCANSTEPS;
958 				if ((bData - ps->bCurrentLineCount) < _SCANSTATE_BYTES)
959 				    continue;
960 		    }
961 
962 		    ps->bMoveDataOutFlag = _DataAfterRefreshState;
963 		}
964 #endif
965 
966 /*
967 // HEINER:A3I
968 //		if( ps->bMoveDataOutFlag != _DataFromStopState )
969 //	    	ps->UpdateDataCurrentReadLine( ps );
970 */
971 		if( bFifoCount >= ps->bMinReadFifo ) {
972 
973 		    /* data is ready */
974 		    for (; !(*ps->pCurrentColorRunTable &
975 				(ps->RedDataReady | ps->GreenDataReady | _BLUE_DATA_READY));
976 												 ps->pCurrentColorRunTable++);
977 
978 #ifdef DEBUG
979 			if( ps->pCurrentColorRunTable >
980 							(ps->pColorRunTable+ps->BufferForColorRunTable))
981 				DBG( DBG_LOW, "WARNING: pCurrentColorRunTab>pColorRunTable\n");
982 #endif
983 
984 		    if (ps->DataInf.wPhyDataType == COLOR_TRUE24) {
985 
986 				/* read color planes (either R/G/B or R/B/G sequence that
987 				 * depends on COLOR CCD, see below
988 				 */
989 				if (*ps->pCurrentColorRunTable & ps->b1stColor) {
990 				    *ps->pCurrentColorRunTable &= ps->b1stMask;
991 				    IOReadScannerImageData (ps, ps->pPutBufR,
992 						  					    ps->DataInf.dwAsicBytesPerPlane);
993 				    ps->pPutBufR += ps->BufferSizePerModel;
994 					if (ps->pPutBufR == ps->pEndBufR)
995 						ps->pPutBufR = ps->pPrescan16;
996 				} else
997 					if (*ps->pCurrentColorRunTable & ps->b2ndColor) {
998 						*ps->pCurrentColorRunTable &= ps->b2ndMask;
999 						IOReadScannerImageData( ps, ps->pPutBufG,
1000 										        ps->DataInf.dwAsicBytesPerPlane);
1001 						ps->pPutBufG += ps->BufferSizePerModel;
1002 						if (ps->pPutBufG == ps->pEndBufG)
1003 						    ps->pPutBufG = ps->pPrescan8;
1004 		    	} else {
1005 					*ps->pCurrentColorRunTable &= ps->b3rdMask;
1006 					ps->pCurrentColorRunTable++;    /* processed this step */
1007 
1008 					/* according to CCD type & image placement method to
1009 					 * read third color into corresponding location.
1010 					 * SONY CCD: Red, Green and Blue.
1011 					 * TOSHIBA CCD: Red, Blue and Green.
1012 					 * SCANDEF_BmpStyle: Blue, Green and Red, Otherwise
1013 					 *  Red, Green and Blue.
1014 					 */
1015 					if (ps->b3rdColor & ps->GreenDataReady) {
1016 					    /* Green always in middle */
1017 					    IOReadScannerImageData (ps,
1018                                                  ps->DataInf.pCurrentBuffer +
1019 											  ps->DataInf.dwAsicBytesPerPlane,
1020 											  ps->DataInf.dwAsicBytesPerPlane);
1021 					} else {
1022 					    /* Blue depends the request style from caller */
1023 					    if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
1024 							/* BMP style, blue is the first one */
1025 							IOReadScannerImageData (ps,
1026                                                    ps->DataInf.pCurrentBuffer,
1027 											  ps->DataInf.dwAsicBytesPerPlane);
1028 						} else {
1029 							/* Blue is the last one */
1030 							IOReadScannerImageData (ps, ps->DataInf.pCurrentBuffer +
1031 											ps->DataInf.dwAsicBytesPerPlane * 2,
1032 											  ps->DataInf.dwAsicBytesPerPlane);
1033 						}
1034 					}
1035 
1036 					/* reassemble 3 color lines for separated RGB value */
1037     				if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
1038 					    /* BMP style, red is last one */
1039 					    memcpy( ps->DataInf.pCurrentBuffer +
1040 								ps->DataInf.dwAsicBytesPerPlane * 2,
1041 								ps->pGetBufR, ps->DataInf.dwAsicBytesPerPlane);
1042 					} else {
1043 					    /* Red is first one */
1044 					    memcpy( ps->DataInf.pCurrentBuffer,
1045 		 					    ps->pGetBufR, ps->DataInf.dwAsicBytesPerPlane );
1046 					}
1047 
1048 					if (ps->b2ndColor & ps->GreenDataReady) {
1049 					    /* Green always in middle */
1050 						memcpy( ps->DataInf.pCurrentBuffer +
1051 							   ps->DataInf.dwAsicBytesPerPlane,
1052 							   ps->pGetBufG, ps->DataInf.dwAsicBytesPerPlane);
1053 					} else {
1054 				    	/* Blue depends the request style from caller */
1055 					    if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) {
1056 							/* BMP style, blue is the first one */
1057 							memcpy( ps->DataInf.pCurrentBuffer,
1058 							        ps->pGetBufG,
1059 							        ps->DataInf.dwAsicBytesPerPlane);
1060 						} else {
1061 							/* BMP style, blue is the last one */
1062 							memcpy( ps->DataInf.pCurrentBuffer +
1063 							        ps->DataInf.dwAsicBytesPerPlane * 2,
1064 							        ps->pGetBufG,
1065 							        ps->DataInf.dwAsicBytesPerPlane );
1066 						}
1067 					}
1068 
1069 					/* Adjust the get pointers */
1070 					ps->pGetBufR += ps->BufferSizePerModel;
1071 					ps->pGetBufG += ps->BufferSizePerModel;
1072 					if (ps->pGetBufR == ps->pEndBufR)
1073 					    ps->pGetBufR = ps->pPrescan16;
1074 
1075 					if (ps->pGetBufG == ps->pEndBufG)
1076 					    ps->pGetBufG = ps->pPrescan8;
1077 
1078     				result = _TRUE; /* Line data in buffer */
1079                     break;
1080 			    }
1081 
1082 				/* reset timer for new 10-second interval */
1083 				MiscStartTimer( &timer, (10 * _SECOND));
1084 
1085 		    } else  {
1086 				/* Gray Image */
1087 				*ps->pCurrentColorRunTable &= 0xf0; /* leave high nibble for debug  */
1088 				ps->pCurrentColorRunTable++;		/* this step has been processed */
1089 				IOReadScannerImageData( ps, ps->DataInf.pCurrentBuffer,
1090 									        ps->DataInf.dwAsicBytesPerPlane );
1091 
1092 				result = _TRUE;
1093                 break;
1094 		    }
1095 		}
1096 
1097 /* HEINER:A3I */
1098 		if( ps->bMoveDataOutFlag != _DataFromStopState )
1099 	    	ps->UpdateDataCurrentReadLine( ps );
1100 
1101     } while (!MiscCheckTimer( &timer));
1102 
1103     if( _TRUE == result ) {
1104         (*ps->Scan.DataProcess)( ps, ps->Scan.bp.pMonoBuf,
1105                                  ps->DataInf.pCurrentBuffer,
1106                                  ps->DataInf.dwAppPhyBytesPerLine );
1107         return _TRUE;
1108     }
1109 
1110 	DBG( DBG_HIGH, "Timeout - Scanner malfunction !!\n" );
1111 	MotorToHomePosition(ps);
1112 
1113     return _FALSE;
1114 }
1115 
1116 /** prepare for scanning
1117  */
imageP96SetupScanSettings(pScanData ps,pScanInfo pInf)1118 static int imageP96SetupScanSettings( pScanData ps, pScanInfo pInf )
1119 {
1120 	DBG( DBG_LOW, "imageSetupP96ScanSettings()\n" );
1121 
1122 	ps->DataInf.dwVxdFlag = 0;
1123 	if (pInf->ImgDef.dwFlag & SCANDEF_BuildBwMap)
1124 		ps->DataInf.dwVxdFlag |= _VF_BUILDMAP;
1125 
1126     ps->DataInf.dwScanFlag = pInf->ImgDef.dwFlag;
1127 
1128     ps->DataInf.crImage = pInf->ImgDef.crArea;
1129 
1130 	/* scale according to DPI */
1131     ps->DataInf.crImage.x  *= ps->PhysicalDpi / _MEASURE_BASE;
1132     ps->DataInf.crImage.cx *= ps->PhysicalDpi / _MEASURE_BASE;
1133 
1134     if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
1135 		ps->DataInf.crImage.x += _Transparency48OriginOffsetX;
1136 		ps->DataInf.crImage.y += _Transparency48OriginOffsetY;
1137     }
1138 
1139     ps->DataInf.xyAppDpi     = pInf->ImgDef.xyDpi;
1140     ps->DataInf.wAppDataType = pInf->ImgDef.wDataType;
1141     ps->DataInf.wDither      = pInf->wDither;
1142 
1143     ps->GetImageInfo( ps, &pInf->ImgDef );
1144 
1145 	/* try to get brightness to work */
1146 	if (ps->DataInf.wPhyDataType != COLOR_BW) { /* if not line art 			*/
1147 		ps->wBrightness = pInf->siBrightness;   /* use internal tables for 	*/
1148 		ps->wContrast   = pInf->siContrast;		/* brightness and contrast	*/
1149 
1150 		pInf->siBrightness = 0;				/* don't use asic for threshold */
1151     }
1152     ps->DataInf.siBrightness = pInf->siBrightness;
1153 
1154     if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle)
1155 		ps->Scan.lBufferAdjust = -(Long)ps->DataInf.dwAppBytesPerLine;
1156     else
1157 		ps->Scan.lBufferAdjust = (Long)ps->DataInf.dwAppBytesPerLine;
1158 
1159     if (ps->DataInf.siBrightness < 0)
1160 		ps->DataInf.siBrightness = 255 - (_DEF_BW_THRESHOLD *
1161 							ps->DataInf.siBrightness / 127 + _DEF_BW_THRESHOLD);
1162     else
1163 		ps->DataInf.siBrightness = 255 - ((255 - _DEF_BW_THRESHOLD) *
1164 							 ps->DataInf.siBrightness / 127 + _DEF_BW_THRESHOLD);
1165 
1166     ps->AsicReg.RD_ThresholdControl = (Byte)ps->DataInf.siBrightness;
1167 
1168     ps->DataInf.pCurrentBuffer = ps->pScanBuffer1;
1169 
1170 	return _OK;
1171 }
1172 
1173 /**
1174  */
imageP98003DataIsReady(pScanData ps)1175 static Bool imageP98003DataIsReady( pScanData ps )
1176 {
1177 	pUChar pb;
1178 
1179     if( ps->Scan.bDiscardAll ) {
1180     	ps->Scan.bDiscardAll--;
1181 
1182     	if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
1183     	    ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
1184     	    IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf,
1185                                         ps->DataInf.dwAsicBytesPerPlane );
1186     	} else {
1187             IOReadColorData( ps, ps->Bufs.b1.pReadBuf,
1188                                  ps->DataInf.dwAsicBytesPerPlane );
1189         }
1190 	    return _FALSE;
1191     }
1192 
1193    	if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
1194 
1195     	ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
1196 		pb = ps->Scan.bp.pMonoBuf;
1197 
1198 		/* use a larger buffer during halftone reads...*/
1199 		if( ps->DataInf.wAppDataType == COLOR_HALFTONE )
1200 			pb = ps->Scan.BufPut.red.bp;
1201 
1202 	    IOReadScannerImageData( ps, pb, ps->DataInf.dwAsicBytesPerPlane );
1203 
1204     } else {
1205     	if( !ps->Scan.DataRead( ps )) {
1206     	    return _FALSE;
1207         }
1208     }
1209 
1210     if( ps->Scan.DoSample( ps )) {
1211 
1212     	if( ps->Scan.dwLinesToRead == 1 &&
1213            !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP))
1214 	        IORegisterToScanner( ps, ps->RegRefreshScanState );
1215 
1216 		/* direct is done here without copying...*/
1217     	if( fnDataDirect != ps->Scan.DataProcess ) {
1218 			(*ps->Scan.DataProcess)(ps, (pVoid)(ps->Scan.bp.pMonoBuf ),
1219                                         (pVoid)(ps->Scan.BufPut.red.bp),
1220                                         ps->DataInf.dwAppPhyBytesPerLine);
1221 		}
1222     	return _TRUE;
1223     }
1224 
1225     return _FALSE;
1226 }
1227 
1228 /**
1229  */
imageP98003ReadOneImageLine(pScanData ps)1230 static Bool imageP98003ReadOneImageLine( pScanData ps )
1231 {
1232     Byte     b, state;
1233 	TimerDef timer, t2;
1234 
1235 	MiscStartTimer( &timer, _LINE_TIMEOUT );
1236 	MiscStartTimer( &t2, _SECOND*2 );
1237     do {
1238 
1239         state = IOGetScanState( ps, _TRUE );
1240         ps->Scan.bNowScanState = (state & _SCANSTATE_MASK);
1241 
1242     	if( state & _SCANSTATE_STOP ) {
1243 
1244 	        MotorP98003ModuleForwardBackward( ps );
1245 
1246     	    if( IOReadFifoLength( ps ) >= ps->Scan.dwMinReadFifo )
1247 	        	if( imageP98003DataIsReady( ps ))
1248 		            return _TRUE;
1249     	} else {
1250 
1251     	    ps->Scan.bModuleState = _MotorInNormalState;
1252     	    b = ps->Scan.bNowScanState - ps->Scan.bOldScanState;
1253 
1254     	    if((char) b < 0)
1255         		b += _NUMBER_OF_SCANSTEPS;
1256 
1257     	    if( b >= ps->Scan.bRefresh ) {
1258         		IORegisterToScanner( ps, ps->RegRefreshScanState );
1259 
1260                 ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE );
1261                 ps->Scan.bOldScanState &= _SCANSTATE_MASK;
1262     	    }
1263 
1264 	        if( IOReadFifoLength( ps ) >= ps->Scan.dwMaxReadFifo ) {
1265             	if( imageP98003DataIsReady( ps ))
1266 	                return _TRUE;
1267     	    } else {
1268 
1269         	    b = ps->Scan.bNowScanState - ps->Scan.bOldScanState;
1270 
1271     	        if((char) b < 0)
1272         	    	b += _NUMBER_OF_SCANSTEPS;
1273 
1274         	    if( b >= ps->Scan.bRefresh ) {
1275             		IORegisterToScanner( ps, ps->RegRefreshScanState );
1276 
1277                     ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE );
1278                     ps->Scan.bOldScanState &= _SCANSTATE_MASK;
1279         	    }
1280 
1281         	    if( IOReadFifoLength( ps ) >= ps->Scan.dwMinReadFifo ) {
1282                 	if( imageP98003DataIsReady( ps ))
1283 	                    return _TRUE;
1284                 }
1285         	}
1286         }
1287 		_DODELAY(5);			     /* delay 5 ms */
1288 
1289     } while( !MiscCheckTimer( &timer ));
1290 
1291 #ifdef __KERNEL__
1292 	_PRINT(
1293 #else
1294 	DBG( DBG_HIGH,
1295 #endif
1296 	"Timeout - Scanner malfunction !!\n" );
1297 	MotorToHomePosition(ps);
1298 
1299 	/* timed out, scanner malfunction */
1300     return _FALSE;
1301 }
1302 
1303 /**
1304  */
imageP98003SetupScanStateVariables(pScanData ps,ULong index)1305 static void imageP98003SetupScanStateVariables( pScanData ps, ULong index )
1306 {
1307     DataType var;
1308 
1309     ps->Scan.dpiIdx = index;
1310 
1311     if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
1312 
1313         if(((ps->IO.portMode == _PORT_BIDI) ||
1314             (ps->IO.portMode == _PORT_SPP)) &&
1315             (ps->DataInf.wPhyDataType > COLOR_TRUE24) &&
1316                                              (ps->DataInf.xyAppDpi.y >= 600)) {
1317 
1318        		ps->Shade.wExposure = nmlScan[ps->IO.portMode][index].exposureTime;
1319 	        ps->Shade.wXStep    = nmlScan[ps->IO.portMode][index].xStepTime;
1320    	    } else {
1321 		    ps->Shade.wExposure = nmlScan[_PORT_EPP][index].exposureTime;
1322     		ps->Shade.wXStep    = nmlScan[_PORT_EPP][index].xStepTime;
1323 	    }
1324 
1325 	    if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) {
1326     	    ps->Shade.wExposure >>= 1;
1327 	        ps->Shade.wXStep    >>= 1;
1328     	}
1329     } else {
1330     	if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) {
1331     	    ps->Shade.wExposure = posScan[index].exposureTime;
1332 	        ps->Shade.wXStep    = posScan[index].xStepTime;
1333     	} else {
1334     	    ps->Shade.wExposure = ps->Scan.negScan[index].exposureTime;
1335 	        ps->Shade.wXStep    = ps->Scan.negScan[index].xStepTime;
1336     	}
1337     }
1338 
1339     ps->Scan.dwInterlace = 0;
1340     ps->Scan.dwInterval  = 1;
1341 
1342     if( ps->DataInf.wPhyDataType == COLOR_BW )
1343 	    var.dwValue = xferSpeed[ps->IO.portMode].thresholdBW;
1344 	else {
1345         if( ps->DataInf.wPhyDataType == COLOR_256GRAY )
1346     		var.dwValue = xferSpeed[ps->IO.portMode].thresholdGray;
1347 	    else
1348 		    var.dwValue = xferSpeed[ps->IO.portMode].thresholdColor;
1349     }
1350 
1351     /* for small size/descreen */
1352     if((ps->DataInf.xyAppDpi.y >= 300) && var.dwValue &&
1353        (ps->DataInf.dwAsicBytesPerPlane <= var.dwValue)) {
1354     	ps->Scan.dwInterval <<= 1;
1355     }
1356 
1357     if( var.dwValue && ps->DataInf.dwAsicBytesPerPlane > var.dwValue ) {
1358     	if((var.dwValue << 1) > ps->DataInf.dwAsicBytesPerPlane)
1359 	        ps->Scan.dwInterval <<= 1;
1360     	else
1361         	if((var.dwValue << 2) > ps->DataInf.dwAsicBytesPerPlane)
1362 		        ps->Scan.dwInterval <<= 2;
1363     	    else
1364 	        	ps->Scan.dwInterval <<= 3;
1365     }
1366 
1367     /* 48 bit/600 dpi/Bpp mode will scan failed */
1368     if(((ps->IO.portMode == _PORT_BIDI) ||
1369         (ps->IO.portMode == _PORT_SPP)) &&
1370         (ps->DataInf.wPhyDataType > COLOR_TRUE24) &&
1371                                              (ps->DataInf.xyAppDpi.y >= 600)) {
1372     	ps->Scan.dwInterval <<= 1;
1373     }
1374 
1375     if( ps->DataInf.wPhyDataType >= COLOR_TRUE24 ) {
1376 
1377     	if( ps->DataInf.xyPhyDpi.y > 75U ) {
1378     	    if( ps->Device.f0_8_16 ) {
1379 	        	ps->Scan.gd_gk.wGreenDiscard = ps->DataInf.xyPhyDpi.y / 75U;
1380     	    } else {
1381 	        	ps->Scan.gd_gk.wGreenDiscard = ps->DataInf.xyPhyDpi.y / 150U;
1382 	        }
1383     	} else {
1384            	ps->Scan.gd_gk.wGreenDiscard = 1;
1385 		}
1386 
1387        	ps->Scan.bd_rk.wBlueDiscard = ps->Scan.gd_gk.wGreenDiscard << 1;
1388     } else {
1389        	ps->Scan.bd_rk.wBlueDiscard = ps->Scan.gd_gk.wGreenDiscard = 0;
1390     }
1391 }
1392 
1393 /** PrepareScanningVariables() !!!
1394  */
imageP98003SetupScanSettings(pScanData ps,pScanInfo pInf)1395 static int imageP98003SetupScanSettings( pScanData ps, pScanInfo pInf )
1396 {
1397 	DBG( DBG_LOW, "imageP98003SetupScanSettings()\n" );
1398 
1399     /* call the one for ASIC 98001 first */
1400     imageP98SetupScanSettings( ps, pInf );
1401 
1402     if( !(ps->DataInf.dwScanFlag & SCANDEF_TPA )) {
1403 
1404         ps->Scan.dwScanOrigin = ps->Device.lUpNormal * 4 + _RFT_SCANNING_ORG;
1405 
1406     } else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency) {
1407 
1408 	    ps->Scan.dwScanOrigin = ps->Device.lUpPositive * 4 +
1409             							   _POS_SCANNING_ORG;
1410 	} else {
1411 	    ps->Scan.dwScanOrigin = ps->Device.lUpNegative * 4 +
1412             							   _NEG_SCANNING_ORG;
1413     }
1414     ps->Scan.dwScanOrigin += ps->Device.dwModelOriginY;
1415 
1416     /* ------- Setup CCD Offset variables ------- */
1417     if( ps->DataInf.xyAppDpi.y <= 75 ) {
1418 
1419     	if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) {
1420 
1421             ps->Scan.bDiscardAll   = 0;
1422     	    ps->DataInf.xyPhyDpi.y = 150;
1423             ps->Shade.bIntermediate |= _ScanMode_AverageOut;
1424     	    imageP98003SetupScanStateVariables( ps, 1 );
1425 	        ps->Scan.gd_gk.wGreenDiscard = 0;
1426 
1427 	        if( ps->DataInf.xyAppDpi.y >= 38 )
1428         		ps->Scan.bd_rk.wBlueDiscard = 1;
1429 	        else
1430         		ps->Scan.bd_rk.wBlueDiscard = 0;
1431 
1432 	        if( ps->DataInf.wPhyDataType >= COLOR_256GRAY ) {
1433         		ps->Shade.wXStep    = 6;
1434 		        ps->Shade.wExposure = 8 * ps->Shade.wXStep;
1435     	    }
1436 	    } else {
1437     	    if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA) &&
1438                 (ps->DataInf.xyAppDpi.y <= 50) &&
1439 				(ps->DataInf.wPhyDataType >= COLOR_TRUE24)) {
1440         		ps->Shade.bIntermediate |= _ScanMode_AverageOut;
1441             }
1442 
1443     	    if((ps->DataInf.wPhyDataType<COLOR_TRUE24) || ps->Device.f0_8_16 ||
1444            			         (ps->Shade.bIntermediate & _ScanMode_AverageOut)) {
1445 
1446         		ps->Scan.bDiscardAll   = 1;
1447         		ps->DataInf.xyPhyDpi.y = 75;
1448 		        imageP98003SetupScanStateVariables( ps, 0 );
1449     	    } else {
1450         		ps->Scan.bDiscardAll   = 2;
1451         		ps->DataInf.xyPhyDpi.y = 150;
1452 		        imageP98003SetupScanStateVariables( ps, 1 );
1453     	    }
1454     	}
1455     } else {
1456     	if( ps->DataInf.xyAppDpi.y <= 150 ) {
1457 
1458     	    ps->Scan.bDiscardAll   = 2;
1459 	        ps->DataInf.xyPhyDpi.y = 150;
1460 	        imageP98003SetupScanStateVariables( ps, 1 );
1461 
1462     	} else if( ps->DataInf.xyAppDpi.y <= 300 ) {
1463 
1464     	    ps->Scan.bDiscardAll   = 4;
1465 	        ps->DataInf.xyPhyDpi.y = 300;
1466 	        imageP98003SetupScanStateVariables( ps, 2 );
1467 
1468 	    } else if( ps->DataInf.xyAppDpi.y <= 600 ) {
1469 
1470     	    ps->Scan.bDiscardAll   = 8;
1471 	        ps->DataInf.xyPhyDpi.y = 600;
1472             imageP98003SetupScanStateVariables( ps, 3 );
1473 
1474 		} else {
1475 
1476     	    ps->Scan.bDiscardAll   = 16;
1477 	        ps->DataInf.xyPhyDpi.y = 1200;
1478 	        imageP98003SetupScanStateVariables( ps, 4 );
1479 		}
1480     }
1481 
1482     /* ------- Lines have to sample or not? ------- */
1483     if( ps->DataInf.xyAppDpi.y == ps->DataInf.xyPhyDpi.y ) {
1484 		DBG( DBG_LOW, "Sample every line\n" );
1485     	ps->Scan.DoSample = fnEveryLines;
1486     } else {
1487     	if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) {
1488 
1489 			DBG( DBG_LOW, "Sample preview\n" );
1490             ps->Scan.DoSample = fnSamplePreview;
1491 	        ps->DataInf.wYSum = 150;
1492 
1493 	        if( ps->DataInf.xyAppDpi.y >= 38 )
1494         		wPreviewScanned = ps->DataInf.xyAppDpi.y * 2;
1495     	    else if( ps->DataInf.xyAppDpi.y >= 19 )
1496 		            wPreviewScanned = ps->DataInf.xyAppDpi.y * 4;
1497         		else
1498             		wPreviewScanned = ps->DataInf.xyAppDpi.y * 8;
1499     	} else {
1500 
1501 			DBG( DBG_LOW, "Sample lines (%u - %u)...\n",
1502 						  ps->DataInf.xyPhyDpi.y, ps->DataInf.xyAppDpi.y );
1503             ps->Scan.DoSample = fnSampleLines;
1504 	        ps->DataInf.wYSum = ps->DataInf.xyPhyDpi.y - ps->DataInf.xyAppDpi.y;
1505     	}
1506     }
1507 
1508     /*
1509      * now assign the buffer pointers for image acquisition
1510      */
1511 	ps->Scan.p48BitBuf.pb = NULL;
1512 
1513     if( ps->DataInf.wPhyDataType >= COLOR_TRUE24 ) {
1514 
1515         ULong r,g,b;
1516 
1517         r = (ULong)_SIZE_REDFIFO /
1518 			ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep;
1519         g = (ULong)_SIZE_GREENFIFO /
1520 			ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep;
1521 
1522     	if((int)r < 16 || (int)g < 16) {
1523 
1524     	    b = (ULong)(ps->Scan.bd_rk.wRedKeep +
1525 						ps->Scan.gd_gk.wGreenKeep + 2U) *
1526 			            ps->DataInf.dwAsicBytesPerPlane;
1527 
1528 			DBG( DBG_LOW, "48Bit buffer request: len=%u bytes, available=%u\n",
1529 						  b, ps->TotalBufferRequire );
1530 
1531 			if( b > ps->TotalBufferRequire )
1532 				return _E_NORESOURCE;
1533 
1534 			ps->Scan.p48BitBuf.pb = ps->Bufs.b1.pReadBuf;
1535 		}
1536     }
1537 
1538     if( ps->Scan.p48BitBuf.pb ){
1539     	ps->Scan.DataRead          = fnReadToDriver;
1540 	    ps->Scan.BufGet.red.bp     =
1541     	ps->Scan.BufPut.red.bp     =
1542 	    ps->Scan.BufBegin.red.bp   = ps->Scan.p48BitBuf.pb;
1543     	ps->Scan.BufEnd.red.bp     =
1544 	    ps->Scan.BufBegin.green.bp =
1545     	ps->Scan.BufGet.green.bp   =
1546 	    ps->Scan.BufPut.green.bp   = ps->Scan.p48BitBuf.pb +
1547 	                			     ps->DataInf.dwAsicBytesPerLine *
1548                                      (ps->Scan.bd_rk.wRedKeep + 1U);
1549 
1550     	ps->Scan.BufEnd.green.bp = ps->Scan.BufBegin.green.bp +
1551 	                			   ps->DataInf.dwAsicBytesPerLine *
1552                 				   (ps->Scan.gd_gk.wGreenKeep + 1U);
1553         ps->Scan.BufPut.blue.bp =
1554     	ps->Scan.BufGet.blue.bp = ps->Bufs.b1.pReadBuf +
1555                                   ps->DataInf.dwAsicBytesPerLine * 2;
1556     } else {
1557     	ps->Scan.DataRead         = fnReadOutScanner;
1558     	ps->Scan.BufPut.red.bp    = ps->Bufs.b1.pReadBuf;
1559     	ps->Scan.BufData.green.bp =
1560 	    ps->Scan.BufPut.green.bp  = ps->Scan.BufPut.red.bp +
1561                 			        ps->DataInf.dwAsicBytesPerLine;
1562     	ps->Scan.BufPut.blue.bp   = ps->Scan.BufPut.green.bp +
1563                 			        ps->DataInf.dwAsicBytesPerLine;
1564 
1565         if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) {
1566     	    ps->Scan.BufData.red.bp  = ps->Scan.BufPut.blue.bp;
1567 	        ps->Scan.BufData.blue.bp = ps->Scan.BufPut.red.bp;
1568     	} else {
1569     	    ps->Scan.BufData.red.bp  = ps->Scan.BufPut.red.bp;
1570 	        ps->Scan.BufData.blue.bp = ps->Scan.BufPut.blue.bp;
1571     	}
1572     }
1573 
1574 /* CHECK: maybe remove this stuff */
1575 	if( ps->DataInf.dwScanFlag & SCANDEF_Transparency) {
1576 	    posScan[1].exposureTime = 96;
1577 	    posScan[1].xStepTime    = 12;
1578 	    posScan[2].exposureTime = 96;
1579 	    posScan[2].xStepTime    = 24;
1580 	    posScan[3].exposureTime = 96;
1581 	    posScan[3].xStepTime    = 48;
1582 	    posScan[4].exposureTime = 96;
1583 	    posScan[4].xStepTime    = 96;
1584 
1585 	    /* Reset shading Exposure Time & xStep Time */
1586 	    ps->Shade.wExposure = posScan[ps->Scan.dpiIdx].exposureTime;
1587 	    ps->Shade.wXStep    = posScan[ps->Scan.dpiIdx].xStepTime;
1588 	}
1589 	else if( ps->DataInf.dwScanFlag & SCANDEF_Negative) {
1590         ps->Scan.negScan[1].exposureTime = 96;
1591         ps->Scan.negScan[1].xStepTime    = 12;
1592         ps->Scan.negScan[2].exposureTime = 96;
1593         ps->Scan.negScan[2].xStepTime    = 24;
1594         ps->Scan.negScan[3].exposureTime = 96;
1595         ps->Scan.negScan[3].xStepTime    = 48;
1596         ps->Scan.negScan[4].exposureTime = 96;
1597         ps->Scan.negScan[4].xStepTime    = 96;
1598 
1599 	    /* Reset shading Exposure Time & xStep Time */
1600     	ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime;
1601 		ps->Shade.wXStep    = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime;
1602     }
1603 
1604 	return _OK;
1605 }
1606 
1607 /************************ exported functions *********************************/
1608 
1609 /**
1610  */
ImageInitialize(pScanData ps)1611 _LOC int ImageInitialize( pScanData ps )
1612 {
1613 	DBG( DBG_HIGH, "ImageInitialize()\n" );
1614 
1615 	if( NULL == ps )
1616 		return _E_NULLPTR;
1617 
1618     ps->Scan.dpiIdx  = 0;
1619     ps->Scan.negScan = negScan;
1620 
1621 	/*
1622 	 * depending on the asic, we set some functions
1623 	 */
1624 	if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
1625 
1626 		ps->GetImageInfo 	  = imageP98GetInfo;
1627 		ps->SetupScanSettings = imageP98SetupScanSettings;
1628 		ps->ReadOneImageLine  = imageP98001ReadOneImageLine;
1629 
1630     } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
1631 
1632 		ps->GetImageInfo 	  = imageP98GetInfo;
1633 		ps->SetupScanSettings = imageP98003SetupScanSettings;
1634 		ps->ReadOneImageLine  = imageP98003ReadOneImageLine;
1635 
1636 	} else if( _IS_ASIC96(ps->sCaps.AsicID)) {
1637 
1638 		ps->GetImageInfo 	  = imageP96GetInfo;
1639 		ps->SetupScanSettings = imageP96SetupScanSettings;
1640 		ps->ReadOneImageLine  = imageP96ReadOneImageLine;
1641 
1642 	} else {
1643 
1644 		DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
1645 		return _E_NOSUPP;
1646 	}
1647 	return _OK;
1648 }
1649 
1650 /* END PLUSTEK-PP_IMAGE.C ...................................................*/
1651