1 /* @file u12_map.c
2 * @brief functions to create and manipulate gamma lookup tables.
3 *
4 * Copyright (C) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de>
5 *
6 * History:
7 * - 0.01 - initial version
8 * - 0.02 - inverting map when scanning binary images
9 * - changed u12map_Adjust()
10 * .
11 * <hr>
12 * This file is part of the SANE package.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 *
27 * As a special exception, the authors of SANE give permission for
28 * additional uses of the libraries contained in this release of SANE.
29 *
30 * The exception is that, if you link a SANE library with other files
31 * to produce an executable, this does not by itself cause the
32 * resulting executable to be covered by the GNU General Public
33 * License. Your use of that executable is in no way restricted on
34 * account of linking the SANE library code into it.
35 *
36 * This exception does not, however, invalidate any other reasons why
37 * the executable file might be covered by the GNU General Public
38 * License.
39 *
40 * If you submit changes to SANE to the maintainers to be included in
41 * a subsequent release, you agree by submitting the changes that
42 * those changes may be distributed with this exception intact.
43 *
44 * If you write modifications of your own for SANE, it is your choice
45 * whether to permit this exception to apply to your modifications.
46 * If you do not wish that, delete this exception notice.
47 * <hr>
48 */
49
50 /**
51 * @param s - pointer to the scanner specific structure
52 * @return The function always returns SANE_STATUS_GOOD
53 */
u12map_InitGammaSettings(U12_Device * dev)54 static SANE_Status u12map_InitGammaSettings( U12_Device *dev )
55 {
56 int i, j, val;
57 double gamma;
58
59 dev->gamma_length = 4096;
60 dev->gamma_range.min = 0;
61 dev->gamma_range.max = 255;
62 dev->gamma_range.quant = 0;
63
64 DBG( _DBG_INFO, "Presetting Gamma tables (len=%u)\n", dev->gamma_length );
65 DBG( _DBG_INFO, "----------------------------------\n" );
66
67 /* preset the gamma maps */
68 for( i = 0; i < 4; i++ ) {
69
70 switch( i ) {
71 case 1: gamma = dev->adj.rgamma; break;
72 case 2: gamma = dev->adj.ggamma; break;
73 case 3: gamma = dev->adj.bgamma; break;
74 default: gamma = dev->adj.graygamma; break;
75 }
76
77 for( j = 0; j < dev->gamma_length; j++ ) {
78
79 val = (dev->gamma_range.max *
80 pow((double) j / ((double)dev->gamma_length - 1.0),
81 1.0 / gamma ));
82
83 if( val > dev->gamma_range.max )
84 val = dev->gamma_range.max;
85
86 dev->gamma_table[i][j] = val;
87 }
88 }
89 return SANE_STATUS_GOOD;
90 }
91
92 /** Check the gamma vectors we got back and limit if necessary
93 * @param s - pointer to the scanner specific structure
94 * @return nothing
95 */
u12map_CheckGammaSettings(U12_Device * dev)96 static void u12map_CheckGammaSettings( U12_Device *dev )
97 {
98 int i, j;
99
100 for( i = 0; i < 4 ; i++ ) {
101 for( j = 0; j < dev->gamma_length; j++ ) {
102 if( dev->gamma_table[i][j] > dev->gamma_range.max ) {
103 dev->gamma_table[i][j] = dev->gamma_range.max;
104 }
105 }
106 }
107 }
108
109 /** adjust according to brightness and contrast
110 */
u12map_Adjust(U12_Device * dev,int which,SANE_Byte * buf)111 static void u12map_Adjust( U12_Device *dev, int which, SANE_Byte *buf )
112 {
113 int i;
114 u_long *pdw;
115 double b, c, tmp;
116
117 DBG( _DBG_INFO, "u12map_Adjust(%u)\n", which );
118
119 /* adjust brightness (b) and contrast (c) using the function:
120 *
121 * s'(x,y) = (s(x,y) + b) * c
122 * b = [-127, 127]
123 * c = [0,2]
124 */
125
126 /* scale brightness and contrast...
127 */
128 b = ((double)dev->DataInf.siBrightness * 192.0)/100.0;
129 c = ((double)dev->DataInf.siContrast + 100.0)/100.0;
130
131 DBG( _DBG_INFO, "* brightness = %i -> %i\n",
132 dev->DataInf.siBrightness, (SANE_Byte)b);
133 DBG( _DBG_INFO, "* contrast*100 = %i -> %i\n",
134 dev->DataInf.siContrast, (int)(c*100));
135
136 for( i = 0; i < dev->gamma_length; i++ ) {
137
138 if((_MAP_MASTER == which) || (_MAP_RED == which)) {
139 tmp = ((double)(dev->gamma_table[0][i] + b)) * c;
140 if( tmp < 0 ) tmp = 0;
141 if( tmp > 255 ) tmp = 255;
142 buf[i] = (SANE_Byte)tmp;
143 }
144
145 if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
146 tmp = ((double)(dev->gamma_table[1][i] + b)) * c;
147 if( tmp < 0 ) tmp = 0;
148 if( tmp > 255 ) tmp = 255;
149 buf[4096+i] = (SANE_Byte)tmp;
150 }
151
152 if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
153 tmp = ((double)(dev->gamma_table[2][i] + b)) * c;
154 if( tmp < 0 ) tmp = 0;
155 if( tmp > 255 ) tmp = 255;
156 buf[8192+i] = (SANE_Byte)tmp;
157 }
158 }
159
160 if((dev->DataInf.dwScanFlag & _SCANDEF_Negative) ||
161 (dev->DataInf.wPhyDataType == COLOR_BW)) {
162 DBG( _DBG_INFO, "inverting...\n" );
163
164 if((_MAP_MASTER == which) || (_MAP_RED == which)) {
165
166 DBG( _DBG_INFO, "inverting RED map\n" );
167 pdw = (u_long*)&buf[0];
168 for( i = dev->gamma_length / 4; i; i--, pdw++ )
169 *pdw = ~(*pdw);
170 }
171
172 if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
173
174 DBG( _DBG_INFO, "inverting GREEN map\n" );
175 pdw = (u_long*)&buf[4096];
176 for( i = dev->gamma_length / 4; i; i--, pdw++ )
177 *pdw = ~(*pdw);
178 }
179
180 if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
181
182 DBG( _DBG_INFO, "inverting BLUE map\n" );
183 pdw = (u_long*)&buf[8192];
184 for( i = dev->gamma_length / 4; i; i--, pdw++ )
185 *pdw = ~(*pdw);
186 }
187 }
188 }
189
190 /* END U12-MAP.C ............................................................*/
191