1 /* @file plustek-pp_tpa.c
2 * @brief Here we find some adjustments according to the scan source.
3 * This file is ASIC P9800x specific
4 *
5 * based on sources acquired from Plustek Inc.
6 * Copyright (C) 1998 Plustek Inc.
7 * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de>
8 * also based on the work done by Rick Bronson
9 *
10 * History:
11 * - 0.30 - initial version
12 * - 0.31 - Added some comments
13 * - 0.32 - no changes
14 * - 0.33 - new header
15 * - 0.34 - no changes
16 * - 0.35 - no changes
17 * - 0.36 - no changes
18 * - 0.37 - cosmetic changes
19 * - 0.38 - Replaced AllPointer by DataPointer
20 * - renamed this file from transform.c tpa.c
21 * - 0.39 - no changes
22 * - 0.40 - no changes
23 * - 0.41 - no changes
24 * - 0.42 - changed include names
25 * - 0.43 - no changes
26 * - 0.44 - fix format string issues, as Long types default to int32_t
27 * now
28 * .
29 * <hr>
30 * This file is part of the SANE package.
31 *
32 * This program is free software; you can redistribute it and/or
33 * modify it under the terms of the GNU General Public License as
34 * published by the Free Software Foundation; either version 2 of the
35 * License, or (at your option) any later version.
36 *
37 * This program is distributed in the hope that it will be useful, but
38 * WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 * General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License
43 * along with this program. If not, see <https://www.gnu.org/licenses/>.
44 *
45 * As a special exception, the authors of SANE give permission for
46 * additional uses of the libraries contained in this release of SANE.
47 *
48 * The exception is that, if you link a SANE library with other files
49 * to produce an executable, this does not by itself cause the
50 * resulting executable to be covered by the GNU General Public
51 * License. Your use of that executable is in no way restricted on
52 * account of linking the SANE library code into it.
53 *
54 * This exception does not, however, invalidate any other reasons why
55 * the executable file might be covered by the GNU General Public
56 * License.
57 *
58 * If you submit changes to SANE to the maintainers to be included in
59 * a subsequent release, you agree by submitting the changes that
60 * those changes may be distributed with this exception intact.
61 *
62 * If you write modifications of your own for SANE, it is your choice
63 * whether to permit this exception to apply to your modifications.
64 * If you do not wish that, delete this exception notice.
65 * <hr>
66 */
67 #include "plustek-pp_scan.h"
68
69 /***************************** local vars ************************************/
70
71 static UShort a_wGainString [] = {
72 50, 75, 100, 125, 150, 175, 200, 225,
73 250, 275, 300, 325, 350, 375, 400, 425,
74 450, 475, 500, 525, 550, 575, 600, 625,
75 650, 675, 700, 725, 750, 775, 800, 825
76 };
77
78 /*************************** local functions *********************************/
79
80 /*.............................................................................
81 *
82 */
tpaP98SubNoise(pScanData ps,pULong pdwSum,pUShort pwShading,ULong dwHilightOff,ULong dwShadowOff)83 static void tpaP98SubNoise( pScanData ps, pULong pdwSum, pUShort pwShading,
84 ULong dwHilightOff, ULong dwShadowOff )
85 {
86 ULong dwPixels, dwLines, dwSum;
87 pUShort pw;
88
89 for (dwPixels = 4; dwPixels--; pdwSum++, pwShading++)
90 *pwShading = (UShort)(*pdwSum >> 5);
91
92 for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++,
93 pdwSum++, pwShading++) {
94
95 pw = (pUShort)ps->Shade.pHilight + dwHilightOff + dwPixels;
96 dwSum = 0;
97
98 for (dwLines = _DEF_BRIGHTEST_SKIP; dwLines--; pw += 5400UL)
99 dwSum += (ULong) *pw;
100
101 pw = ps->pwShadow + dwShadowOff + dwPixels;
102
103 for (dwLines = _DEF_DARKEST_SKIP; dwLines--; pw += 5400UL)
104 dwSum += (ULong) *pw;
105
106 *pwShading = (UShort)((*pdwSum - dwSum) / ps->Shade.dwDiv);
107 }
108 if (ps->dwShadingPixels != 5400UL) {
109 for (dwPixels = 2700UL; dwPixels--; pdwSum++, pwShading++)
110 *pwShading = (UShort)(*pdwSum >> 5);
111 }
112 }
113
114 /*.............................................................................
115 *
116 */
tpaP98ShadingWaveformSum(pScanData ps)117 static void tpaP98ShadingWaveformSum( pScanData ps )
118 {
119 DataPointer pd, pt;
120 ULong dw;
121
122 pd.pdw = (pULong)ps->pScanBuffer1;
123 pt.pw = (pUShort)ps->pScanBuffer1;
124
125 if ((ps->DataInf.dwScanFlag & SCANDEF_TPA ) ||
126 (0 == ps->bShadingTimeFlag)) {
127
128 if( ps->Shade.pHilight ) {
129
130 tpaP98SubNoise( ps, (pULong)ps->pScanBuffer1,
131 (pUShort)ps->pScanBuffer1, 0, 0);
132
133 tpaP98SubNoise( ps ,(pULong)ps->pScanBuffer1 + 5400UL,
134 (pUShort)ps->pScanBuffer1 + 5400UL,
135 ps->dwHilightCh, ps->dwShadowCh);
136
137 tpaP98SubNoise( ps, (pULong)ps->pScanBuffer1 + 5400UL * 2UL,
138 (pUShort)ps->pScanBuffer1 + 5400UL * 2UL,
139 ps->dwHilightCh * 2, ps->dwShadowCh * 2);
140 } else {
141
142 for (dw = 5400 * 3; dw; dw--, pt.pw++, pd.pdw++)
143 *pt.pw = (UShort)(*pd.pdw / 32); /* shift 5 bits */
144 }
145
146 } else {
147
148 if (02 == ps->bShadingTimeFlag ) {
149 for (dw = 5400 * 3; dw; dw--, pt.pw++, pd.pdw++)
150 *pt.pw = (UShort)(*pd.pdw / 16); /* shift 4 bits */
151 } else {
152 for (dw = 5400 * 3; dw; dw--, pt.pw++, pd.pdw++)
153 *pt.pw = (UShort)(*pd.pdw / 4); /* shift 2 bits */
154 }
155 }
156 }
157
158 /*.............................................................................
159 * get wReduceRedFactor, wReduceGreenFactor, wReduceBlueFactor
160 */
tpaP98GetNegativeTempRamData(pScanData ps)161 static void tpaP98GetNegativeTempRamData( pScanData ps )
162 {
163 UShort wRedTemp, wGreenTemp, wBlueTemp;
164 UShort wRedShadingTemp, wGreenShadingTemp, wBlueShadingTemp;
165 ULong dw, dw1;
166 DataPointer p;
167 pULong pdwNegativeSumTemp;
168 pUShort pNegativeTempRam, pNegativeTempRam2;
169
170 ps->bFastMoveFlag = _FastMove_Low_C75_G150;
171
172 MotorP98GoFullStep( ps ,80 );
173
174 pNegativeTempRam = (pUShort)(ps->pScanBuffer1 + 5400 * 6);
175 pdwNegativeSumTemp = (pULong)(pNegativeTempRam + 960 * 3 * 2);
176 pNegativeTempRam2 = (pUShort)(pdwNegativeSumTemp + 960 * 3 * 4);
177
178 /* ClearNegativeSumBuffer() */
179 memset( pdwNegativeSumTemp, 0, (960 * 3 * 4));
180
181 /* SetReadNegativeTempRegister() */
182 ps->AsicReg.RD_Motor0Control = 0;
183
184 IOCmdRegisterToScanner( ps, ps->RegMotor0Control,
185 ps->AsicReg.RD_Motor0Control );
186
187 ps->AsicReg.RD_ModeControl = _ModeScan;
188 ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward;
189 ps->AsicReg.RD_ModelControl = _ModelDpi600 + _LED_CONTROL + _LED_ACTIVITY;
190 ps->AsicReg.RD_Dpi = ps->PhysicalDpi;
191
192 if (!ps->wNegAdjustX) {
193 ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX +
194 _Negative96OriginOffsetX * 2);
195 } else {
196 ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX +
197 ps->wNegAdjustX);
198 }
199
200 ps->AsicReg.RD_Pixels = 960;
201 ps->AsicReg.RD_XStepTime = 32;
202
203 IOPutOnAllRegisters( ps );
204
205 /* NegativeMotorRunLoop() */
206 p.pb = ps->a_nbNewAdrPointer;
207 for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++)
208 *p.pdw = 0x87808780;
209
210 IOSetToMotorRegister( ps );
211
212 for (dw1 = 16; dw1; dw1--) {
213
214 TimerDef timer;
215
216 MiscStartTimer( &timer, _SECOND );
217
218 while((IOReadFifoLength( ps ) < 960) && !MiscCheckTimer( &timer )) {
219
220 _DO_UDELAY(1);
221 }
222
223 /* ReadColorDataIn() - Read 1 RGB line */
224 ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
225 IOReadScannerImageData( ps, (pUChar)pNegativeTempRam, 960 );
226
227 ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
228 IOReadScannerImageData( ps, (pUChar)(pNegativeTempRam + 960), 960 );
229
230 ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
231 IOReadScannerImageData( ps, (pUChar)(pNegativeTempRam + 960 * 2), 960 );
232
233 /* fillNegativeSum() */
234 for (dw = 0; dw < 960 * 3; dw++)
235 pdwNegativeSumTemp[dw] += ((pUShort) pNegativeTempRam)[dw];
236
237 /* one line */
238 if (IOReadFifoLength( ps ) <= (960 * 2))
239 IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
240 }
241
242 /* AverageAndShift() */
243 for( dw = 0, dw1 = 0; dw < 240 * 3; dw++, dw1+=4 ) {
244
245 pNegativeTempRam[dw] = (UShort)((pdwNegativeSumTemp[dw1] +
246 pdwNegativeSumTemp[dw1+1] +
247 pdwNegativeSumTemp[dw1+2] +
248 pdwNegativeSumTemp[dw1+3]) / 128);
249 /* shift 6 bits */
250 }
251
252 /* NegativeAdd1() */
253 if (!ps->wNegAdjustX) {
254 dw1 = (ps->dwOffsetNegative + _Negative96OriginOffsetX * 2 * 2) / 2;
255 } else {
256 dw1 = (ps->dwOffsetNegative + ps->wNegAdjustX * 2) / 2;
257 }
258
259 /* do R shading average */
260 for (dw = 0; dw < 240; dw++, dw1 += 4) {
261 pNegativeTempRam2[dw] = (UShort)(
262 (((pUShort)ps->pScanBuffer1)[dw1] +
263 ((pUShort)ps->pScanBuffer1)[dw1+1] +
264 ((pUShort)ps->pScanBuffer1)[dw1+2] +
265 ((pUShort)ps->pScanBuffer1)[dw1+3]) / 4);
266 }
267
268 /* NegativeAdd1() */
269 if (!ps->wNegAdjustX)
270 dw1 = (ps->dwOffsetNegative + 5400 * 2 + _Negative96OriginOffsetX * 2 * 2) / 2;
271 else
272 dw1 = (ps->dwOffsetNegative + 5400 * 2 + ps->wNegAdjustX * 2) / 2;
273
274 /* do G shading average */
275 for (; dw < 240 * 2; dw++, dw1 += 4) {
276 pNegativeTempRam2[dw] = (UShort)(
277 (((pUShort)ps->pScanBuffer1)[dw1] +
278 ((pUShort)ps->pScanBuffer1)[dw1+1] +
279 ((pUShort)ps->pScanBuffer1)[dw1+2] +
280 ((pUShort)ps->pScanBuffer1)[dw1+3]) / 4);
281 }
282
283 /* NegativeAdd1() */
284 if (!ps->wNegAdjustX)
285 dw1 = (ps->dwOffsetNegative + 5400 * 4 + _Negative96OriginOffsetX * 2 * 2) / 2;
286 else
287 dw1 = (ps->dwOffsetNegative + 5400 * 4 + ps->wNegAdjustX * 2) / 2;
288
289 /* do B shading average */
290 for (; dw < 240 * 3; dw++, dw1 += 4) {
291 pNegativeTempRam2 [dw] = (UShort)(
292 (((pUShort)ps->pScanBuffer1)[dw1] +
293 ((pUShort)ps->pScanBuffer1)[dw1+1] +
294 ((pUShort)ps->pScanBuffer1)[dw1+2] +
295 ((pUShort)ps->pScanBuffer1)[dw1+3]) / 4);
296 }
297
298 wRedTemp = wGreenTemp = wBlueTemp = 0;
299 wRedShadingTemp = wGreenShadingTemp = wBlueShadingTemp = 0;
300
301 /* FindMaxNegValue -- find R */
302 for (dw = 0; dw < 240; dw++) {
303 if (pNegativeTempRam[dw] >= wRedTemp &&
304 pNegativeTempRam[dw + 240] >= wGreenTemp &&
305 pNegativeTempRam[dw + 480] > wBlueTemp) {
306
307 wRedTemp = pNegativeTempRam[dw];
308 wGreenTemp = pNegativeTempRam[dw + 240];
309 wBlueTemp = pNegativeTempRam[dw + 480];
310
311 wRedShadingTemp = pNegativeTempRam2[dw];
312 wGreenShadingTemp = pNegativeTempRam2[dw + 240];
313 wBlueShadingTemp = pNegativeTempRam2[dw + 480];
314 }
315 }
316
317 /* GainAddX = (1/4)*DoubleX + 1/ 2 */
318 if ((ps->bRedGainIndex += (Byte)((wRedShadingTemp / wRedTemp) * 100 - 50) / 25) > 32)
319 ps->bRedGainIndex = 31;
320
321 if ((ps->bGreenGainIndex += (Byte)((wGreenShadingTemp / wGreenTemp) * 100 - 50) / 25) > 32)
322 ps->bGreenGainIndex = 31;
323
324 if ((ps->bBlueGainIndex += (Byte)((wBlueShadingTemp / wBlueTemp) * 100 - 50) / 25) > 32)
325 ps->bBlueGainIndex = 31;
326
327 }
328
329 /*.............................................................................
330 *
331 */
tpaP98RecalculateNegativeShadingGain(pScanData ps)332 static void tpaP98RecalculateNegativeShadingGain( pScanData ps )
333 {
334 Byte b[3];
335 UShort wSum, counter;
336 UShort w, w1, w2;
337 ULong dw, dw1;
338 pUChar pDest, pSrce, pNegativeTempRam;
339 pUChar pbReg[3];
340 TimerDef timer;
341 DataPointer p;
342
343 pNegativeTempRam = (pUChar)(ps->pScanBuffer1 + 5400 * 6);
344
345 /* AdjustDarkCondition () */
346 ps->Shade.pCcdDac->DarkDAC.Colors.Red = ps->bsPreRedDAC;
347 ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC;
348 ps->Shade.pCcdDac->DarkDAC.Colors.Blue = ps->bsPreBlueDAC;
349
350 ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = ps->wsDACCompareHighRed;
351 ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = ps->wsDACCompareLowRed;
352 ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = ps->wsDACCompareHighGreen;
353 ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = ps->wsDACCompareLowGreen;
354 ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = ps->wsDACCompareHighBlue;
355 ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = ps->wsDACCompareLowBlue;
356
357 DacP98FillGainOutDirectPort( ps );
358
359 /* ClearNegativeTempBuffer () */
360 memset( pNegativeTempRam, 0, (960 * 3 * 4));
361
362 /* GetNegGainValue () */
363 ps->PauseColorMotorRunStates( ps );
364
365 /* SetScanMode () set scan mode to Byte mode */
366 ps->AsicReg.RD_ScanControl |= _SCAN_BYTEMODE;
367 ps->AsicReg.RD_ScanControl &= 0xfd;
368 IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
369 DacP98FillGainOutDirectPort( ps );
370
371 /* SetReadNegativeTempRegister() */
372 ps->AsicReg.RD_Motor0Control = 0;
373 IOCmdRegisterToScanner( ps, ps->RegMotor0Control,
374 ps->AsicReg.RD_Motor0Control );
375
376 ps->AsicReg.RD_ModeControl = _ModeScan;
377 ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward;
378 ps->AsicReg.RD_ModelControl = _ModelDpi600 + _LED_CONTROL + _LED_ACTIVITY;
379 ps->AsicReg.RD_Dpi = ps->PhysicalDpi;
380
381 if (!ps->wNegAdjustX) {
382 ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 +
383 ps->Device.DataOriginX +
384 _Negative96OriginOffsetX * 2);
385 } else {
386 ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX +
387 ps->wNegAdjustX);
388 }
389 ps->AsicReg.RD_Pixels = 960;
390 ps->AsicReg.RD_XStepTime = 32;
391 IOPutOnAllRegisters( ps );
392
393 /* ReReadNegativeTemp */
394 MiscStartTimer( &timer, _SECOND );
395
396 while((IOReadFifoLength( ps) < 960) && !MiscCheckTimer( &timer )) {
397
398 _DO_UDELAY(1); /* 1 us delay */
399 }
400
401 /* ReadColorDataIn() - Read 1 RGB line */
402 ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
403 IOReadScannerImageData( ps, pNegativeTempRam, 960);
404
405 ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
406 IOReadScannerImageData( ps, pNegativeTempRam + 960, 960);
407
408 ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
409 IOReadScannerImageData( ps, pNegativeTempRam + 960 * 2, 960);
410
411 /* FindRGBGainValue(); */
412 pDest = pSrce = pNegativeTempRam;
413
414 /* ReAdjustGainAverage() */
415 for (dw1 = 0; dw1 < (960 * 3) / 16; dw1++, pDest++) {
416 for (dw = 0, wSum = 0; dw < 16; dw++, pSrce++)
417 wSum += *pSrce;
418
419 *pDest = wSum / 16;
420 }
421
422 /* FindTheMaxGainValue */
423 for (w = 0, p.pb = pNegativeTempRam; w < 3; w++) {
424 for (dw = 960 / 16, b[w] = 0; dw; dw--, p.pb++) {
425 if (b[w] < *p.pb)
426 b[w] = *p.pb;
427 }
428 }
429 ps->bRedHigh = b[0];
430 ps->bGreenHigh = b[1];
431 ps->bBlueHigh = b[2];
432
433 /* ModifyExposureTime () */
434 if ((ps->bRedHigh < _GAIN_LOW) ||
435 (ps->bGreenHigh < _GAIN_LOW) || (ps->bBlueHigh < _GAIN_LOW)) {
436 ps->AsicReg.RD_LineControl = 192;
437 }
438
439 IOCmdRegisterToScanner( ps, ps->RegLineControl,
440 ps->AsicReg.RD_LineControl );
441 counter = 0;
442
443 /* ReAdjustRGBGain () */
444 for (w1 = 0; w1 < 16; w1++) {
445
446 ps->PauseColorMotorRunStates( ps );
447 DacP98FillGainOutDirectPort( ps );
448
449 /* SetReadNegativeTempRegister () */
450 ps->AsicReg.RD_Motor0Control = 0;
451 IOCmdRegisterToScanner( ps, ps->RegMotor0Control,
452 ps->AsicReg.RD_Motor0Control );
453
454 ps->AsicReg.RD_ModeControl = _ModeScan;
455 ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward;
456 ps->AsicReg.RD_ModelControl = _ModelDpi600 + _LED_CONTROL + _LED_ACTIVITY;
457 ps->AsicReg.RD_Dpi = ps->PhysicalDpi;
458
459 if (!ps->wNegAdjustX) {
460 ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 +
461 ps->Device.DataOriginX +
462 _Negative96OriginOffsetX * 2);
463 } else {
464 ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 +
465 ps->Device.DataOriginX +
466 ps->wNegAdjustX);
467 }
468
469 ps->AsicReg.RD_Pixels = 960;
470 ps->AsicReg.RD_XStepTime = 32;
471 IOPutOnAllRegisters( ps );
472
473 /* ReReadNegativeTemp () */
474 MiscStartTimer( &timer, _SECOND );
475 while((IOReadFifoLength( ps ) < 960) && !MiscCheckTimer( &timer)) {
476
477 _DO_UDELAY(1);
478 }
479
480 /* ReadColorDataIn() - Read 1 RGB line */
481 ps->AsicReg.RD_ModeControl = _ModeFifoRSel;
482 IOReadScannerImageData( ps, pNegativeTempRam, 960 );
483
484 ps->AsicReg.RD_ModeControl = _ModeFifoGSel;
485 IOReadScannerImageData( ps, pNegativeTempRam + 960, 960);
486
487 ps->AsicReg.RD_ModeControl = _ModeFifoBSel;
488 IOReadScannerImageData( ps ,pNegativeTempRam + 960 * 2, 960);
489
490
491 /* ReAdjustGainAverage() */
492 pDest = pSrce = pNegativeTempRam;
493 for( dw1 = 0; dw1 < (960 * 3) / 16; dw1++, pDest++ ) {
494 for( dw = 0, wSum = 0; dw < 16; dw++, pSrce++ )
495 wSum += *pSrce;
496 *pDest = wSum / 16;
497 }
498
499 /* FindTheMaxGainValue */
500 pbReg[0] = &ps->bRedGainIndex;
501 pbReg[1] = &ps->bGreenGainIndex;
502 pbReg[2] = &ps->bBlueGainIndex;
503 for (w = 0, p.pb = pNegativeTempRam; w < 3; w++) {
504
505 for (dw = 960 / 16, b [w] = 0; dw; dw--, p.pb++) {
506 if (b[w] < *p.pb)
507 b[w] = *p.pb;
508 }
509 if (b [w] < _GAIN_LOW) {
510 if (( _GAIN_P98_HIGH - b [w]) < b [w])
511 *(pbReg [w]) += 1;
512 else
513 *(pbReg [w]) += 4;
514 } else {
515
516 if (b [w] > _GAIN_P98_HIGH)
517 *(pbReg [w]) -= 1;
518 }
519 }
520
521 for (w2 = 0; w2 < 3; w2++) {
522 if (*(pbReg[w2]) > 31)
523 (*(pbReg[w2])) = 31;
524 }
525 if ((b[0] == 0) || (b[1] == 0) || (b[2] == 0)) {
526 counter++;
527
528 if (counter < 16) {
529 w1--;
530 ps->bRedGainIndex -= 4;
531 ps->bGreenGainIndex -= 4;
532 ps->bBlueGainIndex -= 4;
533 }
534 }
535 }
536
537 DacP98FillGainOutDirectPort( ps );
538
539 ps->Shade.DarkOffset.Colors.Red = 0;
540 ps->Shade.DarkOffset.Colors.Green = 0;
541 ps->Shade.DarkOffset.Colors.Blue = 0;
542
543 ps->OpenScanPath( ps );
544 DacP98FillShadingDarkToShadingRegister( ps );
545 ps->CloseScanPath( ps );
546
547 DacP98AdjustDark( ps );
548 }
549
550 /*.............................................................................
551 *
552 */
tpaP98RecalculateShadingGainandData(pScanData ps)553 static void tpaP98RecalculateShadingGainandData( pScanData ps )
554 {
555 DataPointer p;
556 ULong dw;
557 UShort filmAdjustX;
558 UShort wOldRedGain, wOldGreenGain, wOldBlueGain;
559 UShort wNewRedGain, wNewGreenGain, wNewBlueGain;
560
561 /* AdjustDarkCondition () */
562 ps->Shade.pCcdDac->DarkDAC.Colors.Red = ps->bsPreRedDAC;
563 ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC;
564 ps->Shade.pCcdDac->DarkDAC.Colors.Blue = ps->bsPreBlueDAC;
565
566 ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = ps->wsDACCompareHighRed;
567 ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = ps->wsDACCompareLowRed;
568 ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = ps->wsDACCompareHighGreen;
569 ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = ps->wsDACCompareLowGreen;
570 ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = ps->wsDACCompareHighBlue;
571 ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = ps->wsDACCompareLowBlue;
572
573 wOldRedGain = a_wGainString[ps->bRedGainIndex] * 100/ps->wReduceRedFactor;
574
575 /* SearchNewGain() */
576 for (ps->bRedGainIndex = 0; ps->bRedGainIndex < 32; ps->bRedGainIndex++) {
577 if (wOldRedGain < a_wGainString[ps->bRedGainIndex])
578 break;
579 }
580
581 if (0 == ps->bRedGainIndex)
582 ps->bRedGainIndex ++;
583
584 wNewRedGain = a_wGainString[--ps->bRedGainIndex];
585
586 wOldGreenGain = a_wGainString[ps->bGreenGainIndex]*100/
587 ps->wReduceGreenFactor;
588
589 /* SearchNewGain() */
590 for (ps->bGreenGainIndex = 0;
591 ps->bGreenGainIndex < 32; ps->bGreenGainIndex++) {
592
593 if (wOldGreenGain < a_wGainString[ps->bGreenGainIndex])
594 break;
595 }
596
597 if (0 == ps->bGreenGainIndex)
598 ps->bGreenGainIndex ++;
599
600 wNewGreenGain = a_wGainString[--ps->bGreenGainIndex];
601
602 wOldBlueGain = a_wGainString[ps->bBlueGainIndex]*100/ps->wReduceBlueFactor;
603
604 /* SearchNewGain() */
605 for (ps->bBlueGainIndex = 0;ps->bBlueGainIndex < 32;ps->bBlueGainIndex++) {
606 if (wOldBlueGain < a_wGainString[ps->bBlueGainIndex])
607 break;
608 }
609 if (0 == ps->bBlueGainIndex)
610 ps->bBlueGainIndex ++;
611
612 wNewBlueGain = a_wGainString[--ps->bBlueGainIndex];
613
614 DacP98FillGainOutDirectPort( ps );
615
616 ps->Shade.DarkOffset.Colors.Red = 0;
617 ps->Shade.DarkOffset.Colors.Green = 0;
618 ps->Shade.DarkOffset.Colors.Blue = 0;
619
620 ps->OpenScanPath( ps );
621 DacP98FillShadingDarkToShadingRegister( ps );
622 ps->CloseScanPath( ps );
623
624 DacP98AdjustDark( ps );
625
626 /* RecalculateTransparencyImage() */
627 if (ps->DataInf.dwScanFlag & SCANDEF_Transparency) {
628 filmAdjustX = ps->wPosAdjustX;
629 } else {
630 filmAdjustX = ps->wNegAdjustX;
631 }
632
633 if (!filmAdjustX) {
634 p.pw = (pUShort)(ps->pScanBuffer1 + ps->dwOffsetNegative +
635 _Negative96OriginOffsetX * 2);
636 } else {
637 p.pw = (pUShort)(ps->pScanBuffer1 +
638 ps->dwOffsetNegative + filmAdjustX);
639 }
640
641 /* RecalculateData() */
642 for (dw= 0; dw < _NegativePageWidth * 2 + 132; dw++, p.pw++)
643 *p.pw = *p.pw * wNewRedGain / wOldRedGain;
644
645 if (!ps->wNegAdjustX) {
646 p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 2 +
647 ps->dwOffsetNegative + _Negative96OriginOffsetX * 2);
648 } else {
649 p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 2 +
650 ps->dwOffsetNegative + ps->wNegAdjustX);
651 }
652
653 /* RecalculateData() */
654 for (dw= 0; dw < _NegativePageWidth * 2 + 132; dw++, p.pw++)
655 *p.pw = *p.pw * wNewGreenGain / wOldGreenGain;
656
657 if (!ps->wNegAdjustX) {
658 p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 4 +
659 ps->dwOffsetNegative + _Negative96OriginOffsetX * 2);
660 } else {
661 p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 4 +
662 ps->dwOffsetNegative + ps->wNegAdjustX);
663 }
664
665 /* RecalculateData() - 64 + dwoffset70 */
666 for (dw= 0; dw < _NegativePageWidth * 2 + 132; dw++, p.pw++)
667 *p.pw = *p.pw * wNewBlueGain / wOldBlueGain;
668 }
669
670 /************************ exported functions *********************************/
671
672 /*.............................................................................
673 * perform some adjustments according to the source (normal, transparency etc)
674 */
TPAP98001AverageShadingData(pScanData ps)675 _LOC void TPAP98001AverageShadingData( pScanData ps )
676 {
677 DBG( DBG_LOW, "TPAP98001AverageShadingData()\n" );
678
679 ps->wNegAdjustX = 0;
680 ps->wPosAdjustX = 0;
681 ps->dwOffsetNegative = 0;
682
683 tpaP98ShadingWaveformSum( ps );
684
685 /*
686 * CHANGE: to support Grayscale images in transparency and negative mode
687 * original code: if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) &&
688 */
689 if((ps->DataInf.wPhyDataType >= COLOR_256GRAY) &&
690 (ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
691
692 if (((ps->DataInf.dwScanFlag & SCANDEF_Negative) && !ps->wNegAdjustX) ||
693 ((ps->DataInf.dwScanFlag & SCANDEF_Transparency) && !ps->wPosAdjustX)) {
694
695 Long dwLeft, dwRight;
696 pUShort pw = (pUShort)ps->pScanBuffer1;
697
698 for (dwLeft = 0; dwLeft < 5400; dwLeft++)
699 if (pw[dwLeft] >= 600)
700 break;
701
702 for (dwRight = 4600; dwRight; dwRight--)
703 if (pw[dwRight] >= 600)
704 break;
705
706 DBG( DBG_LOW, "_TPAPageWidth = %u, _NegativePageWidth = %u\n"
707 "right = %d, left = %d --> right = %d\n",
708 _TPAPageWidth, _NegativePageWidth,
709 dwRight, dwLeft, (((Long)dwRight-(Long)dwLeft)/2));
710
711 dwRight = (dwRight - dwLeft) / 2;
712
713 if (ps->DataInf.dwScanFlag & SCANDEF_Negative) {
714
715 if (dwRight >= (Long)_NegativePageWidth) {
716
717 ps->wNegAdjustX = (UShort)(dwRight - _NegativePageWidth +
718 dwLeft - ps->dwOffset70 -
719 ps->Device.DataOriginX + 4U);
720 if( ps->wNegAdjustX > (_Negative96OriginOffsetX * 2U))
721 ps->wNegAdjustX = (_Negative96OriginOffsetX * 2U);
722
723 ps->DataInf.crImage.x += ps->wNegAdjustX;
724 } else {
725 ps->DataInf.crImage.x += (_Negative96OriginOffsetX * 2U);
726 }
727 } else {
728 if (dwRight >= (Long)_TPAPageWidth) {
729
730 ps->wPosAdjustX = (UShort)(dwRight - _TPAPageWidth +
731 dwLeft - ps->dwOffset70 -
732 ps->Device.DataOriginX + 4U);
733
734 if( ps->wPosAdjustX > (_Transparency96OriginOffsetX * 2U))
735 ps->wPosAdjustX = (_Transparency96OriginOffsetX * 2U);
736
737 ps->DataInf.crImage.x += ps->wPosAdjustX;
738
739 } else {
740 ps->DataInf.crImage.x += (_Transparency96OriginOffsetX * 2U);
741 }
742 }
743 }
744 #if 0
745 else {
746 /* CHANGE: as we always reset the values, we can ignore this code..*/
747
748 if( ps->DataInf.dwScanFlag & SCANDEF_Negative )
749 ps->DataInf.crImage.x += ps->wNegAdjustX;
750 else
751 ps->DataInf.crImage.x += ps->wPosAdjustX;
752 }
753 #endif
754
755 if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) {
756
757 ps->dwOffsetNegative = (ps->dwOffset70 + 64+4) * 2;
758
759 tpaP98GetNegativeTempRamData( ps );
760 tpaP98RecalculateNegativeShadingGain( ps );
761
762 } else {
763 ps->wReduceRedFactor = 0x3e;
764 ps->wReduceGreenFactor = 0x39;
765 ps->wReduceBlueFactor = 0x42;
766
767 if( ps->Device.bCCDID == _CCD_518 ) {
768 ps->wReduceRedFactor = 55;
769 ps->wReduceGreenFactor = 55;
770 ps->wReduceBlueFactor = 55;
771 }
772 if( ps->Device.bCCDID == _CCD_3797 ) {
773 ps->wReduceRedFactor = 42;
774 ps->wReduceGreenFactor = 50;
775 ps->wReduceBlueFactor = 50;
776 }
777
778 tpaP98RecalculateShadingGainandData( ps );
779 }
780 }
781 }
782
783 /*.............................................................................
784 * perform some adjustments according to the source (normal, transparency etc)
785 */
TPAP98003FindCenterPointer(pScanData ps)786 _LOC void TPAP98003FindCenterPointer( pScanData ps )
787 {
788 ULong i;
789 ULong width;
790 ULong left;
791 ULong right;
792 pRGBUShortDef pwSum = ps->Bufs.b2.pSumRGB;
793
794 if( ps->DataInf.dwScanFlag & SCANDEF_Negative )
795 width = _NEG_PAGEWIDTH600;
796 else
797 width = _NEG_PAGEWIDTH600 - 94;
798
799 /* 2.54 cm tolerance */
800 left = ps->Device.DataOriginX + _NEG_ORG_OFFSETX * 2 - 600;
801 right = ps->Device.DataOriginX + _NEG_ORG_OFFSETX * 2 +
802 _NEG_PAGEWIDTH600 + 600;
803
804 for( i = 5400UL - left, pwSum = ps->Bufs.b2.pSumRGB; i--; left++)
805 if( pwSum[left].Red > _NEG_EDGE_VALUE &&
806 pwSum[left].Green > _NEG_EDGE_VALUE &&
807 pwSum[left].Blue > _NEG_EDGE_VALUE)
808 break;
809
810 for( i = 5400UL - left, pwSum = ps->Bufs.b2.pSumRGB; i--; right--)
811 if( pwSum[right].Red > _NEG_EDGE_VALUE &&
812 pwSum[right].Green > _NEG_EDGE_VALUE &&
813 pwSum[right].Blue > _NEG_EDGE_VALUE)
814 break;
815
816 if((right <= left) || ((right - left) < width)) {
817 if( ps->DataInf.dwScanFlag & SCANDEF_Negative )
818 ps->Scan.negBegin = ps->Device.DataOriginX + _NEG_ORG_OFFSETX * 2;
819 else
820 ps->Scan.posBegin = ps->Device.DataOriginX + _POS_ORG_OFFSETX * 2;
821 } else {
822 if( ps->DataInf.dwScanFlag & SCANDEF_Negative )
823 ps->Scan.negBegin = (right + left) / 2UL - _NEG_PAGEWIDTH;
824 else
825 ps->Scan.posBegin = (right + left) / 2UL - _POS_PAGEWIDTH;
826 }
827 }
828
829 /*.............................................................................
830 * this function does some reshading, when scanning negatives on an ASIC 98003
831 * based scanner
832 */
TPAP98003Reshading(pScanData ps)833 _LOC void TPAP98003Reshading( pScanData ps )
834 {
835 Byte bHi[3], bHiLeft[3], bHiRight[3];
836 ULong i, dwR, dwG, dwB, dwSum;
837 ULong dwIndex, dwIndexRight, dwIndexLeft;
838 DataPointer RedPtr, GreenPtr, BluePtr;
839 TimerDef timer;
840
841 bHi[0] = bHi[1] = bHi[2] = 0;
842
843 /* CHECK: Why this ??? */
844 #if 1
845 ps->Scan.negScan[1].exposureTime = 144;
846 ps->Scan.negScan[1].xStepTime = 18;
847 ps->Scan.negScan[2].exposureTime = 144;
848 ps->Scan.negScan[2].xStepTime = 36;
849 ps->Scan.negScan[3].exposureTime = 144;
850 ps->Scan.negScan[3].xStepTime = 72;
851 ps->Scan.negScan[4].exposureTime = 144;
852 ps->Scan.negScan[4].xStepTime = 144;
853 #endif
854
855 ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime;
856 ps->Shade.wXStep = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime;
857
858 MiscStartTimer( &timer, _SECOND );
859
860 while(!(IOGetScanState(ps, _TRUE) & _SCANSTATE_STOP) &&
861 (_OK == MiscCheckTimer(&timer)));
862
863 IODataToRegister( ps, ps->RegXStepTime,
864 (Byte)(ps->AsicReg.RD_LineControl >> 4));
865 _DODELAY( 12 );
866 MotorP98003PositionYProc( ps, _NEG_SHADING_OFFS );
867
868 IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime );
869
870 ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
871 IOSelectLampSource( ps );
872
873 IODataToRegister( ps, ps->RegLineControl, _LOBYTE(ps->Shade.wExposure));
874 IODataToRegister( ps, ps->RegXStepTime, _LOBYTE(ps->Shade.wXStep));
875
876 ps->AsicReg.RD_LineControl = _LOBYTE(ps->Shade.wExposure);
877 ps->AsicReg.RD_ExtLineControl = _HIBYTE(ps->Shade.wExposure);
878 ps->AsicReg.RD_XStepTime = (Byte)(ps->Shade.wExposure);
879 ps->AsicReg.RD_ModeControl = _ModeScan;
880 ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
881
882 ps->AsicReg.RD_Origin = (UShort)ps->Scan.negBegin;
883 ps->AsicReg.RD_Pixels = _NEG_PAGEWIDTH600;
884
885 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
886
887 /* put 9 scan states to make sure there are 8 lines available at least */
888 for( i = 0; i <= 12; i++)
889 ps->a_nbNewAdrPointer[i] = 0x8f;
890
891 IOPutOnAllRegisters( ps );
892 _DODELAY( 70 );
893
894 /* prepare the buffers... */
895 memset( ps->Bufs.TpaBuf.pb, 0, _SizeTpaDataBuf );
896
897 RedPtr.pb = ps->Bufs.b1.pShadingMap;
898 GreenPtr.pb = RedPtr.pb + _NEG_PAGEWIDTH600;
899 BluePtr.pb = GreenPtr.pb + _NEG_PAGEWIDTH600;
900
901 for( dwSum = 8; dwSum--; ) {
902
903 IOReadOneShadingLine( ps, ps->Bufs.b1.pShadingMap, _NEG_PAGEWIDTH600 );
904
905 for( i = 0; i < _NEG_PAGEWIDTH600; i++) {
906
907 ps->Bufs.TpaBuf.pusrgb[i].Red += RedPtr.pb[i];
908 ps->Bufs.TpaBuf.pusrgb[i].Green += GreenPtr.pb[i];
909 ps->Bufs.TpaBuf.pusrgb[i].Blue += BluePtr.pb[i];
910 }
911 }
912
913 for( i = 0; i < (_NEG_PAGEWIDTH600 * 3UL); i++ )
914 ps->Bufs.TpaBuf.pb[i] = ps->Bufs.TpaBuf.pw[i] >> 3;
915
916 RedPtr.pb = ps->Bufs.TpaBuf.pb;
917
918 /* Convert RGB to gray scale (Brightness), and average 16 pixels */
919 for( bHiRight[1] = 0, i = dwIndexRight = 0;
920 i < _NEG_PAGEWIDTH600 / 2; i += 16 ) {
921 bHiRight [0] =
922 (Byte)(((((ULong) RedPtr.pbrgb [i].Red +
923 (ULong) RedPtr.pbrgb[i + 1].Red +
924 (ULong) RedPtr.pbrgb[i + 2].Red +
925 (ULong) RedPtr.pbrgb[i + 3].Red +
926 (ULong) RedPtr.pbrgb[i + 4].Red +
927 (ULong) RedPtr.pbrgb[i + 5].Red +
928 (ULong) RedPtr.pbrgb[i + 6].Red +
929 (ULong) RedPtr.pbrgb[i + 7].Red +
930 (ULong) RedPtr.pbrgb[i + 8].Red +
931 (ULong) RedPtr.pbrgb[i + 9].Red +
932 (ULong) RedPtr.pbrgb[i + 10].Red +
933 (ULong) RedPtr.pbrgb[i + 11].Red +
934 (ULong) RedPtr.pbrgb[i + 12].Red +
935 (ULong) RedPtr.pbrgb[i + 13].Red +
936 (ULong) RedPtr.pbrgb[i + 14].Red +
937 (ULong) RedPtr.pbrgb[i + 15].Red) >> 4) * 30UL +
938 (((ULong) RedPtr.pbrgb[i].Green +
939 (ULong) RedPtr.pbrgb[i + 1].Green +
940 (ULong) RedPtr.pbrgb[i + 2].Green +
941 (ULong) RedPtr.pbrgb[i + 3].Green +
942 (ULong) RedPtr.pbrgb[i + 4].Green +
943 (ULong) RedPtr.pbrgb[i + 5].Green +
944 (ULong) RedPtr.pbrgb[i + 6].Green +
945 (ULong) RedPtr.pbrgb[i + 7].Green +
946 (ULong) RedPtr.pbrgb[i + 8].Green +
947 (ULong) RedPtr.pbrgb[i + 9].Green +
948 (ULong) RedPtr.pbrgb[i + 10].Green +
949 (ULong) RedPtr.pbrgb[i + 11].Green +
950 (ULong) RedPtr.pbrgb[i + 12].Green +
951 (ULong) RedPtr.pbrgb[i + 13].Green +
952 (ULong) RedPtr.pbrgb[i + 14].Green +
953 (ULong) RedPtr.pbrgb[i + 15].Green) >> 4) * 59UL +
954 (((ULong) RedPtr.pbrgb[i].Blue +
955 (ULong) RedPtr.pbrgb[i + 1].Blue +
956 (ULong) RedPtr.pbrgb[i + 2].Blue +
957 (ULong) RedPtr.pbrgb[i + 3].Blue +
958 (ULong) RedPtr.pbrgb[i + 4].Blue +
959 (ULong) RedPtr.pbrgb[i + 5].Blue +
960 (ULong) RedPtr.pbrgb[i + 6].Blue +
961 (ULong) RedPtr.pbrgb[i + 7].Blue +
962 (ULong) RedPtr.pbrgb[i + 8].Blue +
963 (ULong) RedPtr.pbrgb[i + 9].Blue +
964 (ULong) RedPtr.pbrgb[i + 10].Blue +
965 (ULong) RedPtr.pbrgb[i + 11].Blue +
966 (ULong) RedPtr.pbrgb[i + 12].Blue +
967 (ULong) RedPtr.pbrgb[i + 13].Blue +
968 (ULong) RedPtr.pbrgb[i + 14].Blue +
969 (ULong) RedPtr.pbrgb[i + 15].Blue) >> 4) * 11UL) / 100UL);
970
971 if( bHiRight[1] < bHiRight[0] ) {
972 bHiRight[1] = bHiRight[0];
973 dwIndexRight = i;
974 }
975 }
976
977 /* Convert RGB to gray scale (Brightness), and average 16 pixels */
978 for( bHiLeft[1] = 0, i = dwIndexLeft = _NEG_PAGEWIDTH / 2;
979 i < _NEG_PAGEWIDTH600; i += 16 ) {
980 bHiLeft [0] =
981 (Byte)(((((ULong) RedPtr.pbrgb[i].Red +
982 (ULong) RedPtr.pbrgb[i + 1].Red +
983 (ULong) RedPtr.pbrgb[i + 2].Red +
984 (ULong) RedPtr.pbrgb[i + 3].Red +
985 (ULong) RedPtr.pbrgb[i + 4].Red +
986 (ULong) RedPtr.pbrgb[i + 5].Red +
987 (ULong) RedPtr.pbrgb[i + 6].Red +
988 (ULong) RedPtr.pbrgb[i + 7].Red +
989 (ULong) RedPtr.pbrgb[i + 8].Red +
990 (ULong) RedPtr.pbrgb[i + 9].Red +
991 (ULong) RedPtr.pbrgb[i + 10].Red +
992 (ULong) RedPtr.pbrgb[i + 11].Red +
993 (ULong) RedPtr.pbrgb[i + 12].Red +
994 (ULong) RedPtr.pbrgb[i + 13].Red +
995 (ULong) RedPtr.pbrgb[i + 14].Red +
996 (ULong) RedPtr.pbrgb[i + 15].Red) >> 4) * 30UL +
997 (((ULong) RedPtr.pbrgb[i].Green +
998 (ULong) RedPtr.pbrgb[i + 1].Green +
999 (ULong) RedPtr.pbrgb[i + 2].Green +
1000 (ULong) RedPtr.pbrgb[i + 3].Green +
1001 (ULong) RedPtr.pbrgb[i + 4].Green +
1002 (ULong) RedPtr.pbrgb[i + 5].Green +
1003 (ULong) RedPtr.pbrgb[i + 6].Green +
1004 (ULong) RedPtr.pbrgb[i + 7].Green +
1005 (ULong) RedPtr.pbrgb[i + 8].Green +
1006 (ULong) RedPtr.pbrgb[i + 9].Green +
1007 (ULong) RedPtr.pbrgb[i + 10].Green +
1008 (ULong) RedPtr.pbrgb[i + 11].Green +
1009 (ULong) RedPtr.pbrgb[i + 12].Green +
1010 (ULong) RedPtr.pbrgb[i + 13].Green +
1011 (ULong) RedPtr.pbrgb[i + 14].Green +
1012 (ULong) RedPtr.pbrgb[i + 15].Green) >> 4) * 59UL +
1013 (((ULong) RedPtr.pbrgb[i].Blue +
1014 (ULong) RedPtr.pbrgb[i + 1].Blue +
1015 (ULong) RedPtr.pbrgb[i + 2].Blue +
1016 (ULong) RedPtr.pbrgb[i + 3].Blue +
1017 (ULong) RedPtr.pbrgb[i + 4].Blue +
1018 (ULong) RedPtr.pbrgb[i + 5].Blue +
1019 (ULong) RedPtr.pbrgb[i + 6].Blue +
1020 (ULong) RedPtr.pbrgb[i + 7].Blue +
1021 (ULong) RedPtr.pbrgb[i + 8].Blue +
1022 (ULong) RedPtr.pbrgb[i + 9].Blue +
1023 (ULong) RedPtr.pbrgb[i + 10].Blue +
1024 (ULong) RedPtr.pbrgb[i + 11].Blue +
1025 (ULong) RedPtr.pbrgb[i + 12].Blue +
1026 (ULong) RedPtr.pbrgb[i + 13].Blue +
1027 (ULong) RedPtr.pbrgb[i + 14].Blue +
1028 (ULong) RedPtr.pbrgb[i + 15].Blue) >> 4) * 11UL) / 100UL);
1029
1030 if( bHiLeft[1] < bHiLeft[0] ) {
1031 bHiLeft[1] = bHiLeft[0];
1032 dwIndexLeft = i;
1033 }
1034 }
1035
1036 if((bHiLeft[1] < 200) && (bHiRight[1] < 200)) {
1037
1038 if( bHiLeft[1] < bHiRight[1] )
1039 dwIndex = dwIndexRight;
1040 else
1041 dwIndex = dwIndexLeft;
1042 } else {
1043 if( bHiLeft[1] > 200 )
1044 dwIndex = dwIndexRight;
1045 else
1046 dwIndex = dwIndexLeft;
1047 }
1048
1049 /* Get the hilight */
1050 RedPtr.pusrgb = ps->Bufs.b2.pSumRGB + dwIndex +
1051 ps->AsicReg.RD_Origin + _SHADING_BEGINX;
1052
1053 for( dwR = dwG = dwB = 0, i = 16; i--; RedPtr.pusrgb++ ) {
1054 dwR += RedPtr.pusrgb->Red;
1055 dwG += RedPtr.pusrgb->Green;
1056 dwB += RedPtr.pusrgb->Blue;
1057 }
1058
1059 dwR >>= 8;
1060 dwG >>= 8;
1061 dwB >>= 8;
1062
1063 if( dwR > dwG && dwR > dwB )
1064 ps->Shade.bGainHigh = (Byte)dwR; /* >> 4 for average, >> 4 to 8-bit */
1065 else {
1066 if( dwG > dwR && dwG > dwB )
1067 ps->Shade.bGainHigh = (Byte)dwG;
1068 else
1069 ps->Shade.bGainHigh = (Byte)dwB;
1070 }
1071
1072 ps->Shade.bGainHigh = (Byte)(ps->Shade.bGainHigh - 0x18);
1073 ps->Shade.bGainLow = (Byte)(ps->Shade.bGainHigh - 0x10);
1074
1075 /* Reshading to get the new gain */
1076 ps->Shade.Hilight.Colors.Red = 0;
1077 ps->Shade.Hilight.Colors.Green = 0;
1078 ps->Shade.Hilight.Colors.Blue = 0;
1079 ps->Shade.Gain.Colors.Red++;
1080 ps->Shade.Gain.Colors.Green++;
1081 ps->Shade.Gain.Colors.Blue++;
1082 ps->Shade.fStop = _FALSE;
1083
1084 RedPtr.pb = ps->Bufs.b1.pShadingMap + dwIndex;
1085 GreenPtr.pb = RedPtr.pb + _NEG_PAGEWIDTH600;
1086 BluePtr.pb = GreenPtr.pb + _NEG_PAGEWIDTH600;
1087
1088 for( i = 16; i-- && !ps->Shade.fStop;) {
1089
1090 ps->Shade.fStop = _TRUE;
1091
1092 DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain );
1093
1094 IODataToRegister( ps, ps->RegModeControl, _ModeIdle );
1095
1096 ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
1097 IOSelectLampSource( ps );
1098
1099 ps->AsicReg.RD_ModeControl = _ModeScan;
1100 ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
1101 ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
1102
1103 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1104 ps->a_nbNewAdrPointer[1] = 0x77;
1105
1106 IOPutOnAllRegisters( ps );
1107 _DODELAY( 50 );
1108
1109 if(IOReadOneShadingLine(ps,ps->Bufs.b1.pShadingMap,_NEG_PAGEWIDTH600)) {
1110
1111 bHi[0] = DacP98003SumGains( RedPtr.pb, 32 );
1112 bHi[1] = DacP98003SumGains( GreenPtr.pb, 32 );
1113 bHi[2] = DacP98003SumGains( BluePtr.pb, 32 );
1114
1115 if( !bHi[0] || !bHi[1] || !bHi[2]) {
1116 ps->Shade.fStop = _FALSE;
1117 } else {
1118
1119 DacP98003AdjustGain( ps, _CHANNEL_RED, bHi[0] );
1120 DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] );
1121 DacP98003AdjustGain( ps, _CHANNEL_BLUE, bHi[2] );
1122 }
1123 } else
1124 ps->Shade.fStop = _FALSE;
1125 }
1126
1127 DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain );
1128
1129 /* Set RGB Gain */
1130 if( dwR && dwG && dwB ) {
1131
1132 if(ps->Device.bCCDID == _CCD_3797 || ps->Device.bDACType == _DA_ESIC) {
1133 ps->Shade.pCcdDac->GainResize.Colors.Red =
1134 (UShort)((ULong)bHi[0] * 100UL / dwR);
1135 ps->Shade.pCcdDac->GainResize.Colors.Green =
1136 (UShort)((ULong)bHi[1] * 100UL / dwG);
1137 ps->Shade.pCcdDac->GainResize.Colors.Blue =
1138 (UShort)((ULong)bHi[2] * 100UL / dwB);
1139 } else {
1140 ps->Shade.pCcdDac->GainResize.Colors.Red =
1141 (UShort)((ULong)bHi[0] * 90UL / dwR);
1142 ps->Shade.pCcdDac->GainResize.Colors.Green =
1143 (UShort)((ULong)bHi[1] * 77UL / dwG);
1144 ps->Shade.pCcdDac->GainResize.Colors.Blue =
1145 (UShort)((ULong)bHi[2] * 73UL / dwB);
1146 }
1147 ps->Shade.DarkOffset.Colors.Red +=
1148 (UShort)((dwR > bHi[0]) ? dwR - bHi[0] : 0);
1149 ps->Shade.DarkOffset.Colors.Green +=
1150 (UShort)((dwG > bHi[1]) ? dwG - bHi[1] : 0);
1151 ps->Shade.DarkOffset.Colors.Blue +=
1152 (UShort)((dwB > bHi[2]) ? dwB - bHi[2] : 0);
1153
1154 if( ps->Device.bDACType != _DA_ESIC && ps->Device.bCCDID != _CCD_3799 ) {
1155 ps->Shade.DarkOffset.Colors.Red =
1156 (UShort)(ps->Shade.DarkOffset.Colors.Red *
1157 ps->Shade.pCcdDac->GainResize.Colors.Red / 100UL);
1158 ps->Shade.DarkOffset.Colors.Green =
1159 (UShort)(ps->Shade.DarkOffset.Colors.Green *
1160 ps->Shade.pCcdDac->GainResize.Colors.Green / 100UL);
1161 ps->Shade.DarkOffset.Colors.Blue =
1162 (UShort)(ps->Shade.DarkOffset.Colors.Blue *
1163 ps->Shade.pCcdDac->GainResize.Colors.Blue / 100UL);
1164 }
1165 }
1166
1167 /* AdjustDark () */
1168 ps->AsicReg.RD_Origin = _SHADING_BEGINX;
1169 ps->AsicReg.RD_Pixels = 5400;
1170 }
1171
1172 /* END PLUSTEK-PP_TPA.C .....................................................*/
1173