• 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 
47 /* forward declarations */
48 static SANE_Bool Transparent_Reset (void);
49 static SANE_Bool Transparent_ScanSuggest (PTARGETIMAGE pTarget, PSUGGESTSETTING pSuggest);
50 static SANE_Bool Transparent_SetupScan (COLORMODE ColorMode, unsigned short XDpi, unsigned short YDpi,
51 				   SANE_Bool isInvert, unsigned short X, unsigned short Y, unsigned short Width,
52 				   unsigned short Height);
53 static SANE_Bool Transparent_StopScan (void);
54 static SANE_Bool Transparent_GetRows (SANE_Byte * lpBlock, unsigned short * Rows, SANE_Bool isOrderInvert);
55 static SANE_Bool Transparent_AdjustAD (void);
56 static SANE_Bool Transparent_FindTopLeft (unsigned short * lpwStartX, unsigned short * lpwStartY);
57 static SANE_Bool Transparent_LineCalibration16Bits (unsigned short wTAShadingMinus);
58 static SANE_Bool Transparent_PrepareScan (void);
59 
60 
61 /*function description*/
62 
63 /**********************************************************************
64 Author: Jack            Date: 2005/05/13
65 Routine Description:
66 	reset the scanner
67 Parameters:
68 	none
69 Return value:
70 	if operation is success
71 	return TRUE
72 	else
73 	return FALSE
74 ***********************************************************************/
75 static SANE_Bool
Transparent_Reset()76 Transparent_Reset ()
77 {
78   DBG (DBG_FUNC, "Transparent_Reset: call in\n");
79 
80   if (g_bOpened)
81     {
82       DBG (DBG_FUNC, "Transparent_Reset: scanner has been opened\n");
83       return FALSE;
84     }
85   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
86     {
87       DBG (DBG_FUNC, "Transparent_Reset: can not open scanner\n");
88       return FALSE;
89     }
90 
91   if (SANE_STATUS_GOOD != Asic_Reset (&g_chip))
92     {
93       DBG (DBG_FUNC, "Reflective_Reset: Asic_Reset return error\n");
94       return FALSE;
95     }
96 
97   if (SANE_STATUS_GOOD != Asic_SetSource (&g_chip, LS_POSITIVE))
98     {
99       DBG (DBG_FUNC, "Reflective_Reset: Asic_SetSource return error\n");
100       return FALSE;
101     }
102 
103   if (SANE_STATUS_GOOD != Asic_TurnLamp (&g_chip, FALSE))
104     {
105       DBG (DBG_FUNC, "Reflective_Reset: Asic_TurnLamp return error\n");
106       return FALSE;
107     }
108 
109   if (SANE_STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE))
110     {
111       DBG (DBG_FUNC, "Reflective_Reset: Asic_TurnTA return error\n");
112       return FALSE;
113     }
114 
115   if (SANE_STATUS_GOOD != Asic_Close (&g_chip))
116     {
117       DBG (DBG_FUNC, "Reflective_Reset: Asic_Close return error\n");
118       return FALSE;
119     }
120 
121   g_Y = 0;
122   g_wLineartThreshold = 128;
123   g_dwTotalTotalXferLines = 0;
124   g_bFirstReadImage = TRUE;
125   g_pGammaTable = NULL;
126 
127   DBG (DBG_FUNC, "Transparent_Reset: leave Transparent_Reset\n");
128   return TRUE;
129 }
130 
131 /**********************************************************************
132 Author: Jack            Date: 2005/05/13
133 Routine Description:
134 	get suggest parameter of scanning
135 Parameters:
136 	pTarget: the information of scanning
137 	pSuggest: the suggest parameter of scanning
138 Return value:
139 	if operation is success
140 	return TRUE
141 	else
142 	return FALSE
143 ***********************************************************************/
144 static SANE_Bool
Transparent_ScanSuggest(PTARGETIMAGE pTarget,PSUGGESTSETTING pSuggest)145 Transparent_ScanSuggest (PTARGETIMAGE pTarget, PSUGGESTSETTING pSuggest)
146 {
147   unsigned short wMaxWidth, wMaxHeight;
148   int i;
149 
150   DBG (DBG_FUNC, "Transparent_ScanSuggest: call in\n");
151 
152   for (i = 0; s_wOpticalYDpi[i] != 0; i++)
153     {
154       if (s_wOpticalYDpi[i] <= pTarget->wDpi)
155 	{
156 	  pSuggest->wYDpi = s_wOpticalYDpi[i];
157 	  break;
158 	}
159     }
160   if (s_wOpticalYDpi[i] == 0)
161     {
162       i--;
163       pSuggest->wYDpi = s_wOpticalYDpi[i];
164     }
165 
166   for (i = 0; s_wOpticalXDpi[i] != 0; i++)
167     {
168       if (s_wOpticalXDpi[i] <= pTarget->wDpi)
169 	{
170 	  pSuggest->wXDpi = s_wOpticalXDpi[i];
171 	  break;
172 	}
173     }
174   if (s_wOpticalXDpi[i] == 0)
175     {
176       i--;
177       pSuggest->wXDpi = s_wOpticalXDpi[i];
178     }
179 
180   pSuggest->wX =
181     (unsigned short) (((unsigned int) (pTarget->wX) * (unsigned int) (pSuggest->wXDpi)) /
182 	    (unsigned int) (pTarget->wDpi));
183   pSuggest->wY =
184     (unsigned short) (((unsigned int) (pTarget->wY) * (unsigned int) (pSuggest->wYDpi)) /
185 	    (unsigned int) (pTarget->wDpi));
186   pSuggest->wWidth =
187     (unsigned short) (((unsigned int) (pTarget->wWidth) * (unsigned int) (pSuggest->wXDpi)) /
188 	    (unsigned int) (pTarget->wDpi));
189   pSuggest->wHeight =
190     (unsigned short) (((unsigned int) (pTarget->wHeight) * (unsigned int) (pSuggest->wYDpi)) /
191 	    (unsigned int) (pTarget->wDpi));
192 
193   pSuggest->wWidth = (pSuggest->wWidth / 2) * 2;
194 
195   if (pTarget->cmColorMode == CM_TEXT)
196     {
197       pSuggest->wWidth = ((pSuggest->wWidth + 7) >> 3) << 3;
198       if (pSuggest->wWidth < 8)
199 	pSuggest->wWidth = 8;
200     }
201 
202   g_Width = ((pSuggest->wWidth + 15) >> 4) << 4;	/* Real Scan Width */
203   g_Height = pSuggest->wHeight;
204 
205   wMaxWidth = (MAX_SCANNING_WIDTH * pSuggest->wXDpi) / 300;
206   wMaxHeight = (MAX_SCANNING_HEIGHT * pSuggest->wYDpi) / 300;
207 
208   if (pTarget->cmColorMode == CM_TEXT)
209     wMaxWidth = (wMaxWidth >> 3) << 3;
210 
211   if (pSuggest->wWidth > wMaxWidth)
212     pSuggest->wWidth = wMaxWidth;
213   if (pSuggest->wHeight > wMaxHeight)
214     pSuggest->wHeight = wMaxHeight;
215 
216   if (pTarget->isOptimalSpeed)
217     {
218       DBG (DBG_FUNC, "Transparent_ScanSuggest: isOptimalSpeed  is true\n");
219 
220       switch (pTarget->cmColorMode)
221 	{
222 	case CM_RGB48:
223 	  pSuggest->cmScanMode = CM_RGB48;
224 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 6);
225 	  break;
226 	case CM_RGB24:
227 	  pSuggest->cmScanMode = CM_RGB24ext;
228 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 3);
229 	  break;
230 
231 	case CM_GRAY16:
232 	  pSuggest->cmScanMode = CM_GRAY16ext;
233 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 2);
234 	  break;
235 	case CM_GRAY8:
236 	  pSuggest->cmScanMode = CM_GRAY8ext;
237 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth));
238 	  break;
239 	case CM_TEXT:
240 	  pSuggest->cmScanMode = CM_TEXT;
241 	  pSuggest->dwBytesPerRow = (unsigned int) (pSuggest->wWidth) / 8;
242 	  break;
243 	default:
244 	  break;
245 	}
246     }
247   else
248     {
249       DBG (DBG_FUNC, "Transparent_ScanSuggest: isOptimalSpeed  not true\n");
250 
251       switch (pTarget->cmColorMode)
252 	{
253 	case CM_RGB48:
254 	  pSuggest->cmScanMode = CM_RGB48;
255 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 6);
256 	  break;
257 	case CM_RGB24:
258 	  pSuggest->cmScanMode = CM_RGB24ext;
259 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 3);
260 	  break;
261 	case CM_GRAY16:
262 	  pSuggest->cmScanMode = CM_GRAY16ext;
263 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 2);
264 	  break;
265 	case CM_GRAY8:
266 	  pSuggest->cmScanMode = CM_GRAY8ext;
267 	  pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth));
268 	  break;
269 	case CM_TEXT:
270 	  pSuggest->cmScanMode = CM_TEXT;
271 	  pSuggest->dwBytesPerRow = (unsigned int) (pSuggest->wWidth) / 8;
272 	  break;
273 	default:
274 	  break;
275 	}
276     }
277 
278   DBG (DBG_FUNC, "Transparent_ScanSuggest: leave Transparent_ScanSuggest\n");
279   return TRUE;
280 }
281 
282 /**********************************************************************
283 Author: Jack            Date: 2005/05/13
284 Routine Description:
285 	setup scanning process
286 Parameters:
287 	ColorMode: ScanMode of Scanning, CM_RGB48, CM_GRAY and so on
288 	XDpi: X Resolution
289 	YDpi: Y Resolution
290 	isInvert: the RGB order
291 	X: X start coordinate
292 	Y: Y start coordinate
293 	Width: Width of Scan Image
294 	Height: Height of Scan Image
295 Return value:
296 	if the operation is success
297 	return TRUE
298 	else
299 	return FALSE
300 ***********************************************************************/
301 static SANE_Bool
Transparent_SetupScan(COLORMODE ColorMode,unsigned short XDpi,unsigned short YDpi,SANE_Bool isInvert,unsigned short X,unsigned short Y,unsigned short Width,unsigned short Height)302 Transparent_SetupScan (COLORMODE ColorMode, unsigned short XDpi, unsigned short YDpi,
303 		       SANE_Bool isInvert, unsigned short X, unsigned short Y, unsigned short Width, unsigned short Height)
304 {
305   SANE_Bool hasTA;
306   unsigned short wTAShadingMinus = 0;
307 
308   (void) isInvert;
309   DBG (DBG_FUNC, "Transparent_SetupScan: call in\n");
310 
311   if (g_bOpened)
312     {
313       DBG (DBG_FUNC, "Transparent_SetupScan: scanner has been opened\n");
314       return FALSE;
315     }
316 
317   if (!g_bPrepared)
318     {
319       DBG (DBG_FUNC, "Transparent_SetupScan: scanner not prepared\n");
320       return FALSE;
321     }
322 
323   g_ScanMode = ColorMode;
324   g_XDpi = XDpi;
325   g_YDpi = YDpi;
326   g_SWWidth = Width;
327   g_SWHeight = Height;
328 
329   switch (g_YDpi)
330     {
331     case 1200:
332       g_wPixelDistance = 4;
333       g_wLineDistance = 24;
334       g_Height += g_wPixelDistance;
335       break;
336     case 600:
337       g_wPixelDistance = 0;
338       g_wLineDistance = 12;
339       g_Height += g_wPixelDistance;
340       break;
341     case 300:
342       g_wPixelDistance = 0;
343       g_wLineDistance = 6;
344       break;
345     case 150:
346       g_wPixelDistance = 0;
347       g_wLineDistance = 3;
348       break;
349     case 75:
350     case 50:
351       g_wPixelDistance = 0;
352       g_wLineDistance = 1;
353       break;
354     default:
355       g_wLineDistance = 0;
356 
357     }
358 
359   DBG (DBG_FUNC, "Transparent_SetupScan: g_YDpi=%d\n", g_YDpi);
360   DBG (DBG_FUNC, "Transparent_SetupScan: g_wLineDistance=%d\n",
361        g_wLineDistance);
362   DBG (DBG_FUNC, "Transparent_SetupScan: g_wPixelDistance=%d\n",
363        g_wPixelDistance);
364 
365   switch (g_ScanMode)
366     {
367     case CM_RGB48:
368       g_BytesPerRow = 6 * g_Width;	/* ASIC limit : width must be 8x */
369       g_SWBytesPerRow = 6 * g_SWWidth;	/* ASIC limit : width must be 8x */
370       g_bScanBits = 48;
371       g_Height += g_wLineDistance * 2;
372       break;
373     case CM_RGB24ext:
374       g_BytesPerRow = 3 * g_Width;	/*ASIC limit : width must be 8x */
375       g_SWBytesPerRow = 3 * g_SWWidth;
376       g_bScanBits = 24;
377       g_Height += g_wLineDistance * 2;
378       break;
379     case CM_GRAY16ext:
380       g_BytesPerRow = 2 * g_Width;	/* ASIC limit : width must be 8x */
381       g_SWBytesPerRow = 2 * g_SWWidth;
382       g_bScanBits = 16;
383       break;
384     case CM_GRAY8ext:
385     case CM_TEXT:
386       g_BytesPerRow = g_Width;	/*ASIC limit : width must be 8x */
387       g_SWBytesPerRow = g_SWWidth;
388       g_bScanBits = 8;
389       break;
390     default:
391       break;
392     }
393 
394   if (Asic_Open (&g_chip, g_pDeviceFile) != SANE_STATUS_GOOD)
395     {
396       DBG (DBG_FUNC, "Transparent_SetupScan: Asic_Open return error\n");
397       return FALSE;
398     }
399 
400   g_bOpened = TRUE;
401 
402   if (SANE_STATUS_GOOD != Asic_TurnLamp (&g_chip, FALSE))
403     {
404       DBG (DBG_FUNC, "Transparent_SetupScan: Asic_TurnLamp return error\n");
405       return FALSE;
406     }
407 
408   if (Asic_IsTAConnected (&g_chip, &hasTA) != SANE_STATUS_GOOD)
409     {
410       DBG (DBG_FUNC,
411 	   "Transparent_SetupScan: Asic_IsTAConnected return error\n");
412       return FALSE;
413     }
414   if (!hasTA)
415     {
416       DBG (DBG_FUNC, "Transparent_SetupScan: no TA device\n");
417       return FALSE;
418     }
419 
420   if (Asic_TurnTA (&g_chip, TRUE) != SANE_STATUS_GOOD)
421     {
422       DBG (DBG_FUNC, "Transparent_SetupScan: Asic_TurnTA return error\n");
423       return FALSE;
424     }
425 
426   /* Begin Find Left&Top Side */
427   Asic_MotorMove (&g_chip, TRUE, TRAN_START_POS);
428 
429   if (1200 == g_XDpi)
430     {
431       wTAShadingMinus = 1680;
432       g_XDpi = 600;
433       Transparent_AdjustAD ();
434       Transparent_FindTopLeft (&g_X, &g_Y);
435 
436       g_XDpi = 1200;
437       Transparent_AdjustAD ();
438     }
439   else
440     {
441       wTAShadingMinus = 840;
442       Transparent_AdjustAD ();
443       Transparent_FindTopLeft (&g_X, &g_Y);
444     }
445 
446   DBG (DBG_FUNC,
447        "Transparent_SetupScan: after find top and left g_X=%d, g_Y=%d\n", g_X,
448        g_Y);
449 
450   if (1200 == g_XDpi)
451     {
452       g_X =
453 	g_X * 1200 / FIND_LEFT_TOP_CALIBRATE_RESOLUTION + X * 1200 / g_XDpi;
454     }
455   else
456     {
457       if (75 == g_XDpi)
458 	{
459 	  g_X = g_X + X * 600 / g_XDpi - 23;
460 	}
461       else
462 	{
463 	  g_X = g_X + X * 600 / g_XDpi;
464 	}
465     }
466 
467   DBG (DBG_FUNC,
468        "Transparent_SetupScan: before line calibration,g_X=%d,g_Y=%d\n", g_X,
469        g_Y);
470 
471   Transparent_LineCalibration16Bits (wTAShadingMinus);
472 
473   DBG (DBG_FUNC,
474        "Transparent_SetupScan: after Reflective_LineCalibration16Bits,g_X=%d,g_Y=%d\n",
475        g_X, g_Y);
476 
477   DBG (DBG_FUNC,
478        "Transparent_SetupScan: g_bScanBits=%d, g_XDpi=%d, g_YDpi=%d, g_X=%d, g_Y=%d, g_Width=%d, g_Height=%d\n",
479        g_bScanBits, g_XDpi, g_YDpi, g_X, g_Y, g_Width, g_Height);
480 
481   g_Y = Y * 1200 / g_YDpi + (300 - 40) + 189;
482   Asic_MotorMove (&g_chip, TRUE, g_Y - 360);
483   g_Y = 360;
484 
485   Asic_SetWindow (&g_chip, g_bScanBits, g_XDpi, g_YDpi, g_X, g_Y, g_Width,
486 		  g_Height);
487 
488   DBG (DBG_FUNC, "Transparent_SetupScan: leave Transparent_SetupScan\n");
489   return Transparent_PrepareScan ();
490 }
491 
492 /**********************************************************************
493 Author: Jack             Date: 2005/05/14
494 Routine Description:
495 	Stop scan
496 Parameters:
497 	none
498 Return value:
499 	if operation is success
500 	return TRUE
501 	else
502 	return FALSE
503 ***********************************************************************/
504 static SANE_Bool
Transparent_StopScan()505 Transparent_StopScan ()
506 {
507   DBG (DBG_FUNC, "Transparent_StopScan: call in\n");
508 
509   if (!g_bOpened)
510     {
511       return FALSE;
512     }
513   if (!g_bPrepared)
514     {
515       return FALSE;
516     }
517 
518   g_isCanceled = TRUE;
519 
520   pthread_cancel (g_threadid_readimage);
521   pthread_join (g_threadid_readimage, NULL);
522 
523   DBG (DBG_FUNC, "Transparent_StopScan: thread exit\n");
524 
525   Asic_ScanStop (&g_chip);
526   Asic_Close (&g_chip);
527   g_bOpened = FALSE;
528 
529   DBG (DBG_FUNC, "Transparent_StopScan: leave Transparent_StopScan\n");
530   return TRUE;
531 }
532 
533 /**********************************************************************
534 Author: Jack             Date: 2005/05/15
535 Routine Description:
536 	Get the data of image
537 Parameters:
538 	lpBlock: the data of image
539 	Rows: the rows of image
540 	isOrderInvert: the RGB order
541 Return value:
542 	if the operation is success
543 	return TRUE
544 	else
545 	return FALSE
546 ***********************************************************************/
547 static SANE_Bool
Transparent_GetRows(SANE_Byte * lpBlock,unsigned short * Rows,SANE_Bool isOrderInvert)548 Transparent_GetRows (SANE_Byte * lpBlock, unsigned short * Rows, SANE_Bool isOrderInvert)
549 {
550   DBG (DBG_FUNC, "Transparent_GetRows: call in\n");
551 
552   if (!g_bOpened)
553     {
554       return FALSE;
555     }
556   if (!g_bPrepared)
557     {
558       return FALSE;
559     }
560 
561   switch (g_ScanMode)
562     {
563     case CM_RGB48:
564       if (g_XDpi == 1200)
565 	return MustScanner_GetRgb48BitLine1200DPI (lpBlock, isOrderInvert,
566 						   Rows);
567       else
568 	return MustScanner_GetRgb48BitLine (lpBlock, isOrderInvert, Rows);
569 
570     case CM_RGB24ext:
571       if (g_XDpi == 1200)
572 	return MustScanner_GetRgb24BitLine1200DPI (lpBlock, isOrderInvert,
573 						   Rows);
574       else
575 	return MustScanner_GetRgb24BitLine (lpBlock, isOrderInvert, Rows);
576 
577     case CM_GRAY16ext:
578       if (g_XDpi == 1200)
579 	return MustScanner_GetMono16BitLine1200DPI (lpBlock, isOrderInvert,
580 						    Rows);
581       else
582 	return MustScanner_GetMono16BitLine (lpBlock, isOrderInvert, Rows);
583 
584     case CM_GRAY8ext:
585       if (g_XDpi == 1200)
586 	return MustScanner_GetMono8BitLine1200DPI (lpBlock, isOrderInvert,
587 						   Rows);
588       else
589 	return MustScanner_GetMono8BitLine (lpBlock, isOrderInvert, Rows);
590 
591     case CM_TEXT:
592       if (g_XDpi == 1200)
593 	return MustScanner_GetMono1BitLine1200DPI (lpBlock, isOrderInvert,
594 						   Rows);
595       else
596 	return MustScanner_GetMono1BitLine (lpBlock, isOrderInvert, Rows);
597     default:
598       return FALSE;
599     }
600   return FALSE;
601 }
602 
603 /**********************************************************************
604 Author: Jack             Date: 2005/05/13
605 Routine Description:
606 	To adjust the value of offset gain of R/G/B
607 Parameters:
608 	none
609 Return value:
610 	if operation is success
611 	return TRUE
612 	else
613 	return FALSE
614 ***********************************************************************/
615 static SANE_Bool
Transparent_AdjustAD()616 Transparent_AdjustAD ()
617 {
618   SANE_Byte * lpCalData;
619   unsigned short wCalWidth;
620   int nTimesOfCal;
621   unsigned short wMaxValueR, wMinValueR, wMaxValueG, wMinValueG, wMaxValueB, wMinValueB;
622 #if 0
623   float fRFactor = 1.0;
624   float fGFactor = 1.0;
625   float fBFactor = 1.0;
626   SANE_Byte bDarkMaxLevel;
627   SANE_Byte bDarkMinLevel;
628   SANE_Byte bLastMinR, bLastROffset, bROffsetUpperBound = 255, bROffsetLowerBound =
629     0;
630   SANE_Byte bLastMinG, bLastGOffset, bGOffsetUpperBound = 255, bGOffsetLowerBound =
631     0;
632   SANE_Byte bLastMinB, bLastBOffset, bBOffsetUpperBound = 255, bBOffsetLowerBound =
633     0;
634 #endif
635   unsigned short wAdjustADResolution;
636 
637   DBG (DBG_FUNC, "Transparent_AdjustAD: call in\n");
638   if (!g_bOpened)
639     {
640       return FALSE;
641     }
642   if (!g_bPrepared)
643     {
644       return FALSE;
645     }
646 
647 
648   g_chip.AD.DirectionR = R_DIRECTION;
649   g_chip.AD.DirectionG = G_DIRECTION;
650   g_chip.AD.DirectionB = B_DIRECTION;
651   g_chip.AD.GainR = R_GAIN;
652   g_chip.AD.GainG = G_GAIN;
653   g_chip.AD.GainB = B_GAIN;
654   g_chip.AD.OffsetR = 159;
655   g_chip.AD.OffsetG = 50;
656   g_chip.AD.OffsetB = 45;
657 
658   if (g_XDpi <= 600)
659     {
660       wAdjustADResolution = 600;
661     }
662   else
663     {
664       wAdjustADResolution = 1200;
665     }
666 
667   wCalWidth = 10240;
668 
669   lpCalData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * wCalWidth * 3);
670   if (lpCalData == NULL)
671     {
672       return FALSE;
673     }
674 
675   Asic_SetMotorType (&g_chip, FALSE, TRUE);
676 
677   Asic_SetCalibrate (&g_chip, 24, wAdjustADResolution, wAdjustADResolution, 0,
678 		     0, wCalWidth, 1, FALSE);
679   MustScanner_PrepareCalculateMaxMin (wAdjustADResolution);
680   nTimesOfCal = 0;
681 
682 #ifdef DEBUG_SAVE_IMAGE
683   Asic_SetAFEGainOffset (&g_chip);
684   Asic_ScanStart (&g_chip);
685   Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24);
686   Asic_ScanStop (&g_chip);
687 
688   FILE *stream = NULL;
689   SANE_Byte * lpBuf = (SANE_Byte *) malloc (50);
690   if (NULL == lpBuf)
691     {
692       DBG (DBG_FUNC,
693 	   "Transparent_AdjustAD: Leave Transparent_AdjustAD for malloc fail!\n");
694       return FALSE;
695     }
696   memset (lpBuf, 0, 50);
697   stream = fopen ("/root/AD(Tra).pnm", "wb+\n");
698   sprintf (lpBuf, "P6\n%d %d\n255\n", wCalWidth, 3);
699   fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream);
700   fwrite (lpCalData, sizeof (SANE_Byte), wCalWidth * 3, stream);
701   fclose (stream);
702   free (lpBuf);
703 #endif
704 
705   do
706     {
707       DBG (DBG_FUNC,
708 	   "Transparent_AdjustAD: run in first adjust offset do-while\n");
709       Asic_SetAFEGainOffset (&g_chip);
710       Asic_ScanStart (&g_chip);
711       Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24);
712       Asic_ScanStop (&g_chip);
713 
714       MustScanner_CalculateMaxMin (lpCalData, &wMaxValueR, &wMinValueR,
715 				   wAdjustADResolution);
716       MustScanner_CalculateMaxMin (lpCalData + wCalWidth, &wMaxValueG,
717 				   &wMinValueG, wAdjustADResolution);
718       MustScanner_CalculateMaxMin (lpCalData + wCalWidth * 2, &wMaxValueB,
719 				   &wMinValueB, wAdjustADResolution);
720 
721       if (g_chip.AD.DirectionR == 0)
722 	{
723 	  if (wMinValueR > 15)
724 	    {
725 	      if (g_chip.AD.OffsetR < 8)
726 		g_chip.AD.DirectionR = 1;
727 	      else
728 		g_chip.AD.OffsetR -= 8;
729 	    }
730 	  else if (wMinValueR < 5)
731 	    g_chip.AD.OffsetR += 8;
732 	}
733       else
734 	{
735 	  if (wMinValueR > 15)
736 	    g_chip.AD.OffsetR += 8;
737 	  else if (wMinValueR < 5)
738 	    g_chip.AD.OffsetR -= 8;
739 	}
740 
741       if (g_chip.AD.DirectionG == 0)
742 	{
743 	  if (wMinValueG > 15)
744 	    {
745 	      if (g_chip.AD.OffsetG < 8)
746 		g_chip.AD.DirectionG = 1;
747 
748 	      else
749 		g_chip.AD.OffsetG -= 8;
750 	    }
751 	  else if (wMinValueG < 5)
752 	    g_chip.AD.OffsetG += 8;
753 	}
754       else
755 	{
756 	  if (wMinValueG > 15)
757 	    g_chip.AD.OffsetG += 8;
758 	  else if (wMinValueG < 5)
759 	    g_chip.AD.OffsetG -= 8;
760 	}
761 
762       if (g_chip.AD.DirectionB == 0)
763 	{
764 	  if (wMinValueB > 15)
765 	    {
766 	      if (g_chip.AD.OffsetB < 8)
767 		g_chip.AD.DirectionB = 1;
768 	      else
769 		g_chip.AD.OffsetB -= 8;
770 	    }
771 	  else if (wMinValueB < 5)
772 	    g_chip.AD.OffsetB += 8;
773 	}
774       else
775 	{
776 	  if (wMinValueB > 15)
777 	    g_chip.AD.OffsetB += 8;
778 	  else if (wMinValueB < 5)
779 	    g_chip.AD.OffsetB -= 8;
780 	}
781 
782       nTimesOfCal++;
783       if (nTimesOfCal > 10)
784 	break;
785     }
786   while (wMinValueR > 15 || wMinValueR < 5
787 	 || wMinValueG > 15 || wMinValueG < 5
788 	 || wMinValueB > 15 || wMinValueB < 5);
789 
790   g_chip.AD.GainR = 1 - (double) (wMaxValueR - wMinValueR) / 210 > 0 ?
791     (SANE_Byte) (((1 -
792 	      (double) (wMaxValueR - wMinValueR) / 210)) * 63 * 6 / 5) : 0;
793   g_chip.AD.GainG =
794     1 - (double) (wMaxValueG - wMinValueG) / 210 >
795     0 ? (SANE_Byte) (((1 - (double) (wMaxValueG - wMinValueG) / 210)) * 63 * 6 /
796 		5) : 0;
797   g_chip.AD.GainB =
798     1 - (double) (wMaxValueB - wMinValueB) / 210 >
799     0 ? (SANE_Byte) (((1 - (double) (wMaxValueB - wMinValueB) / 210)) * 63 * 6 /
800 		5) : 0;
801 
802   if (g_chip.AD.GainR > 63)
803     g_chip.AD.GainR = 63;
804   if (g_chip.AD.GainG > 63)
805     g_chip.AD.GainG = 63;
806   if (g_chip.AD.GainB > 63)
807     g_chip.AD.GainB = 63;
808 
809 
810 
811   nTimesOfCal = 0;
812   do
813     {
814       Asic_SetAFEGainOffset (&g_chip);
815       Asic_ScanStart (&g_chip);
816       Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24);
817       Asic_ScanStop (&g_chip);
818 
819       MustScanner_CalculateMaxMin (lpCalData, &wMaxValueR, &wMinValueR,
820 				   wAdjustADResolution);
821       MustScanner_CalculateMaxMin (lpCalData + wCalWidth, &wMaxValueG,
822 				   &wMinValueG, wAdjustADResolution);
823       MustScanner_CalculateMaxMin (lpCalData + wCalWidth * 2, &wMaxValueB,
824 				   &wMinValueB, wAdjustADResolution);
825 
826       DBG (DBG_FUNC, "Transparent_AdjustAD: "
827 	   "RGain=%d, ROffset=%d, RDir=%d  GGain=%d, GOffset=%d, GDir=%d  BGain=%d, BOffset=%d, BDir=%d\n",
828 	   g_chip.AD.GainR, g_chip.AD.OffsetR, g_chip.AD.DirectionR,
829 	   g_chip.AD.GainG, g_chip.AD.OffsetG, g_chip.AD.DirectionG,
830 	   g_chip.AD.GainB, g_chip.AD.OffsetB, g_chip.AD.DirectionB);
831 
832       DBG (DBG_FUNC, "Transparent_AdjustAD: "
833 	   "MaxR=%d, MinR=%d  MaxG=%d, MinG=%d  MaxB=%d, MinB=%d\n",
834 	   wMaxValueR, wMinValueR, wMaxValueG, wMinValueG, wMaxValueB,
835 	   wMinValueB);
836 
837       /*R Channel */
838       if ((wMaxValueR - wMinValueR) > TRAN_MAX_LEVEL_RANGE)
839 	{
840 	  if (g_chip.AD.GainR > 0)
841 	    g_chip.AD.GainR--;
842 	}
843       else
844 	{
845 	  if ((wMaxValueR - wMinValueR) < TRAN_MIN_LEVEL_RANGE)
846 	    {
847 	      if (wMaxValueR < TRAN_WHITE_MIN_LEVEL)
848 		{
849 		  g_chip.AD.GainR++;
850 		  if (g_chip.AD.GainR > 63)
851 		    g_chip.AD.GainR = 63;
852 		}
853 	      else
854 		{
855 		  if (wMaxValueR > TRAN_WHITE_MAX_LEVEL)
856 		    {
857 		      if (g_chip.AD.GainR < 1)
858 			g_chip.AD.GainR = 0;
859 		      else
860 			g_chip.AD.GainR--;
861 		    }
862 		  else
863 		    {
864 		      if (g_chip.AD.GainR > 63)
865 			g_chip.AD.GainR = 63;
866 		      else
867 			g_chip.AD.GainR++;
868 		    }
869 		}
870 	    }
871 	  else
872 	    {
873 	      if (wMaxValueR > TRAN_WHITE_MAX_LEVEL)
874 		{
875 		  if (g_chip.AD.GainR < 1)
876 		    g_chip.AD.GainR = 0;
877 		  else
878 		    g_chip.AD.GainR--;
879 		}
880 
881 	      if (wMaxValueR < TRAN_WHITE_MIN_LEVEL)
882 		{
883 		  if (g_chip.AD.GainR > 63)
884 		    g_chip.AD.GainR = 63;
885 		  else
886 		    g_chip.AD.GainR++;
887 
888 		}
889 	    }
890 	}
891 
892       /*G Channel */
893       if ((wMaxValueG - wMinValueG) > TRAN_MAX_LEVEL_RANGE)
894 	{
895 	  if (g_chip.AD.GainG > 0)
896 	    g_chip.AD.GainG--;
897 	}
898       else
899 	{
900 	  if ((wMaxValueG - wMinValueG) < TRAN_MIN_LEVEL_RANGE)
901 	    {
902 	      if (wMaxValueG < TRAN_WHITE_MIN_LEVEL)
903 		{
904 		  g_chip.AD.GainG++;
905 		  if (g_chip.AD.GainG > 63)
906 		    g_chip.AD.GainG = 63;
907 		}
908 	      else
909 		{
910 		  if (wMaxValueG > TRAN_WHITE_MAX_LEVEL)
911 		    {
912 		      if (g_chip.AD.GainG < 1)
913 			g_chip.AD.GainG = 0;
914 		      else
915 			g_chip.AD.GainG--;
916 		    }
917 		  else
918 		    {
919 		      if (g_chip.AD.GainG > 63)
920 			g_chip.AD.GainG = 63;
921 		      else
922 			g_chip.AD.GainG++;
923 		    }
924 		}
925 	    }
926 	  else
927 	    {
928 	      if (wMaxValueG > TRAN_WHITE_MAX_LEVEL)
929 		{
930 		  if (g_chip.AD.GainG < 1)
931 		    g_chip.AD.GainG = 0;
932 		  else
933 		    g_chip.AD.GainG--;
934 		}
935 
936 	      if (wMaxValueG < TRAN_WHITE_MIN_LEVEL)
937 		{
938 		  if (g_chip.AD.GainG > 63)
939 		    g_chip.AD.GainG = 63;
940 		  else
941 		    g_chip.AD.GainG++;
942 		}
943 	    }
944 	}
945 
946       /* B Channel */
947       if ((wMaxValueB - wMinValueB) > TRAN_MAX_LEVEL_RANGE)
948 	{
949 	  if (g_chip.AD.GainB > 0)
950 	    g_chip.AD.GainB--;
951 	}
952       else
953 	{
954 	  if ((wMaxValueB - wMinValueB) < TRAN_MIN_LEVEL_RANGE)
955 	    {
956 	      if (wMaxValueB < TRAN_WHITE_MIN_LEVEL)
957 		{
958 		  g_chip.AD.GainB++;
959 		  if (g_chip.AD.GainB > 63)
960 		    g_chip.AD.GainB = 63;
961 		}
962 	      else
963 		{
964 		  if (wMaxValueB > TRAN_WHITE_MAX_LEVEL)
965 		    {
966 		      if (g_chip.AD.GainB < 1)
967 			g_chip.AD.GainB = 0;
968 		      else
969 			g_chip.AD.GainB--;
970 		    }
971 		  else
972 		    {
973 		      if (g_chip.AD.GainB > 63)
974 			g_chip.AD.GainB = 63;
975 		      else
976 			g_chip.AD.GainB++;
977 		    }
978 		}
979 	    }
980 	  else
981 	    {
982 	      if (wMaxValueB > TRAN_WHITE_MAX_LEVEL)
983 		{
984 		  if (g_chip.AD.GainB < 1)
985 		    g_chip.AD.GainB = 0;
986 		  else
987 		    g_chip.AD.GainB--;
988 		}
989 
990 	      if (wMaxValueB < TRAN_WHITE_MIN_LEVEL)
991 		{
992 		  if (g_chip.AD.GainB > 63)
993 		    g_chip.AD.GainB = 63;
994 		  else
995 		    g_chip.AD.GainB++;
996 		}
997 	    }
998 	}
999 
1000       nTimesOfCal++;
1001       if (nTimesOfCal > 10)
1002 	break;
1003     }
1004   while ((wMaxValueR - wMinValueR) > TRAN_MAX_LEVEL_RANGE
1005 	 || (wMaxValueR - wMinValueR) < TRAN_MIN_LEVEL_RANGE
1006 	 || (wMaxValueG - wMinValueG) > TRAN_MAX_LEVEL_RANGE
1007 	 || (wMaxValueG - wMinValueG) < TRAN_MIN_LEVEL_RANGE
1008 	 || (wMaxValueB - wMinValueB) > TRAN_MAX_LEVEL_RANGE
1009 	 || (wMaxValueB - wMinValueB) < TRAN_MIN_LEVEL_RANGE);
1010 
1011   /* Adjust Offset 2nd */
1012   nTimesOfCal = 0;
1013   do
1014     {
1015       Asic_SetAFEGainOffset (&g_chip);
1016       Asic_ScanStart (&g_chip);
1017       Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24);
1018       Asic_ScanStop (&g_chip);
1019 
1020       MustScanner_CalculateMaxMin (lpCalData, &wMaxValueR, &wMinValueR,
1021 				   wAdjustADResolution);
1022       MustScanner_CalculateMaxMin (lpCalData + wCalWidth, &wMaxValueG,
1023 				   &wMinValueG, wAdjustADResolution);
1024       MustScanner_CalculateMaxMin (lpCalData + wCalWidth * 2, &wMaxValueB,
1025 				   &wMinValueB, wAdjustADResolution);
1026       DBG (DBG_FUNC,
1027 	   "Transparent_AdjustAD: "
1028 	   "RGain=%d, ROffset=%d, RDir=%d  GGain=%d, GOffset=%d, GDir=%d  BGain=%d, BOffset=%d, BDir=%d\n",
1029 	   g_chip.AD.GainR, g_chip.AD.OffsetR, g_chip.AD.DirectionR,
1030 	   g_chip.AD.GainG, g_chip.AD.OffsetG, g_chip.AD.DirectionG,
1031 	   g_chip.AD.GainB, g_chip.AD.OffsetB, g_chip.AD.DirectionB);
1032 
1033       DBG (DBG_FUNC, "Transparent_AdjustAD: "
1034 	   "MaxR=%d, MinR=%d  MaxG=%d, MinG=%d  MaxB=%d, MinB=%d\n",
1035 	   wMaxValueR, wMinValueR, wMaxValueG, wMinValueG, wMaxValueB,
1036 	   wMinValueB);
1037 
1038       if (g_chip.AD.DirectionR == 0)
1039 	{
1040 	  if (wMinValueR > 20)
1041 	    {
1042 	      if (g_chip.AD.OffsetR < 8)
1043 		g_chip.AD.DirectionR = 1;
1044 	      else
1045 		g_chip.AD.OffsetR -= 8;
1046 	    }
1047 	  else if (wMinValueR < 10)
1048 	    g_chip.AD.OffsetR += 8;
1049 	}
1050       else
1051 	{
1052 	  if (wMinValueR > 20)
1053 	    g_chip.AD.OffsetR += 8;
1054 	  else if (wMinValueR < 10)
1055 	    g_chip.AD.OffsetR -= 8;
1056 	}
1057 
1058       if (g_chip.AD.DirectionG == 0)
1059 	{
1060 	  if (wMinValueG > 20)
1061 	    {
1062 	      if (g_chip.AD.OffsetG < 8)
1063 		g_chip.AD.DirectionG = 1;
1064 	      else
1065 		g_chip.AD.OffsetG -= 8;
1066 	    }
1067 	  else if (wMinValueG < 10)
1068 	    g_chip.AD.OffsetG += 8;
1069 	}
1070       else
1071 	{
1072 	  if (wMinValueG > 20)
1073 	    g_chip.AD.OffsetG += 8;
1074 	  else if (wMinValueG < 10)
1075 	    g_chip.AD.OffsetG -= 8;
1076 	}
1077 
1078       if (g_chip.AD.DirectionB == 0)
1079 	{
1080 	  if (wMinValueB > 20)
1081 	    {
1082 	      if (g_chip.AD.OffsetB < 8)
1083 		g_chip.AD.DirectionB = 1;
1084 	      else
1085 		g_chip.AD.OffsetB -= 8;
1086 	    }
1087 	  else if (wMinValueB < 10)
1088 	    g_chip.AD.OffsetB += 8;
1089 	}
1090       else
1091 	{
1092 	  if (wMinValueB > 20)
1093 	    g_chip.AD.OffsetB += 8;
1094 	  else if (wMinValueB < 10)
1095 	    g_chip.AD.OffsetB -= 8;
1096 	}
1097 
1098       nTimesOfCal++;
1099       if (nTimesOfCal > 8)
1100 	break;
1101 
1102     }
1103   while (wMinValueR > 20 || wMinValueR < 10
1104 	 || wMinValueG > 20 || wMinValueG < 10
1105 	 || wMinValueB > 20 || wMinValueB < 10);
1106 
1107   DBG (DBG_FUNC, "Transparent_AdjustAD: leave Transparent_AdjustAD\n");
1108   free (lpCalData);
1109 
1110   return TRUE;
1111 }
1112 
1113 /**********************************************************************
1114 Author: Jack             Date: 2005/05/14
1115 Routine Description:
1116 	Find top and left side
1117 Parameters:
1118 	lpwStartX: the left side
1119 	lpwStartY: the top side
1120 Return value:
1121 	if operation is success
1122 	return TRUE
1123 	else
1124 	return FALSE
1125 ***********************************************************************/
1126 static SANE_Bool
Transparent_FindTopLeft(unsigned short * lpwStartX,unsigned short * lpwStartY)1127 Transparent_FindTopLeft (unsigned short * lpwStartX, unsigned short * lpwStartY)
1128 {
1129   unsigned short wCalWidth = TA_FIND_LEFT_TOP_WIDTH_IN_DIP;
1130   unsigned short wCalHeight = TA_FIND_LEFT_TOP_HEIGHT_IN_DIP;
1131 
1132   int i, j;
1133   unsigned short wLeftSide;
1134   unsigned short wTopSide;
1135   int nScanBlock;
1136   SANE_Byte * lpCalData;
1137   unsigned int dwTotalSize;
1138   unsigned short wXResolution, wYResolution;
1139 
1140   DBG (DBG_FUNC, "Transparent_FindTopLeft: call in\n");
1141   if (!g_bOpened)
1142     {
1143       DBG (DBG_FUNC, "Transparent_FindTopLeft: scanner not opened\n");
1144 
1145       return FALSE;
1146     }
1147   if (!g_bPrepared)
1148     {
1149       DBG (DBG_FUNC, "Transparent_FindTopLeft: scanner not prepared\n");
1150       return FALSE;
1151     }
1152 
1153   wXResolution = wYResolution = FIND_LEFT_TOP_CALIBRATE_RESOLUTION;
1154 
1155 
1156   lpCalData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * wCalWidth * wCalHeight);
1157   if (lpCalData == NULL)
1158     {
1159       DBG (DBG_FUNC, "Transparent_FindTopLeft: lpCalData malloc fail\n");
1160       return FALSE;
1161     }
1162 
1163   dwTotalSize = wCalWidth * wCalHeight;
1164   nScanBlock = (int) (dwTotalSize / g_dwCalibrationSize);
1165 
1166   Asic_SetMotorType (&g_chip, TRUE, TRUE);
1167   Asic_SetCalibrate (&g_chip, 8, wXResolution, wYResolution, 0, 0, wCalWidth,
1168 		     wCalHeight, FALSE);
1169   Asic_SetAFEGainOffset (&g_chip);
1170   Asic_ScanStart (&g_chip);
1171 
1172   for (i = 0; i < nScanBlock; i++)
1173     Asic_ReadCalibrationData (&g_chip, lpCalData + i * g_dwCalibrationSize,
1174 			      g_dwCalibrationSize, 8);
1175 
1176   Asic_ReadCalibrationData (&g_chip,
1177 			    lpCalData + (nScanBlock) * g_dwCalibrationSize,
1178 			    (dwTotalSize - g_dwCalibrationSize * nScanBlock),
1179 			    8);
1180   Asic_ScanStop (&g_chip);
1181 
1182 
1183 #ifdef DEBUG_SAVE_IMAGE
1184   FILE *stream = NULL;
1185   SANE_Byte * lpBuf = (SANE_Byte *) malloc (50);
1186   if (NULL == lpBuf)
1187     {
1188       return FALSE;
1189     }
1190   memset (lpBuf, 0, 50);
1191   stream = fopen ("/root/bound(Tra).pnm", "wb+\n");
1192   sprintf (lpBuf, "P5\n%d %d\n255\n", wCalWidth, wCalHeight);
1193   fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream);
1194   fwrite (lpCalData, sizeof (SANE_Byte), wCalWidth * wCalHeight, stream);
1195   fclose (stream);
1196   free (lpBuf);
1197 #endif
1198 
1199   wLeftSide = 0;
1200   wTopSide = 0;
1201 
1202   /* Find Left Side */
1203   for (i = (wCalWidth - 1); i > 0; i--)
1204     {
1205       wLeftSide = *(lpCalData + i);
1206       wLeftSide += *(lpCalData + wCalWidth * 2 + i);
1207       wLeftSide += *(lpCalData + wCalWidth * 4 + i);
1208       wLeftSide += *(lpCalData + wCalWidth * 6 + i);
1209       wLeftSide += *(lpCalData + wCalWidth * 8 + i);
1210       wLeftSide /= 5;
1211       if (wLeftSide < 60)
1212 	{
1213 	  if (i == (wCalWidth - 1))
1214 	    {
1215 	      break;
1216 	    }
1217 	  *lpwStartX = i;
1218 	  break;
1219 	}
1220     }
1221 
1222   /* Find Top Side i=left side */
1223   for (j = 0; j < wCalHeight; j++)
1224     {
1225       wTopSide = *(lpCalData + wCalWidth * j + i + 2);
1226       wTopSide += *(lpCalData + wCalWidth * j + i + 4);
1227       wTopSide += *(lpCalData + wCalWidth * j + i + 6);
1228       wTopSide += *(lpCalData + wCalWidth * j + i + 8);
1229       wTopSide += *(lpCalData + wCalWidth * j + i + 10);
1230       wTopSide /= 5;
1231       if (wTopSide < 60)
1232 	{
1233 	  if (j == 0)
1234 	    {
1235 	      break;
1236 	    }
1237 	  *lpwStartY = j;
1238 	  break;
1239 	}
1240     }
1241 
1242   if ((*lpwStartX < 2200) || (*lpwStartX > 2300))
1243     {
1244       *lpwStartX = 2260;
1245     }
1246 
1247   if ((*lpwStartY < 100) || (*lpwStartY > 200))
1248     {
1249       *lpwStartY = 124;
1250     }
1251 
1252 
1253   Asic_MotorMove (&g_chip, FALSE,
1254 		  (wCalHeight - *lpwStartY) * 1200 / wYResolution + 300);
1255 
1256   free (lpCalData);
1257 
1258   DBG (DBG_FUNC,
1259        "Transparent_FindTopLeft: *lpwStartY = %d, *lpwStartX = %d\n",
1260        *lpwStartY, *lpwStartX);
1261   DBG (DBG_FUNC, "Transparent_FindTopLeft: leave Transparent_FindTopLeft\n");
1262   return TRUE;
1263 }
1264 
1265 /**********************************************************************
1266 Author: Jack             Date: 2005/05/15
1267 Routine Description:
1268 	Get the calibration data
1269 Parameters:
1270 	none
1271 Return value:
1272 	if the operation is success
1273 	return TRUE
1274 	else
1275 	return FALSE
1276 ***********************************************************************/
1277 static SANE_Bool
Transparent_LineCalibration16Bits(unsigned short wTAShadingMinus)1278 Transparent_LineCalibration16Bits (unsigned short wTAShadingMinus)
1279 {
1280 
1281   unsigned short *lpWhiteShading;
1282   unsigned short *lpDarkShading;
1283   double wRWhiteLevel = 0;
1284   double wGWhiteLevel = 0;
1285   double wBWhiteLevel = 0;
1286   unsigned int dwRDarkLevel = 0;
1287   unsigned int dwGDarkLevel = 0;
1288   unsigned int dwBDarkLevel = 0;
1289   unsigned int dwREvenDarkLevel = 0;
1290   unsigned int dwGEvenDarkLevel = 0;
1291   unsigned int dwBEvenDarkLevel = 0;
1292   unsigned short * lpRWhiteSort;
1293   unsigned short * lpGWhiteSort;
1294   unsigned short * lpBWhiteSort;
1295   unsigned short * lpRDarkSort;
1296   unsigned short * lpGDarkSort;
1297   unsigned short * lpBDarkSort;
1298   int i, j;
1299 
1300   SANE_Byte * lpWhiteData;
1301   SANE_Byte * lpDarkData;
1302   unsigned int dwWhiteTotalSize;
1303   unsigned int dwDarkTotalSize;
1304   unsigned short wCalHeight = LINE_CALIBRATION__16BITS_HEIGHT;
1305   unsigned short wCalWidth = g_Width;
1306 
1307   DBG (DBG_FUNC, "Transparent_LineCalibration16Bits: call in\n");
1308   if (!g_bOpened)
1309     {
1310       DBG (DBG_FUNC,
1311 	   "Transparent_LineCalibration16Bits: scanner not opened\n");
1312       return FALSE;
1313     }
1314   if (!g_bPrepared)
1315     {
1316       DBG (DBG_FUNC,
1317 	   "Transparent_LineCalibration16Bits: scanner not prepared\n");
1318       return FALSE;
1319     }
1320 
1321   if (g_XDpi < 600)
1322     {
1323       wTAShadingMinus = wTAShadingMinus * g_XDpi / 600;
1324     }
1325 
1326   dwWhiteTotalSize = wCalWidth * wCalHeight * 3 * 2;
1327   dwDarkTotalSize = wCalWidth * wCalHeight * 3 * 2;
1328   lpWhiteData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * dwWhiteTotalSize);
1329   lpDarkData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * dwDarkTotalSize);
1330   if (lpWhiteData == NULL || lpDarkData == NULL)
1331     {
1332       DBG (DBG_FUNC,
1333 	   "Transparent_LineCalibration16Bits: lpWhiteData or lpDarkData malloc fail\n");
1334       return FALSE;
1335     }
1336 
1337   /*Read white level data */
1338   Asic_SetMotorType (&g_chip, TRUE, TRUE);
1339   Asic_SetAFEGainOffset (&g_chip);
1340   Asic_SetCalibrate (&g_chip, 48, g_XDpi, g_YDpi, g_X, 0, wCalWidth,
1341 		     wCalHeight, TRUE);
1342   Asic_ScanStart (&g_chip);
1343 
1344   /* Read Data */
1345   Asic_ReadCalibrationData (&g_chip, lpWhiteData, dwWhiteTotalSize, 8);
1346   Asic_ScanStop (&g_chip);
1347 
1348 
1349   /* Read dark level data */
1350   Asic_SetMotorType (&g_chip, FALSE, TRUE);
1351   Asic_SetAFEGainOffset (&g_chip);
1352   Asic_SetCalibrate (&g_chip, 48, g_XDpi, g_YDpi, g_X, 0, wCalWidth,
1353 		     wCalHeight, TRUE);
1354 
1355   Asic_TurnLamp (&g_chip, FALSE);
1356   Asic_TurnTA (&g_chip, FALSE);
1357 
1358   usleep (500000);
1359 
1360   Asic_ScanStart (&g_chip);
1361   Asic_ReadCalibrationData (&g_chip, lpDarkData, dwDarkTotalSize, 8);
1362 
1363   Asic_ScanStop (&g_chip);
1364 
1365   Asic_TurnTA (&g_chip, TRUE);
1366 
1367 #ifdef DEBUG_SAVE_IMAGE
1368   FILE *stream = NULL;
1369   SANE_Byte * lpBuf = (SANE_Byte *) malloc (50);
1370   if (NULL == lpBuf)
1371     {
1372       return FALSE;
1373     }
1374   memset (lpBuf, 0, 50);
1375   stream = fopen ("/root/whiteshading(Tra).pnm", "wb+\n");
1376   sprintf (lpBuf, "P6\n%d %d\n65535\n", wCalWidth, wCalHeight);
1377   fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream);
1378   fwrite (lpWhiteData, sizeof (SANE_Byte), wCalWidth * wCalHeight * 3 * 2, stream);
1379   fclose (stream);
1380 
1381   memset (lpBuf, 0, 50);
1382   stream = fopen ("/root/darkshading(Tra).pnm", "wb+\n");
1383   sprintf (lpBuf, "P6\n%d %d\n65535\n", wCalWidth, wCalHeight);
1384   fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream);
1385   fwrite (lpDarkData, sizeof (SANE_Byte), wCalWidth * wCalHeight * 3 * 2, stream);
1386   fclose (stream);
1387   free (lpBuf);
1388 #endif
1389 
1390   lpWhiteShading = (unsigned short *) malloc (sizeof (unsigned short) * wCalWidth * 3);
1391   lpDarkShading = (unsigned short *) malloc (sizeof (unsigned short) * wCalWidth * 3);
1392 
1393   lpRWhiteSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight);
1394   lpGWhiteSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight);
1395   lpBWhiteSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight);
1396   lpRDarkSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight);
1397   lpGDarkSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight);
1398   lpBDarkSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight);
1399 
1400   if (lpWhiteShading == NULL || lpDarkShading == NULL
1401       || lpRWhiteSort == NULL || lpGWhiteSort == NULL || lpBWhiteSort == NULL
1402       || lpRDarkSort == NULL || lpGDarkSort == NULL || lpBDarkSort == NULL)
1403     {
1404       DBG (DBG_FUNC, "Transparent_LineCalibration16Bits: malloc fail\n");
1405 
1406       free (lpWhiteData);
1407       free (lpDarkData);
1408       return FALSE;
1409     }
1410 
1411   DBG (DBG_FUNC,
1412        "Transparent_LineCalibration16Bits: wCalWidth = %d, wCalHeight = %d\n",
1413        wCalWidth, wCalHeight);
1414 
1415   /* create dark level shading */
1416   dwRDarkLevel = 0;
1417   dwGDarkLevel = 0;
1418   dwBDarkLevel = 0;
1419   dwREvenDarkLevel = 0;
1420   dwGEvenDarkLevel = 0;
1421   dwBEvenDarkLevel = 0;
1422 
1423   for (i = 0; i < wCalWidth; i++)
1424 
1425     {
1426       for (j = 0; j < wCalHeight; j++)
1427 	{
1428 	  lpRDarkSort[j] =
1429 	    (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 0));
1430 	  lpRDarkSort[j] +=
1431 	    (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 1) << 8);
1432 
1433 	  lpGDarkSort[j] =
1434 	    (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 2));
1435 	  lpGDarkSort[j] +=
1436 	    (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 3) << 8);
1437 
1438 	  lpBDarkSort[j] =
1439 	    (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 4));
1440 	  lpBDarkSort[j] +=
1441 	    (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 5) << 8);
1442 	}
1443 
1444       /* sum of dark level for all pixels */
1445       if (g_XDpi == 1200)
1446 	{
1447 	  /* do dark shading table with mean */
1448 	  if (i % 2)
1449 	    {
1450 	      dwRDarkLevel +=
1451 		(unsigned int) MustScanner_FiltLower (lpRDarkSort, wCalHeight, 20,
1452 					       30);
1453 	      dwGDarkLevel +=
1454 		(unsigned int) MustScanner_FiltLower (lpGDarkSort, wCalHeight, 20,
1455 					       30);
1456 	      dwBDarkLevel +=
1457 		(unsigned int) MustScanner_FiltLower (lpBDarkSort, wCalHeight, 20,
1458 					       30);
1459 	    }
1460 	  else
1461 	    {
1462 	      dwREvenDarkLevel +=
1463 		(unsigned int) MustScanner_FiltLower (lpRDarkSort, wCalHeight, 20,
1464 					       30);
1465 	      dwGEvenDarkLevel +=
1466 		(unsigned int) MustScanner_FiltLower (lpGDarkSort, wCalHeight, 20,
1467 					       30);
1468 	      dwBEvenDarkLevel +=
1469 		(unsigned int) MustScanner_FiltLower (lpBDarkSort, wCalHeight, 20,
1470 					       30);
1471 	    }
1472 	}
1473       else
1474 	{
1475 	  dwRDarkLevel +=
1476 	    (unsigned int) MustScanner_FiltLower (lpRDarkSort, wCalHeight, 20, 30);
1477 	  dwGDarkLevel +=
1478 	    (unsigned int) MustScanner_FiltLower (lpGDarkSort, wCalHeight, 20, 30);
1479 	  dwBDarkLevel +=
1480 	    (unsigned int) MustScanner_FiltLower (lpBDarkSort, wCalHeight, 20, 30);
1481 	}
1482     }
1483 
1484   if (g_XDpi == 1200)
1485     {
1486       dwRDarkLevel = (unsigned int) (dwRDarkLevel / (wCalWidth / 2)) - 512;
1487       dwGDarkLevel = (unsigned int) (dwGDarkLevel / (wCalWidth / 2)) - 512;
1488       dwBDarkLevel = (unsigned int) (dwBDarkLevel / (wCalWidth / 2)) - 512;
1489 
1490       dwREvenDarkLevel = (unsigned int) (dwREvenDarkLevel / (wCalWidth / 2)) - 512;
1491       dwGEvenDarkLevel = (unsigned int) (dwGEvenDarkLevel / (wCalWidth / 2)) - 512;
1492       dwBEvenDarkLevel = (unsigned int) (dwBEvenDarkLevel / (wCalWidth / 2)) - 512;
1493     }
1494   else
1495     {
1496       dwRDarkLevel = (unsigned int) (dwRDarkLevel / wCalWidth) - 512;
1497       dwGDarkLevel = (unsigned int) (dwGDarkLevel / wCalWidth) - 512;
1498       dwBDarkLevel = (unsigned int) (dwBDarkLevel / wCalWidth) - 512;
1499     }
1500 
1501   /* Create white shading */
1502   for (i = 0; i < wCalWidth; i++)
1503     {
1504       wRWhiteLevel = 0;
1505       wGWhiteLevel = 0;
1506       wBWhiteLevel = 0;
1507 
1508       for (j = 0; j < wCalHeight; j++)
1509 	{
1510 	  lpRWhiteSort[j] =
1511 	    (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 0));
1512 	  lpRWhiteSort[j] +=
1513 	    (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 1) << 8);
1514 
1515 	  lpGWhiteSort[j] =
1516 	    (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 2));
1517 	  lpGWhiteSort[j] +=
1518 	    (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 3) << 8);
1519 
1520 	  lpBWhiteSort[j] =
1521 	    (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 4));
1522 	  lpBWhiteSort[j] +=
1523 	    (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 5) << 8);
1524 	}
1525 
1526       if (1200 == g_XDpi)
1527 	{
1528 	  if (i % 2)
1529 	    {
1530 	      if (SS_Negative == g_ssScanSource)
1531 		{
1532 		  *(lpDarkShading + i * 3 + 0) = (unsigned short) dwRDarkLevel;
1533 		  *(lpDarkShading + i * 3 + 1) = (unsigned short) dwGDarkLevel;
1534 		  *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBDarkLevel;
1535 		}
1536 	      else
1537 		{
1538 		  *(lpDarkShading + i * 3 + 0) = (unsigned short) dwRDarkLevel;
1539 		  *(lpDarkShading + i * 3 + 1) = (unsigned short) (dwGDarkLevel * 0.78);
1540 		  *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBDarkLevel;
1541 		}
1542 	    }
1543 	  else
1544 	    {
1545 	      if (SS_Negative == g_ssScanSource)
1546 		{
1547 		  *(lpDarkShading + i * 3 + 0) = (unsigned short) dwREvenDarkLevel;
1548 		  *(lpDarkShading + i * 3 + 1) = (unsigned short) dwGEvenDarkLevel;
1549 		  *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBEvenDarkLevel;
1550 		}
1551 	      else
1552 		{
1553 		  *(lpDarkShading + i * 3 + 0) = (unsigned short) dwREvenDarkLevel;
1554 		  *(lpDarkShading + i * 3 + 1) =
1555 		    (unsigned short) (dwGEvenDarkLevel * 0.78);
1556 		  *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBEvenDarkLevel;
1557 		}
1558 	    }
1559 	}
1560       else
1561 	{
1562 	  if (SS_Negative == g_ssScanSource)
1563 	    {
1564 	      *(lpDarkShading + i * 3 + 0) = (unsigned short) dwRDarkLevel;
1565 	      *(lpDarkShading + i * 3 + 1) = (unsigned short) dwRDarkLevel;
1566 	      *(lpDarkShading + i * 3 + 2) = (unsigned short) dwRDarkLevel;
1567 	    }
1568 	  else
1569 	    {
1570 	      *(lpDarkShading + i * 3 + 0) = (unsigned short) dwRDarkLevel;
1571 	      *(lpDarkShading + i * 3 + 1) = (unsigned short) (dwRDarkLevel * 0.78);
1572 	      *(lpDarkShading + i * 3 + 2) = (unsigned short) dwRDarkLevel;
1573 	    }
1574 	}
1575 
1576       /* Create white shading */
1577       wRWhiteLevel =
1578 	(double) (MustScanner_FiltLower (lpRWhiteSort, wCalHeight, 20, 30) -
1579 		  *(lpDarkShading + i * 3 + 0));
1580       wGWhiteLevel =
1581 	(double) (MustScanner_FiltLower (lpGWhiteSort, wCalHeight, 20, 30) -
1582 		  *(lpDarkShading + i * 3 + 1));
1583       wBWhiteLevel =
1584 	(double) (MustScanner_FiltLower (lpBWhiteSort, wCalHeight, 20, 30) -
1585 		  *(lpDarkShading + i * 3 + 2));
1586 
1587       if (g_ssScanSource == SS_Negative)
1588 	{
1589 	  if (wRWhiteLevel > 0)
1590 	    *(lpWhiteShading + i * 3 + 0) =
1591 	      (unsigned short) ((float) 65536 / wRWhiteLevel * 0x1000);
1592 	  else
1593 	    *(lpWhiteShading + i * 3 + 0) = 0x1000;
1594 
1595 	  if (wGWhiteLevel > 0)
1596 	    *(lpWhiteShading + i * 3 + 1) =
1597 	      (unsigned short) ((float) (65536 * 1.5) / wGWhiteLevel * 0x1000);
1598 	  else
1599 	    *(lpWhiteShading + i * 3 + 1) = 0x1000;
1600 
1601 	  if (wBWhiteLevel > 0)
1602 	    *(lpWhiteShading + i * 3 + 2) =
1603 	      (unsigned short) ((float) (65536 * 2.0) / wBWhiteLevel * 0x1000);
1604 	  else
1605 	    *(lpWhiteShading + i * 3 + 2) = 0x1000;
1606 	}
1607       else
1608 	{
1609 	  if (wRWhiteLevel > 0)
1610 	    *(lpWhiteShading + i * 3 + 0) =
1611 	      (unsigned short) ((float) 65536 / wRWhiteLevel * 0x1000);
1612 	  else
1613 	    *(lpWhiteShading + i * 3 + 0) = 0x1000;
1614 
1615 	  if (wGWhiteLevel > 0)
1616 	    *(lpWhiteShading + i * 3 + 1) =
1617 	      (unsigned short) ((float) (65536 * 1.04) / wGWhiteLevel * 0x1000);
1618 	  else
1619 	    *(lpWhiteShading + i * 3 + 1) = 0x1000;
1620 
1621 	  if (wBWhiteLevel > 0)
1622 	    *(lpWhiteShading + i * 3 + 2) =
1623 	      (unsigned short) ((float) 65536 / wBWhiteLevel * 0x1000);
1624 	  else
1625 	    *(lpWhiteShading + i * 3 + 2) = 0x1000;
1626 	}
1627     }
1628 
1629   free (lpWhiteData);
1630   free (lpDarkData);
1631   free (lpRWhiteSort);
1632   free (lpGWhiteSort);
1633   free (lpBWhiteSort);
1634   free (lpRDarkSort);
1635   free (lpGDarkSort);
1636   free (lpBDarkSort);
1637 
1638   Asic_SetShadingTable (&g_chip, lpWhiteShading, lpDarkShading, g_XDpi,
1639 			wCalWidth, 0);
1640 
1641   free (lpWhiteShading);
1642   free (lpDarkShading);
1643 
1644   DBG (DBG_FUNC,
1645        "Transparent_LineCalibration16Bits: leave Transparent_LineCalibration16Bits\n");
1646   return TRUE;
1647 }
1648 
1649 /**********************************************************************
1650 Author: Jack             Date: 2005/05/14
1651 Routine Description:
1652 	Prepare scan image
1653 Parameters:
1654 	none
1655 Return value:
1656 	if operation is success
1657 	return TRUE
1658 	else
1659 	return FALSE
1660 ***********************************************************************/
1661 static SANE_Bool
Transparent_PrepareScan()1662 Transparent_PrepareScan ()
1663 {
1664   DBG (DBG_FUNC, "Transparent_PrepareScan: call in\n");
1665 
1666   g_wScanLinesPerBlock = g_dwBufferSize / g_BytesPerRow;
1667   g_wMaxScanLines = g_dwImageBufferSize / g_BytesPerRow;
1668   g_wMaxScanLines =
1669     (g_wMaxScanLines / g_wScanLinesPerBlock) * g_wScanLinesPerBlock;
1670   g_isCanceled = FALSE;
1671 
1672   g_dwScannedTotalLines = 0;
1673   g_wReadedLines = 0;
1674   g_wtheReadyLines = 0;
1675   g_wReadImageLines = 0;
1676 
1677   g_wReadyShadingLine = 0;
1678   g_wStartShadingLinePos = 0;
1679 
1680   switch (g_ScanMode)
1681     {
1682 
1683     case CM_RGB48:
1684 
1685       g_wtheReadyLines = g_wLineDistance * 2 + g_wPixelDistance;
1686 
1687       g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize);
1688       if (g_lpReadImageHead == NULL)
1689 	{
1690 	  DBG (DBG_FUNC, "Transparent_PrepareScan:malloc fail\n");
1691 	  return FALSE;
1692 	}
1693       break;
1694 
1695     case CM_RGB24ext:
1696       g_wtheReadyLines = g_wLineDistance * 2 + g_wPixelDistance;
1697       g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize);
1698 
1699       if (g_lpReadImageHead == NULL)
1700 	{
1701 	  DBG (DBG_FUNC, "Transparent_PrepareScan:malloc fail\n");
1702 	  return FALSE;
1703 	}
1704       break;
1705 
1706     case CM_GRAY16ext:
1707       g_wtheReadyLines = g_wPixelDistance;
1708       g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize);
1709       if (g_lpReadImageHead == NULL)
1710 	{
1711 	  DBG (DBG_FUNC, "Transparent_PrepareScan:malloc fail\n");
1712 	  return FALSE;
1713 	}
1714       break;
1715 
1716     case CM_GRAY8ext:
1717       g_wtheReadyLines = g_wPixelDistance;
1718       g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize);
1719       if (g_lpReadImageHead == NULL)
1720 	{
1721 	  DBG (DBG_FUNC, "Transparent_PrepareScan:malloc fail\n");
1722 	  return FALSE;
1723 	}
1724       break;
1725 
1726     case CM_TEXT:
1727       g_wtheReadyLines = g_wPixelDistance;
1728       g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize);
1729       if (g_lpReadImageHead == NULL)
1730 	{
1731 	  DBG (DBG_FUNC, "Transparent_PrepareScan:malloc fail\n");
1732 	  return FALSE;
1733 	}
1734       break;
1735     default:
1736       return FALSE;
1737     }
1738 
1739   Asic_ScanStart (&g_chip);
1740 
1741   DBG (DBG_FUNC, "Transparent_PrepareScan: leave Transparent_PrepareScan\n");
1742   return TRUE;
1743 }				/* end of the file ScannerTransparent.c */
1744