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