1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <stdlib.h> 28 29 #include <vcl/bmpacc.hxx> 30 #include <vcl/octree.hxx> 31 #include <vcl/bitmapex.hxx> 32 #include <vcl/bitmap.hxx> 33 34 #include <impoct.hxx> 35 #include <impvect.hxx> 36 37 // ----------- 38 // - Defines - 39 // ----------- 40 41 #define RGB15( _def_cR, _def_cG, _def_cB ) (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB)) 42 #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L)) 43 #define MAP( cVal0, cVal1, nFrac ) ((sal_uInt8)((((long)(cVal0)<<7L)+nFrac*((long)(cVal1)-(cVal0)))>>7L)) 44 45 #define CALC_ERRORS \ 46 nTemp = p1T[nX++] >> 12; \ 47 nBErr = MinMax( nTemp, 0, 255 ); \ 48 nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \ 49 nTemp = p1T[nX++] >> 12; \ 50 nGErr = MinMax( nTemp, 0, 255 ); \ 51 nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \ 52 nTemp = p1T[nX] >> 12; \ 53 nRErr = MinMax( nTemp, 0, 255 ); \ 54 nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ]; 55 56 #define CALC_TABLES3 \ 57 p2T[nX++] += FloydError3[nBErr]; \ 58 p2T[nX++] += FloydError3[nGErr]; \ 59 p2T[nX++] += FloydError3[nRErr]; 60 61 #define CALC_TABLES5 \ 62 p2T[nX++] += FloydError5[nBErr]; \ 63 p2T[nX++] += FloydError5[nGErr]; \ 64 p2T[nX++] += FloydError5[nRErr]; 65 66 #define CALC_TABLES7 \ 67 p1T[++nX] += FloydError7[nBErr]; \ 68 p2T[nX++] += FloydError1[nBErr]; \ 69 p1T[nX] += FloydError7[nGErr]; \ 70 p2T[nX++] += FloydError1[nGErr]; \ 71 p1T[nX] += FloydError7[nRErr]; \ 72 p2T[nX] += FloydError1[nRErr]; 73 74 // ----------- 75 // - Statics - 76 // ----------- 77 78 sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 }; 79 sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 }; 80 sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 }; 81 82 // ------------------------------------------------------------------------ 83 84 sal_uLong nVCLDitherLut[ 256 ] = 85 { 86 0, 49152, 12288, 61440, 3072, 52224, 15360, 64512, 768, 49920, 13056, 87 62208, 3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456, 88 48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192, 89 57344, 4096, 53248, 11264, 60416, 7168, 56320, 8960, 58112, 4864, 54016, 90 12032, 61184, 7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936, 91 23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200, 92 14336, 63488, 1024, 50176, 13312, 62464, 2816, 51968, 15104, 64256, 1792, 93 50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696, 94 35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392, 6144, 95 55296, 9216, 58368, 5120, 54272, 11008, 60160, 6912, 56064, 9984, 59136, 96 5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776, 97 27392, 39680, 23296, 42752, 26368, 38656, 22272, 512, 49664, 12800, 61952, 98 3584, 52736, 15872, 65024, 256, 49408, 12544, 61696, 3328, 52480, 15616, 99 64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640, 100 45312, 28928, 36096, 19712, 48384, 32000, 8704, 57856, 4608, 53760, 11776, 101 60928, 7680, 56832, 8448, 57600, 4352, 53504, 11520, 60672, 7424, 56576, 102 41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120, 103 20736, 44288, 27904, 40192, 23808, 2560, 51712, 14848, 64000, 1536, 50688, 104 13824, 62976, 2304, 51456, 14592, 63744, 1280, 50432, 13568, 62720, 35328, 105 18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976, 106 34048, 17664, 46336, 29952, 10752, 59904, 6656, 55808, 9728, 58880, 5632, 107 54784, 10496, 59648, 6400, 55552, 9472, 58624, 5376, 54528, 43520, 27136, 108 39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240, 109 25856, 38144, 21760 110 }; 111 112 // ------------------------------------------------------------------------ 113 114 sal_uLong nVCLLut[ 256 ] = 115 { 116 0, 1286, 2572, 3858, 5144, 6430, 7716, 9002, 117 10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290, 118 20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578, 119 30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866, 120 41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154, 121 51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442, 122 61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730, 123 72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018, 124 82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306, 125 92592, 93878, 95164, 96450, 97736, 99022,100308,101594, 126 102880,104166,105452,106738,108024,109310,110596,111882, 127 113168,114454,115740,117026,118312,119598,120884,122170, 128 123456,124742,126028,127314,128600,129886,131172,132458, 129 133744,135030,136316,137602,138888,140174,141460,142746, 130 144032,145318,146604,147890,149176,150462,151748,153034, 131 154320,155606,156892,158178,159464,160750,162036,163322, 132 164608,165894,167180,168466,169752,171038,172324,173610, 133 174896,176182,177468,178754,180040,181326,182612,183898, 134 185184,186470,187756,189042,190328,191614,192900,194186, 135 195472,196758,198044,199330,200616,201902,203188,204474, 136 205760,207046,208332,209618,210904,212190,213476,214762, 137 216048,217334,218620,219906,221192,222478,223764,225050, 138 226336,227622,228908,230194,231480,232766,234052,235338, 139 236624,237910,239196,240482,241768,243054,244340,245626, 140 246912,248198,249484,250770,252056,253342,254628,255914, 141 257200,258486,259772,261058,262344,263630,264916,266202, 142 267488,268774,270060,271346,272632,273918,275204,276490, 143 277776,279062,280348,281634,282920,284206,285492,286778, 144 288064,289350,290636,291922,293208,294494,295780,297066, 145 298352,299638,300924,302210,303496,304782,306068,307354, 146 308640,309926,311212,312498,313784,315070,316356,317642, 147 318928,320214,321500,322786,324072,325358,326644,327930 148 }; 149 150 // ------------------------------------------------------------------------ 151 152 long FloydMap[256] = 153 { 154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 156 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 157 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 158 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 159 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 160 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 161 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 162 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 163 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 164 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 165 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 166 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 167 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 168 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 169 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 170 }; 171 172 // ------------------------------------------------------------------------ 173 174 long FloydError1[61] = 175 { 176 -7680, -7424, -7168, -6912, -6656, -6400, -6144, 177 -5888, -5632, -5376, -5120, -4864, -4608, -4352, 178 -4096, -3840, -3584, -3328, -3072, -2816, -2560, 179 -2304, -2048, -1792, -1536, -1280, -1024, -768, 180 -512, -256, 0, 256, 512, 768, 1024, 1280, 1536, 181 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 182 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 183 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680 184 }; 185 186 // ------------------------------------------------------------------------ 187 188 long FloydError3[61] = 189 { 190 -23040, -22272, -21504, -20736, -19968, -19200, 191 -18432, -17664, -16896, -16128, -15360, -14592, 192 -13824, -13056, -12288, -11520, -10752, -9984, 193 -9216, -8448, -7680, -6912, -6144, -5376, -4608, 194 -3840, -3072, -2304, -1536, -768, 0, 768, 1536, 195 2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680, 196 8448, 9216, 9984, 10752, 11520, 12288, 13056, 197 13824, 14592, 15360, 16128, 16896, 17664, 18432, 198 19200, 19968, 20736, 21504, 22272, 23040 199 }; 200 201 // ------------------------------------------------------------------------ 202 203 long FloydError5[61] = 204 { 205 -38400, -37120, -35840, -34560, -33280, -32000, 206 -30720, -29440, -28160, -26880, -25600, -24320, 207 -23040, -21760, -20480, -19200, -17920, -16640, 208 -15360, -14080, -12800, -11520, -10240, -8960, 209 -7680, -6400, -5120, -3840, -2560, -1280, 0, 210 1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240, 211 11520, 12800, 14080, 15360, 16640, 17920, 19200, 212 20480, 21760, 23040, 24320, 25600, 26880, 28160, 213 29440, 30720, 32000, 33280, 34560, 35840, 37120, 214 38400 215 }; 216 217 // ------------------------------------------------------------------------ 218 219 long FloydError7[61] = 220 { 221 -53760, -51968, -50176, -48384, -46592, -44800, 222 -43008, -41216, -39424, -37632, -35840, -34048, 223 -32256, -30464, -28672, -26880, -25088, -23296, 224 -21504, -19712, -17920, -16128, -14336, -12544, 225 -10752, -8960, -7168, -5376, -3584, -1792, 0, 226 1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336, 227 16128, 17920, 19712, 21504, 23296, 25088, 26880, 228 28672, 30464, 32256, 34048, 35840, 37632, 39424, 229 41216, 43008, 44800, 46592, 48384, 50176, 51968, 230 53760 231 }; 232 233 // ------------------------------------------------------------------------ 234 235 long FloydIndexMap[6] = 236 { 237 -30, 21, 72, 123, 174, 225 238 }; 239 240 // -------------------------- 241 // - ImplCreateDitherMatrix - 242 // -------------------------- 243 244 void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] ) 245 { 246 double fVal = 3.125; 247 const double fVal16 = fVal / 16.; 248 long i, j, k, l; 249 sal_uInt16 pMtx[ 16 ][ 16 ]; 250 sal_uInt16 nMax = 0; 251 static sal_uInt8 pMagic[4][4] = { { 0, 14, 3, 13, }, 252 {11, 5, 8, 6, }, 253 {12, 2, 15, 1, }, 254 {7, 9, 4, 10 } }; 255 256 // MagicSquare aufbauen 257 for ( i = 0; i < 4; i++ ) 258 for ( j = 0; j < 4; j++ ) 259 for ( k = 0; k < 4; k++ ) 260 for ( l = 0; l < 4; l++ ) 261 nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] = 262 (sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax ); 263 264 // auf Intervall [0;254] skalieren 265 for ( i = 0, fVal = 254. / nMax; i < 16; i++ ) 266 for( j = 0; j < 16; j++ ) 267 (*pDitherMatrix)[i][j] = (sal_uInt8) ( fVal * pMtx[i][j] ); 268 } 269 270 // ---------- 271 // - Bitmap - 272 // ---------- 273 274 sal_Bool Bitmap::Convert( BmpConversion eConversion ) 275 { 276 const sal_uInt16 nBitCount = GetBitCount(); 277 sal_Bool bRet = sal_False; 278 279 switch( eConversion ) 280 { 281 case( BMP_CONVERSION_1BIT_THRESHOLD ): 282 bRet = ImplMakeMono( 128 ); 283 break; 284 285 case( BMP_CONVERSION_1BIT_MATRIX ): 286 bRet = ImplMakeMonoDither(); 287 break; 288 289 case( BMP_CONVERSION_4BIT_GREYS ): 290 bRet = ImplMakeGreyscales( 16 ); 291 break; 292 293 case( BMP_CONVERSION_4BIT_COLORS ): 294 { 295 if( nBitCount < 4 ) 296 bRet = ImplConvertUp( 4, NULL ); 297 else if( nBitCount > 4 ) 298 bRet = ImplConvertDown( 4, NULL ); 299 else 300 bRet = sal_True; 301 } 302 break; 303 304 case( BMP_CONVERSION_4BIT_TRANS ): 305 { 306 Color aTrans( BMP_COL_TRANS ); 307 308 if( nBitCount < 4 ) 309 bRet = ImplConvertUp( 4, &aTrans ); 310 else 311 bRet = ImplConvertDown( 4, &aTrans ); 312 } 313 break; 314 315 case( BMP_CONVERSION_8BIT_GREYS ): 316 bRet = ImplMakeGreyscales( 256 ); 317 break; 318 319 case( BMP_CONVERSION_8BIT_COLORS ): 320 { 321 if( nBitCount < 8 ) 322 bRet = ImplConvertUp( 8 ); 323 else if( nBitCount > 8 ) 324 bRet = ImplConvertDown( 8 ); 325 else 326 bRet = sal_True; 327 } 328 break; 329 330 case( BMP_CONVERSION_8BIT_TRANS ): 331 { 332 Color aTrans( BMP_COL_TRANS ); 333 334 if( nBitCount < 8 ) 335 bRet = ImplConvertUp( 8, &aTrans ); 336 else 337 bRet = ImplConvertDown( 8, &aTrans ); 338 } 339 break; 340 341 case( BMP_CONVERSION_24BIT ): 342 { 343 if( nBitCount < 24 ) 344 bRet = ImplConvertUp( 24, sal_False ); 345 else 346 bRet = sal_True; 347 } 348 break; 349 350 case( BMP_CONVERSION_GHOSTED ): 351 bRet = ImplConvertGhosted(); 352 break; 353 354 default: 355 DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" ); 356 break; 357 } 358 359 return bRet; 360 } 361 362 // ------------------------------------------------------------------------ 363 364 sal_Bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold ) 365 { 366 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 367 sal_Bool bRet = sal_False; 368 369 if( pReadAcc ) 370 { 371 Bitmap aNewBmp( GetSizePixel(), 1 ); 372 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 373 374 if( pWriteAcc ) 375 { 376 const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); 377 const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 378 const long nWidth = pWriteAcc->Width(); 379 const long nHeight = pWriteAcc->Height(); 380 381 if( pReadAcc->HasPalette() ) 382 { 383 for( long nY = 0L; nY < nHeight; nY++ ) 384 { 385 for( long nX = 0L; nX < nWidth; nX++ ) 386 { 387 const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX ); 388 if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >= 389 cThreshold ) 390 { 391 pWriteAcc->SetPixel( nY, nX, aWhite ); 392 } 393 else 394 pWriteAcc->SetPixel( nY, nX, aBlack ); 395 } 396 } 397 } 398 else 399 { 400 for( long nY = 0L; nY < nHeight; nY++ ) 401 { 402 for( long nX = 0L; nX < nWidth; nX++ ) 403 { 404 if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >= 405 cThreshold ) 406 { 407 pWriteAcc->SetPixel( nY, nX, aWhite ); 408 } 409 else 410 pWriteAcc->SetPixel( nY, nX, aBlack ); 411 } 412 } 413 } 414 415 aNewBmp.ReleaseAccess( pWriteAcc ); 416 bRet = sal_True; 417 } 418 419 ReleaseAccess( pReadAcc ); 420 421 if( bRet ) 422 { 423 const MapMode aMap( maPrefMapMode ); 424 const Size aSize( maPrefSize ); 425 426 *this = aNewBmp; 427 428 maPrefMapMode = aMap; 429 maPrefSize = aSize; 430 } 431 } 432 433 return bRet; 434 } 435 436 // ------------------------------------------------------------------------ 437 438 sal_Bool Bitmap::ImplMakeMonoDither() 439 { 440 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 441 sal_Bool bRet = sal_False; 442 443 if( pReadAcc ) 444 { 445 Bitmap aNewBmp( GetSizePixel(), 1 ); 446 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 447 448 if( pWriteAcc ) 449 { 450 const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); 451 const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) ); 452 const long nWidth = pWriteAcc->Width(); 453 const long nHeight = pWriteAcc->Height(); 454 sal_uInt8 pDitherMatrix[ 16 ][ 16 ]; 455 456 ImplCreateDitherMatrix( &pDitherMatrix ); 457 458 if( pReadAcc->HasPalette() ) 459 { 460 for( long nY = 0L; nY < nHeight; nY++ ) 461 { 462 for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ ) 463 { 464 const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX ); 465 if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() > 466 pDitherMatrix[ nModY ][ nX % 16 ] ) 467 { 468 pWriteAcc->SetPixel( nY, nX, aWhite ); 469 } 470 else 471 pWriteAcc->SetPixel( nY, nX, aBlack ); 472 } 473 } 474 } 475 else 476 { 477 for( long nY = 0L; nY < nHeight; nY++ ) 478 { 479 for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ ) 480 { 481 if( pReadAcc->GetPixel( nY, nX ).GetLuminance() > 482 pDitherMatrix[ nModY ][ nX % 16 ] ) 483 { 484 pWriteAcc->SetPixel( nY, nX, aWhite ); 485 } 486 else 487 pWriteAcc->SetPixel( nY, nX, aBlack ); 488 } 489 } 490 } 491 492 aNewBmp.ReleaseAccess( pWriteAcc ); 493 bRet = sal_True; 494 } 495 496 ReleaseAccess( pReadAcc ); 497 498 if( bRet ) 499 { 500 const MapMode aMap( maPrefMapMode ); 501 const Size aSize( maPrefSize ); 502 503 *this = aNewBmp; 504 505 maPrefMapMode = aMap; 506 maPrefSize = aSize; 507 } 508 } 509 510 return bRet; 511 } 512 513 // ------------------------------------------------------------------------ 514 515 sal_Bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys ) 516 { 517 DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" ); 518 519 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 520 sal_Bool bRet = sal_False; 521 522 if( pReadAcc ) 523 { 524 const BitmapPalette& rPal = GetGreyPalette( nGreys ); 525 sal_uLong nShift = ( ( nGreys == 16 ) ? 4UL : 0UL ); 526 sal_Bool bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() ); 527 528 if( !bPalDiffers ) 529 bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() ); 530 531 if( bPalDiffers ) 532 { 533 Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal ); 534 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 535 536 if( pWriteAcc ) 537 { 538 const long nWidth = pWriteAcc->Width(); 539 const long nHeight = pWriteAcc->Height(); 540 541 if( pReadAcc->HasPalette() ) 542 { 543 for( long nY = 0L; nY < nHeight; nY++ ) 544 { 545 for( long nX = 0L; nX < nWidth; nX++ ) 546 { 547 const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX ); 548 pWriteAcc->SetPixelIndex( nY, nX, 549 (pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) ); 550 } 551 } 552 } 553 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR && 554 pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 555 { 556 nShift += 8; 557 558 for( long nY = 0L; nY < nHeight; nY++ ) 559 { 560 Scanline pReadScan = pReadAcc->GetScanline( nY ); 561 Scanline pWriteScan = pWriteAcc->GetScanline( nY ); 562 563 for( long nX = 0L; nX < nWidth; nX++ ) 564 { 565 const sal_uLong nB = *pReadScan++; 566 const sal_uLong nG = *pReadScan++; 567 const sal_uLong nR = *pReadScan++; 568 569 *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift ); 570 } 571 } 572 } 573 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB && 574 pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 575 { 576 nShift += 8; 577 578 for( long nY = 0L; nY < nHeight; nY++ ) 579 { 580 Scanline pReadScan = pReadAcc->GetScanline( nY ); 581 Scanline pWriteScan = pWriteAcc->GetScanline( nY ); 582 583 for( long nX = 0L; nX < nWidth; nX++ ) 584 { 585 const sal_uLong nR = *pReadScan++; 586 const sal_uLong nG = *pReadScan++; 587 const sal_uLong nB = *pReadScan++; 588 589 *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift ); 590 } 591 } 592 } 593 else 594 { 595 for( long nY = 0L; nY < nHeight; nY++ ) 596 for( long nX = 0L; nX < nWidth; nX++ ) 597 pWriteAcc->SetPixelIndex( nY, nX, (pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift ); 598 } 599 600 aNewBmp.ReleaseAccess( pWriteAcc ); 601 bRet = sal_True; 602 } 603 604 ReleaseAccess( pReadAcc ); 605 606 if( bRet ) 607 { 608 const MapMode aMap( maPrefMapMode ); 609 const Size aSize( maPrefSize ); 610 611 *this = aNewBmp; 612 613 maPrefMapMode = aMap; 614 maPrefSize = aSize; 615 } 616 } 617 else 618 { 619 ReleaseAccess( pReadAcc ); 620 bRet = sal_True; 621 } 622 } 623 624 return bRet; 625 } 626 627 // ------------------------------------------------------------------------ 628 629 sal_Bool Bitmap::ImplConvertUp( sal_uInt16 nBitCount, Color* pExtColor ) 630 { 631 DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" ); 632 633 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 634 sal_Bool bRet = sal_False; 635 636 if( pReadAcc ) 637 { 638 BitmapPalette aPal; 639 Bitmap aNewBmp( GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPal ); 640 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 641 642 if( pWriteAcc ) 643 { 644 const long nWidth = pWriteAcc->Width(); 645 const long nHeight = pWriteAcc->Height(); 646 647 if( pWriteAcc->HasPalette() ) 648 { 649 const sal_uInt16 nOldCount = 1 << GetBitCount(); 650 const BitmapPalette& rOldPal = pReadAcc->GetPalette(); 651 652 aPal.SetEntryCount( 1 << nBitCount ); 653 654 for( sal_uInt16 i = 0; i < nOldCount; i++ ) 655 aPal[ i ] = rOldPal[ i ]; 656 657 if( pExtColor ) 658 aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor; 659 660 pWriteAcc->SetPalette( aPal ); 661 662 for( long nY = 0L; nY < nHeight; nY++ ) 663 for( long nX = 0L; nX < nWidth; nX++ ) 664 pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) ); 665 } 666 else 667 { 668 if( pReadAcc->HasPalette() ) 669 { 670 for( long nY = 0L; nY < nHeight; nY++ ) 671 for( long nX = 0L; nX < nWidth; nX++ ) 672 pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) ); 673 } 674 else 675 { 676 for( long nY = 0L; nY < nHeight; nY++ ) 677 for( long nX = 0L; nX < nWidth; nX++ ) 678 pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) ); 679 } 680 } 681 682 aNewBmp.ReleaseAccess( pWriteAcc ); 683 bRet = sal_True; 684 } 685 686 ReleaseAccess( pReadAcc ); 687 688 if( bRet ) 689 { 690 const MapMode aMap( maPrefMapMode ); 691 const Size aSize( maPrefSize ); 692 693 *this = aNewBmp; 694 695 maPrefMapMode = aMap; 696 maPrefSize = aSize; 697 } 698 } 699 700 return bRet; 701 } 702 703 // ------------------------------------------------------------------------ 704 705 sal_Bool Bitmap::ImplConvertDown( sal_uInt16 nBitCount, Color* pExtColor ) 706 { 707 DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" ); 708 709 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 710 sal_Bool bRet = sal_False; 711 712 if( pReadAcc ) 713 { 714 BitmapPalette aPal; 715 Bitmap aNewBmp( GetSizePixel(), nBitCount, &aPal ); 716 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 717 718 if( pWriteAcc ) 719 { 720 const sal_uInt16 nCount = 1 << nBitCount; 721 const long nWidth = pWriteAcc->Width(); 722 const long nWidth1 = nWidth - 1L; 723 const long nHeight = pWriteAcc->Height(); 724 Octree aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount ); 725 InverseColorMap aColorMap( aPal = aOctree.GetPalette() ); 726 BitmapColor aColor; 727 ImpErrorQuad aErrQuad; 728 ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ]; 729 ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ]; 730 ImpErrorQuad* pQLine1 = pErrQuad1; 731 ImpErrorQuad* pQLine2 = 0; 732 long nX, nY; 733 long nYTmp = 0L; 734 sal_uInt8 cIndex; 735 sal_Bool bQ1 = sal_True; 736 737 if( pExtColor ) 738 { 739 aPal.SetEntryCount( aPal.GetEntryCount() + 1 ); 740 aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor; 741 } 742 743 // set Black/White always, if we have enough space 744 if( aPal.GetEntryCount() < ( nCount - 1 ) ) 745 { 746 aPal.SetEntryCount( aPal.GetEntryCount() + 2 ); 747 aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK ); 748 aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE ); 749 } 750 751 pWriteAcc->SetPalette( aPal ); 752 753 for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ ) 754 { 755 for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ ) 756 { 757 if( pReadAcc->HasPalette() ) 758 pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) ); 759 else 760 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX ); 761 } 762 } 763 764 for( nY = 0L; nY < nHeight; nY++, nYTmp++ ) 765 { 766 // first pixel in the line 767 cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() ); 768 pWriteAcc->SetPixelIndex( nY, 0, cIndex ); 769 770 for( nX = 1L; nX < nWidth1; nX++ ) 771 { 772 cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() ); 773 aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) ); 774 pQLine1[ ++nX ].ImplAddColorError7( aErrQuad ); 775 pQLine2[ nX-- ].ImplAddColorError1( aErrQuad ); 776 pQLine2[ nX-- ].ImplAddColorError5( aErrQuad ); 777 pQLine2[ nX++ ].ImplAddColorError3( aErrQuad ); 778 pWriteAcc->SetPixelIndex( nY, nX, cIndex ); 779 } 780 781 // letztes ZeilenPixel 782 if( nX < nWidth ) 783 { 784 cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() ); 785 pWriteAcc->SetPixelIndex( nY, nX, cIndex ); 786 } 787 788 // Zeilenpuffer neu fuellen/kopieren 789 pQLine1 = pQLine2; 790 pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1; 791 792 if( nYTmp < nHeight ) 793 { 794 for( nX = 0L; nX < nWidth; nX++ ) 795 { 796 if( pReadAcc->HasPalette() ) 797 pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) ); 798 else 799 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX ); 800 } 801 } 802 } 803 804 // Zeilenpuffer zerstoeren 805 delete[] pErrQuad1; 806 delete[] pErrQuad2; 807 808 aNewBmp.ReleaseAccess( pWriteAcc ); 809 bRet = sal_True; 810 } 811 812 ReleaseAccess( pReadAcc ); 813 814 if( bRet ) 815 { 816 const MapMode aMap( maPrefMapMode ); 817 const Size aSize( maPrefSize ); 818 819 *this = aNewBmp; 820 821 maPrefMapMode = aMap; 822 maPrefSize = aSize; 823 } 824 } 825 826 return bRet; 827 } 828 829 // ------------------------------------------------------------------------ 830 831 sal_Bool Bitmap::ImplConvertGhosted() 832 { 833 Bitmap aNewBmp; 834 BitmapReadAccess* pR = AcquireReadAccess(); 835 sal_Bool bRet = sal_False; 836 837 if( pR ) 838 { 839 if( pR->HasPalette() ) 840 { 841 BitmapPalette aNewPal( pR->GetPaletteEntryCount() ); 842 843 for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ ) 844 { 845 const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i ); 846 aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80, 847 ( rOld.GetGreen() >> 1 ) | 0x80, 848 ( rOld.GetBlue() >> 1 ) | 0x80 ); 849 } 850 851 aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal ); 852 BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess(); 853 854 if( pW ) 855 { 856 pW->CopyBuffer( *pR ); 857 aNewBmp.ReleaseAccess( pW ); 858 bRet = sal_True; 859 } 860 } 861 else 862 { 863 aNewBmp = Bitmap( GetSizePixel(), 24 ); 864 865 BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess(); 866 867 if( pW ) 868 { 869 const long nWidth = pR->Width(), nHeight = pR->Height(); 870 871 for( long nY = 0; nY < nHeight; nY++ ) 872 { 873 for( long nX = 0; nX < nWidth; nX++ ) 874 { 875 const BitmapColor aOld( pR->GetPixel( nY, nX ) ); 876 pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80, 877 ( aOld.GetGreen() >> 1 ) | 0x80, 878 ( aOld.GetBlue() >> 1 ) | 0x80 ) ); 879 880 } 881 } 882 883 aNewBmp.ReleaseAccess( pW ); 884 bRet = sal_True; 885 } 886 } 887 888 ReleaseAccess( pR ); 889 } 890 891 if( bRet ) 892 { 893 const MapMode aMap( maPrefMapMode ); 894 const Size aSize( maPrefSize ); 895 896 *this = aNewBmp; 897 898 maPrefMapMode = aMap; 899 maPrefSize = aSize; 900 } 901 902 return bRet; 903 } 904 905 // ------------------------------------------------------------------------ 906 907 sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag ) 908 { 909 if(basegfx::fTools::equalZero(rScaleX) || basegfx::fTools::equalZero(rScaleY)) 910 { 911 // no scale 912 return true; 913 } 914 915 if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0)) 916 { 917 // no scale 918 return true; 919 } 920 921 #ifdef DBG_UTIL 922 // #121233# allow to test the different scalers in debug build with source 923 // level debugger (change nNumber to desired action) 924 static sal_uInt16 nNumber(0); 925 const sal_uInt16 nStartCount(GetBitCount()); 926 927 switch(nNumber) 928 { 929 case 0 : break; 930 case 1: nScaleFlag = BMP_SCALE_FAST; break; 931 case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break; 932 case 3: nScaleFlag = BMP_SCALE_SUPER; break; 933 case 4: nScaleFlag = BMP_SCALE_LANCZOS; break; 934 case 5: nScaleFlag = BMP_SCALE_BICUBIC; break; 935 case 6: nScaleFlag = BMP_SCALE_BILINEAR; break; 936 case 7: nScaleFlag = BMP_SCALE_BOX; break; 937 case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break; 938 case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break; 939 } 940 #endif // DBG_UTIL 941 942 bool bRetval(false); 943 944 if(BMP_SCALE_BESTQUALITY == nScaleFlag) 945 { 946 // Use LANCZOS when best quality is requested 947 nScaleFlag = BMP_SCALE_LANCZOS; 948 } 949 else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag) 950 { 951 // Use BMP_SCALE_SUPER when speed is requested, but not worst quality 952 nScaleFlag = BMP_SCALE_SUPER; 953 } 954 955 switch(nScaleFlag) 956 { 957 default: 958 case BMP_SCALE_NONE : 959 { 960 bRetval = false; 961 break; 962 } 963 case BMP_SCALE_FAST : 964 { 965 bRetval = ImplScaleFast( rScaleX, rScaleY ); 966 break; 967 } 968 case BMP_SCALE_INTERPOLATE : 969 { 970 bRetval = ImplScaleInterpolate( rScaleX, rScaleY ); 971 break; 972 } 973 case BMP_SCALE_SUPER : 974 { 975 if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2) 976 { 977 // fallback to ImplScaleFast 978 bRetval = ImplScaleFast( rScaleX, rScaleY ); 979 } 980 else 981 { 982 // #121233# use method from symphony 983 bRetval = ImplScaleSuper( rScaleX, rScaleY ); 984 } 985 break; 986 } 987 case BMP_SCALE_LANCZOS : 988 { 989 const Lanczos3Kernel kernel; 990 991 bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel); 992 break; 993 } 994 case BMP_SCALE_BICUBIC : 995 { 996 const BicubicKernel kernel; 997 998 bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel ); 999 break; 1000 } 1001 case BMP_SCALE_BILINEAR : 1002 { 1003 const BilinearKernel kernel; 1004 1005 bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel ); 1006 break; 1007 } 1008 case BMP_SCALE_BOX : 1009 { 1010 const BoxKernel kernel; 1011 1012 bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel ); 1013 break; 1014 } 1015 } 1016 1017 #ifdef DBG_UTIL 1018 if(bRetval && nStartCount != GetBitCount()) 1019 { 1020 OSL_ENSURE(false, "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)"); 1021 } 1022 #endif 1023 1024 return bRetval; 1025 } 1026 1027 // ------------------------------------------------------------------------ 1028 1029 sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag ) 1030 { 1031 const Size aSize( GetSizePixel() ); 1032 sal_Bool bRet; 1033 1034 if( aSize.Width() && aSize.Height() ) 1035 { 1036 bRet = Scale( (double) rNewSize.Width() / aSize.Width(), 1037 (double) rNewSize.Height() / aSize.Height(), 1038 nScaleFlag ); 1039 } 1040 else 1041 bRet = sal_True; 1042 1043 return bRet; 1044 } 1045 1046 // ------------------------------------------------------------------------ 1047 1048 void Bitmap::AdaptBitCount(Bitmap& rNew) const 1049 { 1050 ImplAdaptBitCount(rNew); 1051 } 1052 1053 // ------------------------------------------------------------------------ 1054 1055 void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const 1056 { 1057 // aNew is the result of some operation; adapt it's BitCount to the original (this) 1058 if(GetBitCount() != rNew.GetBitCount()) 1059 { 1060 switch(GetBitCount()) 1061 { 1062 case 1: 1063 { 1064 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD); 1065 break; 1066 } 1067 case 4: 1068 { 1069 if(HasGreyPalette()) 1070 { 1071 rNew.Convert(BMP_CONVERSION_4BIT_GREYS); 1072 } 1073 else 1074 { 1075 rNew.Convert(BMP_CONVERSION_4BIT_COLORS); 1076 } 1077 break; 1078 } 1079 case 8: 1080 { 1081 if(HasGreyPalette()) 1082 { 1083 rNew.Convert(BMP_CONVERSION_8BIT_GREYS); 1084 } 1085 else 1086 { 1087 rNew.Convert(BMP_CONVERSION_8BIT_COLORS); 1088 } 1089 break; 1090 } 1091 case 24: 1092 { 1093 rNew.Convert(BMP_CONVERSION_24BIT); 1094 break; 1095 } 1096 default: 1097 { 1098 OSL_ENSURE(false, "BitDepth adaption failed (!)"); 1099 break; 1100 } 1101 } 1102 } 1103 } 1104 1105 // ------------------------------------------------------------------------ 1106 1107 sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY ) 1108 { 1109 const Size aSizePix( GetSizePixel() ); 1110 const long nNewWidth = FRound( aSizePix.Width() * rScaleX ); 1111 const long nNewHeight = FRound( aSizePix.Height() * rScaleY ); 1112 sal_Bool bRet = sal_False; 1113 1114 if( nNewWidth && nNewHeight ) 1115 { 1116 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 1117 if ( !pReadAcc ) 1118 return sal_False; 1119 1120 Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() ); 1121 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 1122 1123 if( pWriteAcc ) 1124 { 1125 const long nScanlineSize = pWriteAcc->GetScanlineSize(); 1126 const long nNewWidth1 = nNewWidth - 1L; 1127 const long nNewHeight1 = nNewHeight - 1L; 1128 const long nWidth = pReadAcc->Width(); 1129 const long nHeight = pReadAcc->Height(); 1130 long* pLutX = new long[ nNewWidth ]; 1131 long* pLutY = new long[ nNewHeight ]; 1132 long nX, nY, nMapY, nActY = 0L; 1133 1134 if( nNewWidth1 && nNewHeight1 ) 1135 { 1136 for( nX = 0L; nX < nNewWidth; nX++ ) 1137 pLutX[ nX ] = nX * nWidth / nNewWidth; 1138 1139 for( nY = 0L; nY < nNewHeight; nY++ ) 1140 pLutY[ nY ] = nY * nHeight / nNewHeight; 1141 1142 while( nActY < nNewHeight ) 1143 { 1144 nMapY = pLutY[ nActY ]; 1145 1146 for( nX = 0L; nX < nNewWidth; nX++ ) 1147 pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) ); 1148 1149 while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) ) 1150 { 1151 memcpy( pWriteAcc->GetScanline( nActY + 1L ), 1152 pWriteAcc->GetScanline( nActY ), nScanlineSize ); 1153 nActY++; 1154 } 1155 1156 nActY++; 1157 } 1158 1159 bRet = sal_True; 1160 } 1161 1162 delete[] pLutX; 1163 delete[] pLutY; 1164 } 1165 1166 ReleaseAccess( pReadAcc ); 1167 aNewBmp.ReleaseAccess( pWriteAcc ); 1168 1169 if( bRet ) 1170 ImplAssignWithSize( aNewBmp ); 1171 } 1172 1173 return bRet; 1174 } 1175 1176 // ------------------------------------------------------------------------ 1177 1178 sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY ) 1179 { 1180 const Size aSizePix( GetSizePixel() ); 1181 const long nNewWidth = FRound( aSizePix.Width() * rScaleX ); 1182 const long nNewHeight = FRound( aSizePix.Height() * rScaleY ); 1183 sal_Bool bRet = sal_False; 1184 1185 if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) ) 1186 { 1187 BitmapColor aCol0; 1188 BitmapColor aCol1; 1189 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 1190 long nWidth = pReadAcc->Width(); 1191 long nHeight = pReadAcc->Height(); 1192 Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 ); 1193 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 1194 long* pLutInt; 1195 long* pLutFrac; 1196 long nX, nY; 1197 long lXB0, lXB1, lXG0, lXG1, lXR0, lXR1; 1198 double fTemp; 1199 long nTemp; 1200 1201 if( pReadAcc && pWriteAcc ) 1202 { 1203 const long nNewWidth1 = nNewWidth - 1L; 1204 const long nWidth1 = pReadAcc->Width() - 1L; 1205 const double fRevScaleX = (double) nWidth1 / nNewWidth1; 1206 1207 pLutInt = new long[ nNewWidth ]; 1208 pLutFrac = new long[ nNewWidth ]; 1209 1210 for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ ) 1211 { 1212 fTemp = nX * fRevScaleX; 1213 pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp ); 1214 fTemp -= pLutInt[ nX ]; 1215 pLutFrac[ nX ] = (long) ( fTemp * 1024. ); 1216 } 1217 1218 for( nY = 0L; nY < nHeight; nY++ ) 1219 { 1220 if( 1 == nWidth ) 1221 { 1222 if( pReadAcc->HasPalette() ) 1223 { 1224 aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) ); 1225 } 1226 else 1227 { 1228 aCol0 = pReadAcc->GetPixel( nY, 0 ); 1229 } 1230 1231 for( nX = 0L; nX < nNewWidth; nX++ ) 1232 { 1233 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1234 } 1235 } 1236 else 1237 { 1238 for( nX = 0L; nX < nNewWidth; nX++ ) 1239 { 1240 nTemp = pLutInt[ nX ]; 1241 1242 if( pReadAcc->HasPalette() ) 1243 { 1244 aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) ); 1245 aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) ); 1246 } 1247 else 1248 { 1249 aCol0 = pReadAcc->GetPixel( nY, nTemp++ ); 1250 aCol1 = pReadAcc->GetPixel( nY, nTemp ); 1251 } 1252 1253 nTemp = pLutFrac[ nX ]; 1254 1255 lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() ); 1256 lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() ); 1257 lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() ); 1258 1259 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) ); 1260 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) ); 1261 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) ); 1262 1263 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1264 } 1265 } 1266 } 1267 1268 delete[] pLutInt; 1269 delete[] pLutFrac; 1270 bRet = sal_True; 1271 } 1272 1273 ReleaseAccess( pReadAcc ); 1274 aNewBmp.ReleaseAccess( pWriteAcc ); 1275 1276 if( bRet ) 1277 { 1278 bRet = sal_False; 1279 const Bitmap aOriginal(*this); 1280 *this = aNewBmp; 1281 aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 ); 1282 pReadAcc = AcquireReadAccess(); 1283 pWriteAcc = aNewBmp.AcquireWriteAccess(); 1284 1285 if( pReadAcc && pWriteAcc ) 1286 { 1287 const long nNewHeight1 = nNewHeight - 1L; 1288 const long nHeight1 = pReadAcc->Height() - 1L; 1289 const double fRevScaleY = (double) nHeight1 / nNewHeight1; 1290 1291 pLutInt = new long[ nNewHeight ]; 1292 pLutFrac = new long[ nNewHeight ]; 1293 1294 for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ ) 1295 { 1296 fTemp = nY * fRevScaleY; 1297 pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp ); 1298 fTemp -= pLutInt[ nY ]; 1299 pLutFrac[ nY ] = (long) ( fTemp * 1024. ); 1300 } 1301 1302 // after 1st step, bitmap *is* 24bit format (see above) 1303 OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)"); 1304 1305 for( nX = 0L; nX < nNewWidth; nX++ ) 1306 { 1307 if( 1 == nHeight ) 1308 { 1309 aCol0 = pReadAcc->GetPixel( 0, nX ); 1310 1311 for( nY = 0L; nY < nNewHeight; nY++ ) 1312 { 1313 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1314 } 1315 } 1316 else 1317 { 1318 for( nY = 0L; nY < nNewHeight; nY++ ) 1319 { 1320 nTemp = pLutInt[ nY ]; 1321 1322 aCol0 = pReadAcc->GetPixel( nTemp++, nX ); 1323 aCol1 = pReadAcc->GetPixel( nTemp, nX ); 1324 1325 nTemp = pLutFrac[ nY ]; 1326 1327 lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() ); 1328 lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() ); 1329 lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() ); 1330 1331 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) ); 1332 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) ); 1333 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) ); 1334 1335 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1336 } 1337 } 1338 } 1339 1340 delete[] pLutInt; 1341 delete[] pLutFrac; 1342 bRet = sal_True; 1343 } 1344 1345 ReleaseAccess( pReadAcc ); 1346 aNewBmp.ReleaseAccess( pWriteAcc ); 1347 1348 if( bRet ) 1349 { 1350 aOriginal.ImplAdaptBitCount(aNewBmp); 1351 *this = aNewBmp; 1352 } 1353 } 1354 } 1355 1356 if( !bRet ) 1357 { 1358 bRet = ImplScaleFast( rScaleX, rScaleY ); 1359 } 1360 1361 return bRet; 1362 } 1363 1364 // ------------------------------------------------------------------------ 1365 // #121233# Added BMP_SCALE_SUPER from symphony code 1366 1367 sal_Bool Bitmap::ImplScaleSuper( 1368 const double& rScaleX, 1369 const double& rScaleY ) 1370 { 1371 const Size aSizePix( GetSizePixel() ); 1372 bool bHMirr = ( rScaleX < 0 ); 1373 bool bVMirr = ( rScaleY < 0 ); 1374 double scaleX = bHMirr ? -rScaleX : rScaleX; 1375 double scaleY = bVMirr ? -rScaleY : rScaleY; 1376 const long nDstW = FRound( aSizePix.Width() * scaleX ); 1377 const long nDstH = FRound( aSizePix.Height() * scaleY ); 1378 const double fScaleThresh = 0.6; 1379 bool bRet = false; 1380 1381 if( ( nDstW > 1L ) && ( nDstH > 1L ) ) 1382 { 1383 BitmapColor aCol0, aCol1, aColRes; 1384 BitmapReadAccess* pAcc = AcquireReadAccess(); 1385 long nW = pAcc->Width() ; 1386 long nH = pAcc->Height() ; 1387 Bitmap aOutBmp( Size( nDstW, nDstH ), 24 ); 1388 BitmapWriteAccess* pWAcc = aOutBmp.AcquireWriteAccess(); 1389 long* pMapIX = new long[ nDstW ]; 1390 long* pMapIY = new long[ nDstH ]; 1391 long* pMapFX = new long[ nDstW ]; 1392 long* pMapFY = new long[ nDstH ]; 1393 long nX, nY, nXDst, nYDst;; 1394 double fTemp; 1395 long nTemp , nTempX, nTempY, nTempFX, nTempFY; 1396 sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1; 1397 long nStartX = 0 , nStartY = 0; 1398 long nEndX = nDstW - 1L; 1399 long nEndY = nDstH - 1L; 1400 long nMax = 1 << 7L; 1401 1402 if( pAcc && pWAcc ) 1403 { 1404 const double fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0; 1405 const double fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0; 1406 1407 // create horizontal mapping table 1408 for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ ) 1409 { 1410 fTemp = nX * fRevScaleX; 1411 1412 if( bHMirr ) 1413 fTemp = nTempX - fTemp; 1414 1415 pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. ); 1416 } 1417 1418 // create vertical mapping table 1419 for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ ) 1420 { 1421 fTemp = nY * fRevScaleY; 1422 1423 if( bVMirr ) 1424 fTemp = nTempY - fTemp; 1425 1426 pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. ); 1427 } 1428 1429 if( pAcc->HasPalette() ) 1430 { 1431 if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 1432 { 1433 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1434 { 1435 Scanline pLine0, pLine1; 1436 1437 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1438 { 1439 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 1440 pLine0 = pAcc->GetScanline( nTempY ); 1441 pLine1 = pAcc->GetScanline( ++nTempY ); 1442 1443 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1444 { 1445 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ]; 1446 1447 const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] ); 1448 const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] ); 1449 const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] ); 1450 const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] ); 1451 1452 cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX ); 1453 cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX ); 1454 cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX ); 1455 1456 cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX ); 1457 cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX ); 1458 cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX ); 1459 1460 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1461 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1462 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1463 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1464 } 1465 } 1466 } 1467 else 1468 { 1469 Scanline pTmpY; 1470 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1471 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1472 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1473 1474 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1475 { 1476 nTop = bVMirr ? ( nY + 1 ) : nY; 1477 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1478 1479 if( nY ==nEndY ) 1480 { 1481 nLineStart = pMapIY[ nY ]; 1482 nLineRange = 0; 1483 } 1484 else 1485 { 1486 nLineStart = pMapIY[ nTop ] ; 1487 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1488 } 1489 1490 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1491 { 1492 nLeft = bHMirr ? ( nX + 1 ) : nX; 1493 nRight = bHMirr ? nX : ( nX + 1 ) ; 1494 1495 if( nX == nEndX ) 1496 { 1497 nRowStart = pMapIX[ nX ]; 1498 nRowRange = 0; 1499 } 1500 else 1501 { 1502 nRowStart = pMapIX[ nLeft ]; 1503 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1504 } 1505 1506 nSumR = nSumG = nSumB = 0; 1507 nTotalWeightY = 0; 1508 1509 for(int i = 0; i<= nLineRange; i++) 1510 { 1511 pTmpY = pAcc->GetScanline( nLineStart + i ); 1512 nSumRowR = nSumRowG = nSumRowB = 0; 1513 nTotalWeightX = 0; 1514 1515 for(int j = 0; j <= nRowRange; j++) 1516 { 1517 const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] ); 1518 1519 if(nX == nEndX ) 1520 { 1521 nSumRowB += rCol.GetBlue() << 7L; 1522 nSumRowG += rCol.GetGreen() << 7L; 1523 nSumRowR += rCol.GetRed() << 7L; 1524 nTotalWeightX += 1 << 7L; 1525 } 1526 else if( j == 0 ) 1527 { 1528 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1529 nSumRowB += ( nWeightX *rCol.GetBlue()) ; 1530 nSumRowG += ( nWeightX *rCol.GetGreen()) ; 1531 nSumRowR += ( nWeightX *rCol.GetRed()) ; 1532 nTotalWeightX += nWeightX; 1533 } 1534 else if ( nRowRange == j ) 1535 { 1536 nWeightX = pMapFX[ nRight ] ; 1537 nSumRowB += ( nWeightX *rCol.GetBlue() ); 1538 nSumRowG += ( nWeightX *rCol.GetGreen() ); 1539 nSumRowR += ( nWeightX *rCol.GetRed() ); 1540 nTotalWeightX += nWeightX; 1541 } 1542 else 1543 { 1544 nSumRowB += rCol.GetBlue() << 7L; 1545 nSumRowG += rCol.GetGreen() << 7L; 1546 nSumRowR += rCol.GetRed() << 7L; 1547 nTotalWeightX += 1 << 7L; 1548 } 1549 } 1550 1551 if( nY == nEndY ) 1552 nWeightY = nMax; 1553 else if( i == 0 ) 1554 nWeightY = nMax - pMapFY[ nTop ]; 1555 else if( nLineRange == 1 ) 1556 nWeightY = pMapFY[ nTop ]; 1557 else if ( nLineRange == i ) 1558 nWeightY = pMapFY[ nBottom ]; 1559 else 1560 nWeightY = nMax; 1561 1562 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1563 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1564 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1565 nTotalWeightY += nWeightY; 1566 } 1567 1568 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1569 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1570 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1571 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1572 1573 } 1574 } 1575 } 1576 } 1577 else 1578 { 1579 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1580 { 1581 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1582 { 1583 nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ]; 1584 1585 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1586 { 1587 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ]; 1588 1589 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) ); 1590 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) ); 1591 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 1592 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 1593 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 1594 1595 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) ); 1596 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) ); 1597 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 1598 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 1599 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 1600 1601 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1602 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1603 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1604 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1605 } 1606 } 1607 1608 } 1609 else 1610 { 1611 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1612 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1613 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1614 1615 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1616 { 1617 nTop = bVMirr ? ( nY + 1 ) : nY; 1618 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1619 1620 if( nY ==nEndY ) 1621 { 1622 nLineStart = pMapIY[ nY ]; 1623 nLineRange = 0; 1624 } 1625 else 1626 { 1627 nLineStart = pMapIY[ nTop ] ; 1628 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1629 } 1630 1631 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1632 { 1633 nLeft = bHMirr ? ( nX + 1 ) : nX; 1634 nRight = bHMirr ? nX : ( nX + 1 ) ; 1635 1636 if( nX == nEndX ) 1637 { 1638 nRowStart = pMapIX[ nX ]; 1639 nRowRange = 0; 1640 } 1641 else 1642 { 1643 nRowStart = pMapIX[ nLeft ]; 1644 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1645 } 1646 1647 nSumR = nSumG = nSumB = 0; 1648 nTotalWeightY = 0; 1649 1650 for(int i = 0; i<= nLineRange; i++) 1651 { 1652 nSumRowR = nSumRowG = nSumRowB = 0; 1653 nTotalWeightX = 0; 1654 1655 for(int j = 0; j <= nRowRange; j++) 1656 { 1657 aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) ); 1658 1659 if(nX == nEndX ) 1660 { 1661 1662 nSumRowB += aCol0.GetBlue() << 7L; 1663 nSumRowG += aCol0.GetGreen() << 7L; 1664 nSumRowR += aCol0.GetRed() << 7L; 1665 nTotalWeightX += 1 << 7L; 1666 } 1667 else if( j == 0 ) 1668 { 1669 1670 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1671 nSumRowB += ( nWeightX *aCol0.GetBlue()) ; 1672 nSumRowG += ( nWeightX *aCol0.GetGreen()) ; 1673 nSumRowR += ( nWeightX *aCol0.GetRed()) ; 1674 nTotalWeightX += nWeightX; 1675 } 1676 else if ( nRowRange == j ) 1677 { 1678 1679 nWeightX = pMapFX[ nRight ] ; 1680 nSumRowB += ( nWeightX *aCol0.GetBlue() ); 1681 nSumRowG += ( nWeightX *aCol0.GetGreen() ); 1682 nSumRowR += ( nWeightX *aCol0.GetRed() ); 1683 nTotalWeightX += nWeightX; 1684 } 1685 else 1686 { 1687 1688 nSumRowB += aCol0.GetBlue() << 7L; 1689 nSumRowG += aCol0.GetGreen() << 7L; 1690 nSumRowR += aCol0.GetRed() << 7L; 1691 nTotalWeightX += 1 << 7L; 1692 } 1693 } 1694 1695 if( nY == nEndY ) 1696 nWeightY = nMax; 1697 else if( i == 0 ) 1698 nWeightY = nMax - pMapFY[ nTop ]; 1699 else if( nLineRange == 1 ) 1700 nWeightY = pMapFY[ nTop ]; 1701 else if ( nLineRange == i ) 1702 nWeightY = pMapFY[ nBottom ]; 1703 else 1704 nWeightY = nMax; 1705 1706 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1707 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1708 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1709 nTotalWeightY += nWeightY; 1710 } 1711 1712 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1713 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1714 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1715 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1716 } 1717 } 1718 } 1719 } 1720 } 1721 else 1722 { 1723 if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 1724 { 1725 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1726 { 1727 Scanline pLine0, pLine1, pTmp0, pTmp1; 1728 long nOff; 1729 1730 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1731 { 1732 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 1733 pLine0 = pAcc->GetScanline( nTempY ); 1734 pLine1 = pAcc->GetScanline( ++nTempY ); 1735 1736 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1737 { 1738 nOff = 3L * ( nTempX = pMapIX[ nX ] ); 1739 nTempFX = pMapFX[ nX ]; 1740 1741 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; 1742 cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1743 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1744 cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); 1745 1746 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; 1747 cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1748 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1749 cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); 1750 1751 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1752 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1753 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1754 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1755 } 1756 } 1757 } 1758 else 1759 { 1760 Scanline pTmpY, pTmpX; 1761 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1762 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1763 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1764 1765 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1766 { 1767 nTop = bVMirr ? ( nY + 1 ) : nY; 1768 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1769 1770 if( nY ==nEndY ) 1771 { 1772 nLineStart = pMapIY[ nY ]; 1773 nLineRange = 0; 1774 } 1775 else 1776 { 1777 nLineStart = pMapIY[ nTop ] ; 1778 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1779 } 1780 1781 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1782 { 1783 nLeft = bHMirr ? ( nX + 1 ) : nX; 1784 nRight = bHMirr ? nX : ( nX + 1 ) ; 1785 1786 if( nX == nEndX ) 1787 { 1788 nRowStart = pMapIX[ nX ]; 1789 nRowRange = 0; 1790 } 1791 else 1792 { 1793 nRowStart = pMapIX[ nLeft ]; 1794 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1795 } 1796 1797 nSumR = nSumG = nSumB = 0; 1798 nTotalWeightY = 0; 1799 1800 for(int i = 0; i<= nLineRange; i++) 1801 { 1802 pTmpY = pAcc->GetScanline( nLineStart + i ); 1803 pTmpX = pTmpY + 3L * nRowStart; 1804 nSumRowR = nSumRowG = nSumRowB = 0; 1805 nTotalWeightX = 0; 1806 1807 for(int j = 0; j <= nRowRange; j++) 1808 { 1809 if(nX == nEndX ) 1810 { 1811 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1812 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1813 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1814 nTotalWeightX += 1 << 7L; 1815 } 1816 else if( j == 0 ) 1817 { 1818 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1819 nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++; 1820 nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++; 1821 nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++; 1822 nTotalWeightX += nWeightX; 1823 } 1824 else if ( nRowRange == j ) 1825 { 1826 nWeightX = pMapFX[ nRight ] ; 1827 nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++; 1828 nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++; 1829 nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++; 1830 nTotalWeightX += nWeightX; 1831 } 1832 else 1833 { 1834 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1835 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1836 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1837 nTotalWeightX += 1 << 7L; 1838 } 1839 } 1840 1841 if( nY == nEndY ) 1842 nWeightY = nMax; 1843 else if( i == 0 ) 1844 nWeightY = nMax - pMapFY[ nTop ]; 1845 else if( nLineRange == 1 ) 1846 nWeightY = pMapFY[ nTop ]; 1847 else if ( nLineRange == i ) 1848 nWeightY = pMapFY[ nBottom ]; 1849 else 1850 nWeightY = nMax; 1851 1852 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1853 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1854 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1855 nTotalWeightY += nWeightY; 1856 } 1857 1858 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1859 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1860 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1861 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1862 1863 } 1864 } 1865 } 1866 } 1867 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ) 1868 { 1869 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1870 { 1871 Scanline pLine0, pLine1, pTmp0, pTmp1; 1872 long nOff; 1873 1874 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1875 { 1876 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 1877 pLine0 = pAcc->GetScanline( nTempY ); 1878 pLine1 = pAcc->GetScanline( ++nTempY ); 1879 1880 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1881 { 1882 nOff = 3L * ( nTempX = pMapIX[ nX ] ); 1883 nTempFX = pMapFX[ nX ]; 1884 1885 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; 1886 cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1887 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1888 cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); 1889 1890 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; 1891 cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1892 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1893 cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); 1894 1895 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1896 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1897 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1898 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1899 } 1900 } 1901 } 1902 else 1903 { 1904 Scanline pTmpY, pTmpX; 1905 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1906 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1907 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1908 1909 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1910 { 1911 nTop = bVMirr ? ( nY + 1 ) : nY; 1912 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1913 1914 if( nY ==nEndY ) 1915 { 1916 nLineStart = pMapIY[ nY ]; 1917 nLineRange = 0; 1918 } 1919 else 1920 { 1921 nLineStart = pMapIY[ nTop ] ; 1922 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1923 } 1924 1925 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1926 { 1927 nLeft = bHMirr ? ( nX + 1 ) : nX; 1928 nRight = bHMirr ? nX : ( nX + 1 ) ; 1929 1930 if( nX == nEndX ) 1931 { 1932 nRowStart = pMapIX[ nX ]; 1933 nRowRange = 0; 1934 } 1935 else 1936 { 1937 nRowStart = pMapIX[ nLeft ]; 1938 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1939 } 1940 1941 nSumR = nSumG = nSumB = 0; 1942 nTotalWeightY = 0; 1943 1944 for(int i = 0; i<= nLineRange; i++) 1945 { 1946 pTmpY = pAcc->GetScanline( nLineStart + i ); 1947 pTmpX = pTmpY + 3L * nRowStart; 1948 nSumRowR = nSumRowG = nSumRowB = 0; 1949 nTotalWeightX = 0; 1950 1951 for(int j = 0; j <= nRowRange; j++) 1952 { 1953 if(nX == nEndX ) 1954 { 1955 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1956 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1957 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1958 nTotalWeightX += 1 << 7L; 1959 } 1960 else if( j == 0 ) 1961 { 1962 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1963 nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++; 1964 nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++; 1965 nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++; 1966 nTotalWeightX += nWeightX; 1967 } 1968 else if ( nRowRange == j ) 1969 { 1970 nWeightX = pMapFX[ nRight ] ; 1971 nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++; 1972 nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++; 1973 nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++; 1974 nTotalWeightX += nWeightX; 1975 } 1976 else 1977 { 1978 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1979 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1980 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1981 nTotalWeightX += 1 << 7L; 1982 } 1983 } 1984 1985 if( nY == nEndY ) 1986 nWeightY = nMax; 1987 else if( i == 0 ) 1988 nWeightY = nMax - pMapFY[ nTop ]; 1989 else if( nLineRange == 1 ) 1990 nWeightY = pMapFY[ nTop ]; 1991 else if ( nLineRange == i ) 1992 nWeightY = pMapFY[ nBottom ]; 1993 else 1994 nWeightY = nMax; 1995 1996 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1997 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1998 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1999 nTotalWeightY += nWeightY; 2000 } 2001 2002 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 2003 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 2004 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 2005 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 2006 2007 } 2008 } 2009 } 2010 } 2011 else 2012 { 2013 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 2014 { 2015 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 2016 { 2017 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 2018 2019 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 2020 { 2021 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ]; 2022 2023 aCol0 = pAcc->GetPixel( nTempY, nTempX ); 2024 aCol1 = pAcc->GetPixel( nTempY, ++nTempX ); 2025 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 2026 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 2027 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 2028 2029 aCol1 = pAcc->GetPixel( ++nTempY, nTempX ); 2030 aCol0 = pAcc->GetPixel( nTempY--, --nTempX ); 2031 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 2032 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 2033 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 2034 2035 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 2036 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 2037 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 2038 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 2039 } 2040 } 2041 } 2042 else 2043 { 2044 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 2045 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 2046 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 2047 2048 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 2049 { 2050 nTop = bVMirr ? ( nY + 1 ) : nY; 2051 nBottom = bVMirr ? nY : ( nY + 1 ) ; 2052 2053 if( nY ==nEndY ) 2054 { 2055 nLineStart = pMapIY[ nY ]; 2056 nLineRange = 0; 2057 } 2058 else 2059 { 2060 nLineStart = pMapIY[ nTop ] ; 2061 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 2062 } 2063 2064 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 2065 { 2066 nLeft = bHMirr ? ( nX + 1 ) : nX; 2067 nRight = bHMirr ? nX : ( nX + 1 ) ; 2068 2069 if( nX == nEndX ) 2070 { 2071 nRowStart = pMapIX[ nX ]; 2072 nRowRange = 0; 2073 } 2074 else 2075 { 2076 nRowStart = pMapIX[ nLeft ]; 2077 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 2078 } 2079 2080 nSumR = nSumG = nSumB = 0; 2081 nTotalWeightY = 0; 2082 2083 for(int i = 0; i<= nLineRange; i++) 2084 { 2085 nSumRowR = nSumRowG = nSumRowB = 0; 2086 nTotalWeightX = 0; 2087 2088 for(int j = 0; j <= nRowRange; j++) 2089 { 2090 aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j ); 2091 2092 if(nX == nEndX ) 2093 { 2094 2095 nSumRowB += aCol0.GetBlue() << 7L; 2096 nSumRowG += aCol0.GetGreen() << 7L; 2097 nSumRowR += aCol0.GetRed() << 7L; 2098 nTotalWeightX += 1 << 7L; 2099 } 2100 else if( j == 0 ) 2101 { 2102 2103 nWeightX = (nMax- pMapFX[ nLeft ]) ; 2104 nSumRowB += ( nWeightX *aCol0.GetBlue()) ; 2105 nSumRowG += ( nWeightX *aCol0.GetGreen()) ; 2106 nSumRowR += ( nWeightX *aCol0.GetRed()) ; 2107 nTotalWeightX += nWeightX; 2108 } 2109 else if ( nRowRange == j ) 2110 { 2111 2112 nWeightX = pMapFX[ nRight ] ; 2113 nSumRowB += ( nWeightX *aCol0.GetBlue() ); 2114 nSumRowG += ( nWeightX *aCol0.GetGreen() ); 2115 nSumRowR += ( nWeightX *aCol0.GetRed() ); 2116 nTotalWeightX += nWeightX; 2117 } 2118 else 2119 { 2120 nSumRowB += aCol0.GetBlue() << 7L; 2121 nSumRowG += aCol0.GetGreen() << 7L; 2122 nSumRowR += aCol0.GetRed() << 7L; 2123 nTotalWeightX += 1 << 7L; 2124 } 2125 } 2126 2127 if( nY == nEndY ) 2128 nWeightY = nMax; 2129 else if( i == 0 ) 2130 nWeightY = nMax - pMapFY[ nTop ]; 2131 else if( nLineRange == 1 ) 2132 nWeightY = pMapFY[ nTop ]; 2133 else if ( nLineRange == i ) 2134 nWeightY = pMapFY[ nBottom ]; 2135 else 2136 nWeightY = nMax; 2137 2138 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 2139 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 2140 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 2141 nTotalWeightY += nWeightY; 2142 } 2143 2144 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 2145 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 2146 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 2147 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 2148 2149 } 2150 } 2151 } 2152 } 2153 } 2154 2155 bRet = true; 2156 } 2157 2158 delete[] pMapIX; 2159 delete[] pMapIY; 2160 delete[] pMapFX; 2161 delete[] pMapFY; 2162 2163 ReleaseAccess( pAcc ); 2164 aOutBmp.ReleaseAccess( pWAcc ); 2165 2166 if( bRet ) 2167 { 2168 ImplAdaptBitCount(aOutBmp); 2169 ImplAssignWithSize(aOutBmp); 2170 } 2171 2172 if( !bRet ) 2173 bRet = ImplScaleFast( scaleX, scaleY ); 2174 } 2175 2176 return bRet; 2177 } 2178 2179 //----------------------------------------------------------------------------------- 2180 2181 namespace 2182 { 2183 void ImplCalculateContributions( 2184 const sal_uInt32 aSourceSize, 2185 const sal_uInt32 aDestinationSize, 2186 sal_uInt32& aNumberOfContributions, 2187 double*& pWeights, 2188 sal_uInt32*& pPixels, 2189 sal_uInt32*& pCount, 2190 const Kernel& aKernel) 2191 { 2192 const double fSamplingRadius(aKernel.GetWidth()); 2193 const double fScale(aDestinationSize / static_cast< double >(aSourceSize)); 2194 const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius); 2195 const double fFilterFactor((fScale < 1.0) ? fScale : 1.0); 2196 2197 aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1; 2198 const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions); 2199 pWeights = new double[nAllocSize]; 2200 pPixels = new sal_uInt32[nAllocSize]; 2201 pCount = new sal_uInt32[aDestinationSize]; 2202 2203 for(sal_uInt32 i(0); i < aDestinationSize; i++) 2204 { 2205 const sal_uInt32 aIndex(i * aNumberOfContributions); 2206 const double aCenter(i / fScale); 2207 const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius))); 2208 const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius))); 2209 sal_uInt32 aCurrentCount(0); 2210 2211 for(sal_Int32 j(aLeft); j <= aRight; j++) 2212 { 2213 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j)))); 2214 2215 // Reduce calculations with ignoring weights of 0.0 2216 if(fabs(aWeight) < 0.0001) 2217 { 2218 continue; 2219 } 2220 2221 // Handling on edges 2222 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1)); 2223 const sal_uInt32 nIndex(aIndex + aCurrentCount); 2224 2225 pWeights[nIndex] = aWeight; 2226 pPixels[nIndex] = aPixelIndex; 2227 2228 aCurrentCount++; 2229 } 2230 2231 pCount[i] = aCurrentCount; 2232 } 2233 } 2234 2235 sal_Bool ImplScaleConvolutionHor( 2236 Bitmap& rSource, 2237 Bitmap& rTarget, 2238 const double& rScaleX, 2239 const Kernel& aKernel) 2240 { 2241 // Do horizontal filtering 2242 OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)"); 2243 const sal_uInt32 nWidth(rSource.GetSizePixel().Width()); 2244 const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX)); 2245 2246 if(nWidth == nNewWidth) 2247 { 2248 return true; 2249 } 2250 2251 BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess(); 2252 2253 if(pReadAcc) 2254 { 2255 double* pWeights = 0; 2256 sal_uInt32* pPixels = 0; 2257 sal_uInt32* pCount = 0; 2258 sal_uInt32 aNumberOfContributions(0); 2259 2260 const sal_uInt32 nHeight(rSource.GetSizePixel().Height()); 2261 ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel); 2262 rTarget = Bitmap(Size(nNewWidth, nHeight), 24); 2263 BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess(); 2264 bool bResult(0 != pWriteAcc); 2265 2266 if(bResult) 2267 { 2268 for(sal_uInt32 y(0); y < nHeight; y++) 2269 { 2270 for(sal_uInt32 x(0); x < nNewWidth; x++) 2271 { 2272 const sal_uInt32 aBaseIndex(x * aNumberOfContributions); 2273 double aSum(0.0); 2274 double aValueRed(0.0); 2275 double aValueGreen(0.0); 2276 double aValueBlue(0.0); 2277 2278 for(sal_uInt32 j(0); j < pCount[x]; j++) 2279 { 2280 const sal_uInt32 aIndex(aBaseIndex + j); 2281 const double aWeight(pWeights[aIndex]); 2282 BitmapColor aColor; 2283 2284 aSum += aWeight; 2285 2286 if(pReadAcc->HasPalette()) 2287 { 2288 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex])); 2289 } 2290 else 2291 { 2292 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]); 2293 } 2294 2295 aValueRed += aWeight * aColor.GetRed(); 2296 aValueGreen += aWeight * aColor.GetGreen(); 2297 aValueBlue += aWeight * aColor.GetBlue(); 2298 } 2299 2300 const BitmapColor aResultColor( 2301 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)), 2302 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)), 2303 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255))); 2304 2305 pWriteAcc->SetPixel(y, x, aResultColor); 2306 } 2307 } 2308 2309 rTarget.ReleaseAccess(pWriteAcc); 2310 } 2311 2312 rSource.ReleaseAccess(pReadAcc); 2313 delete[] pWeights; 2314 delete[] pCount; 2315 delete[] pPixels; 2316 2317 if(bResult) 2318 { 2319 return true; 2320 } 2321 } 2322 2323 return false; 2324 } 2325 2326 bool ImplScaleConvolutionVer( 2327 Bitmap& rSource, 2328 Bitmap& rTarget, 2329 const double& rScaleY, 2330 const Kernel& aKernel) 2331 { 2332 // Do vertical filtering 2333 OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)"); 2334 const sal_uInt32 nHeight(rSource.GetSizePixel().Height()); 2335 const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY)); 2336 2337 if(nHeight == nNewHeight) 2338 { 2339 return true; 2340 } 2341 2342 BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess(); 2343 2344 if(pReadAcc) 2345 { 2346 double* pWeights = 0; 2347 sal_uInt32* pPixels = 0; 2348 sal_uInt32* pCount = 0; 2349 sal_uInt32 aNumberOfContributions(0); 2350 2351 const sal_uInt32 nWidth(rSource.GetSizePixel().Width()); 2352 ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel); 2353 rTarget = Bitmap(Size(nWidth, nNewHeight), 24); 2354 BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess(); 2355 bool bResult(0 != pWriteAcc); 2356 2357 if(pWriteAcc) 2358 { 2359 for(sal_uInt32 x(0); x < nWidth; x++) 2360 { 2361 for(sal_uInt32 y(0); y < nNewHeight; y++) 2362 { 2363 const sal_uInt32 aBaseIndex(y * aNumberOfContributions); 2364 double aSum(0.0); 2365 double aValueRed(0.0); 2366 double aValueGreen(0.0); 2367 double aValueBlue(0.0); 2368 2369 for(sal_uInt32 j(0); j < pCount[y]; j++) 2370 { 2371 const sal_uInt32 aIndex(aBaseIndex + j); 2372 const double aWeight(pWeights[aIndex]); 2373 BitmapColor aColor; 2374 2375 aSum += aWeight; 2376 2377 if(pReadAcc->HasPalette()) 2378 { 2379 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x)); 2380 } 2381 else 2382 { 2383 aColor = pReadAcc->GetPixel(pPixels[aIndex], x); 2384 } 2385 2386 aValueRed += aWeight * aColor.GetRed(); 2387 aValueGreen += aWeight * aColor.GetGreen(); 2388 aValueBlue += aWeight * aColor.GetBlue(); 2389 } 2390 2391 const BitmapColor aResultColor( 2392 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)), 2393 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)), 2394 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255))); 2395 2396 if(pWriteAcc->HasPalette()) 2397 { 2398 pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor))); 2399 } 2400 else 2401 { 2402 pWriteAcc->SetPixel(y, x, aResultColor); 2403 } 2404 } 2405 } 2406 } 2407 2408 rTarget.ReleaseAccess(pWriteAcc); 2409 rSource.ReleaseAccess(pReadAcc); 2410 2411 delete[] pWeights; 2412 delete[] pCount; 2413 delete[] pPixels; 2414 2415 if(bResult) 2416 { 2417 return true; 2418 } 2419 } 2420 2421 return false; 2422 } 2423 } 2424 2425 // #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and 2426 // BMP_SCALE_BOX derived from the original commit from Toma� Vajngerl (see 2427 // bugzilla task for deitails) Thanks! 2428 sal_Bool Bitmap::ImplScaleConvolution( 2429 const double& rScaleX, 2430 const double& rScaleY, 2431 const Kernel& aKernel) 2432 { 2433 const bool bMirrorHor(rScaleX < 0.0); 2434 const bool bMirrorVer(rScaleY < 0.0); 2435 const double fScaleX(bMirrorHor ? -rScaleX : rScaleX); 2436 const double fScaleY(bMirrorVer ? -rScaleY : rScaleY); 2437 const sal_uInt32 nWidth(GetSizePixel().Width()); 2438 const sal_uInt32 nHeight(GetSizePixel().Height()); 2439 const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX)); 2440 const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY)); 2441 const bool bScaleHor(nWidth != nNewWidth); 2442 const bool bScaleVer(nHeight != nNewHeight); 2443 const bool bMirror(bMirrorHor || bMirrorVer); 2444 2445 if(!bMirror && !bScaleHor && !bScaleVer) 2446 { 2447 return true; 2448 } 2449 2450 bool bResult(true); 2451 sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE); 2452 bool bMirrorAfter(false); 2453 2454 if(bMirror) 2455 { 2456 if(bMirrorHor) 2457 { 2458 nMirrorFlags |= BMP_MIRROR_HORZ; 2459 } 2460 2461 if(bMirrorVer) 2462 { 2463 nMirrorFlags |= BMP_MIRROR_VERT; 2464 } 2465 2466 const sal_uInt32 nStartSize(nWidth * nHeight); 2467 const sal_uInt32 nEndSize(nNewWidth * nNewHeight); 2468 2469 bMirrorAfter = nStartSize > nEndSize; 2470 2471 if(!bMirrorAfter) 2472 { 2473 bResult = Mirror(nMirrorFlags); 2474 } 2475 } 2476 2477 Bitmap aResult; 2478 2479 if(bResult) 2480 { 2481 const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth); 2482 const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth); 2483 Bitmap aSource(*this); 2484 2485 if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst) 2486 { 2487 if(bScaleHor) 2488 { 2489 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel); 2490 } 2491 2492 if(bResult && bScaleVer) 2493 { 2494 if(bScaleHor) 2495 { 2496 // copy partial result, independent of color depth 2497 aSource = aResult; 2498 } 2499 2500 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel); 2501 } 2502 } 2503 else 2504 { 2505 if(bScaleVer) 2506 { 2507 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel); 2508 } 2509 2510 if(bResult && bScaleHor) 2511 { 2512 if(bScaleVer) 2513 { 2514 // copy partial result, independent of color depth 2515 aSource = aResult; 2516 } 2517 2518 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel); 2519 } 2520 } 2521 } 2522 2523 if(bResult && bMirrorAfter) 2524 { 2525 bResult = aResult.Mirror(nMirrorFlags); 2526 } 2527 2528 if(bResult) 2529 { 2530 ImplAdaptBitCount(aResult); 2531 *this = aResult; 2532 } 2533 2534 return bResult; 2535 } 2536 2537 // ------------------------------------------------------------------------ 2538 2539 sal_Bool Bitmap::Dither( sal_uLong nDitherFlags ) 2540 { 2541 sal_Bool bRet = sal_False; 2542 2543 const Size aSizePix( GetSizePixel() ); 2544 2545 if( aSizePix.Width() == 1 || aSizePix.Height() == 1 ) 2546 bRet = sal_True; 2547 else if( nDitherFlags & BMP_DITHER_MATRIX ) 2548 bRet = ImplDitherMatrix(); 2549 else if( nDitherFlags & BMP_DITHER_FLOYD ) 2550 bRet = ImplDitherFloyd(); 2551 else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) ) 2552 bRet = ImplDitherFloyd16(); 2553 2554 return bRet; 2555 } 2556 2557 // ------------------------------------------------------------------------ 2558 2559 sal_Bool Bitmap::ImplDitherMatrix() 2560 { 2561 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 2562 Bitmap aNewBmp( GetSizePixel(), 8 ); 2563 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 2564 sal_Bool bRet = sal_False; 2565 2566 if( pReadAcc && pWriteAcc ) 2567 { 2568 const sal_uLong nWidth = pReadAcc->Width(); 2569 const sal_uLong nHeight = pReadAcc->Height(); 2570 BitmapColor aIndex( (sal_uInt8) 0 ); 2571 2572 if( pReadAcc->HasPalette() ) 2573 { 2574 for( sal_uLong nY = 0UL; nY < nHeight; nY++ ) 2575 { 2576 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ ) 2577 { 2578 const BitmapColor aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) ); 2579 const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ]; 2580 const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL; 2581 const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL; 2582 const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL; 2583 2584 aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) ); 2585 pWriteAcc->SetPixel( nY, nX, aIndex ); 2586 } 2587 } 2588 } 2589 else 2590 { 2591 for( sal_uLong nY = 0UL; nY < nHeight; nY++ ) 2592 { 2593 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ ) 2594 { 2595 const BitmapColor aCol( pReadAcc->GetPixel( nY, nX ) ); 2596 const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ]; 2597 const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL; 2598 const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL; 2599 const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL; 2600 2601 aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) ); 2602 pWriteAcc->SetPixel( nY, nX, aIndex ); 2603 } 2604 } 2605 } 2606 2607 bRet = sal_True; 2608 } 2609 2610 ReleaseAccess( pReadAcc ); 2611 aNewBmp.ReleaseAccess( pWriteAcc ); 2612 2613 if( bRet ) 2614 { 2615 const MapMode aMap( maPrefMapMode ); 2616 const Size aSize( maPrefSize ); 2617 2618 *this = aNewBmp; 2619 2620 maPrefMapMode = aMap; 2621 maPrefSize = aSize; 2622 } 2623 2624 return bRet; 2625 } 2626 2627 // ------------------------------------------------------------------------ 2628 2629 sal_Bool Bitmap::ImplDitherFloyd() 2630 { 2631 const Size aSize( GetSizePixel() ); 2632 sal_Bool bRet = sal_False; 2633 2634 if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) ) 2635 { 2636 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 2637 Bitmap aNewBmp( GetSizePixel(), 8 ); 2638 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 2639 2640 if( pReadAcc && pWriteAcc ) 2641 { 2642 BitmapColor aColor; 2643 long nWidth = pReadAcc->Width(); 2644 long nWidth1 = nWidth - 1L; 2645 long nHeight = pReadAcc->Height(); 2646 long nX; 2647 long nW = nWidth * 3L; 2648 long nW2 = nW - 3L; 2649 long nRErr, nGErr, nBErr; 2650 long nRC, nGC, nBC; 2651 long nTemp; 2652 long nZ; 2653 long* p1 = new long[ nW ]; 2654 long* p2 = new long[ nW ]; 2655 long* p1T = p1; 2656 long* p2T = p2; 2657 long* pTmp; 2658 sal_Bool bPal = pReadAcc->HasPalette(); 2659 2660 pTmp = p2T; 2661 2662 if( bPal ) 2663 { 2664 for( nZ = 0; nZ < nWidth; nZ++ ) 2665 { 2666 aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) ); 2667 2668 *pTmp++ = (long) aColor.GetBlue() << 12; 2669 *pTmp++ = (long) aColor.GetGreen() << 12; 2670 *pTmp++ = (long) aColor.GetRed() << 12; 2671 } 2672 } 2673 else 2674 { 2675 for( nZ = 0; nZ < nWidth; nZ++ ) 2676 { 2677 aColor = pReadAcc->GetPixel( 0, nZ ); 2678 2679 *pTmp++ = (long) aColor.GetBlue() << 12; 2680 *pTmp++ = (long) aColor.GetGreen() << 12; 2681 *pTmp++ = (long) aColor.GetRed() << 12; 2682 } 2683 } 2684 2685 for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ ) 2686 { 2687 pTmp = p1T; 2688 p1T = p2T; 2689 p2T = pTmp; 2690 2691 if( nY < nHeight ) 2692 { 2693 if( bPal ) 2694 { 2695 for( nZ = 0; nZ < nWidth; nZ++ ) 2696 { 2697 aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) ); 2698 2699 *pTmp++ = (long) aColor.GetBlue() << 12; 2700 *pTmp++ = (long) aColor.GetGreen() << 12; 2701 *pTmp++ = (long) aColor.GetRed() << 12; 2702 } 2703 } 2704 else 2705 { 2706 for( nZ = 0; nZ < nWidth; nZ++ ) 2707 { 2708 aColor = pReadAcc->GetPixel( nY, nZ ); 2709 2710 *pTmp++ = (long) aColor.GetBlue() << 12; 2711 *pTmp++ = (long) aColor.GetGreen() << 12; 2712 *pTmp++ = (long) aColor.GetRed() << 12; 2713 } 2714 } 2715 } 2716 2717 // erstes Pixel gesondert betrachten 2718 nX = 0; 2719 CALC_ERRORS; 2720 CALC_TABLES7; 2721 nX -= 5; 2722 CALC_TABLES5; 2723 pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) ); 2724 2725 // mittlere Pixel ueber Schleife 2726 long nXAcc; 2727 for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ ) 2728 { 2729 CALC_ERRORS; 2730 CALC_TABLES7; 2731 nX -= 8; 2732 CALC_TABLES3; 2733 CALC_TABLES5; 2734 pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) ); 2735 } 2736 2737 // letztes Pixel gesondert betrachten 2738 CALC_ERRORS; 2739 nX -= 5; 2740 CALC_TABLES3; 2741 CALC_TABLES5; 2742 pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) ); 2743 } 2744 2745 delete[] p1; 2746 delete[] p2; 2747 bRet = sal_True; 2748 } 2749 2750 ReleaseAccess( pReadAcc ); 2751 aNewBmp.ReleaseAccess( pWriteAcc ); 2752 2753 if( bRet ) 2754 { 2755 const MapMode aMap( maPrefMapMode ); 2756 const Size aPrefSize( maPrefSize ); 2757 2758 *this = aNewBmp; 2759 2760 maPrefMapMode = aMap; 2761 maPrefSize = aPrefSize; 2762 } 2763 } 2764 2765 return bRet; 2766 } 2767 2768 // ------------------------------------------------------------------------ 2769 2770 sal_Bool Bitmap::ImplDitherFloyd16() 2771 { 2772 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 2773 Bitmap aNewBmp( GetSizePixel(), 24 ); 2774 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 2775 sal_Bool bRet = sal_False; 2776 2777 if( pReadAcc && pWriteAcc ) 2778 { 2779 const long nWidth = pWriteAcc->Width(); 2780 const long nWidth1 = nWidth - 1L; 2781 const long nHeight = pWriteAcc->Height(); 2782 BitmapColor aColor; 2783 BitmapColor aBestCol; 2784 ImpErrorQuad aErrQuad; 2785 ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ]; 2786 ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ]; 2787 ImpErrorQuad* pQLine1 = pErrQuad1; 2788 ImpErrorQuad* pQLine2 = 0; 2789 long nX, nY; 2790 long nYTmp = 0L; 2791 sal_Bool bQ1 = sal_True; 2792 2793 for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ ) 2794 for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ ) 2795 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX ); 2796 2797 for( nY = 0L; nY < nHeight; nY++, nYTmp++ ) 2798 { 2799 // erstes ZeilenPixel 2800 aBestCol = pQLine1[ 0 ].ImplGetColor(); 2801 aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 ); 2802 aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 ); 2803 aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 ); 2804 pWriteAcc->SetPixel( nY, 0, aBestCol ); 2805 2806 for( nX = 1L; nX < nWidth1; nX++ ) 2807 { 2808 aColor = pQLine1[ nX ].ImplGetColor(); 2809 aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 ); 2810 aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 ); 2811 aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 ); 2812 aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol ); 2813 pQLine1[ ++nX ].ImplAddColorError7( aErrQuad ); 2814 pQLine2[ nX-- ].ImplAddColorError1( aErrQuad ); 2815 pQLine2[ nX-- ].ImplAddColorError5( aErrQuad ); 2816 pQLine2[ nX++ ].ImplAddColorError3( aErrQuad ); 2817 pWriteAcc->SetPixel( nY, nX, aBestCol ); 2818 } 2819 2820 // letztes ZeilenPixel 2821 aBestCol = pQLine1[ nWidth1 ].ImplGetColor(); 2822 aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 ); 2823 aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 ); 2824 aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 ); 2825 pWriteAcc->SetPixel( nY, nX, aBestCol ); 2826 2827 // Zeilenpuffer neu fuellen/kopieren 2828 pQLine1 = pQLine2; 2829 pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1; 2830 2831 if( nYTmp < nHeight ) 2832 for( nX = 0L; nX < nWidth; nX++ ) 2833 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX ); 2834 } 2835 2836 // Zeilenpuffer zerstoeren 2837 delete[] pErrQuad1; 2838 delete[] pErrQuad2; 2839 bRet = sal_True; 2840 } 2841 2842 ReleaseAccess( pReadAcc ); 2843 aNewBmp.ReleaseAccess( pWriteAcc ); 2844 2845 if( bRet ) 2846 { 2847 const MapMode aMap( maPrefMapMode ); 2848 const Size aSize( maPrefSize ); 2849 2850 *this = aNewBmp; 2851 2852 maPrefMapMode = aMap; 2853 maPrefSize = aSize; 2854 } 2855 2856 return bRet; 2857 } 2858 2859 // ------------------------------------------------------------------------ 2860 2861 sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce ) 2862 { 2863 sal_Bool bRet; 2864 2865 if( GetColorCount() <= (sal_uLong) nColorCount ) 2866 bRet = sal_True; 2867 else if( nColorCount ) 2868 { 2869 if( BMP_REDUCE_SIMPLE == eReduce ) 2870 bRet = ImplReduceSimple( nColorCount ); 2871 else if( BMP_REDUCE_POPULAR == eReduce ) 2872 bRet = ImplReducePopular( nColorCount ); 2873 else 2874 bRet = ImplReduceMedian( nColorCount ); 2875 } 2876 else 2877 bRet = sal_False; 2878 2879 return bRet; 2880 } 2881 2882 // ------------------------------------------------------------------------ 2883 2884 sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount ) 2885 { 2886 Bitmap aNewBmp; 2887 BitmapReadAccess* pRAcc = AcquireReadAccess(); 2888 const sal_uInt16 nColCount = Min( nColorCount, (sal_uInt16) 256 ); 2889 sal_uInt16 nBitCount; 2890 sal_Bool bRet = sal_False; 2891 2892 if( nColCount <= 2 ) 2893 nBitCount = 1; 2894 else if( nColCount <= 16 ) 2895 nBitCount = 4; 2896 else 2897 nBitCount = 8; 2898 2899 if( pRAcc ) 2900 { 2901 Octree aOct( *pRAcc, nColCount ); 2902 const BitmapPalette& rPal = aOct.GetPalette(); 2903 BitmapWriteAccess* pWAcc; 2904 2905 aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal ); 2906 pWAcc = aNewBmp.AcquireWriteAccess(); 2907 2908 if( pWAcc ) 2909 { 2910 const long nWidth = pRAcc->Width(); 2911 const long nHeight = pRAcc->Height(); 2912 2913 if( pRAcc->HasPalette() ) 2914 { 2915 for( long nY = 0L; nY < nHeight; nY++ ) 2916 for( long nX =0L; nX < nWidth; nX++ ) 2917 pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) ); 2918 } 2919 else 2920 { 2921 for( long nY = 0L; nY < nHeight; nY++ ) 2922 for( long nX =0L; nX < nWidth; nX++ ) 2923 pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) ); 2924 } 2925 2926 aNewBmp.ReleaseAccess( pWAcc ); 2927 bRet = sal_True; 2928 } 2929 2930 ReleaseAccess( pRAcc ); 2931 } 2932 2933 if( bRet ) 2934 { 2935 const MapMode aMap( maPrefMapMode ); 2936 const Size aSize( maPrefSize ); 2937 2938 *this = aNewBmp; 2939 maPrefMapMode = aMap; 2940 maPrefSize = aSize; 2941 } 2942 2943 return bRet; 2944 } 2945 2946 // ------------------------------------------------------------------------ 2947 2948 struct PopularColorCount 2949 { 2950 sal_uInt32 mnIndex; 2951 sal_uInt32 mnCount; 2952 }; 2953 2954 // ------------------------------------------------------------------------ 2955 2956 extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 ) 2957 { 2958 int nRet; 2959 2960 if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount ) 2961 nRet = 1; 2962 else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount ) 2963 nRet = 0; 2964 else 2965 nRet = -1; 2966 2967 return nRet; 2968 } 2969 2970 // ------------------------------------------------------------------------ 2971 2972 sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount ) 2973 { 2974 BitmapReadAccess* pRAcc = AcquireReadAccess(); 2975 sal_uInt16 nBitCount; 2976 sal_Bool bRet = sal_False; 2977 2978 if( nColCount > 256 ) 2979 nColCount = 256; 2980 2981 if( nColCount < 17 ) 2982 nBitCount = 4; 2983 else 2984 nBitCount = 8; 2985 2986 if( pRAcc ) 2987 { 2988 const sal_uInt32 nValidBits = 4; 2989 const sal_uInt32 nRightShiftBits = 8 - nValidBits; 2990 const sal_uInt32 nLeftShiftBits1 = nValidBits; 2991 const sal_uInt32 nLeftShiftBits2 = nValidBits << 1; 2992 const sal_uInt32 nColorsPerComponent = 1 << nValidBits; 2993 const sal_uInt32 nColorOffset = 256 / nColorsPerComponent; 2994 const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent; 2995 const long nWidth = pRAcc->Width(); 2996 const long nHeight = pRAcc->Height(); 2997 PopularColorCount* pCountTable = new PopularColorCount[ nTotalColors ]; 2998 long nX, nY, nR, nG, nB, nIndex; 2999 3000 rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) ); 3001 3002 for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset ) 3003 { 3004 for( nG = 0; nG < 256; nG += nColorOffset ) 3005 { 3006 for( nB = 0; nB < 256; nB += nColorOffset ) 3007 { 3008 pCountTable[ nIndex ].mnIndex = nIndex; 3009 nIndex++; 3010 } 3011 } 3012 } 3013 3014 if( pRAcc->HasPalette() ) 3015 { 3016 for( nY = 0L; nY < nHeight; nY++ ) 3017 { 3018 for( nX = 0L; nX < nWidth; nX++ ) 3019 { 3020 const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ); 3021 pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3022 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3023 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++; 3024 } 3025 } 3026 } 3027 else 3028 { 3029 for( nY = 0L; nY < nHeight; nY++ ) 3030 { 3031 for( nX = 0L; nX < nWidth; nX++ ) 3032 { 3033 const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) ); 3034 pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3035 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3036 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++; 3037 } 3038 } 3039 } 3040 3041 BitmapPalette aNewPal( nColCount ); 3042 3043 qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc ); 3044 3045 for( sal_uInt16 n = 0; n < nColCount; n++ ) 3046 { 3047 const PopularColorCount& rPop = pCountTable[ n ]; 3048 aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ), 3049 (sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ), 3050 (sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) ); 3051 } 3052 3053 Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal ); 3054 BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess(); 3055 3056 if( pWAcc ) 3057 { 3058 BitmapColor aDstCol( (sal_uInt8) 0 ); 3059 sal_uInt8* pIndexMap = new sal_uInt8[ nTotalColors ]; 3060 3061 for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset ) 3062 for( nG = 0; nG < 256; nG += nColorOffset ) 3063 for( nB = 0; nB < 256; nB += nColorOffset ) 3064 pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) ); 3065 3066 if( pRAcc->HasPalette() ) 3067 { 3068 for( nY = 0L; nY < nHeight; nY++ ) 3069 { 3070 for( nX = 0L; nX < nWidth; nX++ ) 3071 { 3072 const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ); 3073 aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3074 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3075 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] ); 3076 pWAcc->SetPixel( nY, nX, aDstCol ); 3077 } 3078 } 3079 } 3080 else 3081 { 3082 for( nY = 0L; nY < nHeight; nY++ ) 3083 { 3084 for( nX = 0L; nX < nWidth; nX++ ) 3085 { 3086 const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) ); 3087 aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3088 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3089 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] ); 3090 pWAcc->SetPixel( nY, nX, aDstCol ); 3091 } 3092 } 3093 } 3094 3095 delete[] pIndexMap; 3096 aNewBmp.ReleaseAccess( pWAcc ); 3097 bRet = sal_True; 3098 } 3099 3100 delete[] pCountTable; 3101 ReleaseAccess( pRAcc ); 3102 3103 if( bRet ) 3104 { 3105 const MapMode aMap( maPrefMapMode ); 3106 const Size aSize( maPrefSize ); 3107 3108 *this = aNewBmp; 3109 maPrefMapMode = aMap; 3110 maPrefSize = aSize; 3111 } 3112 } 3113 3114 return bRet; 3115 } 3116 3117 // ------------------------------------------------------------------------ 3118 3119 sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount ) 3120 { 3121 BitmapReadAccess* pRAcc = AcquireReadAccess(); 3122 sal_uInt16 nBitCount; 3123 sal_Bool bRet = sal_False; 3124 3125 if( nColCount < 17 ) 3126 nBitCount = 4; 3127 else if( nColCount < 257 ) 3128 nBitCount = 8; 3129 else 3130 { 3131 DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" ); 3132 nBitCount = 8; 3133 nColCount = 256; 3134 } 3135 3136 if( pRAcc ) 3137 { 3138 Bitmap aNewBmp( GetSizePixel(), nBitCount ); 3139 BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess(); 3140 3141 if( pWAcc ) 3142 { 3143 const sal_uLong nSize = 32768UL * sizeof( sal_uLong ); 3144 sal_uLong* pColBuf = (sal_uLong*) rtl_allocateMemory( nSize ); 3145 const long nWidth = pWAcc->Width(); 3146 const long nHeight = pWAcc->Height(); 3147 long nIndex = 0L; 3148 3149 memset( (HPBYTE) pColBuf, 0, nSize ); 3150 3151 // create Buffer 3152 if( pRAcc->HasPalette() ) 3153 { 3154 for( long nY = 0L; nY < nHeight; nY++ ) 3155 { 3156 for( long nX = 0L; nX < nWidth; nX++ ) 3157 { 3158 const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ); 3159 pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++; 3160 } 3161 } 3162 } 3163 else 3164 { 3165 for( long nY = 0L; nY < nHeight; nY++ ) 3166 { 3167 for( long nX = 0L; nX < nWidth; nX++ ) 3168 { 3169 const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) ); 3170 pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++; 3171 } 3172 } 3173 } 3174 3175 // create palette via median cut 3176 BitmapPalette aPal( pWAcc->GetPaletteEntryCount() ); 3177 ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31, 3178 nColCount, nWidth * nHeight, nIndex ); 3179 3180 // do mapping of colors to palette 3181 InverseColorMap aMap( aPal ); 3182 pWAcc->SetPalette( aPal ); 3183 for( long nY = 0L; nY < nHeight; nY++ ) 3184 for( long nX = 0L; nX < nWidth; nX++ ) 3185 pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) ); 3186 3187 rtl_freeMemory( pColBuf ); 3188 aNewBmp.ReleaseAccess( pWAcc ); 3189 bRet = sal_True; 3190 } 3191 3192 ReleaseAccess( pRAcc ); 3193 3194 if( bRet ) 3195 { 3196 const MapMode aMap( maPrefMapMode ); 3197 const Size aSize( maPrefSize ); 3198 3199 *this = aNewBmp; 3200 maPrefMapMode = aMap; 3201 maPrefSize = aSize; 3202 } 3203 } 3204 3205 return bRet; 3206 } 3207 3208 // ------------------------------------------------------------------------ 3209 3210 void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal, 3211 long nR1, long nR2, long nG1, long nG2, long nB1, long nB2, 3212 long nColors, long nPixels, long& rIndex ) 3213 { 3214 if( !nPixels ) 3215 return; 3216 3217 BitmapColor aCol; 3218 const long nRLen = nR2 - nR1; 3219 const long nGLen = nG2 - nG1; 3220 const long nBLen = nB2 - nB1; 3221 long nR, nG, nB; 3222 sal_uLong* pBuf = pColBuf; 3223 3224 if( !nRLen && !nGLen && !nBLen ) 3225 { 3226 if( pBuf[ RGB15( nR1, nG1, nB1 ) ] ) 3227 { 3228 aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) ); 3229 aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) ); 3230 aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) ); 3231 rPal[ (sal_uInt16) rIndex++ ] = aCol; 3232 } 3233 } 3234 else 3235 { 3236 if( 1 == nColors || 1 == nPixels ) 3237 { 3238 long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0; 3239 3240 for( nR = nR1; nR <= nR2; nR++ ) 3241 { 3242 for( nG = nG1; nG <= nG2; nG++ ) 3243 { 3244 for( nB = nB1; nB <= nB2; nB++ ) 3245 { 3246 nPixSum = pBuf[ RGB15( nR, nG, nB ) ]; 3247 3248 if( nPixSum ) 3249 { 3250 nRSum += nR * nPixSum; 3251 nGSum += nG * nPixSum; 3252 nBSum += nB * nPixSum; 3253 } 3254 } 3255 } 3256 } 3257 3258 aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) ); 3259 aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) ); 3260 aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) ); 3261 rPal[ (sal_uInt16) rIndex++ ] = aCol; 3262 } 3263 else 3264 { 3265 const long nTest = ( nPixels >> 1 ); 3266 long nPixOld = 0; 3267 long nPixNew = 0; 3268 3269 if( nBLen > nGLen && nBLen > nRLen ) 3270 { 3271 nB = nB1 - 1; 3272 3273 while( nPixNew < nTest ) 3274 { 3275 nB++, nPixOld = nPixNew; 3276 for( nR = nR1; nR <= nR2; nR++ ) 3277 for( nG = nG1; nG <= nG2; nG++ ) 3278 nPixNew += pBuf[ RGB15( nR, nG, nB ) ]; 3279 } 3280 3281 if( nB < nB2 ) 3282 { 3283 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex ); 3284 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex ); 3285 } 3286 else 3287 { 3288 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex ); 3289 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex ); 3290 } 3291 } 3292 else if( nGLen > nRLen ) 3293 { 3294 nG = nG1 - 1; 3295 3296 while( nPixNew < nTest ) 3297 { 3298 nG++, nPixOld = nPixNew; 3299 for( nR = nR1; nR <= nR2; nR++ ) 3300 for( nB = nB1; nB <= nB2; nB++ ) 3301 nPixNew += pBuf[ RGB15( nR, nG, nB ) ]; 3302 } 3303 3304 if( nG < nG2 ) 3305 { 3306 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex ); 3307 ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex ); 3308 } 3309 else 3310 { 3311 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex ); 3312 ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex ); 3313 } 3314 } 3315 else 3316 { 3317 nR = nR1 - 1; 3318 3319 while( nPixNew < nTest ) 3320 { 3321 nR++, nPixOld = nPixNew; 3322 for( nG = nG1; nG <= nG2; nG++ ) 3323 for( nB = nB1; nB <= nB2; nB++ ) 3324 nPixNew += pBuf[ RGB15( nR, nG, nB ) ]; 3325 } 3326 3327 if( nR < nR2 ) 3328 { 3329 ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex ); 3330 ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex ); 3331 } 3332 else 3333 { 3334 ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex ); 3335 ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex ); 3336 } 3337 } 3338 } 3339 } 3340 } 3341 3342 // ------------------------------------------------------------------------ 3343 3344 sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress ) 3345 { 3346 return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress ); 3347 } 3348 3349 // ------------------------------------------------------------------------ 3350 3351 sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress ) 3352 { 3353 return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress ); 3354 } 3355 3356 // ------------------------------------------------------------------------ 3357 3358 sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent, 3359 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, 3360 double fGamma, sal_Bool bInvert ) 3361 { 3362 sal_Bool bRet = sal_False; 3363 3364 // nothing to do => return quickly 3365 if( !nLuminancePercent && !nContrastPercent && 3366 !nChannelRPercent && !nChannelGPercent && !nChannelBPercent && 3367 ( fGamma == 1.0 ) && !bInvert ) 3368 { 3369 bRet = sal_True; 3370 } 3371 else 3372 { 3373 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 3374 3375 if( pAcc ) 3376 { 3377 BitmapColor aCol; 3378 const long nW = pAcc->Width(); 3379 const long nH = pAcc->Height(); 3380 sal_uInt8* cMapR = new sal_uInt8[ 256 ]; 3381 sal_uInt8* cMapG = new sal_uInt8[ 256 ]; 3382 sal_uInt8* cMapB = new sal_uInt8[ 256 ]; 3383 long nX, nY; 3384 double fM, fROff, fGOff, fBOff, fOff; 3385 3386 // calculate slope 3387 if( nContrastPercent >= 0 ) 3388 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) ); 3389 else 3390 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0; 3391 3392 // total offset = luminance offset + contrast offset 3393 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; 3394 3395 // channel offset = channel offset + total offset 3396 fROff = nChannelRPercent * 2.55 + fOff; 3397 fGOff = nChannelGPercent * 2.55 + fOff; 3398 fBOff = nChannelBPercent * 2.55 + fOff; 3399 3400 // calculate gamma value 3401 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma ); 3402 const sal_Bool bGamma = ( fGamma != 1.0 ); 3403 3404 // create mapping table 3405 for( nX = 0L; nX < 256L; nX++ ) 3406 { 3407 cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); 3408 cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); 3409 cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); 3410 3411 if( bGamma ) 3412 { 3413 cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma ); 3414 cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma ); 3415 cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma ); 3416 } 3417 3418 if( bInvert ) 3419 { 3420 cMapR[ nX ] = ~cMapR[ nX ]; 3421 cMapG[ nX ] = ~cMapG[ nX ]; 3422 cMapB[ nX ] = ~cMapB[ nX ]; 3423 } 3424 } 3425 3426 // do modifying 3427 if( pAcc->HasPalette() ) 3428 { 3429 BitmapColor aNewCol; 3430 3431 for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ ) 3432 { 3433 const BitmapColor& rCol = pAcc->GetPaletteColor( i ); 3434 aNewCol.SetRed( cMapR[ rCol.GetRed() ] ); 3435 aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] ); 3436 aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] ); 3437 pAcc->SetPaletteColor( i, aNewCol ); 3438 } 3439 } 3440 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 3441 { 3442 for( nY = 0L; nY < nH; nY++ ) 3443 { 3444 Scanline pScan = pAcc->GetScanline( nY ); 3445 3446 for( nX = 0L; nX < nW; nX++ ) 3447 { 3448 *pScan = cMapB[ *pScan ]; pScan++; 3449 *pScan = cMapG[ *pScan ]; pScan++; 3450 *pScan = cMapR[ *pScan ]; pScan++; 3451 } 3452 } 3453 } 3454 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ) 3455 { 3456 for( nY = 0L; nY < nH; nY++ ) 3457 { 3458 Scanline pScan = pAcc->GetScanline( nY ); 3459 3460 for( nX = 0L; nX < nW; nX++ ) 3461 { 3462 *pScan = cMapR[ *pScan ]; pScan++; 3463 *pScan = cMapG[ *pScan ]; pScan++; 3464 *pScan = cMapB[ *pScan ]; pScan++; 3465 } 3466 } 3467 } 3468 else 3469 { 3470 for( nY = 0L; nY < nH; nY++ ) 3471 { 3472 for( nX = 0L; nX < nW; nX++ ) 3473 { 3474 aCol = pAcc->GetPixel( nY, nX ); 3475 aCol.SetRed( cMapR[ aCol.GetRed() ] ); 3476 aCol.SetGreen( cMapG[ aCol.GetGreen() ] ); 3477 aCol.SetBlue( cMapB[ aCol.GetBlue() ] ); 3478 pAcc->SetPixel( nY, nX, aCol ); 3479 } 3480 } 3481 } 3482 3483 delete[] cMapR; 3484 delete[] cMapG; 3485 delete[] cMapB; 3486 ReleaseAccess( pAcc ); 3487 bRet = sal_True; 3488 } 3489 } 3490 3491 return bRet; 3492 } 3493