1141cc406Sopenharmony_ci/* @file plustek-pp_map.c
2141cc406Sopenharmony_ci * @brief functions to create and manipulate lookup tables.
3141cc406Sopenharmony_ci *
4141cc406Sopenharmony_ci * based on sources acquired from Plustek Inc.
5141cc406Sopenharmony_ci * Copyright (C) 1998 Plustek Inc.
6141cc406Sopenharmony_ci * Copyright (C) 2000-2004 Gerhard Jaeger <gerhard@gjaeger.de>
7141cc406Sopenharmony_ci * also based on the work done by Rick Bronson
8141cc406Sopenharmony_ci *
9141cc406Sopenharmony_ci * History:
10141cc406Sopenharmony_ci * - 0.30 - initial version
11141cc406Sopenharmony_ci * - 0.31 - brightness and contrast is working (see mapAdjust)
12141cc406Sopenharmony_ci * - 0.32 - no changes
13141cc406Sopenharmony_ci * - 0.33 - disabled a few functions
14141cc406Sopenharmony_ci * - 0.34 - added new dither matrix for checking
15141cc406Sopenharmony_ci * - 0.35 - no changes
16141cc406Sopenharmony_ci * - 0.36 - activated Dithermap 1
17141cc406Sopenharmony_ci *        - removed some unused functions
18141cc406Sopenharmony_ci *        - added additional SCANDEF_Inverse check to MapSetupDither()
19141cc406Sopenharmony_ci *        - fixed the double inversion bug, the map always compensates
20141cc406Sopenharmony_ci *        - the scanner hw-settings
21141cc406Sopenharmony_ci * - 0.37 - code cleanup
22141cc406Sopenharmony_ci * - 0.38 - added P12 stuff
23141cc406Sopenharmony_ci * - 0.39 - no changes
24141cc406Sopenharmony_ci * - 0.40 - no changes
25141cc406Sopenharmony_ci * - 0.41 - no changes
26141cc406Sopenharmony_ci * - 0.42 - made MapAdjust global
27141cc406Sopenharmony_ci *        - changed include names
28141cc406Sopenharmony_ci * - 0.43 - cleanup, removed floating point stuff
29141cc406Sopenharmony_ci * .
30141cc406Sopenharmony_ci * <hr>
31141cc406Sopenharmony_ci * This file is part of the SANE package.
32141cc406Sopenharmony_ci *
33141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or
34141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as
35141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the
36141cc406Sopenharmony_ci * License, or (at your option) any later version.
37141cc406Sopenharmony_ci *
38141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
39141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
40141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41141cc406Sopenharmony_ci * General Public License for more details.
42141cc406Sopenharmony_ci *
43141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License
44141cc406Sopenharmony_ci * along with this program.  If not, see <https://www.gnu.org/licenses/>.
45141cc406Sopenharmony_ci *
46141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for
47141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE.
48141cc406Sopenharmony_ci *
49141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files
50141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the
51141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public
52141cc406Sopenharmony_ci * License.  Your use of that executable is in no way restricted on
53141cc406Sopenharmony_ci * account of linking the SANE library code into it.
54141cc406Sopenharmony_ci *
55141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why
56141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public
57141cc406Sopenharmony_ci * License.
58141cc406Sopenharmony_ci *
59141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in
60141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that
61141cc406Sopenharmony_ci * those changes may be distributed with this exception intact.
62141cc406Sopenharmony_ci *
63141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice
64141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications.
65141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice.
66141cc406Sopenharmony_ci * <hr>
67141cc406Sopenharmony_ci */
68141cc406Sopenharmony_ci#include "plustek-pp_scan.h"
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci/*************************** local vars **************************************/
71141cc406Sopenharmony_ci
72141cc406Sopenharmony_ci/*WORK:
73141cc406Sopenharmony_ci *    create other thresholds for the dither maps
74141cc406Sopenharmony_ci */
75141cc406Sopenharmony_cistatic Byte mapDitherMatrix0[_DITHERSIZE] =
76141cc406Sopenharmony_ci{
77141cc406Sopenharmony_ci     0, 32, 8,  40, 2,  34, 10, 42,
78141cc406Sopenharmony_ci    48, 16, 56, 24, 50, 18, 58, 26,
79141cc406Sopenharmony_ci    12, 44, 4,  36, 14, 46, 6,  38,
80141cc406Sopenharmony_ci    60, 28, 52, 20, 62, 30, 54, 22,
81141cc406Sopenharmony_ci     3, 35, 11, 43, 1,  33, 9,  41,
82141cc406Sopenharmony_ci    51, 19, 59, 27, 49, 17, 57, 25,
83141cc406Sopenharmony_ci    15, 47, 7,  39, 13, 45, 5,  37,
84141cc406Sopenharmony_ci	63, 31, 55, 23, 61, 29, 53, 21
85141cc406Sopenharmony_ci};
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_cistatic Byte mapDitherMatrix1[_DITHERSIZE] =
88141cc406Sopenharmony_ci{
89141cc406Sopenharmony_ci     2, 60, 16, 56,  3, 57, 13, 53,
90141cc406Sopenharmony_ci    34, 18, 48, 32, 35, 19, 45, 29,
91141cc406Sopenharmony_ci    10, 50,  6, 63, 11, 51,  7, 61,
92141cc406Sopenharmony_ci    42, 26, 38, 22, 43, 27, 39, 23,
93141cc406Sopenharmony_ci     4, 58, 14, 54,  1, 59, 15, 55,
94141cc406Sopenharmony_ci    36, 20, 46, 30, 33, 17, 47, 31,
95141cc406Sopenharmony_ci    12, 52,  8, 62,  9, 49,  5, 63,
96141cc406Sopenharmony_ci    44, 28, 40, 24, 41, 25, 37, 21
97141cc406Sopenharmony_ci};
98141cc406Sopenharmony_ci
99141cc406Sopenharmony_ci/*************************** local functions *********************************/
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_ci/** set the selected dither maps...
102141cc406Sopenharmony_ci */
103141cc406Sopenharmony_cistatic void mapSetDitherMap( pScanData ps )
104141cc406Sopenharmony_ci{
105141cc406Sopenharmony_ci	ULong  i;
106141cc406Sopenharmony_ci	pUChar pDitherSource;
107141cc406Sopenharmony_ci	pUChar pDither = ps->a_bDitherPattern;
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_ci	if( 0 == ps->DataInf.wDither ) {
110141cc406Sopenharmony_ci		DBG( DBG_LOW, "Using Dithermatrix 0\n" );
111141cc406Sopenharmony_ci		pDitherSource = mapDitherMatrix0;
112141cc406Sopenharmony_ci	} else {
113141cc406Sopenharmony_ci		DBG( DBG_LOW, "Using Dithermatrix 1\n" );
114141cc406Sopenharmony_ci		pDitherSource = mapDitherMatrix1;
115141cc406Sopenharmony_ci	}
116141cc406Sopenharmony_ci
117141cc406Sopenharmony_ci	for( i = 0; i < _DITHERSIZE; i++ ) {
118141cc406Sopenharmony_ci		pDither[i] = pDitherSource[i];
119141cc406Sopenharmony_ci	}
120141cc406Sopenharmony_ci}
121141cc406Sopenharmony_ci
122141cc406Sopenharmony_ci/** nothing more to say
123141cc406Sopenharmony_ci */
124141cc406Sopenharmony_cistatic void mapInvertMap( pScanData ps )
125141cc406Sopenharmony_ci{
126141cc406Sopenharmony_ci	pULong pdw;
127141cc406Sopenharmony_ci    ULong  dw, size;
128141cc406Sopenharmony_ci
129141cc406Sopenharmony_ci	DBG( DBG_LOW, "mapInvertMap()\n" );
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci	if( _IS_ASIC98(ps->sCaps.AsicID)) {
132141cc406Sopenharmony_ci		size = 4096;
133141cc406Sopenharmony_ci	} else {
134141cc406Sopenharmony_ci		size = 256;
135141cc406Sopenharmony_ci    }
136141cc406Sopenharmony_ci
137141cc406Sopenharmony_ci    for (pdw = (pULong)ps->a_bMapTable, dw = size * 3 / 4; dw; dw--, pdw++) {
138141cc406Sopenharmony_ci		*pdw = ~(*pdw);
139141cc406Sopenharmony_ci	}
140141cc406Sopenharmony_ci}
141141cc406Sopenharmony_ci
142141cc406Sopenharmony_ci/** as the name says...
143141cc406Sopenharmony_ci */
144141cc406Sopenharmony_cistatic void mapInvertDitherMap( pScanData ps )
145141cc406Sopenharmony_ci{
146141cc406Sopenharmony_ci	if( ps->DataInf.dwScanFlag & SCANDEF_Inverse ) {
147141cc406Sopenharmony_ci
148141cc406Sopenharmony_ci		ULong  dw;
149141cc406Sopenharmony_ci		pULong pDither = (pULong)ps->a_bDitherPattern;
150141cc406Sopenharmony_ci
151141cc406Sopenharmony_ci		DBG( DBG_LOW, "mapInvertDitherMap()\n" );
152141cc406Sopenharmony_ci
153141cc406Sopenharmony_ci		mapInvertMap( ps );
154141cc406Sopenharmony_ci		for (dw = 0; dw < 16; dw++) {
155141cc406Sopenharmony_ci	    	pDither[dw] = ~pDither[dw];
156141cc406Sopenharmony_ci		}
157141cc406Sopenharmony_ci    }
158141cc406Sopenharmony_ci}
159141cc406Sopenharmony_ci
160141cc406Sopenharmony_ci/** build linear map...
161141cc406Sopenharmony_ci */
162141cc406Sopenharmony_cistatic void mapBuildLinearMap( pScanData ps )
163141cc406Sopenharmony_ci{
164141cc406Sopenharmony_ci	ULong i;
165141cc406Sopenharmony_ci
166141cc406Sopenharmony_ci	DBG( DBG_LOW, "mapBuildLinearMap()\n" );
167141cc406Sopenharmony_ci
168141cc406Sopenharmony_ci	if( _IS_ASIC98(ps->sCaps.AsicID)) {
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_ci		for( i = 0; i < 4096; i++ ) {
171141cc406Sopenharmony_ci			ps->a_bMapTable[i] 	    = (UChar)(i >> 4);
172141cc406Sopenharmony_ci			ps->a_bMapTable[4096+i] = (UChar)(i >> 4);
173141cc406Sopenharmony_ci			ps->a_bMapTable[8192+i] = (UChar)(i >> 4);
174141cc406Sopenharmony_ci		}
175141cc406Sopenharmony_ci
176141cc406Sopenharmony_ci	} else {
177141cc406Sopenharmony_ci
178141cc406Sopenharmony_ci		for( i = 0; i < 256; i++ ) {
179141cc406Sopenharmony_ci			ps->a_bMapTable[i] 	   = (UChar)(i & 0xff);
180141cc406Sopenharmony_ci			ps->a_bMapTable[256+i] = (UChar)(i & 0xff);
181141cc406Sopenharmony_ci			ps->a_bMapTable[512+i] = (UChar)(i & 0xff);
182141cc406Sopenharmony_ci		}
183141cc406Sopenharmony_ci	}
184141cc406Sopenharmony_ci}
185141cc406Sopenharmony_ci
186141cc406Sopenharmony_ci/************************ exported functions *********************************/
187141cc406Sopenharmony_ci
188141cc406Sopenharmony_ci/** create a mapping table
189141cc406Sopenharmony_ci *  in the original code this map will be created by the TWAIN application
190141cc406Sopenharmony_ci *  and the is being downloaded to the driver, as I don't have the code
191141cc406Sopenharmony_ci *  we have to try to build up such a table here
192141cc406Sopenharmony_ci */
193141cc406Sopenharmony_ci_LOC void MapInitialize( pScanData ps )
194141cc406Sopenharmony_ci{
195141cc406Sopenharmony_ci	mapBuildLinearMap( ps );
196141cc406Sopenharmony_ci	MapAdjust( ps, _MAP_MASTER );
197141cc406Sopenharmony_ci}
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_ci/** setup dither maps
200141cc406Sopenharmony_ci */
201141cc406Sopenharmony_ci_LOC void MapSetupDither( pScanData ps )
202141cc406Sopenharmony_ci{
203141cc406Sopenharmony_ci	DBG( DBG_LOW, "MapSetupDither() - %u\n", ps->DataInf.wAppDataType );
204141cc406Sopenharmony_ci
205141cc406Sopenharmony_ci	if( COLOR_HALFTONE == ps->DataInf.wAppDataType ) {
206141cc406Sopenharmony_ci
207141cc406Sopenharmony_ci		mapSetDitherMap( ps );
208141cc406Sopenharmony_ci	    if (ps->DataInf.dwScanFlag & SCANDEF_Inverse)
209141cc406Sopenharmony_ci			mapInvertDitherMap( ps );
210141cc406Sopenharmony_ci	}
211141cc406Sopenharmony_ci}
212141cc406Sopenharmony_ci
213141cc406Sopenharmony_ci/** adjust according to brightness and contrast
214141cc406Sopenharmony_ci */
215141cc406Sopenharmony_ci_LOC void MapAdjust( pScanData ps, int which )
216141cc406Sopenharmony_ci{
217141cc406Sopenharmony_ci	ULong  i, tabLen, dw;
218141cc406Sopenharmony_ci	ULong *pdw;
219141cc406Sopenharmony_ci	long   b, c, tmp;
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_ci	DBG( DBG_LOW, "MapAdjust(%u)\n", which );
222141cc406Sopenharmony_ci
223141cc406Sopenharmony_ci	if( _IS_ASIC98(ps->sCaps.AsicID)) {
224141cc406Sopenharmony_ci		tabLen = 4096;
225141cc406Sopenharmony_ci	} else {
226141cc406Sopenharmony_ci		tabLen = 256;
227141cc406Sopenharmony_ci	}
228141cc406Sopenharmony_ci
229141cc406Sopenharmony_ci	/* adjust brightness (b) and contrast (c) using the function:
230141cc406Sopenharmony_ci	 * s'(x,y) = (s(x,y) + b) * c
231141cc406Sopenharmony_ci	 * b = [-127, 127]
232141cc406Sopenharmony_ci	 * c = [0,2]
233141cc406Sopenharmony_ci	 */
234141cc406Sopenharmony_ci
235141cc406Sopenharmony_ci	/* scale brightness and contrast...
236141cc406Sopenharmony_ci	 */
237141cc406Sopenharmony_ci	b = ps->wBrightness * 192;
238141cc406Sopenharmony_ci	c = ps->wContrast   + 100;
239141cc406Sopenharmony_ci
240141cc406Sopenharmony_ci	DBG( DBG_LOW, "brightness   = %i -> %i\n", ps->wBrightness, (UChar)(b/100));
241141cc406Sopenharmony_ci	DBG( DBG_LOW, "contrast*100 = %i -> %i\n", ps->wContrast, (int)(c));
242141cc406Sopenharmony_ci
243141cc406Sopenharmony_ci	for( i = 0; i < tabLen; i++ ) {
244141cc406Sopenharmony_ci
245141cc406Sopenharmony_ci		if((_MAP_MASTER == which) || (_MAP_RED == which)) {
246141cc406Sopenharmony_ci			tmp = ((((long)ps->a_bMapTable[i] * 100) + b) *c ) / 10000;
247141cc406Sopenharmony_ci			if( tmp < 0 )   tmp = 0;
248141cc406Sopenharmony_ci			if( tmp > 255 ) tmp = 255;
249141cc406Sopenharmony_ci			ps->a_bMapTable[i] = (UChar)tmp;
250141cc406Sopenharmony_ci		}
251141cc406Sopenharmony_ci
252141cc406Sopenharmony_ci		if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
253141cc406Sopenharmony_ci			tmp = ((((long)ps->a_bMapTable[tabLen+i] * 100) + b) * c) / 10000;
254141cc406Sopenharmony_ci			if( tmp < 0 )   tmp = 0;
255141cc406Sopenharmony_ci			if( tmp > 255 ) tmp = 255;
256141cc406Sopenharmony_ci			ps->a_bMapTable[tabLen+i] = (UChar)tmp;
257141cc406Sopenharmony_ci    	}
258141cc406Sopenharmony_ci
259141cc406Sopenharmony_ci		if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
260141cc406Sopenharmony_ci			tmp = ((((long)ps->a_bMapTable[tabLen*2+i] * 100) + b) * c) / 10000;
261141cc406Sopenharmony_ci			if( tmp < 0 )   tmp = 0;
262141cc406Sopenharmony_ci			if( tmp > 255 ) tmp = 255;
263141cc406Sopenharmony_ci			ps->a_bMapTable[tabLen*2+i] = (UChar)tmp;
264141cc406Sopenharmony_ci		}
265141cc406Sopenharmony_ci	}
266141cc406Sopenharmony_ci
267141cc406Sopenharmony_ci    if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) {
268141cc406Sopenharmony_ci		DBG( DBG_LOW, "inverting...\n" );
269141cc406Sopenharmony_ci
270141cc406Sopenharmony_ci		if((_MAP_MASTER == which) || (_MAP_RED == which)) {
271141cc406Sopenharmony_ci
272141cc406Sopenharmony_ci			DBG( DBG_LOW, "inverting RED map\n" );
273141cc406Sopenharmony_ci
274141cc406Sopenharmony_ci			pdw = (pULong)ps->a_bMapTable;
275141cc406Sopenharmony_ci
276141cc406Sopenharmony_ci		    for( dw = tabLen / 4; dw; dw--, pdw++ )
277141cc406Sopenharmony_ci				*pdw = ~(*pdw);
278141cc406Sopenharmony_ci    	}
279141cc406Sopenharmony_ci
280141cc406Sopenharmony_ci		if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
281141cc406Sopenharmony_ci
282141cc406Sopenharmony_ci			DBG( DBG_LOW, "inverting GREEN map\n" );
283141cc406Sopenharmony_ci
284141cc406Sopenharmony_ci			pdw = (pULong)&ps->a_bMapTable[tabLen];
285141cc406Sopenharmony_ci
286141cc406Sopenharmony_ci		    for( dw = tabLen / 4; dw; dw--, pdw++ )
287141cc406Sopenharmony_ci				*pdw = ~(*pdw);
288141cc406Sopenharmony_ci    	}
289141cc406Sopenharmony_ci
290141cc406Sopenharmony_ci		if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
291141cc406Sopenharmony_ci
292141cc406Sopenharmony_ci			DBG( DBG_LOW, "inverting BLUE map\n" );
293141cc406Sopenharmony_ci
294141cc406Sopenharmony_ci			pdw = (pULong)&ps->a_bMapTable[tabLen*2];
295141cc406Sopenharmony_ci
296141cc406Sopenharmony_ci		    for( dw = tabLen / 4; dw; dw--, pdw++ )
297141cc406Sopenharmony_ci				*pdw = ~(*pdw);
298141cc406Sopenharmony_ci    	}
299141cc406Sopenharmony_ci	}
300141cc406Sopenharmony_ci}
301141cc406Sopenharmony_ci
302141cc406Sopenharmony_ci/* END PLUSTEK-PP_MAP.C .....................................................*/
303