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