1 /*.............................................................................
2 * Project : SANE library for Plustek flatbed scanners.
3 *.............................................................................
4 */
5
6 /** @file plustek-usbimg.c
7 * @brief Image processing functions for copying and scaling image lines.
8 *
9 * Based on sources acquired from Plustek Inc.<br>
10 * Copyright (C) 2001-2007 Gerhard Jaeger <gerhard@gjaeger.de>
11 *
12 * History:
13 * - 0.40 - starting version of the USB support
14 * - 0.41 - fixed the 14bit problem for LM9831 devices
15 * - 0.42 - no changes
16 * - 0.43 - no changes
17 * - 0.44 - added CIS parts and dumpPic function
18 * - 0.45 - added gray scaling functions for CIS devices
19 * - fixed usb_GrayScale16 function
20 * - fixed a bug in usb_ColorScale16_2 function
21 * - fixed endless loop bug
22 * - fixed a bug in usb_GrayScalePseudo16 function
23 * - fixed a bug in usb_GrayDuplicatePseudo16 function
24 * - removed the scaler stuff for CIS devices
25 * - 0.46 - minor fixes
26 * - 0.47 - added big-endian/little endian stuff
27 * - 0.48 - fixed usb_ColorDuplicateGray16() and
28 * usb_ColorScaleGray16()
29 * - added usb_BWScaleFromColor() and usb_BWDuplicateFromColor()
30 * - cleanup
31 * - 0.49 - a_bRegs is now part of the device structure
32 * - 0.50 - cleanup
33 * - 0.51 - added usb_ColorDuplicateGray16_2(), usb_ColorScaleGray16_2()
34 * usb_BWScaleFromColor_2() and usb_BWDuplicateFromColor_2()
35 * - 0.52 - cleanup
36 * .
37 * <hr>
38 * This file is part of the SANE package.
39 *
40 * This program is free software; you can redistribute it and/or
41 * modify it under the terms of the GNU General Public License as
42 * published by the Free Software Foundation; either version 2 of the
43 * License, or (at your option) any later version.
44 *
45 * This program is distributed in the hope that it will be useful, but
46 * WITHOUT ANY WARRANTY; without even the implied warranty of
47 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48 * General Public License for more details.
49 *
50 * You should have received a copy of the GNU General Public License
51 * along with this program. If not, see <https://www.gnu.org/licenses/>.
52 *
53 * As a special exception, the authors of SANE give permission for
54 * additional uses of the libraries contained in this release of SANE.
55 *
56 * The exception is that, if you link a SANE library with other files
57 * to produce an executable, this does not by itself cause the
58 * resulting executable to be covered by the GNU General Public
59 * License. Your use of that executable is in no way restricted on
60 * account of linking the SANE library code into it.
61 *
62 * This exception does not, however, invalidate any other reasons why
63 * the executable file might be covered by the GNU General Public
64 * License.
65 *
66 * If you submit changes to SANE to the maintainers to be included in
67 * a subsequent release, you agree by submitting the changes that
68 * those changes may be distributed with this exception intact.
69 *
70 * If you write modifications of your own for SANE, it is your choice
71 * whether to permit this exception to apply to your modifications.
72 * If you do not wish that, delete this exception notice.
73 * <hr>
74 */
75
76 #define _SCALER 1000
77
78 static u_char bShift, Shift;
79 static u_short wSum, Mask;
80
81 /*
82 */
83 static u_char BitTable[8] = {
84 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
85 };
86
87 static u_char BitsReverseTable[256] = {
88 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
89 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
90 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
91 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
92 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
93 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
94 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
95 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
96 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
97 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
98 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
99 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
100 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
101 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
102 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
103 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
104 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
105 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
106 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
107 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
108 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
109 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
110 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
111 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
112 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
113 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
114 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
115 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
116 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
117 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
118 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
119 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
120 };
121
122 /************************ some helper functions ******************************/
123
ReverseBits(int b,u_char ** pTar,int * iByte,int * iWeightSum,int iSrcWeight,int iTarWeight,int cMax)124 static void ReverseBits( int b, u_char **pTar, int *iByte, int *iWeightSum,
125 int iSrcWeight, int iTarWeight, int cMax )
126 {
127 int bit;
128
129 cMax = (1 << cMax);
130 if(iSrcWeight == iTarWeight) {
131 for( bit = 1; bit < cMax; bit <<= 1) {
132 *iByte <<= 1;
133 if(b & bit)
134 *iByte |= 1;
135 if(*iByte >= 0x100) {
136 **pTar++ = (u_char)*iByte;
137 *iByte = 1;
138 }
139 }
140 } else {
141 for( bit = 1; bit < cMax; bit <<= 1 ) {
142
143 *iWeightSum += iTarWeight;
144 while(*iWeightSum >= iSrcWeight)
145 {
146 *iWeightSum -= iSrcWeight;
147 *iByte <<= 1;
148 if(b & bit)
149 *iByte |= 1;
150 if(*iByte >= 0x100)
151 {
152 **pTar++ = (u_char)*iByte;
153 *iByte = 1;
154 }
155 }
156 }
157 }
158 }
159
usb_ReverseBitStream(u_char * pSrc,u_char * pTar,int iPixels,int iBufSize,int iSrcWeight,int iTarWeight,int iPadBit)160 static void usb_ReverseBitStream( u_char *pSrc, u_char *pTar, int iPixels,
161 int iBufSize, int iSrcWeight/* = 0*/,
162 int iTarWeight/* = 0*/, int iPadBit/* = 1*/)
163 {
164 int i;
165 int iByte = 1;
166 int cBytes = iPixels / 8;
167 int cBits = iPixels % 8;
168 u_char bPad = iPadBit? 0xff: 0;
169 u_char *pTarget = pTar;
170 int iWeightSum = 0;
171
172 if(iSrcWeight == iTarWeight) {
173 if(cBits)
174 {
175 int cShift = 8 - cBits;
176 for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--, pTar++)
177 *pTar = BitsReverseTable[(u_char)((*pSrc << cBits) | (*(pSrc+1) >> cShift))];
178 ReverseBits(*(pSrc+1) >> cShift, &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, cBits);
179 }
180 else /* byte boundary */
181 {
182 for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--, pTar++)
183 *pTar = BitsReverseTable[*pSrc];
184 }
185 }
186 else /* To shrink or enlarge */
187 {
188 if(cBits) {
189 int cShift = 8 - cBits;
190 for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--)
191 ReverseBits((*pSrc << cBits) | (*(pSrc+1) >> cShift), &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, 8);
192 ReverseBits(*(pSrc+1) >> cShift, &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, cBits);
193 }
194 else /* byte boundary */
195 {
196 for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--)
197 ReverseBits(*pSrc, &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, 8);
198 }
199 }
200
201 if(iByte != 1) {
202 while(iByte < 0x100)
203 {
204 iByte <<= 1;
205 iByte |= iPadBit;
206 }
207 *pTar++ = (u_char)iByte;
208 }
209
210 cBytes = (int)(pTar - pTarget);
211
212 for(i = iBufSize - cBytes; i > 0; i--, pTar++)
213 *pTar = bPad;
214 }
215
216 /**
217 */
usb_AverageColorByte(Plustek_Device * dev)218 static void usb_AverageColorByte( Plustek_Device *dev )
219 {
220 u_long dw;
221 ScanDef *scan = &dev->scanning;
222
223 if((scan->sParam.bSource == SOURCE_Negative ||
224 scan->sParam.bSource == SOURCE_Transparency) &&
225 scan->sParam.PhyDpi.x > 800) {
226
227 for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++)
228 {
229 scan->Red.pcb[dw].a_bColor[0] =
230 (u_char)(((u_short)scan->Red.pcb[dw].a_bColor[0] +
231 (u_short)scan->Red.pcb[dw + 1].a_bColor[0]) / 2);
232
233 scan->Green.pcb[dw].a_bColor[0] =
234 (u_char)(((u_short)scan->Green.pcb[dw].a_bColor[0] +
235 (u_short)scan->Green.pcb[dw + 1].a_bColor[0]) / 2);
236
237 scan->Blue.pcb[dw].a_bColor[0] =
238 (u_char)(((u_short)scan->Blue.pcb[dw].a_bColor[0] +
239 (u_short)scan->Blue.pcb[dw + 1].a_bColor[0]) / 2);
240 }
241 }
242 }
243
244 /**
245 */
usb_AverageColorWord(Plustek_Device * dev)246 static void usb_AverageColorWord( Plustek_Device *dev )
247 {
248 u_char ls = 2;
249 u_long dw;
250 ScanDef *scan = &dev->scanning;
251
252 if((scan->sParam.bSource == SOURCE_Negative ||
253 scan->sParam.bSource == SOURCE_Transparency) &&
254 scan->sParam.PhyDpi.x > 800) {
255
256 scan->Red.pcw[0].Colors[0] = _HILO2WORD(scan->Red.pcw[0].HiLo[0]) >> ls;
257 scan->Green.pcw[0].Colors[0] = _HILO2WORD(scan->Green.pcw[0].HiLo[0]) >> ls;
258 scan->Blue.pcw[0].Colors[0] = _HILO2WORD(scan->Blue.pcw[0].HiLo[0]) >> ls;
259
260 for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++)
261 {
262 scan->Red.pcw[dw + 1].Colors[0] = _HILO2WORD(scan->Red.pcw[dw + 1].HiLo[0]) >> ls;
263 scan->Green.pcw[dw + 1].Colors[0] = _HILO2WORD(scan->Green.pcw[dw + 1].HiLo[0]) >> ls;
264 scan->Blue.pcw[dw + 1].Colors[0] = _HILO2WORD(scan->Blue.pcw[dw + 1].HiLo[0]) >> ls;
265
266 scan->Red.pcw[dw].Colors[0] = (u_short)(((u_long)scan->Red.pcw[dw].Colors[0] +
267 (u_long)scan->Red.pcw[dw + 1].Colors[0]) / 2);
268 scan->Green.pcw[dw].Colors[0] = (u_short)(((u_long)scan->Green.pcw[dw].Colors[0] +
269 (u_long)scan->Green.pcw[dw + 1].Colors[0]) / 2);
270 scan->Blue.pcw[dw].Colors[0] = (u_short)(((u_long)scan->Blue.pcw[dw].Colors[0] +
271 (u_long)scan->Blue.pcw[dw + 1].Colors[0]) / 2);
272
273 scan->Red.pcw[dw].Colors[0] = _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) << ls;
274 scan->Green.pcw[dw].Colors[0] = _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) << ls;
275 scan->Blue.pcw[dw].Colors[0] = _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) << ls;
276 }
277
278 scan->Red.pcw[dw].Colors[0] = _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) << ls;
279 scan->Green.pcw[dw].Colors[0] = _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) << ls;
280 scan->Blue.pcw[dw].Colors[0] = _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) << ls;
281 }
282 }
283
284 /**
285 */
usb_AverageGrayByte(Plustek_Device * dev)286 static void usb_AverageGrayByte( Plustek_Device *dev )
287 {
288 u_long dw;
289 ScanDef *scan = &dev->scanning;
290
291 if((scan->sParam.bSource == SOURCE_Negative ||
292 scan->sParam.bSource == SOURCE_Transparency) &&
293 scan->sParam.PhyDpi.x > 800)
294 {
295 for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++)
296 scan->Green.pb[dw] = (u_char)(((u_short)scan->Green.pb[dw]+
297 (u_short)scan->Green.pb[dw+1]) / 2);
298 }
299 }
300
301 /**
302 */
usb_AverageGrayWord(Plustek_Device * dev)303 static void usb_AverageGrayWord( Plustek_Device *dev )
304 {
305 u_long dw;
306 ScanDef *scan = &dev->scanning;
307
308 if((scan->sParam.bSource == SOURCE_Negative ||
309 scan->sParam.bSource == SOURCE_Transparency) &&
310 scan->sParam.PhyDpi.x > 800)
311 {
312 scan->Green.pw[0] = _HILO2WORD(scan->Green.philo[0]) >> 2;
313
314 for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++)
315 {
316 scan->Green.pw[dw + 1] = _HILO2WORD(scan->Green.philo[dw+1]) >> 2;
317 scan->Green.pw[dw] = (u_short)(((u_long)scan->Green.pw[dw]+
318 (u_long)scan->Green.pw[dw+1]) / 2);
319 scan->Green.pw[dw] = _HILO2WORD(scan->Green.philo[dw]) << 2;
320 }
321
322 scan->Green.pw[dw] = _HILO2WORD(scan->Green.philo[dw]) << 2;
323 }
324 }
325
326 /**
327 * returns the zoom value, used for our scaling algorithm (DDA algo
328 * digital differential analyzer).
329 */
usb_GetScaler(ScanDef * scan)330 static int usb_GetScaler( ScanDef *scan )
331 {
332 double ratio;
333
334 ratio = (double)scan->sParam.UserDpi.x/
335 (double)scan->sParam.PhyDpi.x;
336
337 return (int)(1.0/ratio * _SCALER);
338 }
339
340 /******************************* the copy functions **************************/
341
342 /** do a simple memcopy from scan-buffer to user buffer
343 */
usb_ColorDuplicate8(Plustek_Device * dev)344 static void usb_ColorDuplicate8( Plustek_Device *dev )
345 {
346 int next;
347 u_long dw, pixels;
348 ScanDef *scan = &dev->scanning;
349
350 usb_AverageColorByte( dev );
351
352 if( scan->sParam.bSource == SOURCE_ADF ) {
353 next = -1;
354 pixels = scan->sParam.Size.dwPixels - 1;
355 } else {
356 next = 1;
357 pixels = 0;
358 }
359
360 for( dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next ) {
361
362 scan->UserBuf.pb_rgb[pixels].Red = scan->Red.pcb[dw].a_bColor[0];
363 scan->UserBuf.pb_rgb[pixels].Green = scan->Green.pcb[dw].a_bColor[0];
364 scan->UserBuf.pb_rgb[pixels].Blue = scan->Blue.pcb[dw].a_bColor[0];
365 }
366 }
367
368 /** reorder from rgb line to rgb pixel (CIS scanner)
369 */
usb_ColorDuplicate8_2(Plustek_Device * dev)370 static void usb_ColorDuplicate8_2( Plustek_Device *dev )
371 {
372 int next;
373 u_long dw, pixels;
374 ScanDef *scan = &dev->scanning;
375
376 if( scan->sParam.bSource == SOURCE_ADF ) {
377 next = -1;
378 pixels = scan->sParam.Size.dwPixels - 1;
379 } else {
380 next = 1;
381 pixels = 0;
382 }
383
384 for( dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next ) {
385
386 scan->UserBuf.pb_rgb[pixels].Red = (u_char)scan->Red.pb[dw];
387 scan->UserBuf.pb_rgb[pixels].Green = (u_char)scan->Green.pb[dw];
388 scan->UserBuf.pb_rgb[pixels].Blue = (u_char)scan->Blue.pb[dw];
389 }
390 }
391
392 /**
393 */
usb_ColorDuplicate16(Plustek_Device * dev)394 static void usb_ColorDuplicate16( Plustek_Device *dev )
395 {
396 int next;
397 u_char ls;
398 u_long dw, pixels;
399 ScanDef *scan = &dev->scanning;
400 SANE_Bool swap = usb_HostSwap();
401
402 usb_AverageColorWord( dev );
403
404 if( scan->sParam.bSource == SOURCE_ADF ) {
405 next = -1;
406 pixels = scan->sParam.Size.dwPixels - 1;
407 } else {
408 next = 1;
409 pixels = 0;
410 }
411
412 if( scan->dwFlag & SCANFLAG_RightAlign )
413 ls = Shift;
414 else
415 ls = 0;
416
417 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
418
419 if( swap ) {
420 scan->UserBuf.pw_rgb[pixels].Red =
421 _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) >> ls;
422 scan->UserBuf.pw_rgb[pixels].Green =
423 _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) >> ls;
424 scan->UserBuf.pw_rgb[pixels].Blue =
425 _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) >> ls;
426 } else {
427 scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[dw] >> ls;
428 scan->UserBuf.pw_rgb[pixels].Green= scan->Green.pw[dw] >> ls;
429 scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[dw] >> ls;
430 }
431 }
432 }
433
434 /**
435 */
usb_ColorDuplicate16_2(Plustek_Device * dev)436 static void usb_ColorDuplicate16_2( Plustek_Device *dev )
437 {
438 int next;
439 u_char ls;
440 HiLoDef tmp;
441 u_long dw, pixels;
442 ScanDef *scan = &dev->scanning;
443 SANE_Bool swap = usb_HostSwap();
444
445 usb_AverageColorWord( dev );
446
447 if( scan->sParam.bSource == SOURCE_ADF ) {
448 next = -1;
449 pixels = scan->sParam.Size.dwPixels - 1;
450 } else {
451 next = 1;
452 pixels = 0;
453 }
454
455 if( scan->dwFlag & SCANFLAG_RightAlign )
456 ls = Shift;
457 else
458 ls = 0;
459
460 for( dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
461
462 if( swap ) {
463 tmp = *((HiLoDef*)&scan->Red.pw[dw]);
464 scan->UserBuf.pw_rgb[pixels].Red = _HILO2WORD(tmp) >> ls;
465
466 tmp = *((HiLoDef*)&scan->Green.pw[dw]);
467 scan->UserBuf.pw_rgb[pixels].Green = _HILO2WORD(tmp) >> ls;
468
469 tmp = *((HiLoDef*)&scan->Blue.pw[dw]);
470 scan->UserBuf.pw_rgb[pixels].Blue = _HILO2WORD(tmp) >> ls;
471
472 } else {
473
474 scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[dw] >> ls;
475 scan->UserBuf.pw_rgb[pixels].Green = scan->Green.pw[dw] >> ls;
476 scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[dw] >> ls;
477 }
478 }
479 }
480
481 /**
482 */
usb_ColorDuplicatePseudo16(Plustek_Device * dev)483 static void usb_ColorDuplicatePseudo16( Plustek_Device *dev )
484 {
485 int next;
486 u_short wR, wG, wB;
487 u_long dw, pixels;
488 ScanDef *scan = &dev->scanning;
489
490 usb_AverageColorByte( dev );
491
492 if (scan->sParam.bSource == SOURCE_ADF) {
493 next = -1;
494 pixels = scan->sParam.Size.dwPixels - 1;
495 } else {
496 next = 1;
497 pixels = 0;
498 }
499
500 wR = (u_short)scan->Red.pcb[0].a_bColor[0];
501 wG = (u_short)scan->Green.pcb[0].a_bColor[0];
502 wB = (u_short)scan->Blue.pcb[0].a_bColor[0];
503
504 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
505
506 scan->UserBuf.pw_rgb[pixels].Red =
507 (wR + scan->Red.pcb[dw].a_bColor[0]) << bShift;
508 scan->UserBuf.pw_rgb[pixels].Green =
509 (wG + scan->Green.pcb[dw].a_bColor[0]) << bShift;
510 scan->UserBuf.pw_rgb[pixels].Blue =
511 (wB + scan->Blue.pcb[dw].a_bColor[0]) << bShift;
512
513 wR = (u_short)scan->Red.pcb[dw].a_bColor[0];
514 wG = (u_short)scan->Green.pcb[dw].a_bColor[0];
515 wB = (u_short)scan->Blue.pcb[dw].a_bColor[0];
516 }
517 }
518
519 /**
520 */
usb_ColorDuplicateGray(Plustek_Device * dev)521 static void usb_ColorDuplicateGray( Plustek_Device *dev )
522 {
523 int next;
524 u_long dw, pixels;
525 ScanDef *scan = &dev->scanning;
526
527 usb_AverageColorByte( dev );
528
529 if (scan->sParam.bSource == SOURCE_ADF) {
530 next = -1;
531 pixels = scan->sParam.Size.dwPixels - 1;
532 } else {
533 next = 1;
534 pixels = 0;
535 }
536
537 switch(scan->fGrayFromColor) {
538
539 case 1:
540 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
541 scan->UserBuf.pb[pixels] = scan->Red.pcb[dw].a_bColor[0];
542 break;
543 case 2:
544 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
545 scan->UserBuf.pb[pixels] = scan->Green.pcb[dw].a_bColor[0];
546 break;
547 case 3:
548 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
549 scan->UserBuf.pb[pixels] = scan->Blue.pcb[dw].a_bColor[0];
550 break;
551 }
552 }
553
554 /**
555 */
usb_ColorDuplicateGray_2(Plustek_Device * dev)556 static void usb_ColorDuplicateGray_2( Plustek_Device *dev )
557 {
558 int next;
559 u_long dw, pixels;
560 ScanDef *scan = &dev->scanning;
561
562 usb_AverageColorByte( dev );
563
564 if (scan->sParam.bSource == SOURCE_ADF) {
565 next = -1;
566 pixels = scan->sParam.Size.dwPixels - 1;
567 } else {
568 next = 1;
569 pixels = 0;
570 }
571
572 switch(scan->fGrayFromColor)
573 {
574 case 1:
575 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
576 scan->UserBuf.pb[pixels] = scan->Red.pb[dw];
577 break;
578 case 3:
579 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
580 scan->UserBuf.pb[pixels] = scan->Blue.pb[dw];
581 break;
582 default:
583 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
584 scan->UserBuf.pb[pixels] = scan->Green.pb[dw];
585 break;
586 }
587 }
588
589 /**
590 */
usb_ColorDuplicateGray16(Plustek_Device * dev)591 static void usb_ColorDuplicateGray16( Plustek_Device *dev )
592 {
593 int next;
594 u_char ls;
595 u_long dw, pixels;
596 ScanDef *scan = &dev->scanning;
597 SANE_Bool swap = usb_HostSwap();
598
599 usb_AverageColorWord( dev );
600
601 if (scan->sParam.bSource == SOURCE_ADF) {
602 next = -1;
603 pixels = scan->sParam.Size.dwPixels - 1;
604 } else {
605 next = 1;
606 pixels = 0;
607 }
608 if( scan->dwFlag & SCANFLAG_RightAlign )
609 ls = Shift;
610 else
611 ls = 0;
612
613 switch(scan->fGrayFromColor) {
614
615 case 1:
616 if( swap ) {
617 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
618 scan->UserBuf.pw[pixels] =
619 _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) >> ls;
620 } else {
621 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
622 scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls;
623 }
624 break;
625 case 2:
626 if( swap ) {
627 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
628 scan->UserBuf.pw[pixels] =
629 _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) >> ls;
630 } else {
631 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
632 scan->UserBuf.pw[pixels] = scan->Green.pw[dw] >> ls;
633 }
634 break;
635 case 3:
636 if( swap ) {
637 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
638 scan->UserBuf.pw[pixels] =
639 _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) >> ls;
640 } else {
641 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next)
642 scan->UserBuf.pw[pixels] = scan->Blue.pw[dw] >> ls;
643 }
644 break;
645 }
646 }
647
648 /**
649 */
usb_ColorDuplicateGray16_2(Plustek_Device * dev)650 static void usb_ColorDuplicateGray16_2( Plustek_Device *dev )
651 {
652 int next;
653 u_char ls;
654 u_long dw, pixels;
655 HiLoDef tmp;
656 ScanDef *scan = &dev->scanning;
657 SANE_Bool swap = usb_HostSwap();
658
659 usb_AverageColorWord( dev );
660
661 if (scan->sParam.bSource == SOURCE_ADF) {
662 next = -1;
663 pixels = scan->sParam.Size.dwPixels - 1;
664 } else {
665 next = 1;
666 pixels = 0;
667 }
668 if( scan->dwFlag & SCANFLAG_RightAlign )
669 ls = Shift;
670 else
671 ls = 0;
672
673 switch(scan->fGrayFromColor) {
674 case 1:
675 if( swap ) {
676 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
677 tmp = *((HiLoDef*)&scan->Red.pw[dw]);
678 scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
679 }
680 } else {
681 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
682 scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls;
683 }
684 }
685 break;
686 case 2:
687 if( swap ) {
688 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
689 tmp = *((HiLoDef*)&scan->Green.pw[dw]);
690 scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
691 }
692 } else {
693 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
694 scan->UserBuf.pw[pixels] = scan->Green.pw[dw] >> ls;
695 }
696 }
697 break;
698 case 3:
699 if( swap ) {
700 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
701 tmp = *((HiLoDef*)&scan->Blue.pw[dw]);
702 scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
703 }
704 } else {
705 for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
706 scan->UserBuf.pw[pixels] = scan->Blue.pw[dw] >> ls;
707 }
708 }
709 break;
710 }
711 }
712
713 /**
714 */
usb_GrayDuplicate8(Plustek_Device * dev)715 static void usb_GrayDuplicate8( Plustek_Device *dev )
716 {
717 u_char *dest, *src;
718 u_long pixels;
719 ScanDef *scan = &dev->scanning;
720
721 usb_AverageGrayByte( dev );
722
723 if( scan->sParam.bSource == SOURCE_ADF ) {
724
725 pixels = scan->sParam.Size.dwPixels;
726 src = scan->Green.pb;
727 dest = scan->UserBuf.pb + pixels - 1;
728
729 for(; pixels; pixels--, src++, dest--)
730 *dest = *src;
731 } else {
732 memcpy( scan->UserBuf.pb, scan->Green.pb, scan->sParam.Size.dwBytes );
733 }
734 }
735
736 /**
737 */
usb_GrayDuplicate16(Plustek_Device * dev)738 static void usb_GrayDuplicate16( Plustek_Device *dev )
739 {
740 int next;
741 u_char ls;
742 u_short *dest;
743 u_long pixels;
744 HiLoDef *pwm;
745 ScanDef *scan = &dev->scanning;
746 SANE_Bool swap = usb_HostSwap();
747
748 usb_AverageGrayWord( dev );
749
750 if( scan->sParam.bSource == SOURCE_ADF ) {
751 next = -1;
752 dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1;
753 } else {
754 next = 1;
755 dest = scan->UserBuf.pw;
756 }
757
758 if( scan->dwFlag & SCANFLAG_RightAlign )
759 ls = Shift;
760 else
761 ls = 0;
762
763 pwm = scan->Green.philo;
764 for( pixels=scan->sParam.Size.dwPixels; pixels--; pwm++, dest += next ) {
765 if( swap )
766 *dest = (_PHILO2WORD(pwm)) >> ls;
767 else
768 *dest = (_PLOHI2WORD(pwm)) >> ls;
769 }
770 }
771
772 /**
773 */
usb_GrayDuplicatePseudo16(Plustek_Device * dev)774 static void usb_GrayDuplicatePseudo16( Plustek_Device *dev )
775 {
776 u_char *src;
777 int next;
778 u_short g;
779 u_short *dest;
780 u_long pixels;
781 ScanDef *scan = &dev->scanning;
782
783 usb_AverageGrayByte( dev );
784
785 if (scan->sParam.bSource == SOURCE_ADF) {
786 next = -1;
787 dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1;
788 } else {
789 next = 1;
790 dest = scan->UserBuf.pw;
791 }
792
793 src = scan->Green.pb;
794 g = (u_short)*src;
795
796 for( pixels=scan->sParam.Size.dwPixels; pixels--; src++, dest += next ) {
797
798 *dest = (g + *src) << bShift;
799 g = (u_short)*src;
800 }
801 }
802
803 /** copy binary data to the user buffer
804 */
usb_BWDuplicate(Plustek_Device * dev)805 static void usb_BWDuplicate( Plustek_Device *dev )
806 {
807 ScanDef *scan = &dev->scanning;
808
809 if(scan->sParam.bSource == SOURCE_ADF)
810 {
811 usb_ReverseBitStream( scan->Green.pb, scan->UserBuf.pb,
812 scan->sParam.Size.dwValidPixels,
813 scan->dwBytesLine, 0, 0, 1 );
814 } else {
815 memcpy( scan->UserBuf.pb, scan->Green.pb, scan->sParam.Size.dwBytes );
816 }
817 }
818
819 /** generate binary data from one of the three color inputs according to the
820 * value in fGrayFromColor (CCD version)
821 */
usb_BWDuplicateFromColor(Plustek_Device * dev)822 static void usb_BWDuplicateFromColor( Plustek_Device *dev )
823 {
824 int next;
825 u_char d, s, *dest;
826 u_short j;
827 u_long pixels;
828 ColorByteDef *src;
829 ScanDef *scan = &dev->scanning;
830
831 if( scan->sParam.bSource == SOURCE_ADF ) {
832 dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
833 next = -1;
834 } else {
835 dest = scan->UserBuf.pb;
836 next = 1;
837 }
838
839 switch(scan->fGrayFromColor) {
840 case 1: src = scan->Red.pcb; break;
841 case 3: src = scan->Blue.pcb; break;
842 default: src = scan->Green.pcb; break;
843 }
844
845 d = j = 0;
846 for( pixels = scan->sParam.Size.dwPixels; pixels; pixels--, src++ ) {
847
848 s = src->a_bColor[0];
849 if( s != 0 )
850 d |= BitTable[j];
851 j++;
852 if( j == 8 ) {
853 *dest = d;
854 dest += next;
855
856 d = j = 0;
857 }
858 }
859 }
860
861 /** generate binary data from one of the three color inputs according to the
862 * value in fGrayFromColor (CIS version)
863 */
usb_BWDuplicateFromColor_2(Plustek_Device * dev)864 static void usb_BWDuplicateFromColor_2( Plustek_Device *dev )
865 {
866 int next;
867 u_char d, *dest, *src;
868 u_short j;
869 u_long pixels;
870 ScanDef *scan = &dev->scanning;
871
872 if( scan->sParam.bSource == SOURCE_ADF ) {
873 dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
874 next = -1;
875 } else {
876 dest = scan->UserBuf.pb;
877 next = 1;
878 }
879
880 switch(scan->fGrayFromColor) {
881 case 1: src = scan->Red.pb; break;
882 case 3: src = scan->Blue.pb; break;
883 default: src = scan->Green.pb; break;
884 }
885
886 d = j = 0;
887 for( pixels = scan->sParam.Size.dwPixels; pixels; pixels--, src++ ) {
888
889 if( *src != 0 )
890 d |= BitTable[j];
891 j++;
892 if( j == 8 ) {
893 *dest = d;
894 dest += next;
895
896 d = j = 0;
897 }
898 }
899 }
900
901 /************************** the scaling functions ****************************/
902
903 /**
904 */
usb_ColorScaleGray(Plustek_Device * dev)905 static void usb_ColorScaleGray( Plustek_Device *dev )
906 {
907 int izoom, ddax, next;
908 u_long dw, pixels;
909 ColorByteDef *src;
910 ScanDef *scan = &dev->scanning;
911
912 usb_AverageColorByte( dev );
913
914 dw = scan->sParam.Size.dwPixels;
915
916 if( scan->sParam.bSource == SOURCE_ADF ) {
917 next = -1;
918 pixels = scan->sParam.Size.dwPixels - 1;
919 } else {
920 next = 1;
921 pixels = 0;
922 }
923
924 switch(scan->fGrayFromColor) {
925 case 1: src = scan->Red.pcb; break;
926 case 3: src = scan->Blue.pcb; break;
927 default: src = scan->Green.pcb; break;
928 }
929
930 izoom = usb_GetScaler( scan );
931
932 for( ddax = 0; dw; src++ ) {
933
934 ddax -= _SCALER;
935 while((ddax < 0) && (dw > 0)) {
936
937 scan->UserBuf.pb[pixels] = src->a_bColor[0];
938
939 pixels += next;
940 ddax += izoom;
941 dw--;
942 }
943 }
944 }
945
946 /**
947 */
usb_ColorScaleGray_2(Plustek_Device * dev)948 static void usb_ColorScaleGray_2( Plustek_Device *dev )
949 {
950 u_char *src;
951 int izoom, ddax, next;
952 u_long dw, pixels;
953 ScanDef *scan = &dev->scanning;
954
955 usb_AverageColorByte( dev );
956
957 dw = scan->sParam.Size.dwPixels;
958
959 if( scan->sParam.bSource == SOURCE_ADF ) {
960 next = -1;
961 pixels = scan->sParam.Size.dwPixels - 1;
962 } else {
963 next = 1;
964 pixels = 0;
965 }
966
967 switch(scan->fGrayFromColor) {
968 case 1: src = scan->Red.pb; break;
969 case 3: src = scan->Blue.pb; break;
970 default: src = scan->Green.pb; break;
971 }
972
973 izoom = usb_GetScaler( scan );
974
975 for( ddax = 0; dw; src++ ) {
976
977 ddax -= _SCALER;
978 while((ddax < 0) && (dw > 0)) {
979
980 scan->UserBuf.pb[pixels] = *src;
981
982 pixels += next;
983 ddax += izoom;
984 dw--;
985 }
986 }
987 }
988
989 /**
990 */
usb_ColorScaleGray16(Plustek_Device * dev)991 static void usb_ColorScaleGray16( Plustek_Device *dev )
992 {
993 u_char ls;
994 int izoom, ddax, next;
995 u_long dw, pixels, bitsput;
996 SANE_Bool swap = usb_HostSwap();
997 ScanDef *scan = &dev->scanning;
998
999 usb_AverageColorByte( dev );
1000
1001 dw = scan->sParam.Size.dwPixels;
1002
1003 if( scan->sParam.bSource == SOURCE_ADF ) {
1004 next = -1;
1005 pixels = scan->sParam.Size.dwPixels - 1;
1006 } else {
1007 next = 1;
1008 pixels = 0;
1009 }
1010
1011 izoom = usb_GetScaler( scan );
1012
1013 if( scan->dwFlag & SCANFLAG_RightAlign )
1014 ls = Shift;
1015 else
1016 ls = 0;
1017
1018 switch( scan->fGrayFromColor ) {
1019
1020 case 1:
1021 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1022
1023 ddax -= _SCALER;
1024
1025 while((ddax < 0) && (dw > 0)) {
1026 if( swap ) {
1027 scan->UserBuf.pw[pixels] =
1028 _HILO2WORD(scan->Red.pcw[bitsput].HiLo[0]) >> ls;
1029 } else {
1030 scan->UserBuf.pw[pixels] = scan->Red.pw[bitsput] >> ls;
1031 }
1032 pixels += next;
1033 ddax += izoom;
1034 dw--;
1035 }
1036 }
1037 break;
1038
1039 case 2:
1040 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1041
1042 ddax -= _SCALER;
1043
1044 while((ddax < 0) && (dw > 0)) {
1045 if( swap ) {
1046 scan->UserBuf.pw[pixels] =
1047 _HILO2WORD(scan->Green.pcw[bitsput].HiLo[0]) >> ls;
1048 } else {
1049 scan->UserBuf.pw[pixels] = scan->Green.pw[bitsput] >> ls;
1050 }
1051 pixels += next;
1052 ddax += izoom;
1053 dw--;
1054 }
1055 }
1056 break;
1057
1058 case 3:
1059 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1060
1061 ddax -= _SCALER;
1062
1063 while((ddax < 0) && (dw > 0)) {
1064 if( swap ) {
1065 scan->UserBuf.pw[pixels] =
1066 _HILO2WORD(scan->Blue.pcw[bitsput].HiLo[0]) >> ls;
1067 } else {
1068 scan->UserBuf.pw[pixels] = scan->Blue.pw[bitsput] >> ls;
1069 }
1070 pixels += next;
1071 ddax += izoom;
1072 dw--;
1073 }
1074 }
1075 break;
1076 }
1077 }
1078
1079 /**
1080 */
usb_ColorScaleGray16_2(Plustek_Device * dev)1081 static void usb_ColorScaleGray16_2( Plustek_Device *dev )
1082 {
1083 u_char ls;
1084 int izoom, ddax, next;
1085 u_long dw, pixels, bitsput;
1086 HiLoDef tmp;
1087 SANE_Bool swap = usb_HostSwap();
1088 ScanDef *scan = &dev->scanning;
1089
1090 usb_AverageColorByte( dev );
1091
1092 dw = scan->sParam.Size.dwPixels;
1093
1094 if( scan->sParam.bSource == SOURCE_ADF ) {
1095 next = -1;
1096 pixels = scan->sParam.Size.dwPixels - 1;
1097 } else {
1098 next = 1;
1099 pixels = 0;
1100 }
1101
1102 izoom = usb_GetScaler( scan );
1103
1104 if( scan->dwFlag & SCANFLAG_RightAlign )
1105 ls = Shift;
1106 else
1107 ls = 0;
1108
1109 switch( scan->fGrayFromColor ) {
1110
1111 case 1:
1112 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1113
1114 ddax -= _SCALER;
1115
1116 while((ddax < 0) && (dw > 0)) {
1117 if( swap ) {
1118 tmp = *((HiLoDef*)&scan->Red.pw[bitsput]);
1119 scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
1120 } else {
1121 scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls;
1122 }
1123 pixels += next;
1124 ddax += izoom;
1125 dw--;
1126 }
1127 }
1128 break;
1129
1130 case 2:
1131 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1132
1133 ddax -= _SCALER;
1134
1135 while((ddax < 0) && (dw > 0)) {
1136 if( swap ) {
1137 tmp = *((HiLoDef*)&scan->Green.pw[bitsput]);
1138 scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
1139 } else {
1140 scan->UserBuf.pw[pixels] = scan->Green.pw[bitsput] >> ls;
1141 }
1142 pixels += next;
1143 ddax += izoom;
1144 dw--;
1145 }
1146 }
1147 break;
1148
1149 case 3:
1150 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1151
1152 ddax -= _SCALER;
1153
1154 while((ddax < 0) && (dw > 0)) {
1155 if( swap ) {
1156 tmp = *((HiLoDef*)&scan->Blue.pw[bitsput]);
1157 scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
1158 } else {
1159 scan->UserBuf.pw[pixels] = scan->Blue.pw[bitsput] >> ls;
1160 }
1161 pixels += next;
1162 ddax += izoom;
1163 dw--;
1164 }
1165 }
1166 break;
1167 }
1168 }
1169
1170 /** here we copy and scale from scanner world to user world...
1171 */
usb_ColorScale8(Plustek_Device * dev)1172 static void usb_ColorScale8( Plustek_Device *dev )
1173 {
1174 int izoom, ddax, next;
1175 u_long dw, pixels, bitsput;
1176 ScanDef *scan = &dev->scanning;
1177
1178 usb_AverageColorByte( dev );
1179
1180 dw = scan->sParam.Size.dwPixels;
1181
1182 if( scan->sParam.bSource == SOURCE_ADF ) {
1183 next = -1;
1184 pixels = scan->sParam.Size.dwPixels - 1;
1185 } else {
1186 next = 1;
1187 pixels = 0;
1188 }
1189
1190 izoom = usb_GetScaler( scan );
1191
1192 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1193
1194 ddax -= _SCALER;
1195
1196 while((ddax < 0) && (dw > 0)) {
1197
1198 scan->UserBuf.pb_rgb[pixels].Red =
1199 scan->Red.pcb[bitsput].a_bColor[0];
1200 scan->UserBuf.pb_rgb[pixels].Green =
1201 scan->Green.pcb[bitsput].a_bColor[0];
1202 scan->UserBuf.pb_rgb[pixels].Blue =
1203 scan->Blue.pcb[bitsput].a_bColor[0];
1204 pixels += next;
1205 ddax += izoom;
1206 dw--;
1207 }
1208 }
1209 }
1210
usb_ColorScale8_2(Plustek_Device * dev)1211 static void usb_ColorScale8_2( Plustek_Device *dev )
1212 {
1213 int izoom, ddax, next;
1214 u_long dw, pixels, bitsput;
1215 ScanDef *scan = &dev->scanning;
1216
1217 dw = scan->sParam.Size.dwPixels;
1218
1219 if( scan->sParam.bSource == SOURCE_ADF ) {
1220 next = -1;
1221 pixels = scan->sParam.Size.dwPixels - 1;
1222 } else {
1223 next = 1;
1224 pixels = 0;
1225 }
1226
1227 izoom = usb_GetScaler( scan );
1228
1229 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1230
1231 ddax -= _SCALER;
1232
1233 while((ddax < 0) && (dw > 0)) {
1234
1235 scan->UserBuf.pb_rgb[pixels].Red = scan->Red.pb[bitsput];
1236 scan->UserBuf.pb_rgb[pixels].Green = scan->Green.pb[bitsput];
1237 scan->UserBuf.pb_rgb[pixels].Blue = scan->Blue.pb[bitsput];
1238
1239 pixels += next;
1240 ddax += izoom;
1241 dw--;
1242 }
1243 }
1244 }
1245
1246 /**
1247 */
usb_ColorScale16(Plustek_Device * dev)1248 static void usb_ColorScale16( Plustek_Device *dev )
1249 {
1250 u_char ls;
1251 int izoom, ddax, next;
1252 u_long dw, pixels, bitsput;
1253 SANE_Bool swap = usb_HostSwap();
1254 ScanDef *scan = &dev->scanning;
1255
1256 usb_AverageColorWord( dev );
1257
1258 dw = scan->sParam.Size.dwPixels;
1259
1260 if( scan->sParam.bSource == SOURCE_ADF ) {
1261 next = -1;
1262 pixels = scan->sParam.Size.dwPixels - 1;
1263 } else {
1264 next = 1;
1265 pixels = 0;
1266 }
1267
1268 izoom = usb_GetScaler( scan );
1269
1270 if( scan->dwFlag & SCANFLAG_RightAlign )
1271 ls = Shift;
1272 else
1273 ls = 0;
1274
1275 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1276
1277 ddax -= _SCALER;
1278
1279 while((ddax < 0) && (dw > 0)) {
1280
1281 if( swap ) {
1282
1283 scan->UserBuf.pw_rgb[pixels].Red =
1284 _HILO2WORD(scan->Red.pcw[bitsput].HiLo[0]) >> ls;
1285
1286 scan->UserBuf.pw_rgb[pixels].Green =
1287 _HILO2WORD(scan->Green.pcw[bitsput].HiLo[0]) >> ls;
1288
1289 scan->UserBuf.pw_rgb[pixels].Blue =
1290 _HILO2WORD(scan->Blue.pcw[bitsput].HiLo[0]) >> ls;
1291
1292 } else {
1293
1294 scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[bitsput]>>ls;
1295 scan->UserBuf.pw_rgb[pixels].Green = scan->Green.pw[bitsput] >> ls;
1296 scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[bitsput] >> ls;
1297 }
1298 pixels += next;
1299 ddax += izoom;
1300 dw--;
1301 }
1302 }
1303 }
1304
1305 /**
1306 */
usb_ColorScale16_2(Plustek_Device * dev)1307 static void usb_ColorScale16_2( Plustek_Device *dev )
1308 {
1309 u_char ls;
1310 HiLoDef tmp;
1311 int izoom, ddax, next;
1312 u_long dw, pixels, bitsput;
1313 SANE_Bool swap = usb_HostSwap();
1314 ScanDef *scan = &dev->scanning;
1315
1316 usb_AverageColorWord( dev );
1317
1318 dw = scan->sParam.Size.dwPixels;
1319
1320 if( scan->sParam.bSource == SOURCE_ADF ) {
1321 next = -1;
1322 pixels = scan->sParam.Size.dwPixels - 1;
1323 } else {
1324 next = 1;
1325 pixels = 0;
1326 }
1327
1328 izoom = usb_GetScaler( scan );
1329
1330 if( scan->dwFlag & SCANFLAG_RightAlign )
1331 ls = Shift;
1332 else
1333 ls = 0;
1334
1335 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1336
1337 ddax -= _SCALER;
1338
1339 while((ddax < 0) && (dw > 0)) {
1340
1341 if( swap ) {
1342
1343 tmp = *((HiLoDef*)&scan->Red.pw[bitsput]);
1344 scan->UserBuf.pw_rgb[pixels].Red = _HILO2WORD(tmp) >> ls;
1345
1346 tmp = *((HiLoDef*)&scan->Green.pw[bitsput]);
1347 scan->UserBuf.pw_rgb[pixels].Green = _HILO2WORD(tmp) >> ls;
1348
1349 tmp = *((HiLoDef*)&scan->Blue.pw[bitsput]);
1350 scan->UserBuf.pw_rgb[pixels].Blue = _HILO2WORD(tmp) >> ls;
1351
1352 } else {
1353
1354 scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[bitsput] >> ls;
1355 scan->UserBuf.pw_rgb[pixels].Green = scan->Green.pw[bitsput] >> ls;
1356 scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[bitsput] >> ls;
1357 }
1358 pixels += next;
1359 ddax += izoom;
1360 dw--;
1361 }
1362 }
1363 }
1364
1365 /**
1366 */
usb_ColorScalePseudo16(Plustek_Device * dev)1367 static void usb_ColorScalePseudo16( Plustek_Device *dev )
1368 {
1369 int izoom, ddax, next;
1370 u_short wR, wG, wB;
1371 u_long dw, pixels, bitsput;
1372 ScanDef *scan = &dev->scanning;
1373
1374 usb_AverageColorByte( dev );
1375
1376 dw = scan->sParam.Size.dwPixels;
1377
1378 if( scan->sParam.bSource == SOURCE_ADF ) {
1379 next = -1;
1380 pixels = scan->sParam.Size.dwPixels - 1;
1381 } else {
1382 next = 1;
1383 pixels = 0;
1384 }
1385
1386 izoom = usb_GetScaler( scan );
1387
1388 wR = (u_short)scan->Red.pcb[0].a_bColor[0];
1389 wG = (u_short)scan->Green.pcb[0].a_bColor[1];
1390 wB = (u_short)scan->Blue.pcb[0].a_bColor[2];
1391
1392 for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
1393
1394 ddax -= _SCALER;
1395
1396 while((ddax < 0) && (dw > 0)) {
1397
1398 scan->UserBuf.pw_rgb[pixels].Red =
1399 (wR + scan->Red.pcb[bitsput].a_bColor[0]) << bShift;
1400
1401 scan->UserBuf.pw_rgb[pixels].Green =
1402 (wG + scan->Green.pcb[bitsput].a_bColor[0]) << bShift;
1403
1404 scan->UserBuf.pw_rgb[pixels].Blue =
1405 (wB + scan->Blue.pcb[bitsput].a_bColor[0]) << bShift;
1406
1407 pixels += next;
1408 ddax += izoom;
1409 dw--;
1410 }
1411
1412 wR = (u_short)scan->Red.pcb[bitsput].a_bColor[0];
1413 wG = (u_short)scan->Green.pcb[bitsput].a_bColor[0];
1414 wB = (u_short)scan->Blue.pcb[bitsput].a_bColor[0];
1415 }
1416 }
1417
1418 /**
1419 */
usb_BWScale(Plustek_Device * dev)1420 static void usb_BWScale( Plustek_Device *dev )
1421 {
1422 u_char tmp, *dest, *src;
1423 int izoom, ddax;
1424 u_long i, dw;
1425 ScanDef *scan = &dev->scanning;
1426
1427 src = scan->Green.pb;
1428 if( scan->sParam.bSource == SOURCE_ADF ) {
1429 int iSum = wSum;
1430 usb_ReverseBitStream(scan->Green.pb, scan->UserBuf.pb,
1431 scan->sParam.Size.dwValidPixels,
1432 scan->dwBytesLine, scan->sParam.PhyDpi.x,
1433 scan->sParam.UserDpi.x, 1 );
1434 wSum = iSum;
1435 return;
1436 } else {
1437 dest = scan->UserBuf.pb;
1438 }
1439
1440 izoom = usb_GetScaler( scan );
1441
1442 memset( dest, 0, scan->dwBytesLine );
1443 ddax = 0;
1444 dw = 0;
1445
1446 for( i = 0; i < scan->sParam.Size.dwValidPixels; i++ ) {
1447
1448 ddax -= _SCALER;
1449
1450 while( ddax < 0 ) {
1451
1452 tmp = src[(i>>3)];
1453
1454 if((dw>>3) < scan->sParam.Size.dwValidPixels ) {
1455
1456 if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7))))
1457 dest[dw>>3] |= (1 << ((~(dw & 0x7))&0x7));
1458 }
1459 dw++;
1460 ddax += izoom;
1461 }
1462 }
1463 }
1464
1465 /**
1466 */
usb_BWScaleFromColor(Plustek_Device * dev)1467 static void usb_BWScaleFromColor( Plustek_Device *dev )
1468 {
1469 u_char d, s, *dest;
1470 u_short j;
1471 u_long pixels;
1472 int izoom, ddax, next;
1473 ColorByteDef *src;
1474 ScanDef *scan = &dev->scanning;
1475
1476 if (scan->sParam.bSource == SOURCE_ADF) {
1477 dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
1478 next = -1;
1479 } else {
1480 dest = scan->UserBuf.pb;
1481 next = 1;
1482 }
1483
1484 /* setup the source buffer */
1485 switch(scan->fGrayFromColor) {
1486 case 1: src = scan->Red.pcb; break;
1487 case 3: src = scan->Blue.pcb; break;
1488 default: src = scan->Green.pcb; break;
1489 }
1490
1491 izoom = usb_GetScaler( scan );
1492 ddax = 0;
1493
1494 d = j = 0;
1495 for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) {
1496
1497 ddax -= _SCALER;
1498
1499 while((ddax < 0) && (pixels > 0)) {
1500
1501 s = src->a_bColor[0];
1502 if( s != 0 )
1503 d |= BitTable[j];
1504 j++;
1505 if( j == 8 ) {
1506 *dest = d;
1507 dest += next;
1508 d = j = 0;
1509 }
1510 ddax += izoom;
1511 pixels--;
1512 }
1513 }
1514 }
1515
1516 /**
1517 */
usb_BWScaleFromColor_2(Plustek_Device * dev)1518 static void usb_BWScaleFromColor_2( Plustek_Device *dev )
1519 {
1520 u_char d, *dest, *src;
1521 u_short j;
1522 u_long pixels;
1523 int izoom, ddax, next;
1524 ScanDef *scan = &dev->scanning;
1525
1526 if (scan->sParam.bSource == SOURCE_ADF) {
1527 dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
1528 next = -1;
1529 } else {
1530 dest = scan->UserBuf.pb;
1531 next = 1;
1532 }
1533
1534 /* setup the source buffer */
1535 switch(scan->fGrayFromColor) {
1536 case 1: src = scan->Red.pb; break;
1537 case 3: src = scan->Blue.pb; break;
1538 default: src = scan->Green.pb; break;
1539 }
1540
1541 izoom = usb_GetScaler( scan );
1542 ddax = 0;
1543
1544 d = j = 0;
1545 for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) {
1546
1547 ddax -= _SCALER;
1548
1549 while((ddax < 0) && (pixels > 0)) {
1550
1551 if( *src != 0 )
1552 d |= BitTable[j];
1553 j++;
1554 if( j == 8 ) {
1555 *dest = d;
1556 dest += next;
1557 d = j = 0;
1558 }
1559 ddax += izoom;
1560 pixels--;
1561 }
1562 }
1563 }
1564
1565 /**
1566 */
usb_GrayScale8(Plustek_Device * dev)1567 static void usb_GrayScale8( Plustek_Device *dev )
1568 {
1569 u_char *dest, *src;
1570 int izoom, ddax, next;
1571 u_long pixels;
1572 ScanDef *scan = &dev->scanning;
1573
1574 usb_AverageGrayByte( dev );
1575
1576 src = scan->Green.pb;
1577 if( scan->sParam.bSource == SOURCE_ADF ) {
1578 dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
1579 next = -1;
1580 } else {
1581 dest = scan->UserBuf.pb;
1582 next = 1;
1583 }
1584
1585 izoom = usb_GetScaler( scan );
1586 ddax = 0;
1587
1588 for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) {
1589
1590 ddax -= _SCALER;
1591
1592 while((ddax < 0) && (pixels > 0)) {
1593
1594 *dest = *src;
1595 dest += next;
1596 ddax += izoom;
1597 pixels--;
1598 }
1599 }
1600 }
1601
1602 /**
1603 */
usb_GrayScale16(Plustek_Device * dev)1604 static void usb_GrayScale16( Plustek_Device *dev )
1605 {
1606 u_char ls;
1607 int izoom, ddax, next;
1608 u_short *dest;
1609 u_long pixels;
1610 HiLoDef *pwm;
1611 ScanDef *scan = &dev->scanning;
1612 SANE_Bool swap = usb_HostSwap();
1613
1614 usb_AverageGrayWord( dev);
1615
1616 pwm = scan->Green.philo;
1617 wSum = scan->sParam.PhyDpi.x;
1618
1619 if( scan->sParam.bSource == SOURCE_ADF ) {
1620 next = -1;
1621 dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1;
1622 } else {
1623 next = 1;
1624 dest = scan->UserBuf.pw;
1625 }
1626
1627 izoom = usb_GetScaler( scan );
1628 ddax = 0;
1629
1630 if( scan->dwFlag & SCANFLAG_RightAlign )
1631 ls = Shift;
1632 else
1633 ls = 0;
1634
1635 for( pixels = scan->sParam.Size.dwPixels; pixels; pwm++ ) {
1636
1637 ddax -= _SCALER;
1638
1639 while((ddax < 0) && (pixels > 0)) {
1640
1641 if( swap )
1642 *dest = _PHILO2WORD(pwm) >> ls;
1643 else
1644 *dest = _PLOHI2WORD(pwm) >> ls;
1645
1646 dest += next;
1647 ddax += izoom;
1648 pixels--;
1649 }
1650 }
1651 }
1652
1653 /**
1654 */
usb_GrayScalePseudo16(Plustek_Device * dev)1655 static void usb_GrayScalePseudo16( Plustek_Device *dev )
1656 {
1657 u_char *src;
1658 int izoom, ddax, next;
1659 u_short *dest, g;
1660 u_long pixels;
1661 ScanDef *scan = &dev->scanning;
1662
1663 usb_AverageGrayByte( dev );
1664
1665 if( scan->sParam.bSource == SOURCE_ADF ) {
1666 next = -1;
1667 dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1;
1668 } else {
1669 next = 1;
1670 dest = scan->UserBuf.pw;
1671 }
1672
1673 src = scan->Green.pb;
1674 g = (u_short)*src;
1675
1676 izoom = usb_GetScaler( scan );
1677 ddax = 0;
1678
1679 for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) {
1680
1681 ddax -= _SCALER;
1682
1683 while((ddax < 0) && (pixels > 0)) {
1684
1685 *dest = (g + *src) << bShift;
1686 dest += next;
1687 ddax += izoom;
1688 pixels--;
1689 }
1690 g = (u_short)*src;
1691 }
1692 }
1693
1694 /** function to select the appropriate pixel copy function
1695 */
usb_GetImageProc(Plustek_Device * dev)1696 static void usb_GetImageProc( Plustek_Device *dev )
1697 {
1698 ScanDef *scan = &dev->scanning;
1699 DCapsDef *sc = &dev->usbDev.Caps;
1700 HWDef *hw = &dev->usbDev.HwSetting;
1701
1702 bShift = 0;
1703
1704 if( scan->sParam.UserDpi.x != scan->sParam.PhyDpi.x ) {
1705
1706 /* Pixel scaling... */
1707 switch( scan->sParam.bDataType ) {
1708
1709 case SCANDATATYPE_Color:
1710 if (scan->sParam.bBitDepth > 8) {
1711
1712 if( usb_IsCISDevice(dev)){
1713 scan->pfnProcess = usb_ColorScale16_2;
1714 DBG( _DBG_INFO, "ImageProc is: ColorScale16_2\n" );
1715 } else {
1716 scan->pfnProcess = usb_ColorScale16;
1717 DBG( _DBG_INFO, "ImageProc is: ColorScale16\n" );
1718 }
1719 if (scan->fGrayFromColor) {
1720 if( usb_IsCISDevice(dev)){
1721 scan->pfnProcess = usb_ColorScaleGray16_2;
1722 DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16_2\n" );
1723 } else {
1724 scan->pfnProcess = usb_ColorScaleGray16;
1725 DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16\n" );
1726 }
1727 }
1728 } else if (scan->dwFlag & SCANFLAG_Pseudo48) {
1729 scan->pfnProcess = usb_ColorScalePseudo16;
1730 DBG( _DBG_INFO, "ImageProc is: ColorScalePseudo16\n" );
1731
1732 } else if (scan->fGrayFromColor) {
1733
1734 if( usb_IsCISDevice(dev)){
1735 if (scan->fGrayFromColor > 7 ) {
1736 scan->pfnProcess = usb_BWScaleFromColor_2;
1737 DBG( _DBG_INFO, "ImageProc is: BWScaleFromColor_2\n" );
1738 } else {
1739 scan->pfnProcess = usb_ColorScaleGray_2;
1740 DBG( _DBG_INFO, "ImageProc is: ColorScaleGray_2\n" );
1741 }
1742 } else {
1743 if (scan->fGrayFromColor > 7 ) {
1744 scan->pfnProcess = usb_BWScaleFromColor;
1745 DBG( _DBG_INFO, "ImageProc is: BWScaleFromColor\n" );
1746 } else {
1747 scan->pfnProcess = usb_ColorScaleGray;
1748 DBG( _DBG_INFO, "ImageProc is: ColorScaleGray\n" );
1749 }
1750 }
1751 } else {
1752
1753 if( usb_IsCISDevice(dev)){
1754 scan->pfnProcess = usb_ColorScale8_2;
1755 DBG( _DBG_INFO, "ImageProc is: ColorScale8_2\n" );
1756 } else {
1757 scan->pfnProcess = usb_ColorScale8;
1758 DBG( _DBG_INFO, "ImageProc is: ColorScale8\n" );
1759 }
1760 }
1761 break;
1762
1763 case SCANDATATYPE_Gray:
1764 if (scan->sParam.bBitDepth > 8) {
1765 scan->pfnProcess = usb_GrayScale16;
1766 DBG( _DBG_INFO, "ImageProc is: GrayScale16\n" );
1767 } else {
1768
1769 if (scan->dwFlag & SCANFLAG_Pseudo48) {
1770 scan->pfnProcess = usb_GrayScalePseudo16;
1771 DBG( _DBG_INFO, "ImageProc is: GrayScalePseudo16\n" );
1772 } else {
1773 scan->pfnProcess = usb_GrayScale8;
1774 DBG( _DBG_INFO, "ImageProc is: GrayScale8\n" );
1775 }
1776 }
1777 break;
1778
1779 default:
1780 scan->pfnProcess = usb_BWScale;
1781 DBG( _DBG_INFO, "ImageProc is: BWScale\n" );
1782 break;
1783 }
1784
1785 } else {
1786
1787 /* Pixel copy */
1788 switch( scan->sParam.bDataType ) {
1789
1790 case SCANDATATYPE_Color:
1791 if (scan->sParam.bBitDepth > 8) {
1792 if( usb_IsCISDevice(dev)){
1793 scan->pfnProcess = usb_ColorDuplicate16_2;
1794 DBG( _DBG_INFO, "ImageProc is: ColorDuplicate16_2\n" );
1795 } else {
1796 scan->pfnProcess = usb_ColorDuplicate16;
1797 DBG( _DBG_INFO, "ImageProc is: ColorDuplicate16\n" );
1798 }
1799 if (scan->fGrayFromColor) {
1800 if( usb_IsCISDevice(dev)){
1801 scan->pfnProcess = usb_ColorDuplicateGray16_2;
1802 DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16_2\n" );
1803 } else {
1804 scan->pfnProcess = usb_ColorDuplicateGray16;
1805 DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16\n" );
1806 }
1807 }
1808 } else if (scan->dwFlag & SCANFLAG_Pseudo48) {
1809 scan->pfnProcess = usb_ColorDuplicatePseudo16;
1810 DBG( _DBG_INFO, "ImageProc is: ColorDuplicatePseudo16\n" );
1811 } else if (scan->fGrayFromColor) {
1812 if( usb_IsCISDevice(dev)){
1813 if (scan->fGrayFromColor > 7 ) {
1814 scan->pfnProcess = usb_BWDuplicateFromColor_2;
1815 DBG( _DBG_INFO, "ImageProc is: BWDuplicateFromColor_2\n" );
1816 } else {
1817 scan->pfnProcess = usb_ColorDuplicateGray_2;
1818 DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray_2\n" );
1819 }
1820 } else {
1821 if (scan->fGrayFromColor > 7 ) {
1822 scan->pfnProcess = usb_BWDuplicateFromColor;
1823 DBG( _DBG_INFO, "ImageProc is: BWDuplicateFromColor\n" );
1824 } else {
1825 scan->pfnProcess = usb_ColorDuplicateGray;
1826 DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray\n" );
1827 }
1828 }
1829 } else {
1830 if( usb_IsCISDevice(dev)){
1831 scan->pfnProcess = usb_ColorDuplicate8_2;
1832 DBG( _DBG_INFO, "ImageProc is: ColorDuplicate8_2\n" );
1833 } else {
1834 scan->pfnProcess = usb_ColorDuplicate8;
1835 DBG( _DBG_INFO, "ImageProc is: ColorDuplicate8\n" );
1836 }
1837 }
1838 break;
1839
1840 case SCANDATATYPE_Gray:
1841 if (scan->sParam.bBitDepth > 8) {
1842 scan->pfnProcess = usb_GrayDuplicate16;
1843 DBG( _DBG_INFO, "ImageProc is: GrayDuplicate16\n" );
1844 } else {
1845 if (scan->dwFlag & SCANFLAG_Pseudo48) {
1846 scan->pfnProcess = usb_GrayDuplicatePseudo16;
1847 DBG( _DBG_INFO, "ImageProc is: GrayDuplicatePseudo16\n" );
1848 } else {
1849 scan->pfnProcess = usb_GrayDuplicate8;
1850 DBG( _DBG_INFO, "ImageProc is: GrayDuplicate8\n" );
1851 }
1852 }
1853 break;
1854
1855 default:
1856 scan->pfnProcess = usb_BWDuplicate;
1857 DBG( _DBG_INFO, "ImageProc is: BWDuplicate\n" );
1858 break;
1859 }
1860 }
1861
1862 if( scan->sParam.bBitDepth == 8 ) {
1863
1864 if( scan->dwFlag & SCANFLAG_Pseudo48 ) {
1865 if( scan->dwFlag & SCANFLAG_RightAlign ) {
1866 bShift = 5;
1867 } else {
1868
1869 /* this should fix the Bearpaw/U12 discrepancy
1870 * in general the fix is needed, but not for the U12
1871 * why? - no idea!
1872 */
1873 if(_WAF_BSHIFT7_BUG == (_WAF_BSHIFT7_BUG & sc->workaroundFlag))
1874 bShift = 0; /* Holger Bischof 16.12.2001 */
1875 else
1876 bShift = 7;
1877 }
1878 DBG( _DBG_INFO, "bShift adjusted: %u\n", bShift );
1879 }
1880 }
1881
1882 if( _LM9833 == hw->chip ) {
1883 Shift = 0;
1884 Mask = 0xFFFF;
1885 } else {
1886 Shift = 2;
1887 Mask = 0xFFFC;
1888 }
1889 }
1890
1891 /**
1892 * here we read the image data into our intermediate buffer (in the NT version
1893 * the function was implemented as thread)
1894 */
usb_ReadData(Plustek_Device * dev)1895 static SANE_Int usb_ReadData( Plustek_Device *dev )
1896 {
1897 u_long dw, dwRet, dwBytes, pl;
1898 ScanDef *scan = &dev->scanning;
1899 HWDef *hw = &dev->usbDev.HwSetting;
1900
1901 DBG( _DBG_READ, "usb_ReadData()\n" );
1902
1903 pl = dev->usbDev.a_bRegs[0x4e] * hw->wDRAMSize/128;
1904
1905 while( scan->sParam.Size.dwTotalBytes ) {
1906
1907 if( usb_IsEscPressed()) {
1908 DBG( _DBG_INFO, "usb_ReadData() - Cancel detected...\n" );
1909 return 0;
1910 }
1911
1912 if( scan->sParam.Size.dwTotalBytes > scan->dwBytesScanBuf )
1913 dw = scan->dwBytesScanBuf;
1914 else
1915 dw = scan->sParam.Size.dwTotalBytes;
1916
1917 scan->sParam.Size.dwTotalBytes -= dw;
1918
1919 if(!scan->sParam.Size.dwTotalBytes && dw < (pl * 1024))
1920 {
1921 if(!(dev->usbDev.a_bRegs[0x4e] = (u_char)ceil((double)dw /
1922 (4.0 * hw->wDRAMSize)))) {
1923 dev->usbDev.a_bRegs[0x4e] = 1;
1924 }
1925 dev->usbDev.a_bRegs[0x4f] = 0;
1926
1927 sanei_lm983x_write( dev->fd, 0x4e, &dev->usbDev.a_bRegs[0x4e], 2, SANE_TRUE );
1928 }
1929
1930 while( scan->bLinesToSkip ) {
1931
1932 DBG( _DBG_READ, "Skipping %u lines\n", scan->bLinesToSkip );
1933
1934 dwBytes = scan->bLinesToSkip * scan->sParam.Size.dwPhyBytes;
1935
1936 if (dwBytes > scan->dwBytesScanBuf) {
1937
1938 dwBytes = scan->dwBytesScanBuf;
1939 scan->bLinesToSkip -= scan->dwLinesScanBuf;
1940 } else {
1941 scan->bLinesToSkip = 0;
1942 }
1943
1944 if( !usb_ScanReadImage( dev, scan->pbGetDataBuf, dwBytes ))
1945 return 0;
1946 }
1947
1948 if( usb_ScanReadImage( dev, scan->pbGetDataBuf, dw )) {
1949
1950 dumpPic("plustek-pic.raw", scan->pbGetDataBuf, dw, 0);
1951
1952 if( scan->dwLinesDiscard ) {
1953
1954 DBG(_DBG_READ, "Discarding %lu lines\n", scan->dwLinesDiscard);
1955
1956 dwRet = dw / scan->sParam.Size.dwPhyBytes;
1957
1958 if (scan->dwLinesDiscard > dwRet) {
1959 scan->dwLinesDiscard -= dwRet;
1960 dwRet = 0;
1961 } else {
1962 dwRet -= scan->dwLinesDiscard;
1963 scan->dwLinesDiscard = 0;
1964 }
1965 } else {
1966
1967 dwRet = dw / scan->sParam.Size.dwPhyBytes;
1968 }
1969
1970 scan->pbGetDataBuf += scan->dwBytesScanBuf;
1971 if( scan->pbGetDataBuf >= scan->pbScanBufEnd ) {
1972 scan->pbGetDataBuf = scan->pbScanBufBegin;
1973 }
1974
1975 if( dwRet )
1976 return dwRet;
1977 }
1978 }
1979 return 0;
1980 }
1981
1982 /* END PLUSTEK-USBIMG.C .....................................................*/
1983