1 /* @file plustek-pp_map.c
2 * @brief functions to create and manipulate lookup tables.
3 *
4 * based on sources acquired from Plustek Inc.
5 * Copyright (C) 1998 Plustek Inc.
6 * Copyright (C) 2000-2004 Gerhard Jaeger <gerhard@gjaeger.de>
7 * also based on the work done by Rick Bronson
8 *
9 * History:
10 * - 0.30 - initial version
11 * - 0.31 - brightness and contrast is working (see mapAdjust)
12 * - 0.32 - no changes
13 * - 0.33 - disabled a few functions
14 * - 0.34 - added new dither matrix for checking
15 * - 0.35 - no changes
16 * - 0.36 - activated Dithermap 1
17 * - removed some unused functions
18 * - added additional SCANDEF_Inverse check to MapSetupDither()
19 * - fixed the double inversion bug, the map always compensates
20 * - the scanner hw-settings
21 * - 0.37 - code cleanup
22 * - 0.38 - added P12 stuff
23 * - 0.39 - no changes
24 * - 0.40 - no changes
25 * - 0.41 - no changes
26 * - 0.42 - made MapAdjust global
27 * - changed include names
28 * - 0.43 - cleanup, removed floating point stuff
29 * .
30 * <hr>
31 * This file is part of the SANE package.
32 *
33 * This program is free software; you can redistribute it and/or
34 * modify it under the terms of the GNU General Public License as
35 * published by the Free Software Foundation; either version 2 of the
36 * License, or (at your option) any later version.
37 *
38 * This program is distributed in the hope that it will be useful, but
39 * WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 * General Public License for more details.
42 *
43 * You should have received a copy of the GNU General Public License
44 * along with this program. If not, see <https://www.gnu.org/licenses/>.
45 *
46 * As a special exception, the authors of SANE give permission for
47 * additional uses of the libraries contained in this release of SANE.
48 *
49 * The exception is that, if you link a SANE library with other files
50 * to produce an executable, this does not by itself cause the
51 * resulting executable to be covered by the GNU General Public
52 * License. Your use of that executable is in no way restricted on
53 * account of linking the SANE library code into it.
54 *
55 * This exception does not, however, invalidate any other reasons why
56 * the executable file might be covered by the GNU General Public
57 * License.
58 *
59 * If you submit changes to SANE to the maintainers to be included in
60 * a subsequent release, you agree by submitting the changes that
61 * those changes may be distributed with this exception intact.
62 *
63 * If you write modifications of your own for SANE, it is your choice
64 * whether to permit this exception to apply to your modifications.
65 * If you do not wish that, delete this exception notice.
66 * <hr>
67 */
68 #include "plustek-pp_scan.h"
69
70 /*************************** local vars **************************************/
71
72 /*WORK:
73 * create other thresholds for the dither maps
74 */
75 static Byte mapDitherMatrix0[_DITHERSIZE] =
76 {
77 0, 32, 8, 40, 2, 34, 10, 42,
78 48, 16, 56, 24, 50, 18, 58, 26,
79 12, 44, 4, 36, 14, 46, 6, 38,
80 60, 28, 52, 20, 62, 30, 54, 22,
81 3, 35, 11, 43, 1, 33, 9, 41,
82 51, 19, 59, 27, 49, 17, 57, 25,
83 15, 47, 7, 39, 13, 45, 5, 37,
84 63, 31, 55, 23, 61, 29, 53, 21
85 };
86
87 static Byte mapDitherMatrix1[_DITHERSIZE] =
88 {
89 2, 60, 16, 56, 3, 57, 13, 53,
90 34, 18, 48, 32, 35, 19, 45, 29,
91 10, 50, 6, 63, 11, 51, 7, 61,
92 42, 26, 38, 22, 43, 27, 39, 23,
93 4, 58, 14, 54, 1, 59, 15, 55,
94 36, 20, 46, 30, 33, 17, 47, 31,
95 12, 52, 8, 62, 9, 49, 5, 63,
96 44, 28, 40, 24, 41, 25, 37, 21
97 };
98
99 /*************************** local functions *********************************/
100
101 /** set the selected dither maps...
102 */
mapSetDitherMap( pScanData ps )103 static void mapSetDitherMap( pScanData ps )
104 {
105 ULong i;
106 pUChar pDitherSource;
107 pUChar pDither = ps->a_bDitherPattern;
108
109 if( 0 == ps->DataInf.wDither ) {
110 DBG( DBG_LOW, "Using Dithermatrix 0\n" );
111 pDitherSource = mapDitherMatrix0;
112 } else {
113 DBG( DBG_LOW, "Using Dithermatrix 1\n" );
114 pDitherSource = mapDitherMatrix1;
115 }
116
117 for( i = 0; i < _DITHERSIZE; i++ ) {
118 pDither[i] = pDitherSource[i];
119 }
120 }
121
122 /** nothing more to say
123 */
mapInvertMap( pScanData ps )124 static void mapInvertMap( pScanData ps )
125 {
126 pULong pdw;
127 ULong dw, size;
128
129 DBG( DBG_LOW, "mapInvertMap()\n" );
130
131 if( _IS_ASIC98(ps->sCaps.AsicID)) {
132 size = 4096;
133 } else {
134 size = 256;
135 }
136
137 for (pdw = (pULong)ps->a_bMapTable, dw = size * 3 / 4; dw; dw--, pdw++) {
138 *pdw = ~(*pdw);
139 }
140 }
141
142 /** as the name says...
143 */
mapInvertDitherMap( pScanData ps )144 static void mapInvertDitherMap( pScanData ps )
145 {
146 if( ps->DataInf.dwScanFlag & SCANDEF_Inverse ) {
147
148 ULong dw;
149 pULong pDither = (pULong)ps->a_bDitherPattern;
150
151 DBG( DBG_LOW, "mapInvertDitherMap()\n" );
152
153 mapInvertMap( ps );
154 for (dw = 0; dw < 16; dw++) {
155 pDither[dw] = ~pDither[dw];
156 }
157 }
158 }
159
160 /** build linear map...
161 */
mapBuildLinearMap( pScanData ps )162 static void mapBuildLinearMap( pScanData ps )
163 {
164 ULong i;
165
166 DBG( DBG_LOW, "mapBuildLinearMap()\n" );
167
168 if( _IS_ASIC98(ps->sCaps.AsicID)) {
169
170 for( i = 0; i < 4096; i++ ) {
171 ps->a_bMapTable[i] = (UChar)(i >> 4);
172 ps->a_bMapTable[4096+i] = (UChar)(i >> 4);
173 ps->a_bMapTable[8192+i] = (UChar)(i >> 4);
174 }
175
176 } else {
177
178 for( i = 0; i < 256; i++ ) {
179 ps->a_bMapTable[i] = (UChar)(i & 0xff);
180 ps->a_bMapTable[256+i] = (UChar)(i & 0xff);
181 ps->a_bMapTable[512+i] = (UChar)(i & 0xff);
182 }
183 }
184 }
185
186 /************************ exported functions *********************************/
187
188 /** create a mapping table
189 * in the original code this map will be created by the TWAIN application
190 * and the is being downloaded to the driver, as I don't have the code
191 * we have to try to build up such a table here
192 */
MapInitialize( pScanData ps )193 _LOC void MapInitialize( pScanData ps )
194 {
195 mapBuildLinearMap( ps );
196 MapAdjust( ps, _MAP_MASTER );
197 }
198
199 /** setup dither maps
200 */
MapSetupDither( pScanData ps )201 _LOC void MapSetupDither( pScanData ps )
202 {
203 DBG( DBG_LOW, "MapSetupDither() - %u\n", ps->DataInf.wAppDataType );
204
205 if( COLOR_HALFTONE == ps->DataInf.wAppDataType ) {
206
207 mapSetDitherMap( ps );
208 if (ps->DataInf.dwScanFlag & SCANDEF_Inverse)
209 mapInvertDitherMap( ps );
210 }
211 }
212
213 /** adjust according to brightness and contrast
214 */
MapAdjust( pScanData ps, int which )215 _LOC void MapAdjust( pScanData ps, int which )
216 {
217 ULong i, tabLen, dw;
218 ULong *pdw;
219 long b, c, tmp;
220
221 DBG( DBG_LOW, "MapAdjust(%u)\n", which );
222
223 if( _IS_ASIC98(ps->sCaps.AsicID)) {
224 tabLen = 4096;
225 } else {
226 tabLen = 256;
227 }
228
229 /* adjust brightness (b) and contrast (c) using the function:
230 * s'(x,y) = (s(x,y) + b) * c
231 * b = [-127, 127]
232 * c = [0,2]
233 */
234
235 /* scale brightness and contrast...
236 */
237 b = ps->wBrightness * 192;
238 c = ps->wContrast + 100;
239
240 DBG( DBG_LOW, "brightness = %i -> %i\n", ps->wBrightness, (UChar)(b/100));
241 DBG( DBG_LOW, "contrast*100 = %i -> %i\n", ps->wContrast, (int)(c));
242
243 for( i = 0; i < tabLen; i++ ) {
244
245 if((_MAP_MASTER == which) || (_MAP_RED == which)) {
246 tmp = ((((long)ps->a_bMapTable[i] * 100) + b) *c ) / 10000;
247 if( tmp < 0 ) tmp = 0;
248 if( tmp > 255 ) tmp = 255;
249 ps->a_bMapTable[i] = (UChar)tmp;
250 }
251
252 if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
253 tmp = ((((long)ps->a_bMapTable[tabLen+i] * 100) + b) * c) / 10000;
254 if( tmp < 0 ) tmp = 0;
255 if( tmp > 255 ) tmp = 255;
256 ps->a_bMapTable[tabLen+i] = (UChar)tmp;
257 }
258
259 if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
260 tmp = ((((long)ps->a_bMapTable[tabLen*2+i] * 100) + b) * c) / 10000;
261 if( tmp < 0 ) tmp = 0;
262 if( tmp > 255 ) tmp = 255;
263 ps->a_bMapTable[tabLen*2+i] = (UChar)tmp;
264 }
265 }
266
267 if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) {
268 DBG( DBG_LOW, "inverting...\n" );
269
270 if((_MAP_MASTER == which) || (_MAP_RED == which)) {
271
272 DBG( DBG_LOW, "inverting RED map\n" );
273
274 pdw = (pULong)ps->a_bMapTable;
275
276 for( dw = tabLen / 4; dw; dw--, pdw++ )
277 *pdw = ~(*pdw);
278 }
279
280 if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
281
282 DBG( DBG_LOW, "inverting GREEN map\n" );
283
284 pdw = (pULong)&ps->a_bMapTable[tabLen];
285
286 for( dw = tabLen / 4; dw; dw--, pdw++ )
287 *pdw = ~(*pdw);
288 }
289
290 if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
291
292 DBG( DBG_LOW, "inverting BLUE map\n" );
293
294 pdw = (pULong)&ps->a_bMapTable[tabLen*2];
295
296 for( dw = tabLen / 4; dw; dw--, pdw++ )
297 *pdw = ~(*pdw);
298 }
299 }
300 }
301
302 /* END PLUSTEK-PP_MAP.C .....................................................*/
303