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 */ 75static 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 87static 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 */ 103static 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 */ 124static 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 */ 144static 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 */ 162static 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 */ 193_LOC void MapInitialize( pScanData ps ) 194{ 195 mapBuildLinearMap( ps ); 196 MapAdjust( ps, _MAP_MASTER ); 197} 198 199/** setup dither maps 200 */ 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 */ 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