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