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