• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 2005 Mustek.
4    Originally maintained by Mustek
5    Author:Jack Roy 2005.5.24
6 
7    This file is part of the SANE package.
8 
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2 of the
12    License, or (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <https://www.gnu.org/licenses/>.
21 
22    As a special exception, the authors of SANE give permission for
23    additional uses of the libraries contained in this release of SANE.
24 
25    The exception is that, if you link a SANE library with other files
26    to produce an executable, this does not by itself cause the
27    resulting executable to be covered by the GNU General Public
28    License.  Your use of that executable is in no way restricted on
29    account of linking the SANE library code into it.
30 
31    This exception does not, however, invalidate any other reasons why
32    the executable file might be covered by the GNU General Public
33    License.
34 
35    If you submit changes to SANE to the maintainers to be included in
36    a subsequent release, you agree by submitting the changes that
37    those changes may be distributed with this exception intact.
38 
39    If you write modifications of your own for SANE, it is your choice
40    whether to permit this exception to apply to your modifications.
41    If you do not wish that, delete this exception notice.
42 
43    This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro
44    and similar USB2 scanners. */
45 
46 #include <pthread.h>		/* HOLD */
47 #include <stdlib.h>
48 
49 /* local header files */
50 #include "mustek_usb2_asic.c"
51 
52 #include "mustek_usb2_high.h"
53 
54 /* ******************++ spuicall_g.h ****************************/
55 
56 /*global variable HOLD: these should go to scanner structure */
57 
58 /*base type*/
59 static SANE_Bool g_bOpened;
60 static SANE_Bool g_bPrepared;
61 static SANE_Bool g_isCanceled;
62 static SANE_Bool g_bSharpen;
63 static SANE_Bool g_bFirstReadImage;
64 static SANE_Bool g_isScanning;
65 static SANE_Bool g_isSelfGamma;
66 
67 static SANE_Byte g_bScanBits;
68 static SANE_Byte *g_lpReadImageHead;
69 
70 static unsigned short s_wOpticalYDpi[] = { 1200, 600, 300, 150, 75, 0 };
71 static unsigned short s_wOpticalXDpi[] = { 1200, 600, 300, 150, 75, 0 };
72 static unsigned short g_X;
73 static unsigned short g_Y;
74 static unsigned short g_Width;
75 static unsigned short g_Height;
76 static unsigned short g_XDpi;
77 static unsigned short g_YDpi;
78 static unsigned short g_SWWidth;
79 static unsigned short g_SWHeight;
80 static unsigned short g_wPixelDistance;		/*even & odd sensor problem */
81 static unsigned short g_wLineDistance;
82 static unsigned short g_wScanLinesPerBlock;
83 static unsigned short g_wReadedLines;
84 static unsigned short g_wReadImageLines;
85 static unsigned short g_wReadyShadingLine;
86 static unsigned short g_wStartShadingLinePos;
87 static unsigned short g_wLineartThreshold;
88 
89 static unsigned int g_wtheReadyLines;
90 static unsigned int g_wMaxScanLines;
91 static unsigned int g_dwScannedTotalLines;
92 static unsigned int g_dwImageBufferSize;
93 static unsigned int g_BytesPerRow;
94 static unsigned int g_SWBytesPerRow;
95 static unsigned int g_dwCalibrationSize;
96 static unsigned int g_dwBufferSize;
97 
98 static unsigned int g_dwTotalTotalXferLines;
99 
100 static unsigned short *g_pGammaTable;
101 static unsigned char *g_pDeviceFile;
102 
103 static pthread_t g_threadid_readimage;
104 
105 /*user define type*/
106 static COLORMODE g_ScanMode;
107 static TARGETIMAGE g_tiTarget;
108 static SCANTYPE g_ScanType = ST_Reflective;
109 static SCANSOURCE g_ssScanSource;
110 static PIXELFLAVOR g_PixelFlavor;
111 
112 static SUGGESTSETTING g_ssSuggest;
113 static Asic g_chip;
114 
115 static int g_nSecLength, g_nDarkSecLength;
116 static int g_nSecNum, g_nDarkSecNum;
117 static unsigned short g_wCalWidth;
118 static unsigned short g_wDarkCalWidth;
119 static int g_nPowerNum;
120 static unsigned short g_wStartPosition;
121 
122 static pthread_mutex_t g_scannedLinesMutex = PTHREAD_MUTEX_INITIALIZER;
123 static pthread_mutex_t g_readyLinesMutex = PTHREAD_MUTEX_INITIALIZER;
124 
125 /*for modify the last point*/
126 static SANE_Byte * g_lpBefLineImageData = NULL;
127 static SANE_Bool g_bIsFirstReadBefData = TRUE;
128 static unsigned int g_dwAlreadyGetLines = 0;
129 
130 /* forward declarations */
131 static SANE_Bool MustScanner_Init (void);
132 static SANE_Bool MustScanner_GetScannerState (void);
133 static SANE_Bool MustScanner_PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn);
134 static SANE_Bool MustScanner_BackHome (void);
135 static SANE_Bool MustScanner_Prepare (SANE_Byte bScanSource);
136 #ifdef SANE_UNUSED
137 static SANE_Bool MustScanner_AdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset,
138 				      SANE_Byte * bLastMin, SANE_Byte * bLastOffset,
139 				      unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound,
140 				      SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel,
141 				      unsigned short wStdMaxLevel);
142 static SANE_Bool MustScanner_SecondAdjustOffset (int nTimes, SANE_Bool * bDirection,
143 					    SANE_Byte * bOffset, SANE_Byte * bLastMin,
144 					    SANE_Byte * bLastOffset, unsigned short * wMinValue,
145 					    SANE_Byte * bOffsetUpperBound,
146 					    SANE_Byte * bOffsetLowerBound,
147 					    unsigned short wStdMinLevel, unsigned short wStdMaxLevel);
148 #endif
149 static unsigned short MustScanner_FiltLower (unsigned short * pSort, unsigned short TotalCount, unsigned short LowCount,
150 				   unsigned short HighCount);
151 static SANE_Bool MustScanner_GetRgb48BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
152 					 unsigned short * wLinesCount);
153 static SANE_Bool MustScanner_GetRgb48BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
154 						unsigned short * wLinesCount);
155 static SANE_Bool MustScanner_GetRgb24BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
156 					 unsigned short * wLinesCount);
157 static SANE_Bool MustScanner_GetRgb24BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
158 						unsigned short * wLinesCount);
159 static SANE_Bool MustScanner_GetMono16BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
160 					  unsigned short * wLinesCount);
161 static SANE_Bool MustScanner_GetMono16BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
162 						 unsigned short * wLinesCount);
163 static SANE_Bool MustScanner_GetMono8BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
164 					 unsigned short * wLinesCount);
165 static SANE_Bool MustScanner_GetMono8BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
166 						unsigned short * wLinesCount);
167 static SANE_Bool MustScanner_GetMono1BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
168 					 unsigned short * wLinesCount);
169 static SANE_Bool MustScanner_GetMono1BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
170 						unsigned short * wLinesCount);
171 static void *MustScanner_ReadDataFromScanner (void * dummy);
172 static void MustScanner_PrepareCalculateMaxMin (unsigned short wResolution);
173 static void MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * lpMaxValue,
174 					 unsigned short * lpMinValue, unsigned short wResolution);
175 
176 static SANE_Byte QBET4 (SANE_Byte A, SANE_Byte B);
177 static unsigned int GetScannedLines (void);
178 static unsigned int GetReadyLines (void);
179 static void AddScannedLines (unsigned short wAddLines);
180 static void AddReadyLines (void);
181 static void ModifyLinePoint (SANE_Byte * lpImageData,
182 			     SANE_Byte * lpImageDataBefore,
183 			     unsigned int dwBytesPerLine,
184 			     unsigned int dwLinesCount,
185 			     unsigned short wPixDistance, unsigned short wModPtCount);
186 
187 #include "mustek_usb2_reflective.c"
188 #include "mustek_usb2_transparent.c"
189 
190 /**********************************************************************
191 Author: Jack            Date: 2005/05/13
192 	Routine Description:
193 Parameters:
194 	none
195 Return value:
196 	if initialize the scanner success
197 	return TRUE
198 	else
199 	return FALSE
200 ***********************************************************************/
201 static SANE_Bool
MustScanner_Init()202 MustScanner_Init ()
203 {
204   DBG (DBG_FUNC, "MustScanner_Init: Call in\n");
205 
206   g_chip.firmwarestate = FS_NULL;
207   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
208     {
209       DBG (DBG_FUNC, "MustScanner_Init: Asic_Open return error\n");
210       return FALSE;
211     }
212 
213   if (SANE_STATUS_GOOD != Asic_Initialize (&g_chip))
214     {
215       DBG (DBG_FUNC, "MustScanner_Init: Asic_Initialize return error\n");
216       return FALSE;
217     }
218 
219   g_dwImageBufferSize = 24L * 1024L * 1024L;
220   g_dwBufferSize = 64L * 1024L;
221   g_dwCalibrationSize = 64L * 1024L;
222   g_lpReadImageHead = NULL;
223 
224   g_isCanceled = FALSE;
225   g_bFirstReadImage = TRUE;
226   g_bOpened = FALSE;
227   g_bPrepared = FALSE;
228   g_bSharpen = FALSE;
229 
230   g_isScanning = FALSE;
231   g_isSelfGamma = FALSE;
232   g_pGammaTable = NULL;
233 
234   if (NULL != g_pDeviceFile)
235     {
236       free (g_pDeviceFile);
237       g_pDeviceFile = NULL;
238     }
239 
240   g_ssScanSource = SS_Reflective;
241   g_PixelFlavor = PF_BlackIs0;
242 
243   Asic_Close (&g_chip);
244 
245   DBG (DBG_FUNC, "MustScanner_Init: leave MustScanner_Init\n");
246 
247   return TRUE;
248 }
249 
250 /**********************************************************************
251 Author: Jack            Date: 2005/05/13
252 Routine Description:
253 	check the scanner connect status
254 Parameters:
255 	none
256 Return value:
257 	if scanner's status is OK
258 	return TRUE
259 	else
260 	return FASLE
261 ***********************************************************************/
262 static SANE_Bool
MustScanner_GetScannerState()263 MustScanner_GetScannerState ()
264 {
265 
266   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
267     {
268       DBG (DBG_FUNC, "MustScanner_GetScannerState: Asic_Open return error\n");
269       return FALSE;
270     }
271   else
272     {
273       Asic_Close (&g_chip);
274       return TRUE;
275     }
276 }
277 
278 /**********************************************************************
279 Author: Jack            Date: 2005/05/13
280 Routine Description:
281 	Turn the lamp on or off
282 Parameters:
283 	isLampOn: turn the lamp on or off
284 	isTALampOn: turn the TA lamp on or off
285 Return value:
286 	if operation success
287 	return TRUE
288 	else
289 	return FALSE
290 ***********************************************************************/
291 static SANE_Bool
MustScanner_PowerControl(SANE_Bool isLampOn,SANE_Bool isTALampOn)292 MustScanner_PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn)
293 {
294   SANE_Bool hasTA;
295   DBG (DBG_FUNC, "MustScanner_PowerControl: Call in\n");
296   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
297     {
298       DBG (DBG_FUNC, "MustScanner_PowerControl: Asic_Open return error\n");
299       return FALSE;
300     }
301 
302   if (SANE_STATUS_GOOD != Asic_TurnLamp (&g_chip, isLampOn))
303     {
304       DBG (DBG_FUNC,
305 	   "MustScanner_PowerControl: Asic_TurnLamp return error\n");
306       return FALSE;
307     }
308 
309   if (SANE_STATUS_GOOD != Asic_IsTAConnected (&g_chip, &hasTA))
310     {
311       DBG (DBG_FUNC,
312 	   "MustScanner_PowerControl: Asic_IsTAConnected return error\n");
313       return FALSE;
314     }
315 
316   if (hasTA)
317     {
318       if (SANE_STATUS_GOOD != Asic_TurnTA (&g_chip, isTALampOn))
319 	{
320 	  DBG (DBG_FUNC,
321 	       "MustScanner_PowerControl: Asic_TurnTA return error\n");
322 	  return FALSE;
323 	}
324     }
325 
326   Asic_Close (&g_chip);
327 
328   DBG (DBG_FUNC,
329        "MustScanner_PowerControl: leave MustScanner_PowerControl\n");
330   return TRUE;
331 }
332 
333 /**********************************************************************
334 Author: Jack            Date: 2005/05/13
335 Routine Description:
336 	Turn the carriage home
337 Parameters:
338 	none
339 Return value:
340 	if the operation success
341 	return TRUE
342 	else
343 	return FALSE
344 ***********************************************************************/
345 static SANE_Bool
MustScanner_BackHome()346 MustScanner_BackHome ()
347 {
348   DBG (DBG_FUNC, "MustScanner_BackHome: call in \n");
349 
350   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
351     {
352       DBG (DBG_FUNC, "MustScanner_BackHome: Asic_Open return error\n");
353       return FALSE;
354     }
355 
356   if (SANE_STATUS_GOOD != Asic_CarriageHome (&g_chip, FALSE))
357     {
358       DBG (DBG_FUNC,
359 	   "MustScanner_BackHome: Asic_CarriageHome return error\n");
360       return FALSE;
361     }
362 
363   if (SANE_STATUS_GOOD != Asic_WaitUnitReady (&g_chip))
364     {
365       DBG (DBG_FUNC,
366 	   "MustScanner_BackHome: Asic_WaitUnitReady return error\n");
367       return FALSE;
368     }
369 
370   Asic_Close (&g_chip);
371 
372   DBG (DBG_FUNC, "MustScanner_BackHome: leave  MustScanner_BackHome\n");
373   return TRUE;
374 }
375 
376 /**********************************************************************
377 Author: Jack            Date: 2005/05/13
378 Routine Description:
379 	prepare the scan image
380 Parameters:
381 	bScanSource: the scan source
382 Return value:
383 	if operation is success
384 	return TRUE
385 	else
386 	return FALSE
387 ***********************************************************************/
388 static SANE_Bool
MustScanner_Prepare(SANE_Byte bScanSource)389 MustScanner_Prepare (SANE_Byte bScanSource)
390 {
391   DBG (DBG_FUNC, "MustScanner_Prepare: call in\n");
392 
393   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
394 
395 
396     {
397       DBG (DBG_FUNC, "MustScanner_Prepare: Asic_Open return error\n");
398       return FALSE;
399     }
400   if (SANE_STATUS_GOOD != Asic_WaitUnitReady (&g_chip))
401     {
402       DBG (DBG_FUNC,
403 	   "MustScanner_Prepare: Asic_WaitUnitReady return error\n");
404       return FALSE;
405     }
406 
407   if (SS_Reflective == bScanSource)
408     {
409       DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Reflective\n");
410       if (SANE_STATUS_GOOD != Asic_TurnLamp (&g_chip, TRUE))
411 	{
412 	  DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnLamp return error\n");
413 	  return FALSE;
414 	}
415 
416       if (SANE_STATUS_GOOD != Asic_SetSource (&g_chip, LS_REFLECTIVE))
417 	{
418 	  DBG (DBG_FUNC,
419 	       "MustScanner_Prepare: Asic_SetSource return error\n");
420 	  return FALSE;
421 	}
422     }
423   else if (SS_Positive == bScanSource)
424     {
425       DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Positive\n");
426       if (SANE_STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE))
427 	{
428 	  DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnTA return error\n");
429 	  return FALSE;
430 	}
431       if (SANE_STATUS_GOOD != Asic_SetSource (&g_chip, LS_POSITIVE))
432 	{
433 	  DBG (DBG_FUNC,
434 	       "MustScanner_Prepare: Asic_SetSource return error\n");
435 	  return FALSE;
436 	}
437     }
438   else if (SS_Negative == bScanSource)
439     {
440       DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Negative\n");
441 
442       if (SANE_STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE))
443 	{
444 	  DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnTA return error\n");
445 	  return FALSE;
446 	}
447 
448       if (SANE_STATUS_GOOD != Asic_SetSource (&g_chip, LS_NEGATIVE))
449 	{
450 	  DBG (DBG_FUNC,
451 	       "MustScanner_Prepare: Asic_SetSource return error\n");
452 	  return FALSE;
453 	}
454       DBG (DBG_FUNC, "MustScanner_Prepare: Asic_SetSource return good\n");
455     }
456 
457   Asic_Close (&g_chip);
458   g_bPrepared = TRUE;
459 
460   DBG (DBG_FUNC, "MustScanner_Prepare: leave MustScanner_Prepare\n");
461   return TRUE;
462 }
463 
464 #ifdef SANE_UNUSED
465 /**********************************************************************
466 Author: Jack             Date: 2005/05/15
467 Routine Description:
468 	Adjuest the offset
469 Parameters:
470 	nTimes: Adjuest offset the times
471 	bDirection: whether direction
472 	bOffset: the data of offset
473 	bLastMin: the last min data
474 	bLastOffset: the last offset data
475 	wMinValue: the min value of offset
476 	bOffsetUpperBound: the upper bound of offset
477 	bOffsetLowerBound: the lower bound of offset
478 	wStdMinLevel: the min level of offset
479 	wStdMaxLevel: the max level of offset
480 Return value:
481 	if the operation is success
482 	return TRUE
483 	else
484 	return FALSE
485 ***********************************************************************/
486 static SANE_Bool
MustScanner_AdjustOffset(int nTimes,SANE_Bool * bDirection,SANE_Byte * bOffset,SANE_Byte * bLastMin,SANE_Byte * bLastOffset,unsigned short * wMinValue,SANE_Byte * bOffsetUpperBound,SANE_Byte * bOffsetLowerBound,unsigned short wStdMinLevel,unsigned short wStdMaxLevel)487 MustScanner_AdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset,
488 			  SANE_Byte * bLastMin, SANE_Byte * bLastOffset,
489 			  unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound,
490 			  SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel,
491 			  unsigned short wStdMaxLevel)
492 {
493   if ((*wMinValue <= wStdMaxLevel) && (*wMinValue >= wStdMinLevel))
494     {
495       return TRUE;
496     }
497 
498   if (nTimes == 0)
499     {
500       *bLastMin = LOSANE_Byte (*wMinValue);
501       *bLastOffset = *bOffset;
502 
503       if (*wMinValue == 255)
504 	{
505 	  *bOffset = 0;
506 	}
507       else
508 	{
509 	  *bOffset = 255;
510 	}
511     }
512 
513   if (nTimes == 1)
514     {
515       if (*wMinValue > *bLastMin)
516 	{
517 	  if (*wMinValue > wStdMaxLevel && *bLastMin > wStdMaxLevel)
518 	    {
519 	      *bDirection = !(*bDirection);
520 	      return TRUE;
521 	    }
522 
523 	  if (*wMinValue < wStdMinLevel && *bLastMin < wStdMinLevel)
524 	    return TRUE;
525 	}
526 
527       if (*wMinValue < *bLastMin)
528 	{
529 	  if (*wMinValue < wStdMinLevel && *bLastMin < wStdMinLevel)
530 	    *bDirection = !(*bDirection);
531 
532 	  if (*wMinValue > wStdMaxLevel && *bLastMin > wStdMaxLevel)
533 	    return TRUE;
534 	}
535     }
536 
537   if (nTimes > 1)
538     {
539       if (*wMinValue > *bLastMin)
540 	{
541 	  SANE_Byte bTemp;
542 
543 	  bTemp = *bOffset;
544 
545 	  *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
546 
547 	  if (nTimes > 2)
548 	    {
549 	      if (*wMinValue > wStdMaxLevel)
550 		if (bDirection)
551 		  *bOffsetLowerBound = bTemp;
552 		else
553 		  *bOffsetUpperBound = bTemp;
554 
555 
556 	      else if (bDirection)
557 		*bOffsetUpperBound = bTemp;
558 	      else
559 		*bOffsetLowerBound = bTemp;
560 	    }
561 
562 	  *bLastOffset = bTemp;
563 	  *bLastMin = (SANE_Byte) * wMinValue;
564 	}
565       else
566 	{
567 	  SANE_Byte bTemp;
568 
569 	  bTemp = *bOffset;
570 
571 	  *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
572 
573 	  if (nTimes > 2)
574 	    {
575 	      if (*wMinValue == *bLastMin)
576 		{
577 		  if (*wMinValue > wStdMaxLevel)
578 		    {
579 		      if (!bDirection)
580 			*bOffsetUpperBound = bTemp;
581 		      else
582 			*bOffsetLowerBound = bTemp;
583 		    }
584 		  else
585 		    {
586 		      if (!bDirection)
587 			*bOffsetLowerBound = bTemp;
588 		      else
589 			*bOffsetUpperBound = bTemp;
590 		    }
591 		}
592 	      else
593 		{
594 		  if (*wMinValue > wStdMaxLevel)
595 		    {
596 		      if (bDirection)
597 			*bOffsetUpperBound = bTemp;
598 		      else
599 			*bOffsetLowerBound = bTemp;
600 		    }
601 		  else
602 		    {
603 		      if (bDirection)
604 			*bOffsetLowerBound = bTemp;
605 		      else
606 			*bOffsetUpperBound = bTemp;
607 		    }
608 		}
609 	    }
610 
611 	  *bLastOffset = bTemp;
612 	  *bLastMin = (SANE_Byte) * wMinValue;
613 
614 	}
615     }				/* end of if(nTimes > 1) */
616 
617   return TRUE;
618 }
619 #endif
620 
621 #ifdef SANE_UNUSED
622 /**********************************************************************
623 
624 Author: Jack             Date: 2005/05/15
625 Routine Description:
626 	Adjuest the offset second times
627 Parameters:
628 	nTimes: Adjuest offset the times
629 	bDirection: whether direction
630 	bOffset: the data of offset
631 	bLastMin: the last min data
632 	bLastOffset: the last offset data
633 	wMinValue: the min value of offset
634 	bOffsetUpperBound: the upper bound of offset
635 	bOffsetLowerBound: the lower bound of offset
636 	wStdMinLevel: the min level of offset
637 	wStdMaxLevel: the max level of offset
638 Return value:
639 	if the operation is success
640 	return TRUE
641 	else
642 	return FALSE
643 ***********************************************************************/
644 static SANE_Bool
MustScanner_SecondAdjustOffset(int nTimes,SANE_Bool * bDirection,SANE_Byte * bOffset,SANE_Byte * bLastMin,SANE_Byte * bLastOffset,unsigned short * wMinValue,SANE_Byte * bOffsetUpperBound,SANE_Byte * bOffsetLowerBound,unsigned short wStdMinLevel,unsigned short wStdMaxLevel)645 MustScanner_SecondAdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset,
646 				SANE_Byte * bLastMin, SANE_Byte * bLastOffset,
647 				unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound,
648 				SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel,
649 				unsigned short wStdMaxLevel)
650 {
651   if ((*wMinValue <= wStdMaxLevel) && (*wMinValue >= wStdMinLevel))
652     {
653       return TRUE;
654     }
655   if (nTimes == 0)
656     {
657       *bLastMin = LOSANE_Byte (*wMinValue);
658       *bLastOffset = *bOffset;
659 
660       if (*bDirection == 0)
661 	{
662 	  *bOffsetUpperBound = *bLastOffset;
663 	  *bOffsetLowerBound = 0;
664 	  *bOffset = 0;
665 	}
666       else
667 	{
668 	  *bOffsetUpperBound = 255;
669 	  *bOffsetLowerBound = *bLastOffset;
670 	  *bOffset = 255;
671 	}
672     }
673 
674   if (nTimes >= 1)
675     {
676       if (*wMinValue > wStdMaxLevel)
677 	{
678 	  if (*wMinValue > *bLastMin)
679 	    {
680 	      if (*bDirection == 0)
681 		{
682 		  *bOffsetUpperBound = *bOffset;
683 		}
684 	      else
685 		{
686 		  *bOffsetLowerBound = *bOffset;
687 		}
688 
689 	      *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
690 	    }
691 	  else
692 	    {
693 	      if (*bDirection == 1)
694 		{
695 		  *bOffsetUpperBound = *bOffset;
696 		  *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
697 		}
698 	      else
699 		{
700 		  *bOffsetLowerBound = *bOffset;
701 		  *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
702 		}
703 	    }
704 	}			/*end of if(*wMinValue > MAX_OFFSET) */
705 
706 
707       if (*wMinValue < wStdMinLevel)
708 	{
709 	  if (*wMinValue > *bLastMin)
710 	    {
711 	      if (*bDirection == 0)
712 		{
713 		  *bOffsetLowerBound = *bOffset;
714 		}
715 	      else
716 		{
717 		  *bOffsetUpperBound = *bOffset;
718 		}
719 
720 	      *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
721 	    }
722 	  else
723 	    {
724 	      if (*bDirection == 1)
725 		{
726 		  *bOffsetUpperBound = *bOffset;
727 		  *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
728 		}
729 	      else
730 		{
731 		  *bOffsetLowerBound = *bOffset;
732 		  *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
733 		}
734 	    }
735 	}			/*end of if(*wMinValue > MIN_OFFSET) */
736       *bLastMin = (SANE_Byte) * wMinValue;
737     }				/*end of if(nTimes >= 1)     */
738 
739   /* HOLD: missing return value! Correct? */
740   return FALSE;
741 }
742 #endif
743 
744 /**********************************************************************
745 Author: Jack             Date: 2005/05/15
746 Routine Description:
747 	Filter the data
748 Parameters:
749 	pSort: the sort data
750 	TotalCount: the total count
751 	LowCount: the low count
752 	HighCount: the upper count
753 Return value:
754 	the data of Filter
755 ***********************************************************************/
756 static unsigned short
MustScanner_FiltLower(unsigned short * pSort,unsigned short TotalCount,unsigned short LowCount,unsigned short HighCount)757 MustScanner_FiltLower (unsigned short * pSort, unsigned short TotalCount, unsigned short LowCount,
758 		       unsigned short HighCount)
759 {
760   unsigned short Bound = TotalCount - 1;
761   unsigned short LeftCount = HighCount - LowCount;
762   int Temp = 0;
763   unsigned int Sum = 0;
764   unsigned short i, j;
765 
766   for (i = 0; i < Bound; i++)
767 
768     {
769       for (j = 0; j < Bound - i; j++)
770 	{
771 	  if (pSort[j + 1] > pSort[j])
772 	    {
773 	      Temp = pSort[j];
774 	      pSort[j] = pSort[j + 1];
775 	      pSort[j + 1] = Temp;
776 	    }
777 	}
778     }
779 
780   for (i = 0; i < LeftCount; i++)
781     Sum += pSort[i + LowCount];
782   return (unsigned short) (Sum / LeftCount);
783 }
784 
785 /**********************************************************************
786 Author: Jack             Date: 2005/05/15
787 Routine Description:
788 	Repair line when single CCD and color is 48bit
789 Parameters:
790 	lpLine: point to image be repaired
791 	isOrderInvert: RGB or BGR
792 	wLinesCount: how many line be repaired
793 Return value:
794 	if the operation is success
795 	return TRUE
796 	else
797 	return FALSE
798 ***********************************************************************/
799 static SANE_Bool
MustScanner_GetRgb48BitLine(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)800 MustScanner_GetRgb48BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
801 			     unsigned short * wLinesCount)
802 {
803   unsigned short wWantedTotalLines;
804   unsigned short TotalXferLines;
805   unsigned short wRLinePos = 0;
806   unsigned short wGLinePos = 0;
807   unsigned short wBLinePos = 0;
808   unsigned short wRTempData;
809   unsigned short wGTempData;
810   unsigned short wBTempData;
811   unsigned short i;
812 
813   DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: call in \n");
814 
815   g_isCanceled = FALSE;
816   g_isScanning = TRUE;
817   wWantedTotalLines = *wLinesCount;
818   TotalXferLines = 0;
819 
820   if (g_bFirstReadImage)
821     {
822       pthread_create (&g_threadid_readimage, NULL,
823 		      MustScanner_ReadDataFromScanner, NULL);
824       DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread create\n");
825       g_bFirstReadImage = FALSE;
826     }
827 
828   if (!isOrderInvert)
829     {
830       for (; TotalXferLines < wWantedTotalLines;)
831 	{
832 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
833 	    {
834 	      pthread_cancel (g_threadid_readimage);
835 	      pthread_join (g_threadid_readimage, NULL);
836 	      DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
837 
838 	      *wLinesCount = TotalXferLines;
839 	      g_isScanning = FALSE;
840 	      return TRUE;
841 	    }
842 
843 	  if (GetScannedLines () > g_wtheReadyLines)
844 	    {
845 	      wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
846 	      wGLinePos =
847 		(g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
848 	      wBLinePos =
849 		(g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
850 
851 	      for (i = 0; i < g_SWWidth; i++)
852 		{
853 		  wRTempData =
854 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
855 		      0);
856 		  wRTempData +=
857 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
858 		      1) << 8;
859 		  wGTempData =
860 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
861 		      2);
862 		  wGTempData +=
863 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
864 		      3) << 8;
865 		  wBTempData =
866 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
867 		      4);
868 		  wBTempData +=
869 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
870 		      5) << 8;
871 		  *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wRTempData]);
872 		  *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wRTempData]);
873 		  *(lpLine + i * 6 + 2) =
874 		    LOBYTE (g_pGammaTable[wGTempData + 65536]);
875 		  *(lpLine + i * 6 + 3) =
876 		    HIBYTE (g_pGammaTable[wGTempData + 65536]);
877 		  *(lpLine + i * 6 + 4) =
878 		    LOBYTE (g_pGammaTable[wBTempData + 131072]);
879 		  *(lpLine + i * 6 + 5) =
880 		    HIBYTE (g_pGammaTable[wBTempData + 131072]);
881 		}
882 	      TotalXferLines++;
883 	      g_dwTotalTotalXferLines++;
884 	      lpLine += g_SWBytesPerRow;
885 	      AddReadyLines ();
886 	    }
887 
888 	  if (g_isCanceled)
889 	    {
890 	      pthread_cancel (g_threadid_readimage);
891 	      pthread_join (g_threadid_readimage, NULL);
892 
893 	      DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
894 
895 	      break;
896 	    }
897 	}
898     }
899   else
900     {
901       for (; TotalXferLines < wWantedTotalLines;)
902 	{
903 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
904 	    {
905 	      pthread_cancel (g_threadid_readimage);
906 	      pthread_join (g_threadid_readimage, NULL);
907 
908 	      DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
909 
910 
911 	      *wLinesCount = TotalXferLines;
912 	      g_isScanning = FALSE;
913 	      return TRUE;
914 	    }
915 
916 	  if (GetScannedLines () > g_wtheReadyLines)
917 	    {
918 	      wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
919 	      wGLinePos =
920 		(g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
921 	      wBLinePos =
922 		(g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
923 
924 	      for (i = 0; i < g_SWWidth; i++)
925 		{
926 		  wRTempData =
927 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
928 		      0);
929 		  wRTempData +=
930 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
931 		      1) << 8;
932 		  wGTempData =
933 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
934 		      2);
935 		  wGTempData +=
936 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
937 		      3) << 8;
938 		  wBTempData =
939 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
940 		      4);
941 		  wBTempData +=
942 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
943 		      5) << 8;
944 		  *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wRTempData]);
945 		  *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wRTempData]);
946 		  *(lpLine + i * 6 + 2) =
947 		    LOBYTE (g_pGammaTable[wGTempData + 65536]);
948 		  *(lpLine + i * 6 + 3) =
949 		    HIBYTE (g_pGammaTable[wGTempData + 65536]);
950 		  *(lpLine + i * 6 + 0) =
951 		    LOBYTE (g_pGammaTable[wBTempData + 131072]);
952 		  *(lpLine + i * 6 + 1) =
953 		    HIBYTE (g_pGammaTable[wBTempData + 131072]);
954 		}
955 
956 	      TotalXferLines++;
957 	      g_dwTotalTotalXferLines++;
958 	      lpLine += g_SWBytesPerRow;
959 	      AddReadyLines ();
960 
961 	    }
962 	  if (g_isCanceled)
963 	    {
964 	      pthread_cancel (g_threadid_readimage);
965 	      pthread_join (g_threadid_readimage, NULL);
966 
967 	      DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
968 	      break;
969 	    }
970 	}			/*end for */
971     }
972 
973   *wLinesCount = TotalXferLines;
974   g_isScanning = FALSE;
975 
976   DBG (DBG_FUNC,
977        "MustScanner_GetRgb48BitLine: leave MustScanner_GetRgb48BitLine\n");
978   return TRUE;
979 }
980 
981 /**********************************************************************
982 Author: Jack             Date: 2005/05/15
983 Routine Description:
984 	Repair line when double CCD and color is 48bit
985 Parameters:
986 	lpLine: point to image be repaired
987 	isOrderInvert: RGB or BGR
988 	wLinesCount: how many line be repaired
989 Return value:
990 	if the operation is success
991 	return TRUE
992 	else
993 	return FALSE
994 ***********************************************************************/
995 static SANE_Bool
MustScanner_GetRgb48BitLine1200DPI(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)996 MustScanner_GetRgb48BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
997 				    unsigned short * wLinesCount)
998 {
999   unsigned short wWantedTotalLines;
1000   unsigned short TotalXferLines;
1001 
1002   unsigned short wRLinePosOdd = 0;
1003   unsigned short wGLinePosOdd = 0;
1004   unsigned short wBLinePosOdd = 0;
1005   unsigned short wRLinePosEven = 0;
1006   unsigned short wGLinePosEven = 0;
1007   unsigned short wBLinePosEven = 0;
1008   unsigned int wRTempData;
1009   unsigned int wGTempData;
1010   unsigned int wBTempData;
1011   unsigned int wNextTempData;
1012   unsigned short i;
1013 
1014   DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: call in \n");
1015 
1016   TotalXferLines = 0;
1017   wWantedTotalLines = *wLinesCount;
1018 
1019   g_isCanceled = FALSE;
1020   g_isScanning = TRUE;
1021 
1022   if (g_bFirstReadImage)
1023     {
1024       pthread_create (&g_threadid_readimage, NULL,
1025 		      MustScanner_ReadDataFromScanner, NULL);
1026       DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread create\n");
1027       g_bFirstReadImage = FALSE;
1028     }
1029 
1030   if (!isOrderInvert)
1031     {
1032       for (; TotalXferLines < wWantedTotalLines;)
1033 	{
1034 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
1035 	    {
1036 	      pthread_cancel (g_threadid_readimage);
1037 	      pthread_join (g_threadid_readimage, NULL);
1038 	      DBG (DBG_FUNC,
1039 		   "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
1040 
1041 	      *wLinesCount = TotalXferLines;
1042 	      g_isScanning = FALSE;
1043 	      return TRUE;
1044 	    }
1045 
1046 	  if (GetScannedLines () > g_wtheReadyLines)
1047 	    {
1048 	      if (ST_Reflective == g_ScanType)
1049 		{
1050 		  wRLinePosOdd =
1051 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1052 		  wGLinePosOdd =
1053 		    (g_wtheReadyLines - g_wLineDistance -
1054 		     g_wPixelDistance) % g_wMaxScanLines;
1055 		  wBLinePosOdd =
1056 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1057 		     g_wPixelDistance) % g_wMaxScanLines;
1058 		  wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
1059 		  wGLinePosEven =
1060 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1061 		  wBLinePosEven =
1062 		    (g_wtheReadyLines -
1063 		     g_wLineDistance * 2) % g_wMaxScanLines;
1064 		}
1065 	      else
1066 		{
1067 		  wRLinePosEven =
1068 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1069 		  wGLinePosEven =
1070 		    (g_wtheReadyLines - g_wLineDistance -
1071 		     g_wPixelDistance) % g_wMaxScanLines;
1072 		  wBLinePosEven =
1073 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1074 		     g_wPixelDistance) % g_wMaxScanLines;
1075 		  wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
1076 		  wGLinePosOdd =
1077 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1078 		  wBLinePosOdd =
1079 		    (g_wtheReadyLines -
1080 		     g_wLineDistance * 2) % g_wMaxScanLines;
1081 		}
1082 
1083 	      for (i = 0; i < g_SWWidth;)
1084 		{
1085 		  if (i + 1 != g_SWWidth)
1086 		    {
1087 		      wRTempData =
1088 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1089 			  i * 6 + 0);
1090 		      wRTempData +=
1091 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1092 			  i * 6 + 1) << 8;
1093 		      wNextTempData =
1094 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1095 			  (i + 1) * 6 + 0);
1096 		      wNextTempData +=
1097 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1098 			  (i + 1) * 6 + 1) << 8;
1099 		      wRTempData = (wRTempData + wNextTempData) >> 1;
1100 
1101 		      wGTempData =
1102 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1103 			  i * 6 + 2);
1104 		      wGTempData +=
1105 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1106 			  i * 6 + 3) << 8;
1107 		      wNextTempData =
1108 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1109 			  (i + 1) * 6 + 2);
1110 		      wNextTempData +=
1111 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1112 			  (i + 1) * 6 + 3) << 8;
1113 		      wGTempData = (wGTempData + wNextTempData) >> 1;
1114 
1115 		      wBTempData =
1116 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1117 			  i * 6 + 4);
1118 		      wBTempData +=
1119 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1120 			  i * 6 + 5) << 8;
1121 		      wNextTempData =
1122 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1123 			  (i + 1) * 6 + 4);
1124 		      wNextTempData +=
1125 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1126 			  (i + 1) * 6 + 5) << 8;
1127 		      wBTempData = (wBTempData + wNextTempData) >> 1;
1128 
1129 		      *(lpLine + i * 6 + 0) =
1130 			LOBYTE (g_pGammaTable[wRTempData]);
1131 		      *(lpLine + i * 6 + 1) =
1132 			HIBYTE (g_pGammaTable[wRTempData]);
1133 		      *(lpLine + i * 6 + 2) =
1134 			LOBYTE (g_pGammaTable[wGTempData + 65536]);
1135 		      *(lpLine + i * 6 + 3) =
1136 			HIBYTE (g_pGammaTable[wGTempData + 65536]);
1137 		      *(lpLine + i * 6 + 4) =
1138 			LOBYTE (g_pGammaTable[wBTempData + 131072]);
1139 		      *(lpLine + i * 6 + 5) =
1140 			HIBYTE (g_pGammaTable[wBTempData + 131072]);
1141 		      i++;
1142 		      if (i >= g_SWWidth)
1143 			{
1144 			  break;
1145 			}
1146 
1147 		      wRTempData =
1148 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1149 			  i * 6 + 0);
1150 		      wRTempData +=
1151 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1152 			  i * 6 + 1) << 8;
1153 		      wNextTempData =
1154 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1155 			  (i + 1) * 6 + 0);
1156 		      wNextTempData +=
1157 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1158 			  (i + 1) * 6 + 1) << 8;
1159 		      wRTempData = (wRTempData + wNextTempData) >> 1;
1160 
1161 		      wGTempData =
1162 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1163 			  i * 6 + 2);
1164 		      wGTempData +=
1165 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1166 			  i * 6 + 3) << 8;
1167 		      wNextTempData =
1168 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1169 			  (i + 1) * 6 + 2);
1170 		      wNextTempData +=
1171 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1172 			  (i + 1) * 6 + 3) << 8;
1173 		      wGTempData = (wGTempData + wNextTempData) >> 1;
1174 
1175 		      wBTempData =
1176 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1177 			  i * 6 + 4);
1178 		      wBTempData +=
1179 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1180 			  i * 6 + 5) << 8;
1181 		      wNextTempData =
1182 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1183 			  (i + 1) * 6 + 4);
1184 		      wNextTempData +=
1185 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1186 			  (i + 1) * 6 + 5) << 8;
1187 		      wBTempData = (wBTempData + wNextTempData) >> 1;
1188 
1189 		      *(lpLine + i * 6 + 0) =
1190 			LOBYTE (g_pGammaTable[wRTempData]);
1191 		      *(lpLine + i * 6 + 1) =
1192 			HIBYTE (g_pGammaTable[wRTempData]);
1193 		      *(lpLine + i * 6 + 2) =
1194 			LOBYTE (g_pGammaTable[wGTempData + 65536]);
1195 		      *(lpLine + i * 6 + 3) =
1196 			HIBYTE (g_pGammaTable[wGTempData + 65536]);
1197 		      *(lpLine + i * 6 + 4) =
1198 			LOBYTE (g_pGammaTable[wBTempData + 131072]);
1199 		      *(lpLine + i * 6 + 5) =
1200 			HIBYTE (g_pGammaTable[wBTempData + 131072]);
1201 
1202 		      i++;
1203 		    }
1204 		}
1205 
1206 	      TotalXferLines++;
1207 	      g_dwTotalTotalXferLines++;
1208 	      lpLine += g_SWBytesPerRow;
1209 	      AddReadyLines ();
1210 	    }
1211 	  if (g_isCanceled)
1212 	    {
1213 	      pthread_cancel (g_threadid_readimage);
1214 	      pthread_join (g_threadid_readimage, NULL);
1215 	      DBG (DBG_FUNC,
1216 		   "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
1217 	      break;
1218 
1219 	    }
1220 	}
1221 
1222 
1223     }
1224   else
1225     {
1226       for (; TotalXferLines < wWantedTotalLines;)
1227 	{
1228 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
1229 	    {
1230 	      pthread_cancel (g_threadid_readimage);
1231 	      pthread_join (g_threadid_readimage, NULL);
1232 	      DBG (DBG_FUNC,
1233 		   "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
1234 
1235 	      *wLinesCount = TotalXferLines;
1236 	      g_isScanning = FALSE;
1237 	      return TRUE;
1238 	    }
1239 
1240 	  if (GetScannedLines () > g_wtheReadyLines)
1241 	    {
1242 	      if (ST_Reflective == g_ScanType)
1243 		{
1244 		  wRLinePosOdd =
1245 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1246 		  wGLinePosOdd =
1247 		    (g_wtheReadyLines - g_wLineDistance -
1248 		     g_wPixelDistance) % g_wMaxScanLines;
1249 		  wBLinePosOdd =
1250 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1251 		     g_wPixelDistance) % g_wMaxScanLines;
1252 		  wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
1253 		  wGLinePosEven =
1254 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1255 		  wBLinePosEven =
1256 		    (g_wtheReadyLines -
1257 		     g_wLineDistance * 2) % g_wMaxScanLines;
1258 		}
1259 	      else
1260 		{
1261 		  wRLinePosEven =
1262 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1263 		  wGLinePosEven =
1264 		    (g_wtheReadyLines - g_wLineDistance -
1265 		     g_wPixelDistance) % g_wMaxScanLines;
1266 		  wBLinePosEven =
1267 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1268 		     g_wPixelDistance) % g_wMaxScanLines;
1269 		  wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
1270 		  wGLinePosOdd =
1271 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1272 		  wBLinePosOdd =
1273 		    (g_wtheReadyLines -
1274 		     g_wLineDistance * 2) % g_wMaxScanLines;
1275 		}
1276 
1277 	      for (i = 0; i < g_SWWidth;)
1278 		{
1279 		  if ((i + 1) != g_SWWidth)
1280 		    {
1281 		      wRTempData =
1282 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1283 			  i * 6 + 0);
1284 		      wRTempData +=
1285 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1286 			  i * 6 + 1) << 8;
1287 		      wNextTempData =
1288 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1289 			  (i + 1) * 6 + 0);
1290 		      wNextTempData +=
1291 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1292 			  (i + 1) * 6 + 1) << 8;
1293 		      wRTempData = (wRTempData + wNextTempData) >> 1;
1294 
1295 		      wGTempData =
1296 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1297 			  i * 6 + 2);
1298 		      wGTempData +=
1299 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1300 			  i * 6 + 3) << 8;
1301 		      wNextTempData =
1302 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1303 			  (i + 1) * 6 + 2);
1304 		      wNextTempData +=
1305 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1306 			  (i + 1) * 6 + 3) << 8;
1307 		      wGTempData = (wGTempData + wNextTempData) >> 1;
1308 
1309 		      wBTempData =
1310 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1311 			  i * 6 + 4);
1312 		      wBTempData +=
1313 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1314 			  i * 6 + 5) << 8;
1315 		      wNextTempData =
1316 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1317 			  (i + 1) * 6 + 4);
1318 		      wNextTempData +=
1319 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1320 			  (i + 1) * 6 + 5) << 8;
1321 		      wBTempData = (wBTempData + wNextTempData) >> 1;
1322 
1323 		      *(lpLine + i * 6 + 4) =
1324 			LOBYTE (g_pGammaTable[wRTempData]);
1325 		      *(lpLine + i * 6 + 5) =
1326 			HIBYTE (g_pGammaTable[wRTempData]);
1327 		      *(lpLine + i * 6 + 2) =
1328 			LOBYTE (g_pGammaTable[wGTempData + 65536]);
1329 		      *(lpLine + i * 6 + 3) =
1330 			HIBYTE (g_pGammaTable[wGTempData + 65536]);
1331 		      *(lpLine + i * 6 + 0) =
1332 			LOBYTE (g_pGammaTable[wBTempData + 131072]);
1333 		      *(lpLine + i * 6 + 1) =
1334 			HIBYTE (g_pGammaTable[wBTempData + 131072]);
1335 		      i++;
1336 		      if (i >= g_SWWidth)
1337 			{
1338 			  break;
1339 			}
1340 
1341 		      wRTempData =
1342 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1343 			  i * 6 + 0);
1344 		      wRTempData +=
1345 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1346 			  i * 6 + 1) << 8;
1347 		      wNextTempData =
1348 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1349 			  (i + 1) * 6 + 0);
1350 		      wNextTempData +=
1351 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1352 			  (i + 1) * 6 + 1) << 8;
1353 		      wRTempData = (wRTempData + wNextTempData) >> 1;
1354 
1355 		      wGTempData =
1356 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1357 			  i * 6 + 2);
1358 		      wGTempData +=
1359 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1360 			  i * 6 + 3) << 8;
1361 		      wNextTempData =
1362 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1363 			  (i + 1) * 6 + 2);
1364 		      wNextTempData +=
1365 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1366 			  (i + 1) * 6 + 3) << 8;
1367 		      wGTempData = (wGTempData + wNextTempData) >> 1;
1368 
1369 
1370 		      wBTempData =
1371 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1372 			  i * 6 + 4);
1373 		      wBTempData +=
1374 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1375 			  i * 6 + 5) << 8;
1376 		      wNextTempData =
1377 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1378 			  (i + 1) * 6 + 4);
1379 		      wNextTempData +=
1380 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1381 			  (i + 1) * 6 + 5) << 8;
1382 		      wBTempData = (wBTempData + wNextTempData) >> 1;
1383 
1384 		      *(lpLine + i * 6 + 4) =
1385 			LOBYTE (g_pGammaTable[wRTempData]);
1386 		      *(lpLine + i * 6 + 5) =
1387 			HIBYTE (g_pGammaTable[wRTempData]);
1388 		      *(lpLine + i * 6 + 2) =
1389 			LOBYTE (g_pGammaTable[wGTempData + 65536]);
1390 		      *(lpLine + i * 6 + 3) =
1391 			HIBYTE (g_pGammaTable[wGTempData + 65536]);
1392 		      *(lpLine + i * 6 + 0) =
1393 			LOBYTE (g_pGammaTable[wBTempData + 131072]);
1394 		      *(lpLine + i * 6 + 1) =
1395 			HIBYTE (g_pGammaTable[wBTempData + 131072]);
1396 		      i++;
1397 		    }
1398 		}
1399 
1400 	      TotalXferLines++;
1401 	      g_dwTotalTotalXferLines++;
1402 	      lpLine += g_SWBytesPerRow;
1403 	      AddReadyLines ();
1404 	    }
1405 	  if (g_isCanceled)
1406 	    {
1407 	      pthread_cancel (g_threadid_readimage);
1408 	      pthread_join (g_threadid_readimage, NULL);
1409 
1410 	      DBG (DBG_FUNC,
1411 		   "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
1412 
1413 	      break;
1414 	    }
1415 	}
1416     }
1417 
1418   *wLinesCount = TotalXferLines;
1419   g_isScanning = FALSE;
1420 
1421   DBG (DBG_FUNC,
1422        "MustScanner_GetRgb48BitLine1200DPI: leave MustScanner_GetRgb48BitLine1200DPI\n");
1423   return TRUE;
1424 }
1425 
1426 /**********************************************************************
1427 Author: Jack             Date: 2005/05/15
1428 Routine Description:
1429 	Repair line when single CCD and color is 24bit
1430 Parameters:
1431 	lpLine: point to image be repaired
1432 	isOrderInvert: RGB or BGR
1433 	wLinesCount: how many line be repaired
1434 Return value:
1435 	if the operation is success
1436 	return TRUE
1437 	else
1438 	return FALSE
1439 ***********************************************************************/
1440 static SANE_Bool
MustScanner_GetRgb24BitLine(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)1441 MustScanner_GetRgb24BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
1442 			     unsigned short * wLinesCount)
1443 {
1444   unsigned short wWantedTotalLines;
1445   unsigned short TotalXferLines;
1446   unsigned short wRLinePos = 0;
1447   unsigned short wGLinePos = 0;
1448   unsigned short wBLinePos = 0;
1449   SANE_Byte byRed;
1450   SANE_Byte byGreen;
1451   SANE_Byte byBlue;
1452   SANE_Byte bNextPixel = 0;
1453   unsigned short i;
1454 
1455   unsigned short tempR, tempG, tempB;
1456 
1457   DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: call in\n");
1458 
1459   g_isCanceled = FALSE;
1460   g_isScanning = TRUE;
1461 
1462   wWantedTotalLines = *wLinesCount;
1463   DBG (DBG_FUNC,
1464        "MustScanner_GetRgb24BitLine: get wWantedTotalLines= %d\n",
1465        wWantedTotalLines);
1466 
1467   TotalXferLines = 0;
1468 
1469   if (g_bFirstReadImage)
1470     {
1471       pthread_create (&g_threadid_readimage, NULL,
1472 		      MustScanner_ReadDataFromScanner, NULL);
1473       DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread create\n");
1474 
1475       g_bFirstReadImage = FALSE;
1476     }
1477 
1478   if (!isOrderInvert)
1479     {
1480       DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: !isOrderInvert\n");
1481 
1482       for (; TotalXferLines < wWantedTotalLines;)
1483 	{
1484 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
1485 	    {
1486 	      pthread_cancel (g_threadid_readimage);
1487 	      pthread_join (g_threadid_readimage, NULL);
1488 	      DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
1489 
1490 	      *wLinesCount = TotalXferLines;
1491 	      g_isScanning = FALSE;
1492 	      return TRUE;
1493 	    }
1494 
1495 	  if (GetScannedLines () > g_wtheReadyLines)
1496 	    {
1497 	      wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
1498 	      wGLinePos =
1499 		(g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1500 	      wBLinePos =
1501 		(g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
1502 
1503 	      for (i = 0; i < g_SWWidth; i++)
1504 		{
1505 		  byRed =
1506 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 3 +
1507 		      0);
1508 		  bNextPixel =
1509 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow +
1510 		      (i + 1) * 3 + 0);
1511 		  byRed = (byRed + bNextPixel) >> 1;
1512 
1513 		  byGreen =
1514 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 3 +
1515 		      1);
1516 		  bNextPixel =
1517 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow +
1518 		      (i + 1) * 3 + 1);
1519 		  byGreen = (byGreen + bNextPixel) >> 1;
1520 
1521 		  byBlue =
1522 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 3 +
1523 		      2);
1524 		  bNextPixel =
1525 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow +
1526 		      (i + 1) * 3 + 2);
1527 		  byBlue = (byBlue + bNextPixel) >> 1;
1528 
1529 #ifdef ENABLE_GAMMA
1530 		  tempR = (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen));
1531 		  tempG = (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue));
1532 		  tempB = (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed));
1533 
1534 		  *(lpLine + i * 3 + 0) =
1535 		    (unsigned char) (*(g_pGammaTable + tempR));
1536 		  *(lpLine + i * 3 + 1) =
1537 		    (unsigned char) (*(g_pGammaTable + 4096 + tempG));
1538 		  *(lpLine + i * 3 + 2) =
1539 		    (unsigned char) (*(g_pGammaTable + 8192 + tempB));
1540 #else
1541 		  *(lpLine + i * 3 + 0) = (unsigned char) byRed;
1542 		  *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
1543 		  *(lpLine + i * 3 + 2) = (unsigned char) byBlue;
1544 #endif
1545 		}
1546 
1547 	      TotalXferLines++;
1548 	      g_dwTotalTotalXferLines++;
1549 	      lpLine += g_SWBytesPerRow;
1550 	      AddReadyLines ();
1551 
1552 	      DBG (DBG_FUNC,
1553 		   "MustScanner_GetRgb24BitLine: g_dwTotalTotalXferLines=%d,g_SWHeight=%d\n",
1554 		   g_dwTotalTotalXferLines, g_SWHeight);
1555 	      DBG (DBG_FUNC,
1556 		   "MustScanner_GetRgb24BitLine: g_SWBytesPerRow=%d\n",
1557 		   g_SWBytesPerRow);
1558 	    }
1559 	  if (g_isCanceled)
1560 	    {
1561 	      pthread_cancel (g_threadid_readimage);
1562 	      pthread_join (g_threadid_readimage, NULL);
1563 	      DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
1564 
1565 	      break;
1566 	    }
1567 	}
1568     }
1569   else
1570     {
1571       DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: isOrderInvert is TRUE\n");
1572       for (; TotalXferLines < wWantedTotalLines;)
1573 	{
1574 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
1575 	    {
1576 	      pthread_cancel (g_threadid_readimage);
1577 	      pthread_join (g_threadid_readimage, NULL);
1578 	      DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
1579 
1580 	      *wLinesCount = TotalXferLines;
1581 	      g_isScanning = FALSE;
1582 	      return TRUE;
1583 	    }
1584 
1585 	  if (GetScannedLines () > g_wtheReadyLines)
1586 	    {
1587 	      wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
1588 	      wGLinePos =
1589 		(g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1590 	      wBLinePos =
1591 		(g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
1592 
1593 	      for (i = 0; i < g_SWWidth; i++)
1594 		{
1595 		  DBG (DBG_FUNC,
1596 		       "MustScanner_GetRgb24BitLine: before byRed\n");
1597 		  byRed =
1598 		    *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 3 +
1599 		      0);
1600 		  bNextPixel = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + (i + 1) * 3 + 0);	/*R-channel */
1601 		  byRed = (byRed + bNextPixel) >> 1;
1602 
1603 		  DBG (DBG_FUNC,
1604 		       "MustScanner_GetRgb24BitLine: before byGreen\n");
1605 
1606 		  byGreen =
1607 		    *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 3 +
1608 		      1);
1609 		  bNextPixel = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + (i + 1) * 3 + 1);	/*G-channel */
1610 		  byGreen = (byGreen + bNextPixel) >> 1;
1611 
1612 		  DBG (DBG_FUNC,
1613 		       "MustScanner_GetRgb24BitLine: before byBlue\n");
1614 
1615 		  byBlue =
1616 		    *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 3 +
1617 		      2);
1618 		  bNextPixel = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + (i + 1) * 3 + 2);	/*B-channel */
1619 		  byBlue = (byBlue + bNextPixel) >> 1;
1620 
1621 
1622 		  DBG (DBG_FUNC,
1623 		       "MustScanner_GetRgb24BitLine: before set lpLine\n");
1624 		  DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: i=%d\n", i);
1625 #ifdef ENABLE_GAMMA
1626 		  *(lpLine + i * 3 + 2) =
1627 		    (unsigned
1628 		     char) (*(g_pGammaTable +
1629 			      (unsigned short) ((byRed << 4) |
1630 				      QBET4 (byBlue, byGreen))));
1631 		  *(lpLine + i * 3 + 1) =
1632 		    (unsigned
1633 		     char) (*(g_pGammaTable + 4096 +
1634 			      (unsigned short) ((byGreen << 4) |
1635 				      QBET4 (byRed, byBlue))));
1636 		  *(lpLine + i * 3 + 0) =
1637 		    (unsigned
1638 		     char) (*(g_pGammaTable + 8192 +
1639 			      (unsigned short) ((byBlue << 4) |
1640 				      QBET4 (byGreen, byRed))));
1641 #else
1642 		  *(lpLine + i * 3 + 2) = (unsigned char) byRed;
1643 		  *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
1644 		  *(lpLine + i * 3 + 0) = (unsigned char) byBlue;
1645 #endif
1646 		}
1647 
1648 	      TotalXferLines++;
1649 	      g_dwTotalTotalXferLines++;
1650 	      lpLine += g_SWBytesPerRow;
1651 	      AddReadyLines ();
1652 
1653 	      DBG (DBG_FUNC,
1654 		   "MustScanner_GetRgb24BitLine: g_dwTotalTotalXferLines=%d,g_SWHeight=%d\n",
1655 		   g_dwTotalTotalXferLines, g_SWHeight);
1656 	      DBG (DBG_FUNC,
1657 		   "MustScanner_GetRgb24BitLine: g_SWBytesPerRow=%d\n",
1658 		   g_SWBytesPerRow);
1659 	    }
1660 	  if (g_isCanceled)
1661 	    {
1662 	      pthread_cancel (g_threadid_readimage);
1663 	      pthread_join (g_threadid_readimage, NULL);
1664 	      DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
1665 
1666 	      break;
1667 	    }
1668 	}			/*end for */
1669     }
1670 
1671   *wLinesCount = TotalXferLines;
1672   g_isScanning = FALSE;
1673 
1674   DBG (DBG_FUNC,
1675        "MustScanner_GetRgb24BitLine: leave MustScanner_GetRgb24BitLine\n");
1676   return TRUE;
1677 }
1678 
1679 /**********************************************************************
1680 Author: Jack             Date: 2005/05/15
1681 Routine Description:
1682 	Repair line when double CCD and color is 24bit
1683 Parameters:
1684 	lpLine: point to image be repaired
1685 	isOrderInvert: RGB or BGR
1686 	wLinesCount: how many line be repaired
1687 Return value:
1688 	if the operation is success
1689 	return TRUE
1690 	else
1691 	return FALSE
1692 ***********************************************************************/
1693 static SANE_Bool
MustScanner_GetRgb24BitLine1200DPI(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)1694 MustScanner_GetRgb24BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
1695 				    unsigned short * wLinesCount)
1696 {
1697   unsigned short wWantedTotalLines;
1698   unsigned short TotalXferLines;
1699   unsigned short wRLinePosOdd = 0;
1700   unsigned short wGLinePosOdd = 0;
1701   unsigned short wBLinePosOdd = 0;
1702   unsigned short wRLinePosEven = 0;
1703   unsigned short wGLinePosEven = 0;
1704   unsigned short wBLinePosEven = 0;
1705   SANE_Byte byRed;
1706   SANE_Byte byGreen;
1707   SANE_Byte byBlue;
1708   SANE_Byte bNextPixel = 0;
1709   unsigned short i;
1710 
1711   DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: call in\n");
1712 
1713   g_isCanceled = FALSE;
1714   g_isScanning = TRUE;
1715   TotalXferLines = 0;
1716   wWantedTotalLines = *wLinesCount;
1717 
1718   if (g_bFirstReadImage)
1719     {
1720       pthread_create (&g_threadid_readimage, NULL,
1721 		      MustScanner_ReadDataFromScanner, NULL);
1722       DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread create\n");
1723 
1724       g_bFirstReadImage = FALSE;
1725     }
1726 
1727   if (!isOrderInvert)
1728     {
1729       for (; TotalXferLines < wWantedTotalLines;)
1730 	{
1731 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
1732 	    {
1733 	      DBG (DBG_FUNC,
1734 		   "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
1735 		   g_dwTotalTotalXferLines);
1736 	      DBG (DBG_FUNC,
1737 		   "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
1738 		   g_Height);
1739 
1740 	      pthread_cancel (g_threadid_readimage);
1741 	      pthread_join (g_threadid_readimage, NULL);
1742 	      DBG (DBG_FUNC,
1743 		   "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
1744 
1745 	      *wLinesCount = TotalXferLines;
1746 	      g_isScanning = FALSE;
1747 	      return TRUE;
1748 	    }
1749 
1750 	  if (GetScannedLines () > g_wtheReadyLines)
1751 	    {
1752 	      if (ST_Reflective == g_ScanType)
1753 		{
1754 		  wRLinePosOdd =
1755 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1756 		  wGLinePosOdd =
1757 		    (g_wtheReadyLines - g_wLineDistance -
1758 		     g_wPixelDistance) % g_wMaxScanLines;
1759 		  wBLinePosOdd =
1760 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1761 		     g_wPixelDistance) % g_wMaxScanLines;
1762 		  wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
1763 		  wGLinePosEven =
1764 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1765 		  wBLinePosEven =
1766 		    (g_wtheReadyLines -
1767 		     g_wLineDistance * 2) % g_wMaxScanLines;
1768 		}
1769 	      else
1770 		{
1771 		  wRLinePosEven =
1772 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1773 		  wGLinePosEven =
1774 		    (g_wtheReadyLines - g_wLineDistance -
1775 		     g_wPixelDistance) % g_wMaxScanLines;
1776 		  wBLinePosEven =
1777 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1778 		     g_wPixelDistance) % g_wMaxScanLines;
1779 		  wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
1780 		  wGLinePosOdd =
1781 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1782 		  wBLinePosOdd =
1783 		    (g_wtheReadyLines -
1784 		     g_wLineDistance * 2) % g_wMaxScanLines;
1785 		}
1786 
1787 
1788 
1789 	      for (i = 0; i < g_SWWidth;)
1790 		{
1791 		  if ((i + 1) != g_SWWidth)
1792 		    {
1793 		      byRed =
1794 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1795 			  i * 3 + 0);
1796 		      bNextPixel = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 3 + 0);	/*R-channel */
1797 		      byRed = (byRed + bNextPixel) >> 1;
1798 
1799 		      byGreen =
1800 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1801 			  i * 3 + 1);
1802 		      bNextPixel = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 3 + 1);	/*G-channel */
1803 		      byGreen = (byGreen + bNextPixel) >> 1;
1804 
1805 		      byBlue =
1806 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1807 			  i * 3 + 2);
1808 		      bNextPixel = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 3 + 2);	/*B-channel */
1809 		      byBlue = (byBlue + bNextPixel) >> 1;
1810 #ifdef ENABLE_GAMMA
1811 		      *(lpLine + i * 3 + 0) =
1812 			(unsigned
1813 			 char) (*(g_pGammaTable +
1814 				  (unsigned short) ((byRed << 4) |
1815 					  QBET4 (byBlue, byGreen))));
1816 		      *(lpLine + i * 3 + 1) =
1817 			(unsigned
1818 			 char) (*(g_pGammaTable + 4096 +
1819 				  (unsigned short) ((byGreen << 4) |
1820 					  QBET4 (byRed, byBlue))));
1821 		      *(lpLine + i * 3 + 2) =
1822 			(unsigned
1823 			 char) (*(g_pGammaTable + 8192 +
1824 				  (unsigned short) ((byBlue << 4) |
1825 					  QBET4 (byGreen, byRed))));
1826 #else
1827 		      *(lpLine + i * 3 + 0) = (unsigned char) byRed;
1828 		      *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
1829 		      *(lpLine + i * 3 + 2) = (unsigned char) byBlue;
1830 #endif
1831 
1832 		      i++;
1833 		      if (i >= g_SWWidth)
1834 			{
1835 			  break;
1836 			}
1837 
1838 		      byRed =
1839 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1840 			  i * 3 + 0);
1841 		      bNextPixel =
1842 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1843 			  (i + 1) * 3 + 0);
1844 		      byRed = (byRed + bNextPixel) >> 1;
1845 
1846 		      byGreen =
1847 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1848 			  i * 3 + 1);
1849 		      bNextPixel =
1850 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1851 			  (i + 1) * 3 + 1);
1852 		      byGreen = (byGreen + bNextPixel) >> 1;
1853 
1854 		      byBlue =
1855 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1856 			  i * 3 + 2);
1857 		      bNextPixel =
1858 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1859 			  (i + 1) * 3 + 2);
1860 		      byBlue = (byBlue + bNextPixel) >> 1;
1861 #ifdef ENABLE_GAMMA
1862 		      *(lpLine + i * 3 + 0) =
1863 			(unsigned
1864 			 char) (*(g_pGammaTable +
1865 				  (unsigned short) ((byRed << 4) |
1866 					  QBET4 (byBlue, byGreen))));
1867 		      *(lpLine + i * 3 + 1) =
1868 			(unsigned
1869 			 char) (*(g_pGammaTable + 4096 +
1870 				  (unsigned short) ((byGreen << 4) |
1871 					  QBET4 (byRed, byBlue))));
1872 		      *(lpLine + i * 3 + 2) =
1873 			(unsigned
1874 			 char) (*(g_pGammaTable + 8192 +
1875 				  (unsigned short) ((byBlue << 4) |
1876 					  QBET4 (byGreen, byRed))));
1877 #else
1878 		      *(lpLine + i * 3 + 0) = (unsigned char) byRed;
1879 		      *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
1880 		      *(lpLine + i * 3 + 2) = (unsigned char) byBlue;
1881 #endif
1882 		      i++;
1883 		    }
1884 		}
1885 
1886 
1887 	      TotalXferLines++;
1888 	      g_dwTotalTotalXferLines++;
1889 	      lpLine += g_SWBytesPerRow;
1890 	      AddReadyLines ();
1891 
1892 	      DBG (DBG_FUNC,
1893 		   "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
1894 		   g_dwTotalTotalXferLines);
1895 	      DBG (DBG_FUNC,
1896 		   "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
1897 		   g_Height);
1898 
1899 	    }
1900 	  if (g_isCanceled)
1901 	    {
1902 	      pthread_cancel (g_threadid_readimage);
1903 	      pthread_join (g_threadid_readimage, NULL);
1904 	      DBG (DBG_FUNC,
1905 		   "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
1906 
1907 	      break;
1908 	    }
1909 
1910 	}
1911     }
1912   else
1913     {
1914 
1915       for (; TotalXferLines < wWantedTotalLines;)
1916 	{
1917 	  if (g_dwTotalTotalXferLines >= g_SWHeight)
1918 	    {
1919 	      DBG (DBG_FUNC,
1920 		   "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
1921 		   g_dwTotalTotalXferLines);
1922 	      DBG (DBG_FUNC,
1923 		   "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
1924 		   g_Height);
1925 
1926 	      pthread_cancel (g_threadid_readimage);
1927 	      pthread_join (g_threadid_readimage, NULL);
1928 	      DBG (DBG_FUNC,
1929 		   "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
1930 
1931 	      *wLinesCount = TotalXferLines;
1932 	      g_isScanning = FALSE;
1933 	      return TRUE;
1934 	    }
1935 
1936 	  if (GetScannedLines () > g_wtheReadyLines)
1937 	    {
1938 	      if (ST_Reflective == g_ScanType)
1939 		{
1940 		  wRLinePosOdd =
1941 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1942 		  wGLinePosOdd =
1943 		    (g_wtheReadyLines - g_wLineDistance -
1944 		     g_wPixelDistance) % g_wMaxScanLines;
1945 		  wBLinePosOdd =
1946 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1947 		     g_wPixelDistance) % g_wMaxScanLines;
1948 		  wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
1949 		  wGLinePosEven =
1950 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1951 		  wBLinePosEven =
1952 		    (g_wtheReadyLines -
1953 		     g_wLineDistance * 2) % g_wMaxScanLines;
1954 		}
1955 	      else
1956 		{
1957 		  wRLinePosEven =
1958 		    (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
1959 		  wGLinePosEven =
1960 		    (g_wtheReadyLines - g_wLineDistance -
1961 		     g_wPixelDistance) % g_wMaxScanLines;
1962 		  wBLinePosEven =
1963 		    (g_wtheReadyLines - g_wLineDistance * 2 -
1964 		     g_wPixelDistance) % g_wMaxScanLines;
1965 		  wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
1966 		  wGLinePosOdd =
1967 		    (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
1968 		  wBLinePosOdd =
1969 		    (g_wtheReadyLines -
1970 		     g_wLineDistance * 2) % g_wMaxScanLines;
1971 		}
1972 
1973 	      for (i = 0; i < g_SWWidth;)
1974 		{
1975 		  if ((i + 1) != g_SWWidth)
1976 		    {
1977 		      byRed =
1978 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
1979 			  i * 3 + 0);
1980 		      bNextPixel =
1981 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
1982 			  (i + 1) * 3 + 0);
1983 		      byRed = (byRed + bNextPixel) >> 1;
1984 
1985 		      byGreen =
1986 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
1987 			  i * 3 + 1);
1988 		      bNextPixel =
1989 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
1990 			  (i + 1) * 3 + 1);
1991 		      byGreen = (byGreen + bNextPixel) >> 1;
1992 
1993 		      byBlue =
1994 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
1995 			  i * 3 + 2);
1996 		      bNextPixel =
1997 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
1998 			  (i + 1) * 3 + 2);
1999 		      byBlue = (byBlue + bNextPixel) >> 1;
2000 
2001 #ifdef ENABLE_GAMMA
2002 		      *(lpLine + i * 3 + 2) =
2003 			(unsigned
2004 			 char) (*(g_pGammaTable +
2005 				  (unsigned short) ((byRed << 4) |
2006 					  QBET4 (byBlue, byGreen))));
2007 		      *(lpLine + i * 3 + 1) =
2008 			(unsigned
2009 			 char) (*(g_pGammaTable + 4096 +
2010 				  (unsigned short) ((byGreen << 4) |
2011 					  QBET4 (byRed, byBlue))));
2012 		      *(lpLine + i * 3 + 0) =
2013 			(unsigned
2014 			 char) (*(g_pGammaTable + 8192 +
2015 				  (unsigned short) ((byBlue << 4) |
2016 					  QBET4 (byGreen, byRed))));
2017 #else
2018 		      *(lpLine + i * 3 + 2) = (unsigned char) byRed;
2019 		      *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
2020 		      *(lpLine + i * 3 + 0) = (unsigned char) byBlue;
2021 #endif
2022 		      i++;
2023 		      if (i >= g_SWWidth)
2024 			{
2025 			  break;
2026 			}
2027 
2028 		      byRed =
2029 			*(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
2030 			  i * 3 + 0);
2031 		      bNextPixel =
2032 			*(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
2033 			  (i + 1) * 3 + 0);
2034 		      byRed = (byRed + bNextPixel) >> 1;
2035 
2036 		      byGreen =
2037 			*(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
2038 			  i * 3 + 1);
2039 		      bNextPixel =
2040 			*(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
2041 			  (i + 1) * 3 + 1);
2042 		      byGreen = (byGreen + bNextPixel) >> 1;
2043 
2044 		      byBlue =
2045 			*(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
2046 			  i * 3 + 2);
2047 		      bNextPixel =
2048 			*(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
2049 			  (i + 1) * 3 + 2);
2050 		      byBlue = (byBlue + bNextPixel) >> 1;
2051 #ifdef ENABLE_GAMMA
2052 		      *(lpLine + i * 3 + 2) =
2053 			(unsigned
2054 			 char) (*(g_pGammaTable +
2055 				  (unsigned short) ((byRed << 4) |
2056 					  QBET4 (byBlue, byGreen))));
2057 		      *(lpLine + i * 3 + 1) =
2058 			(unsigned
2059 			 char) (*(g_pGammaTable + 4096 +
2060 				  (unsigned short) ((byGreen << 4) |
2061 					  QBET4 (byRed, byBlue))));
2062 		      *(lpLine + i * 3 + 0) =
2063 			(unsigned
2064 			 char) (*(g_pGammaTable + 8192 +
2065 				  (unsigned short) ((byBlue << 4) |
2066 					  QBET4 (byGreen, byRed))));
2067 #else
2068 		      *(lpLine + i * 3 + 2) = (unsigned char) byRed;
2069 		      *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
2070 		      *(lpLine + i * 3 + 0) = (unsigned char) byBlue;
2071 #endif
2072 		      i++;
2073 		    }
2074 		}
2075 
2076 	      TotalXferLines++;
2077 	      g_dwTotalTotalXferLines++;
2078 	      lpLine += g_SWBytesPerRow;
2079 	      AddReadyLines ();
2080 
2081 	      DBG (DBG_FUNC,
2082 		   "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
2083 		   g_dwTotalTotalXferLines);
2084 	      DBG (DBG_FUNC,
2085 		   "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
2086 		   g_Height);
2087 
2088 	    }
2089 	  if (g_isCanceled)
2090 	    {
2091 	      pthread_cancel (g_threadid_readimage);
2092 	      pthread_join (g_threadid_readimage, NULL);
2093 	      DBG (DBG_FUNC,
2094 		   "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
2095 
2096 
2097 	      break;
2098 	    }
2099 	}
2100     }
2101 
2102   *wLinesCount = TotalXferLines;
2103   g_isScanning = FALSE;
2104 
2105   DBG (DBG_FUNC,
2106        "MustScanner_GetRgb24BitLine1200DPI: leave MustScanner_GetRgb24BitLine1200DPI\n");
2107   return TRUE;
2108 }
2109 
2110 /**********************************************************************
2111 Author: Jack             Date: 2005/05/15
2112 Routine Description:
2113 	Repair line when single CCD and color is 16bit
2114 Parameters:
2115 	lpLine: point to image be repaired
2116 	isOrderInvert: RGB or BGR
2117 	wLinesCount: how many line be repaired
2118 Return value:
2119 	if the operation is success
2120 	return TRUE
2121 	else
2122 	return FALSE
2123 ***********************************************************************/
2124 static SANE_Bool
MustScanner_GetMono16BitLine(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)2125 MustScanner_GetMono16BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
2126 			      unsigned short * wLinesCount)
2127 {
2128   unsigned short wWantedTotalLines;
2129   unsigned short TotalXferLines;
2130   unsigned int wTempData;
2131 
2132   unsigned short wLinePos = 0;
2133   unsigned short i;
2134 
2135   (void) isOrderInvert;
2136 
2137   DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: call in\n");
2138 
2139   TotalXferLines = 0;
2140   g_isCanceled = FALSE;
2141   g_isScanning = TRUE;
2142   wWantedTotalLines = *wLinesCount;
2143 
2144   if (g_bFirstReadImage)
2145     {
2146       pthread_create (&g_threadid_readimage, NULL,
2147 		      MustScanner_ReadDataFromScanner, NULL);
2148       DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread create\n");
2149       g_bFirstReadImage = FALSE;
2150     }
2151 
2152   for (; TotalXferLines < wWantedTotalLines;)
2153     {
2154 
2155       if (g_dwTotalTotalXferLines >= g_SWHeight)
2156 	{
2157 	  pthread_cancel (g_threadid_readimage);
2158 	  pthread_join (g_threadid_readimage, NULL);
2159 	  DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread exit\n");
2160 
2161 	  *wLinesCount = TotalXferLines;
2162 	  g_isScanning = FALSE;
2163 	  return TRUE;
2164 	}
2165 
2166       if (GetScannedLines () > g_wtheReadyLines)
2167 	{
2168 	  wLinePos = g_wtheReadyLines % g_wMaxScanLines;
2169 
2170 	  for (i = 0; i < g_SWWidth; i++)
2171 	    {
2172 	      wTempData =
2173 		*(g_lpReadImageHead + wLinePos * g_BytesPerRow + i * 2 + 0);
2174 	      wTempData +=
2175 		*(g_lpReadImageHead + wLinePos * g_BytesPerRow + i * 2 +
2176 		  1) << 8;
2177 	      *(lpLine + i * 2 + 0) = LOBYTE (g_pGammaTable[wTempData]);
2178 	      *(lpLine + i * 2 + 1) = HIBYTE (g_pGammaTable[wTempData]);
2179 	    }
2180 
2181 	  TotalXferLines++;
2182 	  g_dwTotalTotalXferLines++;
2183 
2184 	  lpLine += g_SWBytesPerRow;
2185 	  AddReadyLines ();
2186 	}
2187       if (g_isCanceled)
2188 	{
2189 	  pthread_cancel (g_threadid_readimage);
2190 	  pthread_join (g_threadid_readimage, NULL);
2191 	  DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread exit\n");
2192 
2193 	  break;
2194 	}
2195     }
2196 
2197   *wLinesCount = TotalXferLines;
2198   g_isScanning = FALSE;
2199 
2200   DBG (DBG_FUNC,
2201        "MustScanner_GetMono16BitLine: leave MustScanner_GetMono16BitLine\n");
2202   return TRUE;
2203 }
2204 
2205 /**********************************************************************
2206 Author: Jack             Date: 2005/05/15
2207 Routine Description:
2208 	Repair line when double CCD and color is 16bit
2209 Parameters:
2210 	lpLine: point to image be repaired
2211 	isOrderInvert: RGB or BGR
2212 	wLinesCount: how many line be repaired
2213 Return value:
2214 	if the operation is success
2215 	return TRUE
2216 	else
2217 	return FALSE
2218 ***********************************************************************/
2219 static SANE_Bool
MustScanner_GetMono16BitLine1200DPI(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)2220 MustScanner_GetMono16BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
2221 				     unsigned short * wLinesCount)
2222 {
2223   unsigned short wWantedTotalLines;
2224   unsigned short TotalXferLines;
2225   unsigned int dwTempData;
2226   unsigned short wLinePosOdd = 0;
2227   unsigned short wLinePosEven = 0;
2228   unsigned short i;
2229   SANE_Byte * lpTemp = lpLine;
2230 
2231   (void) isOrderInvert;
2232   DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: call in\n");
2233 
2234   TotalXferLines = 0;
2235   g_isCanceled = FALSE;
2236   g_isScanning = TRUE;
2237   wWantedTotalLines = *wLinesCount;
2238 
2239   if (g_bFirstReadImage)
2240     {
2241       pthread_create (&g_threadid_readimage, NULL,
2242 		      MustScanner_ReadDataFromScanner, NULL);
2243       DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: thread create\n");
2244       g_bFirstReadImage = FALSE;
2245     }
2246 
2247   for (; TotalXferLines < wWantedTotalLines;)
2248     {
2249       if (g_dwTotalTotalXferLines >= g_SWHeight)
2250 	{
2251 	  pthread_cancel (g_threadid_readimage);
2252 	  pthread_join (g_threadid_readimage, NULL);
2253 	  DBG (DBG_FUNC,
2254 	       "MustScanner_GetMono16BitLine1200DPI: thread exit\n");
2255 
2256 	  *wLinesCount = TotalXferLines;
2257 	  g_isScanning = FALSE;
2258 	  return TRUE;
2259 	}
2260 
2261       if (GetScannedLines () > g_wtheReadyLines)
2262 	{
2263 	  if (ST_Reflective == g_ScanType)
2264 	    {
2265 	      wLinePosOdd =
2266 		(g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
2267 	      wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
2268 	    }
2269 	  else
2270 	    {
2271 	      wLinePosEven =
2272 		(g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
2273 	      wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
2274 	    }
2275 
2276 
2277 	  for (i = 0; i < g_SWWidth;)
2278 	    {
2279 	      if ((i + 1) != g_SWWidth)
2280 		{
2281 		  dwTempData =
2282 		    (unsigned int) (*
2283 			     (g_lpReadImageHead +
2284 			      wLinePosOdd * g_BytesPerRow + i * 2 + 0));
2285 		  dwTempData +=
2286 		    (unsigned int) (*
2287 			     (g_lpReadImageHead +
2288 			      wLinePosOdd * g_BytesPerRow + i * 2 + 1) << 8);
2289 		  dwTempData +=
2290 		    (unsigned int) (*
2291 			     (g_lpReadImageHead +
2292 			      wLinePosEven * g_BytesPerRow + (i + 1) * 2 +
2293 			      0));
2294 		  dwTempData +=
2295 		    (unsigned int) (*
2296 			     (g_lpReadImageHead +
2297 			      wLinePosEven * g_BytesPerRow + (i + 1) * 2 +
2298 			      1) << 8);
2299 		  dwTempData = g_pGammaTable[dwTempData >> 1];
2300 		  *(lpLine + i * 2 + 0) = LOBYTE ((unsigned short) dwTempData);
2301 		  *(lpLine + i * 2 + 1) = HIBYTE ((unsigned short) dwTempData);
2302 		  i++;
2303 		  if (i >= g_SWWidth)
2304 		    {
2305 		      break;
2306 		    }
2307 
2308 		  dwTempData =
2309 		    (unsigned int) (*
2310 			     (g_lpReadImageHead +
2311 			      wLinePosEven * g_BytesPerRow + i * 2 + 0));
2312 		  dwTempData +=
2313 		    (unsigned int) (*
2314 			     (g_lpReadImageHead +
2315 			      wLinePosEven * g_BytesPerRow + i * 2 + 1) << 8);
2316 		  dwTempData +=
2317 		    (unsigned int) (*
2318 			     (g_lpReadImageHead +
2319 			      wLinePosOdd * g_BytesPerRow + (i + 1) * 2 + 0));
2320 		  dwTempData +=
2321 		    (unsigned int) (*
2322 			     (g_lpReadImageHead +
2323 			      wLinePosOdd * g_BytesPerRow + (i + 1) * 2 +
2324 			      1) << 8);
2325 		  dwTempData = g_pGammaTable[dwTempData >> 1];
2326 		  *(lpLine + i * 2 + 0) = LOBYTE ((unsigned short) dwTempData);
2327 		  *(lpLine + i * 2 + 1) = HIBYTE ((unsigned short) dwTempData);
2328 		  i++;
2329 		}
2330 	    }
2331 
2332 	  TotalXferLines++;
2333 	  g_dwTotalTotalXferLines++;
2334 	  lpLine += g_SWBytesPerRow;
2335 	  AddReadyLines ();
2336 	}
2337       if (g_isCanceled)
2338 	{
2339 	  pthread_cancel (g_threadid_readimage);
2340 	  pthread_join (g_threadid_readimage, NULL);
2341 	  DBG (DBG_FUNC,
2342 	       "MustScanner_GetMono16BitLine1200DPI: thread exit\n");
2343 
2344 	  break;
2345 	}
2346     }
2347 
2348   *wLinesCount = TotalXferLines;
2349   g_isScanning = FALSE;
2350 
2351   /*for modify the last point */
2352   if (g_bIsFirstReadBefData)
2353     {
2354       g_lpBefLineImageData = (SANE_Byte *) malloc (g_SWBytesPerRow);
2355       if (NULL == g_lpBefLineImageData)
2356 	{
2357 	  return FALSE;
2358 	}
2359       memset (g_lpBefLineImageData, 0, g_SWBytesPerRow);
2360       memcpy (g_lpBefLineImageData, lpTemp, g_SWBytesPerRow);
2361       g_bIsFirstReadBefData = FALSE;
2362     }
2363 
2364   ModifyLinePoint (lpTemp, g_lpBefLineImageData, g_SWBytesPerRow,
2365 		   wWantedTotalLines, 2, 4);
2366 
2367   memcpy (g_lpBefLineImageData,
2368 	  lpTemp + (wWantedTotalLines - 1) * g_SWBytesPerRow,
2369 	  g_SWBytesPerRow);
2370   g_dwAlreadyGetLines += wWantedTotalLines;
2371   if (g_dwAlreadyGetLines >= g_SWHeight)
2372     {
2373       DBG (DBG_FUNC,
2374 	   "MustScanner_GetMono16BitLine1200DPI: free before line data!\n");
2375       free (g_lpBefLineImageData);
2376       g_lpBefLineImageData = NULL;
2377       g_dwAlreadyGetLines = 0;
2378       g_bIsFirstReadBefData = TRUE;
2379     }
2380 
2381   DBG (DBG_FUNC,
2382        "MustScanner_GetMono16BitLine1200DPI: leave MustScanner_GetMono16BitLine1200DPI\n");
2383   return TRUE;
2384 }
2385 
2386 /**********************************************************************
2387 Author: Jack             Date: 2005/05/15
2388 Routine Description:
2389 	Repair line when single CCD and color is 8bit
2390 Parameters:
2391 	lpLine: point to image be repaired
2392 	isOrderInvert: RGB or BGR
2393 	wLinesCount: how many line be repaired
2394 Return value:
2395 	if the operation is success
2396 	return TRUE
2397 	else
2398 	return FALSE
2399 ***********************************************************************/
2400 static SANE_Bool
MustScanner_GetMono8BitLine(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)2401 MustScanner_GetMono8BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
2402 			     unsigned short * wLinesCount)
2403 {
2404   unsigned short wWantedTotalLines;
2405   unsigned short TotalXferLines;
2406 
2407   unsigned short i;
2408   unsigned short wLinePos = 0;
2409 
2410   (void) isOrderInvert;
2411   DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: call in\n");
2412 
2413   TotalXferLines = 0;
2414   g_isCanceled = FALSE;
2415   g_isScanning = TRUE;
2416   wWantedTotalLines = *wLinesCount;
2417 
2418   if (g_bFirstReadImage)
2419     {
2420       pthread_create (&g_threadid_readimage, NULL,
2421 		      MustScanner_ReadDataFromScanner, NULL);
2422       DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread create\n");
2423       g_bFirstReadImage = FALSE;
2424     }
2425 
2426   for (; TotalXferLines < wWantedTotalLines;)
2427     {
2428       if (g_dwTotalTotalXferLines >= g_SWHeight)
2429 	{
2430 	  pthread_cancel (g_threadid_readimage);
2431 	  pthread_join (g_threadid_readimage, NULL);
2432 	  DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread exit\n");
2433 
2434 	  *wLinesCount = TotalXferLines;
2435 	  g_isScanning = FALSE;
2436 	  return TRUE;
2437 	}
2438 
2439       if (GetScannedLines () > g_wtheReadyLines)
2440 	{
2441 	  wLinePos = g_wtheReadyLines % g_wMaxScanLines;
2442 
2443 	  for (i = 0; i < g_SWWidth; i++)
2444 	    {
2445 	      *(lpLine + i) =
2446 		(SANE_Byte) * (g_pGammaTable +
2447 			  (unsigned short) ((*
2448 				   (g_lpReadImageHead +
2449 				    wLinePos * g_BytesPerRow +
2450 				    i) << 4) | (rand () & 0x0f)));
2451 	    }
2452 
2453 	  TotalXferLines++;
2454 	  g_dwTotalTotalXferLines++;
2455 	  lpLine += g_SWBytesPerRow;
2456 	  AddReadyLines ();
2457 
2458 	}
2459       if (g_isCanceled)
2460 	{
2461 	  pthread_cancel (g_threadid_readimage);
2462 	  pthread_join (g_threadid_readimage, NULL);
2463 	  DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread exit\n");
2464 
2465 	  break;
2466 	}
2467     }
2468 
2469   *wLinesCount = TotalXferLines;
2470   g_isScanning = FALSE;
2471 
2472   DBG (DBG_FUNC,
2473        "MustScanner_GetMono8BitLine: leave MustScanner_GetMono8BitLine\n");
2474   return TRUE;
2475 }
2476 
2477 /**********************************************************************
2478 Author: Jack             Date: 2005/05/15
2479 Routine Description:
2480 	Repair line when double CCD and color is 8bit
2481 Parameters:
2482 	lpLine: point to image be repaired
2483 	isOrderInvert: RGB or BGR
2484 	wLinesCount: how many line be repaired
2485 Return value:
2486 	if the operation is success
2487 	return TRUE
2488 	else
2489 	return FALSE
2490 ***********************************************************************/
2491 static SANE_Bool
MustScanner_GetMono8BitLine1200DPI(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)2492 MustScanner_GetMono8BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
2493 				    unsigned short * wLinesCount)
2494 {
2495   SANE_Byte *lpTemp;
2496   unsigned short wWantedTotalLines;
2497   unsigned short TotalXferLines;
2498 
2499   unsigned short wLinePosOdd = 0;
2500   unsigned short wLinePosEven = 0;
2501   SANE_Byte byGray;
2502   unsigned short i;
2503   SANE_Byte bNextPixel = 0;
2504 
2505   (void) isOrderInvert;
2506   DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: call in\n");
2507 
2508   TotalXferLines = 0;
2509   g_isCanceled = FALSE;
2510   g_isScanning = TRUE;
2511   wWantedTotalLines = *wLinesCount;
2512   lpTemp = lpLine;
2513 
2514   if (g_bFirstReadImage)
2515     {
2516       pthread_create (&g_threadid_readimage, NULL,
2517 		      MustScanner_ReadDataFromScanner, NULL);
2518       DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread create\n");
2519       g_bFirstReadImage = FALSE;
2520     }
2521 
2522   for (; TotalXferLines < wWantedTotalLines;)
2523     {
2524       if (g_dwTotalTotalXferLines >= g_SWHeight)
2525 	{
2526 	  pthread_cancel (g_threadid_readimage);
2527 	  pthread_join (g_threadid_readimage, NULL);
2528 	  DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread exit\n");
2529 
2530 	  *wLinesCount = TotalXferLines;
2531 	  g_isScanning = FALSE;
2532 	  return TRUE;
2533 	}
2534 
2535       if (GetScannedLines () > g_wtheReadyLines)
2536 	{
2537 	  if (ST_Reflective == g_ScanType)
2538 
2539 	    {
2540 	      wLinePosOdd =
2541 		(g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
2542 	      wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
2543 	    }
2544 	  else
2545 	    {
2546 	      wLinePosEven =
2547 		(g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
2548 	      wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
2549 	    }
2550 
2551 
2552 	  for (i = 0; i < g_SWWidth;)
2553 	    {
2554 	      if ((i + 1) != g_SWWidth)
2555 		{
2556 		  byGray =
2557 		    *(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i);
2558 		  bNextPixel =
2559 		    *(g_lpReadImageHead + wLinePosEven * g_BytesPerRow +
2560 		      (i + 1));
2561 		  byGray = (byGray + bNextPixel) >> 1;
2562 
2563 		  *(lpLine + i) =
2564 		    (SANE_Byte) * (g_pGammaTable +
2565 			      (byGray << 4 | (rand () & 0x0f)));
2566 		  i++;
2567 		  if (i >= g_SWWidth)
2568 		    {
2569 		      break;
2570 		    }
2571 
2572 		  byGray =
2573 		    *(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i);
2574 		  bNextPixel =
2575 		    *(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow +
2576 		      (i + 1));
2577 		  byGray = (byGray + bNextPixel) >> 1;
2578 
2579 		  *(lpLine + i) =
2580 		    (SANE_Byte) * (g_pGammaTable +
2581 			      (byGray << 4 | (rand () & 0x0f)));
2582 		  i++;
2583 		}
2584 	    }
2585 
2586 	  TotalXferLines++;
2587 	  g_dwTotalTotalXferLines++;
2588 	  lpLine += g_SWBytesPerRow;
2589 	  AddReadyLines ();
2590 	}
2591       if (g_isCanceled)
2592 	{
2593 	  pthread_cancel (g_threadid_readimage);
2594 	  pthread_join (g_threadid_readimage, NULL);
2595 	  DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread exit\n");
2596 
2597 	  break;
2598 	}
2599     }
2600 
2601 
2602   *wLinesCount = TotalXferLines;
2603   g_isScanning = FALSE;
2604 
2605   /*for modify the last point */
2606   if (g_bIsFirstReadBefData)
2607     {
2608       g_lpBefLineImageData = (SANE_Byte *) malloc (g_SWBytesPerRow);
2609       if (NULL == g_lpBefLineImageData)
2610 	{
2611 	  return FALSE;
2612 	}
2613       memset (g_lpBefLineImageData, 0, g_SWBytesPerRow);
2614       memcpy (g_lpBefLineImageData, lpTemp, g_SWBytesPerRow);
2615       g_bIsFirstReadBefData = FALSE;
2616     }
2617 
2618   ModifyLinePoint (lpTemp, g_lpBefLineImageData, g_SWBytesPerRow,
2619 		   wWantedTotalLines, 1, 4);
2620 
2621   memcpy (g_lpBefLineImageData,
2622 	  lpTemp + (wWantedTotalLines - 1) * g_SWBytesPerRow,
2623 	  g_SWBytesPerRow);
2624   g_dwAlreadyGetLines += wWantedTotalLines;
2625   if (g_dwAlreadyGetLines >= g_SWHeight)
2626     {
2627       DBG (DBG_FUNC,
2628 	   "MustScanner_GetMono8BitLine1200DPI: free the before line data!\n");
2629       free (g_lpBefLineImageData);
2630       g_lpBefLineImageData = NULL;
2631       g_dwAlreadyGetLines = 0;
2632       g_bIsFirstReadBefData = TRUE;
2633     }
2634 
2635   DBG (DBG_FUNC,
2636        "MustScanner_GetMono8BitLine1200DPI: leave MustScanner_GetMono8BitLine1200DPI\n");
2637   return TRUE;
2638 }
2639 
2640 /**********************************************************************
2641 Author: Jack             Date: 2005/05/15
2642 Routine Description:
2643 	Repair line when single CCD and color is 1bit
2644 Parameters:
2645 	lpLine: point to image be repaired
2646 	isOrderInvert: RGB or BGR
2647 	wLinesCount: how many line be repaired
2648 Return value:
2649 	if the operation is success
2650 	return TRUE
2651 	else
2652 	return FALSE
2653 ***********************************************************************/
2654 static SANE_Bool
MustScanner_GetMono1BitLine(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)2655 MustScanner_GetMono1BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
2656 			     unsigned short * wLinesCount)
2657 {
2658   unsigned short wWantedTotalLines;
2659   unsigned short TotalXferLines;
2660   unsigned short wLinePos;
2661   unsigned short i;
2662 
2663   (void) isOrderInvert;
2664 
2665   DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: call in\n");
2666 
2667   g_isCanceled = FALSE;
2668   g_isScanning = TRUE;
2669   wWantedTotalLines = *wLinesCount;
2670 
2671   if (g_bFirstReadImage)
2672     {
2673       pthread_create (&g_threadid_readimage, NULL,
2674 		      MustScanner_ReadDataFromScanner, NULL);
2675       DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread create\n");
2676       g_bFirstReadImage = FALSE;
2677     }
2678 
2679   memset (lpLine, 0, wWantedTotalLines * g_SWWidth / 8);
2680 
2681   for (TotalXferLines = 0; TotalXferLines < wWantedTotalLines;)
2682 
2683     {
2684       if (g_dwTotalTotalXferLines >= g_SWHeight)
2685 	{
2686 	  pthread_cancel (g_threadid_readimage);
2687 	  pthread_join (g_threadid_readimage, NULL);
2688 	  DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread exit\n");
2689 
2690 	  *wLinesCount = TotalXferLines;
2691 	  g_isScanning = FALSE;
2692 	  return TRUE;
2693 	}
2694 
2695       if (GetScannedLines () > g_wtheReadyLines)
2696 	{
2697 	  wLinePos = g_wtheReadyLines % g_wMaxScanLines;
2698 
2699 	  for (i = 0; i < g_SWWidth; i++)
2700 	    {
2701 	      if (*(g_lpReadImageHead + wLinePos * g_BytesPerRow + i) >
2702 		  g_wLineartThreshold)
2703 		{
2704 		  *(lpLine + i / 8) += (0x80 >> (i % 8));
2705 		}
2706 	    }
2707 
2708 	  TotalXferLines++;
2709 	  g_dwTotalTotalXferLines++;
2710 	  lpLine += (g_SWBytesPerRow / 8);
2711 	  AddReadyLines ();
2712 	}
2713       if (g_isCanceled)
2714 	{
2715 	  pthread_cancel (g_threadid_readimage);
2716 	  pthread_join (g_threadid_readimage, NULL);
2717 	  DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread exit\n");
2718 
2719 	  break;
2720 	}
2721     }
2722 
2723   *wLinesCount = TotalXferLines;
2724   g_isScanning = FALSE;
2725 
2726   DBG (DBG_FUNC,
2727        "MustScanner_GetMono1BitLine: leave MustScanner_GetMono1BitLine\n");
2728   return TRUE;
2729 }
2730 
2731 /**********************************************************************
2732 Author: Jack             Date: 2005/05/15
2733 Routine Description:
2734 	Repair line when double CCD and color is 1bit
2735 Parameters:
2736 	lpLine: point to image be repaired
2737 	isOrderInvert: RGB or BGR
2738 	wLinesCount: how many line be repaired
2739 Return value:
2740 	if the operation is success
2741 	return TRUE
2742 	else
2743 	return FALSE
2744 ***********************************************************************/
2745 static SANE_Bool
MustScanner_GetMono1BitLine1200DPI(SANE_Byte * lpLine,SANE_Bool isOrderInvert,unsigned short * wLinesCount)2746 MustScanner_GetMono1BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
2747 				    unsigned short * wLinesCount)
2748 {
2749   unsigned short wWantedTotalLines;
2750   unsigned short TotalXferLines;
2751   unsigned short i;
2752   unsigned short wLinePosOdd;
2753   unsigned short wLinePosEven;
2754 
2755   (void) isOrderInvert;
2756 
2757   DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: call in\n");
2758 
2759   g_isCanceled = FALSE;
2760   g_isScanning = TRUE;
2761   wWantedTotalLines = *wLinesCount;
2762 
2763   if (g_bFirstReadImage)
2764     {
2765       pthread_create (&g_threadid_readimage, NULL,
2766 		      MustScanner_ReadDataFromScanner, NULL);
2767       DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread create\n");
2768       g_bFirstReadImage = FALSE;
2769     }
2770 
2771   memset (lpLine, 0, wWantedTotalLines * g_SWWidth / 8);
2772 
2773   for (TotalXferLines = 0; TotalXferLines < wWantedTotalLines;)
2774     {
2775       if (g_dwTotalTotalXferLines >= g_SWHeight)
2776 	{
2777 	  pthread_cancel (g_threadid_readimage);
2778 	  pthread_join (g_threadid_readimage, NULL);
2779 	  DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread exit\n");
2780 
2781 	  *wLinesCount = TotalXferLines;
2782 	  g_isScanning = FALSE;
2783 	  return TRUE;
2784 	}
2785 
2786       if (GetScannedLines () > g_wtheReadyLines)
2787 	{
2788 	  if (ST_Reflective == g_ScanType)
2789 	    {
2790 	      wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
2791 	      wLinePosOdd =
2792 		(g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
2793 	    }
2794 	  else
2795 	    {
2796 	      wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
2797 	      wLinePosEven =
2798 		(g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
2799 	    }
2800 
2801 
2802 
2803 	  for (i = 0; i < g_SWWidth;)
2804 	    {
2805 	      if ((i + 1) != g_SWWidth)
2806 		{
2807 		  if (*(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i) >
2808 		      g_wLineartThreshold)
2809 		    *(lpLine + i / 8) += (0x80 >> (i % 8));
2810 		  i++;
2811 		  if (i >= g_SWWidth)
2812 		    {
2813 		      break;
2814 		    }
2815 
2816 		  if (*(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i)
2817 		      > g_wLineartThreshold)
2818 		    *(lpLine + i / 8) += (0x80 >> (i % 8));
2819 		  i++;
2820 		}
2821 	    }
2822 
2823 	  TotalXferLines++;
2824 	  g_dwTotalTotalXferLines++;
2825 	  lpLine += g_SWBytesPerRow / 8;
2826 	  AddReadyLines ();
2827 
2828 
2829 	}
2830       if (g_isCanceled)
2831 	{
2832 	  pthread_cancel (g_threadid_readimage);
2833 	  pthread_join (g_threadid_readimage, NULL);
2834 	  DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread exit\n");
2835 
2836 	  break;
2837 	}
2838     }				/*end for */
2839 
2840   *wLinesCount = TotalXferLines;
2841   g_isScanning = FALSE;
2842 
2843   DBG (DBG_FUNC,
2844        "MustScanner_GetMono1BitLine1200DPI: leave MustScanner_GetMono1BitLine1200DPI\n");
2845   return TRUE;
2846 }
2847 
2848 /**********************************************************************
2849 Author: Jack            Date: 2005/05/21
2850 Routine Description:
2851 	prepare calculate Max and Min value
2852 Parameters:
2853 	wResolution: the scan resolution
2854 Return value:
2855 	none
2856 ***********************************************************************/
2857 static void
MustScanner_PrepareCalculateMaxMin(unsigned short wResolution)2858 MustScanner_PrepareCalculateMaxMin (unsigned short wResolution)
2859 {
2860   g_wDarkCalWidth = 52;
2861   if (wResolution <= 600)
2862     {
2863       g_wCalWidth = ((5120 * wResolution / 600 + 511) >> 9) << 9;
2864       g_wDarkCalWidth = g_wDarkCalWidth / (1200 / wResolution);
2865 
2866       if (wResolution < 200)
2867 	{
2868 	  g_nPowerNum = 3;
2869 	  g_nSecLength = 8;	/* 2^nPowerNum */
2870 	  g_nDarkSecLength = g_wDarkCalWidth / 2;	/* Dark has at least 2 sections */
2871 	}
2872       else
2873 	{
2874 	  g_nPowerNum = 6;
2875 	  g_nSecLength = 64;	/* 2^nPowerNum */
2876 	  g_nDarkSecLength = g_wDarkCalWidth / 3;
2877 	}
2878     }
2879   else
2880     {
2881       g_nPowerNum = 6;
2882       g_nSecLength = 64;	/*2^nPowerNum */
2883       g_wCalWidth = 10240;
2884       g_nDarkSecLength = g_wDarkCalWidth / 5;
2885     }
2886 
2887   if (g_nDarkSecLength <= 0)
2888     {
2889       g_nDarkSecLength = 1;
2890     }
2891 
2892   g_wStartPosition = 13 * wResolution / 1200;
2893   g_wCalWidth -= g_wStartPosition;
2894 
2895 
2896   /* start of find Max value */
2897   g_nSecNum = (int) (g_wCalWidth / g_nSecLength);
2898 
2899   /* start of fin min value */
2900   g_nDarkSecNum = (int) (g_wDarkCalWidth / g_nDarkSecLength);
2901 }
2902 
2903 /**********************************************************************
2904 Author: Jack            Date: 2005/05/21
2905 Routine Description:
2906 	calculate the Max and Min value
2907 Parameters:
2908 	pBuffer: the image data
2909 	lpMaxValue: the max value
2910 	lpMinValue: the min value
2911 	wResolution: the scan resolution
2912 Return value:
2913 	none
2914 ***********************************************************************/
2915 static void
MustScanner_CalculateMaxMin(SANE_Byte * pBuffer,unsigned short * lpMaxValue,unsigned short * lpMinValue,unsigned short wResolution)2916 MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * lpMaxValue,
2917 			     unsigned short * lpMinValue, unsigned short wResolution)
2918 {
2919   unsigned short *wSecData = NULL, *wDarkSecData = NULL;
2920   int i, j;
2921 
2922   (void) wResolution;
2923 
2924   wSecData = (unsigned short *) malloc (sizeof (unsigned short) * g_nSecNum);
2925   if (wSecData == NULL)
2926     {
2927       return;
2928     }
2929   else
2930     {
2931       memset (wSecData, 0, g_nSecNum * sizeof (unsigned short));
2932     }
2933 
2934   for (i = 0; i < g_nSecNum; i++)
2935     {
2936 
2937       for (j = 0; j < g_nSecLength; j++)
2938 	wSecData[i] += *(pBuffer + g_wStartPosition + i * g_nSecLength + j);
2939       wSecData[i] >>= g_nPowerNum;
2940     }
2941 
2942   *lpMaxValue = wSecData[0];
2943   for (i = 0; i < g_nSecNum; i++)
2944     {
2945       if (*lpMaxValue < wSecData[i])
2946 	*lpMaxValue = wSecData[i];
2947     }
2948 
2949   free (wSecData);
2950 
2951   wDarkSecData = (unsigned short *) malloc (sizeof (unsigned short) * g_nDarkSecNum);
2952   if (wDarkSecData == NULL)
2953     {
2954       return;
2955     }
2956   else
2957     {
2958       memset (wDarkSecData, 0, g_nDarkSecNum * sizeof (unsigned short));
2959     }
2960 
2961   for (i = 0; i < g_nDarkSecNum; i++)
2962     {
2963       for (j = 0; j < g_nDarkSecLength; j++)
2964 	wDarkSecData[i] +=
2965 	  *(pBuffer + g_wStartPosition + i * g_nDarkSecLength + j);
2966 
2967       wDarkSecData[i] /= g_nDarkSecLength;
2968     }
2969 
2970   *lpMinValue = wDarkSecData[0];
2971   for (i = 0; i < g_nDarkSecNum; i++)
2972     {
2973       if (*lpMinValue > wDarkSecData[i])
2974 	*lpMinValue = wDarkSecData[i];
2975     }
2976   free (wDarkSecData);
2977 }
2978 
2979 
2980 /**********************************************************************
2981 Author: Jack             Date: 2005/05/15
2982 Routine Description:
2983 	Read the data from scanner
2984 Parameters:
2985 	none
2986 Return value:
2987 	if operation is success
2988 	return TRUE
2989 	else
2990 	return FALSE
2991 ***********************************************************************/
2992 static void *
MustScanner_ReadDataFromScanner(void * dummy)2993 MustScanner_ReadDataFromScanner (void * dummy)
2994 {
2995   unsigned short wTotalReadImageLines = 0;
2996   unsigned short wWantedLines = g_Height;
2997   SANE_Byte * lpReadImage = g_lpReadImageHead;
2998   SANE_Bool isWaitImageLineDiff = FALSE;
2999   unsigned int wMaxScanLines = g_wMaxScanLines;
3000   unsigned short wReadImageLines = 0;
3001   unsigned short wScanLinesThisBlock;
3002   unsigned short wBufferLines = g_wLineDistance * 2 + g_wPixelDistance;
3003 
3004   (void) dummy;
3005   DBG (DBG_FUNC,
3006        "MustScanner_ReadDataFromScanner: call in, and in new thread\n");
3007 
3008   while (wTotalReadImageLines < wWantedLines && g_lpReadImageHead)
3009     {
3010       if (!isWaitImageLineDiff)
3011 	{
3012 	  wScanLinesThisBlock =
3013 	    (wWantedLines - wTotalReadImageLines) <
3014 	    g_wScanLinesPerBlock ? (wWantedLines -
3015 				    wTotalReadImageLines) :
3016 	    g_wScanLinesPerBlock;
3017 
3018 	  DBG (DBG_FUNC,
3019 	       "MustScanner_ReadDataFromScanner: wWantedLines=%d\n",
3020 	       wWantedLines);
3021 
3022 	  DBG (DBG_FUNC,
3023 	       "MustScanner_ReadDataFromScanner: wScanLinesThisBlock=%d\n",
3024 	       wScanLinesThisBlock);
3025 
3026 	  if (SANE_STATUS_GOOD !=
3027 	      Asic_ReadImage (&g_chip, lpReadImage, wScanLinesThisBlock))
3028 	    {
3029 	      DBG (DBG_FUNC,
3030 		   "MustScanner_ReadDataFromScanner:Asic_ReadImage return error\n");
3031 	      DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner:thread exit\n");
3032 	      return NULL;
3033 	    }
3034 
3035 	  /*has read in memory Buffer */
3036 	  wReadImageLines += wScanLinesThisBlock;
3037 
3038 	  AddScannedLines (wScanLinesThisBlock);
3039 
3040 	  wTotalReadImageLines += wScanLinesThisBlock;
3041 
3042 	  lpReadImage += wScanLinesThisBlock * g_BytesPerRow;
3043 
3044 	  /*Buffer is full */
3045 	  if (wReadImageLines >= wMaxScanLines)
3046 	    {
3047 	      lpReadImage = g_lpReadImageHead;
3048 	      wReadImageLines = 0;
3049 	    }
3050 
3051 	  if ((g_dwScannedTotalLines - GetReadyLines ())
3052 	      >= (wMaxScanLines - (wBufferLines + g_wScanLinesPerBlock))
3053 	      && g_dwScannedTotalLines > GetReadyLines ())
3054 	    {
3055 	      isWaitImageLineDiff = TRUE;
3056 	    }
3057 	}
3058       else if (g_dwScannedTotalLines <=
3059 	       GetReadyLines () + wBufferLines + g_wScanLinesPerBlock)
3060 	{
3061 	  isWaitImageLineDiff = FALSE;
3062 	}
3063 
3064       pthread_testcancel ();
3065     }
3066 
3067   DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: Read image ok\n");
3068   DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: thread exit\n");
3069   DBG (DBG_FUNC,
3070        "MustScanner_ReadDataFromScanner: leave MustScanner_ReadDataFromScanner\n");
3071   return NULL;
3072 }
3073 
3074 /**********************************************************************
3075 Author: Jack            Date: 2005/05/26
3076 Routine Description:
3077 	get the lines of scanned
3078 Parameters:
3079 	none
3080 Return value:
3081 	the lines of scanned
3082 ***********************************************************************/
3083 static unsigned int
GetScannedLines()3084 GetScannedLines ()
3085 {
3086   unsigned int dwScannedLines = 0;
3087 
3088   pthread_mutex_lock (&g_scannedLinesMutex);
3089   dwScannedLines = g_dwScannedTotalLines;
3090   pthread_mutex_unlock (&g_scannedLinesMutex);
3091 
3092   return dwScannedLines;
3093 }
3094 
3095 /**********************************************************************
3096 Author: Jack            Date: 2005/05/26
3097 
3098 Routine Description:
3099 	get lines which pass to superstratum
3100 Parameters:
3101 	none
3102 Return value:
3103 	the lines which pass to superstratum
3104 ***********************************************************************/
3105 static unsigned int
GetReadyLines()3106 GetReadyLines ()
3107 {
3108   unsigned int dwReadyLines = 0;
3109 
3110   pthread_mutex_lock (&g_readyLinesMutex);
3111   dwReadyLines = g_wtheReadyLines;
3112   pthread_mutex_unlock (&g_readyLinesMutex);
3113 
3114   return dwReadyLines;
3115 }
3116 
3117 /**********************************************************************
3118 Author: Jack            Date: 2005/05/26
3119 Routine Description:
3120 	add the scanned total lines
3121 Parameters:
3122 	wAddLines: add the lines
3123 Return value:
3124 	none
3125 ***********************************************************************/
3126 static void
AddScannedLines(unsigned short wAddLines)3127 AddScannedLines (unsigned short wAddLines)
3128 {
3129   pthread_mutex_lock (&g_scannedLinesMutex);
3130 
3131   g_dwScannedTotalLines += wAddLines;
3132 
3133   pthread_mutex_unlock (&g_scannedLinesMutex);
3134 }
3135 
3136 /**********************************************************************
3137 Author: Jack            Date: 2005/05/26
3138 Routine Description:
3139 	add the ready lines
3140 Parameters:
3141 	none
3142 Return value:
3143 	none
3144 ***********************************************************************/
3145 static void
AddReadyLines()3146 AddReadyLines ()
3147 {
3148   pthread_mutex_lock (&g_readyLinesMutex);
3149   g_wtheReadyLines++;
3150   pthread_mutex_unlock (&g_readyLinesMutex);
3151 }
3152 
3153 /**********************************************************************
3154 Author: Jack            Date: 2005/05/26
3155 Routine Description:
3156 	modify the point
3157 Parameters:
3158 	lpImageData: the data of image
3159   lpImageDataBefore: the data of before line image
3160   dwBytesPerLine: the bytes of per line
3161   dwLinesCount: the line count
3162   wPixDistance: the pixel distance
3163   wModPtCount: the modify point count
3164 Return value:
3165 	none
3166 ***********************************************************************/
3167 static void
ModifyLinePoint(SANE_Byte * lpImageData,SANE_Byte * lpImageDataBefore,unsigned int dwBytesPerLine,unsigned int dwLinesCount,unsigned short wPixDistance,unsigned short wModPtCount)3168 ModifyLinePoint (SANE_Byte * lpImageData,
3169 		 SANE_Byte * lpImageDataBefore,
3170 		 unsigned int dwBytesPerLine,
3171 		 unsigned int dwLinesCount, unsigned short wPixDistance, unsigned short wModPtCount)
3172 {
3173   unsigned short i = 0;
3174   unsigned short j = 0;
3175   unsigned short wLines = 0;
3176   unsigned int dwWidth = dwBytesPerLine / wPixDistance;
3177   for (i = wModPtCount; i > 0; i--)
3178     {
3179       for (j = 0; j < wPixDistance; j++)
3180 	{
3181 	  /*modify the first line */
3182 	  *(lpImageData + (dwWidth - i) * wPixDistance + j) =
3183 	    (*(lpImageData + (dwWidth - i - 1) * wPixDistance + j) +
3184 	     *(lpImageDataBefore + (dwWidth - i) * wPixDistance + j)) / 2;
3185 	  /*modify other lines */
3186 	  for (wLines = 1; wLines < dwLinesCount; wLines++)
3187 	    {
3188 	      unsigned int dwBytesBefor = (wLines - 1) * dwBytesPerLine;
3189 	      unsigned int dwBytes = wLines * dwBytesPerLine;
3190 	      *(lpImageData + dwBytes + (dwWidth - i) * wPixDistance + j) =
3191 		(*
3192 		 (lpImageData + dwBytes + (dwWidth - i - 1) * wPixDistance +
3193 		  j) + *(lpImageData + dwBytesBefor + (dwWidth -
3194 						       i) * wPixDistance +
3195 			 j)) / 2;
3196 	    }
3197 	}
3198     }
3199 }
3200 
3201 /**********************************************************************
3202 Author: Jack             Date: 2005/05/15
3203 Routine Description:
3204 	Modify the image data
3205 Parameters:
3206 	A: the input the image data
3207 	B: the input the image data
3208 Return value:
3209 	the modified data
3210 ***********************************************************************/
3211 static SANE_Byte
QBET4(SANE_Byte A,SANE_Byte B)3212 QBET4 (SANE_Byte A, SANE_Byte B)
3213 {
3214   SANE_Byte bQBET[16][16] = {
3215     {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
3216     {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
3217     {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
3218     {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
3219     {1, 1, 1, 1, 3, 3, 3, 3, 6, 6, 6, 6, 10, 10, 11, 11},
3220     {1, 1, 1, 1, 3, 3, 3, 3, 6, 6, 6, 6, 10, 10, 11, 11},
3221     {2, 2, 2, 2, 3, 3, 3, 3, 7, 7, 7, 7, 10, 10, 11, 11},
3222     {2, 2, 2, 2, 3, 3, 3, 3, 7, 7, 7, 7, 10, 10, 11, 11},
3223     {4, 4, 4, 4, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
3224     {4, 4, 4, 4, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
3225     {5, 5, 5, 5, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
3226     {5, 5, 5, 5, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
3227     {8, 8, 8, 8, 10, 10, 10, 10, 13, 13, 13, 13, 15, 15, 15, 15},
3228     {8, 8, 8, 8, 10, 10, 10, 10, 13, 13, 13, 13, 15, 15, 15, 15},
3229     {9, 9, 9, 9, 11, 11, 11, 11, 14, 14, 14, 14, 15, 15, 15, 15},
3230     {9, 9, 9, 9, 11, 11, 11, 11, 14, 14, 14, 14, 15, 15, 15, 15}
3231   };
3232 
3233   A = A & 0x0f;
3234   B = B & 0x0f;
3235   return bQBET[A][B];
3236 }				/* end of the file MustScanner.c */
3237