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_uLong nScaleFlag ) 908 { 909 #ifdef DBG_UTIL 910 // #121233# allow to test the different scalers in debug build with source 911 // level debugger (change nNumber to desired action) 912 static sal_uInt16 nNumber(0); 913 914 switch(nNumber) 915 { 916 case 0 : break; 917 case 1: nScaleFlag = BMP_SCALE_FAST; break; 918 case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break; 919 case 3: nScaleFlag = BMP_SCALE_SUPER; break; 920 case 4: nScaleFlag = BMP_SCALE_LANCZOS; break; 921 case 5: nScaleFlag = BMP_SCALE_BICUBIC; break; 922 case 6: nScaleFlag = BMP_SCALE_BILINEAR; break; 923 case 7: nScaleFlag = BMP_SCALE_BOX; break; 924 case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break; 925 case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break; 926 } 927 #endif // DBG_UTIL 928 929 if(basegfx::fTools::equalZero(rScaleX) && basegfx::fTools::equalZero(rScaleY)) 930 { 931 // no scale 932 return true; 933 } 934 else 935 { 936 if(BMP_SCALE_BESTQUALITY == nScaleFlag) 937 { 938 // Use LANCZOS when best quality is requested 939 nScaleFlag = BMP_SCALE_LANCZOS; 940 } 941 else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag) 942 { 943 // Use BMP_SCALE_SUPER when speed is requested, but not worst quality 944 nScaleFlag = BMP_SCALE_SUPER; 945 } 946 947 switch(nScaleFlag) 948 { 949 default: 950 case BMP_SCALE_NONE : 951 { 952 return false; 953 break; 954 } 955 case BMP_SCALE_FAST : 956 { 957 return ImplScaleFast( rScaleX, rScaleY ); 958 break; 959 } 960 case BMP_SCALE_INTERPOLATE : 961 { 962 return ImplScaleInterpolate( rScaleX, rScaleY ); 963 break; 964 } 965 case BMP_SCALE_SUPER : 966 { 967 if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2) 968 { 969 // fallback to ImplScaleFast 970 return ImplScaleFast( rScaleX, rScaleY ); 971 } 972 else 973 { 974 // #121233# use method from symphony 975 return ImplScaleSuper( rScaleX, rScaleY ); 976 } 977 break; 978 } 979 case BMP_SCALE_LANCZOS : 980 { 981 const Lanczos3Kernel kernel; 982 983 return ImplScaleConvolution( rScaleX, rScaleY, kernel); 984 break; 985 } 986 case BMP_SCALE_BICUBIC : 987 { 988 const BicubicKernel kernel; 989 990 return ImplScaleConvolution( rScaleX, rScaleY, kernel ); 991 break; 992 } 993 case BMP_SCALE_BILINEAR : 994 { 995 const BilinearKernel kernel; 996 997 return ImplScaleConvolution( rScaleX, rScaleY, kernel ); 998 break; 999 } 1000 case BMP_SCALE_BOX : 1001 { 1002 const BoxKernel kernel; 1003 1004 return ImplScaleConvolution( rScaleX, rScaleY, kernel ); 1005 break; 1006 } 1007 } 1008 } 1009 1010 // should not happen 1011 return false; 1012 } 1013 1014 // ------------------------------------------------------------------------ 1015 1016 sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag ) 1017 { 1018 const Size aSize( GetSizePixel() ); 1019 sal_Bool bRet; 1020 1021 if( aSize.Width() && aSize.Height() ) 1022 { 1023 bRet = Scale( (double) rNewSize.Width() / aSize.Width(), 1024 (double) rNewSize.Height() / aSize.Height(), 1025 nScaleFlag ); 1026 } 1027 else 1028 bRet = sal_True; 1029 1030 return bRet; 1031 } 1032 1033 // ------------------------------------------------------------------------ 1034 1035 void Bitmap::AdaptBitCount(Bitmap& rNew) const 1036 { 1037 ImplAdaptBitCount(rNew); 1038 } 1039 1040 // ------------------------------------------------------------------------ 1041 1042 void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const 1043 { 1044 // aNew is the result of some operation; adapt it's BitCount to the original (this) 1045 if(GetBitCount() != rNew.GetBitCount()) 1046 { 1047 switch(GetBitCount()) 1048 { 1049 case 1: 1050 { 1051 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD); 1052 break; 1053 } 1054 case 4: 1055 { 1056 if(HasGreyPalette()) 1057 { 1058 rNew.Convert(BMP_CONVERSION_4BIT_GREYS); 1059 } 1060 else 1061 { 1062 rNew.Convert(BMP_CONVERSION_4BIT_COLORS); 1063 } 1064 break; 1065 } 1066 case 8: 1067 { 1068 if(HasGreyPalette()) 1069 { 1070 rNew.Convert(BMP_CONVERSION_8BIT_GREYS); 1071 } 1072 else 1073 { 1074 rNew.Convert(BMP_CONVERSION_8BIT_COLORS); 1075 } 1076 break; 1077 } 1078 case 24: 1079 { 1080 rNew.Convert(BMP_CONVERSION_24BIT); 1081 break; 1082 } 1083 default: 1084 { 1085 OSL_ENSURE(false, "BitDepth adaption failed (!)"); 1086 break; 1087 } 1088 } 1089 } 1090 } 1091 1092 // ------------------------------------------------------------------------ 1093 1094 sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY ) 1095 { 1096 const Size aSizePix( GetSizePixel() ); 1097 const long nNewWidth = FRound( aSizePix.Width() * rScaleX ); 1098 const long nNewHeight = FRound( aSizePix.Height() * rScaleY ); 1099 sal_Bool bRet = sal_False; 1100 1101 if( nNewWidth && nNewHeight ) 1102 { 1103 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 1104 if ( !pReadAcc ) 1105 return sal_False; 1106 1107 Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() ); 1108 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 1109 1110 if( pWriteAcc ) 1111 { 1112 const long nScanlineSize = pWriteAcc->GetScanlineSize(); 1113 const long nNewWidth1 = nNewWidth - 1L; 1114 const long nNewHeight1 = nNewHeight - 1L; 1115 const long nWidth = pReadAcc->Width(); 1116 const long nHeight = pReadAcc->Height(); 1117 long* pLutX = new long[ nNewWidth ]; 1118 long* pLutY = new long[ nNewHeight ]; 1119 long nX, nY, nMapY, nActY = 0L; 1120 1121 if( nNewWidth1 && nNewHeight1 ) 1122 { 1123 for( nX = 0L; nX < nNewWidth; nX++ ) 1124 pLutX[ nX ] = nX * nWidth / nNewWidth; 1125 1126 for( nY = 0L; nY < nNewHeight; nY++ ) 1127 pLutY[ nY ] = nY * nHeight / nNewHeight; 1128 1129 while( nActY < nNewHeight ) 1130 { 1131 nMapY = pLutY[ nActY ]; 1132 1133 for( nX = 0L; nX < nNewWidth; nX++ ) 1134 pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) ); 1135 1136 while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) ) 1137 { 1138 memcpy( pWriteAcc->GetScanline( nActY + 1L ), 1139 pWriteAcc->GetScanline( nActY ), nScanlineSize ); 1140 nActY++; 1141 } 1142 1143 nActY++; 1144 } 1145 1146 bRet = sal_True; 1147 } 1148 1149 delete[] pLutX; 1150 delete[] pLutY; 1151 } 1152 1153 ReleaseAccess( pReadAcc ); 1154 aNewBmp.ReleaseAccess( pWriteAcc ); 1155 1156 if( bRet ) 1157 ImplAssignWithSize( aNewBmp ); 1158 } 1159 1160 return bRet; 1161 } 1162 1163 // ------------------------------------------------------------------------ 1164 1165 sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY ) 1166 { 1167 const Size aSizePix( GetSizePixel() ); 1168 const long nNewWidth = FRound( aSizePix.Width() * rScaleX ); 1169 const long nNewHeight = FRound( aSizePix.Height() * rScaleY ); 1170 sal_Bool bRet = sal_False; 1171 1172 if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) ) 1173 { 1174 BitmapColor aCol0; 1175 BitmapColor aCol1; 1176 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 1177 long nWidth = pReadAcc->Width(); 1178 long nHeight = pReadAcc->Height(); 1179 Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 ); 1180 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 1181 long* pLutInt; 1182 long* pLutFrac; 1183 long nX, nY; 1184 long lXB0, lXB1, lXG0, lXG1, lXR0, lXR1; 1185 double fTemp; 1186 long nTemp; 1187 1188 if( pReadAcc && pWriteAcc ) 1189 { 1190 const long nNewWidth1 = nNewWidth - 1L; 1191 const long nWidth1 = pReadAcc->Width() - 1L; 1192 const double fRevScaleX = (double) nWidth1 / nNewWidth1; 1193 1194 pLutInt = new long[ nNewWidth ]; 1195 pLutFrac = new long[ nNewWidth ]; 1196 1197 for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ ) 1198 { 1199 fTemp = nX * fRevScaleX; 1200 pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp ); 1201 fTemp -= pLutInt[ nX ]; 1202 pLutFrac[ nX ] = (long) ( fTemp * 1024. ); 1203 } 1204 1205 for( nY = 0L; nY < nHeight; nY++ ) 1206 { 1207 if( 1 == nWidth ) 1208 { 1209 if( pReadAcc->HasPalette() ) 1210 { 1211 aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) ); 1212 } 1213 else 1214 { 1215 aCol0 = pReadAcc->GetPixel( nY, 0 ); 1216 } 1217 1218 for( nX = 0L; nX < nNewWidth; nX++ ) 1219 { 1220 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1221 } 1222 } 1223 else 1224 { 1225 for( nX = 0L; nX < nNewWidth; nX++ ) 1226 { 1227 nTemp = pLutInt[ nX ]; 1228 1229 if( pReadAcc->HasPalette() ) 1230 { 1231 aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) ); 1232 aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) ); 1233 } 1234 else 1235 { 1236 aCol0 = pReadAcc->GetPixel( nY, nTemp++ ); 1237 aCol1 = pReadAcc->GetPixel( nY, nTemp ); 1238 } 1239 1240 nTemp = pLutFrac[ nX ]; 1241 1242 lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() ); 1243 lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() ); 1244 lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() ); 1245 1246 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) ); 1247 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) ); 1248 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) ); 1249 1250 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1251 } 1252 } 1253 } 1254 1255 delete[] pLutInt; 1256 delete[] pLutFrac; 1257 bRet = sal_True; 1258 } 1259 1260 ReleaseAccess( pReadAcc ); 1261 aNewBmp.ReleaseAccess( pWriteAcc ); 1262 1263 if( bRet ) 1264 { 1265 bRet = sal_False; 1266 const Bitmap aOriginal(*this); 1267 *this = aNewBmp; 1268 aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 ); 1269 pReadAcc = AcquireReadAccess(); 1270 pWriteAcc = aNewBmp.AcquireWriteAccess(); 1271 1272 if( pReadAcc && pWriteAcc ) 1273 { 1274 const long nNewHeight1 = nNewHeight - 1L; 1275 const long nHeight1 = pReadAcc->Height() - 1L; 1276 const double fRevScaleY = (double) nHeight1 / nNewHeight1; 1277 1278 pLutInt = new long[ nNewHeight ]; 1279 pLutFrac = new long[ nNewHeight ]; 1280 1281 for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ ) 1282 { 1283 fTemp = nY * fRevScaleY; 1284 pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp ); 1285 fTemp -= pLutInt[ nY ]; 1286 pLutFrac[ nY ] = (long) ( fTemp * 1024. ); 1287 } 1288 1289 // after 1st step, bitmap *is* 24bit format (see above) 1290 OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)"); 1291 1292 for( nX = 0L; nX < nNewWidth; nX++ ) 1293 { 1294 if( 1 == nHeight ) 1295 { 1296 aCol0 = pReadAcc->GetPixel( 0, nX ); 1297 1298 for( nY = 0L; nY < nNewHeight; nY++ ) 1299 { 1300 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1301 } 1302 } 1303 else 1304 { 1305 for( nY = 0L; nY < nNewHeight; nY++ ) 1306 { 1307 nTemp = pLutInt[ nY ]; 1308 1309 aCol0 = pReadAcc->GetPixel( nTemp++, nX ); 1310 aCol1 = pReadAcc->GetPixel( nTemp, nX ); 1311 1312 nTemp = pLutFrac[ nY ]; 1313 1314 lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() ); 1315 lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() ); 1316 lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() ); 1317 1318 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) ); 1319 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) ); 1320 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) ); 1321 1322 pWriteAcc->SetPixel( nY, nX, aCol0 ); 1323 } 1324 } 1325 } 1326 1327 delete[] pLutInt; 1328 delete[] pLutFrac; 1329 bRet = sal_True; 1330 } 1331 1332 ReleaseAccess( pReadAcc ); 1333 aNewBmp.ReleaseAccess( pWriteAcc ); 1334 1335 if( bRet ) 1336 { 1337 aOriginal.ImplAdaptBitCount(aNewBmp); 1338 *this = aNewBmp; 1339 } 1340 } 1341 } 1342 1343 if( !bRet ) 1344 { 1345 bRet = ImplScaleFast( rScaleX, rScaleY ); 1346 } 1347 1348 return bRet; 1349 } 1350 1351 // ------------------------------------------------------------------------ 1352 // #121233# Added BMP_SCALE_SUPER from symphony code 1353 1354 sal_Bool Bitmap::ImplScaleSuper( 1355 const double& rScaleX, 1356 const double& rScaleY ) 1357 { 1358 const Size aSizePix( GetSizePixel() ); 1359 bool bHMirr = ( rScaleX < 0 ); 1360 bool bVMirr = ( rScaleY < 0 ); 1361 double scaleX = bHMirr ? -rScaleX : rScaleX; 1362 double scaleY = bVMirr ? -rScaleY : rScaleY; 1363 const long nDstW = FRound( aSizePix.Width() * scaleX ); 1364 const long nDstH = FRound( aSizePix.Height() * scaleY ); 1365 const double fScaleThresh = 0.6; 1366 bool bRet = false; 1367 1368 if( ( nDstW > 1L ) && ( nDstH > 1L ) ) 1369 { 1370 BitmapColor aCol0, aCol1, aColRes; 1371 BitmapReadAccess* pAcc = AcquireReadAccess(); 1372 long nW = pAcc->Width() ; 1373 long nH = pAcc->Height() ; 1374 Bitmap aOutBmp( Size( nDstW, nDstH ), 24 ); 1375 BitmapWriteAccess* pWAcc = aOutBmp.AcquireWriteAccess(); 1376 long* pMapIX = new long[ nDstW ]; 1377 long* pMapIY = new long[ nDstH ]; 1378 long* pMapFX = new long[ nDstW ]; 1379 long* pMapFY = new long[ nDstH ]; 1380 long nX, nY, nXDst, nYDst;; 1381 double fTemp; 1382 long nTemp , nTempX, nTempY, nTempFX, nTempFY; 1383 sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1; 1384 long nStartX = 0 , nStartY = 0; 1385 long nEndX = nDstW - 1L; 1386 long nEndY = nDstH - 1L; 1387 long nMax = 1 << 7L; 1388 1389 if( pAcc && pWAcc ) 1390 { 1391 const double fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0; 1392 const double fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0; 1393 1394 // create horizontal mapping table 1395 for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ ) 1396 { 1397 fTemp = nX * fRevScaleX; 1398 1399 if( bHMirr ) 1400 fTemp = nTempX - fTemp; 1401 1402 pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. ); 1403 } 1404 1405 // create vertical mapping table 1406 for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ ) 1407 { 1408 fTemp = nY * fRevScaleY; 1409 1410 if( bVMirr ) 1411 fTemp = nTempY - fTemp; 1412 1413 pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. ); 1414 } 1415 1416 if( pAcc->HasPalette() ) 1417 { 1418 if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 1419 { 1420 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1421 { 1422 Scanline pLine0, pLine1; 1423 1424 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1425 { 1426 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 1427 pLine0 = pAcc->GetScanline( nTempY ); 1428 pLine1 = pAcc->GetScanline( ++nTempY ); 1429 1430 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1431 { 1432 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ]; 1433 1434 const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] ); 1435 const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] ); 1436 const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] ); 1437 const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] ); 1438 1439 cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX ); 1440 cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX ); 1441 cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX ); 1442 1443 cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX ); 1444 cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX ); 1445 cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX ); 1446 1447 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1448 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1449 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1450 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1451 } 1452 } 1453 } 1454 else 1455 { 1456 Scanline pTmpY; 1457 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1458 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1459 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1460 1461 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1462 { 1463 nTop = bVMirr ? ( nY + 1 ) : nY; 1464 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1465 1466 if( nY ==nEndY ) 1467 { 1468 nLineStart = pMapIY[ nY ]; 1469 nLineRange = 0; 1470 } 1471 else 1472 { 1473 nLineStart = pMapIY[ nTop ] ; 1474 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1475 } 1476 1477 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1478 { 1479 nLeft = bHMirr ? ( nX + 1 ) : nX; 1480 nRight = bHMirr ? nX : ( nX + 1 ) ; 1481 1482 if( nX == nEndX ) 1483 { 1484 nRowStart = pMapIX[ nX ]; 1485 nRowRange = 0; 1486 } 1487 else 1488 { 1489 nRowStart = pMapIX[ nLeft ]; 1490 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1491 } 1492 1493 nSumR = nSumG = nSumB = 0; 1494 nTotalWeightY = 0; 1495 1496 for(int i = 0; i<= nLineRange; i++) 1497 { 1498 pTmpY = pAcc->GetScanline( nLineStart + i ); 1499 nSumRowR = nSumRowG = nSumRowB = 0; 1500 nTotalWeightX = 0; 1501 1502 for(int j = 0; j <= nRowRange; j++) 1503 { 1504 const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] ); 1505 1506 if(nX == nEndX ) 1507 { 1508 nSumRowB += rCol.GetBlue() << 7L; 1509 nSumRowG += rCol.GetGreen() << 7L; 1510 nSumRowR += rCol.GetRed() << 7L; 1511 nTotalWeightX += 1 << 7L; 1512 } 1513 else if( j == 0 ) 1514 { 1515 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1516 nSumRowB += ( nWeightX *rCol.GetBlue()) ; 1517 nSumRowG += ( nWeightX *rCol.GetGreen()) ; 1518 nSumRowR += ( nWeightX *rCol.GetRed()) ; 1519 nTotalWeightX += nWeightX; 1520 } 1521 else if ( nRowRange == j ) 1522 { 1523 nWeightX = pMapFX[ nRight ] ; 1524 nSumRowB += ( nWeightX *rCol.GetBlue() ); 1525 nSumRowG += ( nWeightX *rCol.GetGreen() ); 1526 nSumRowR += ( nWeightX *rCol.GetRed() ); 1527 nTotalWeightX += nWeightX; 1528 } 1529 else 1530 { 1531 nSumRowB += rCol.GetBlue() << 7L; 1532 nSumRowG += rCol.GetGreen() << 7L; 1533 nSumRowR += rCol.GetRed() << 7L; 1534 nTotalWeightX += 1 << 7L; 1535 } 1536 } 1537 1538 if( nY == nEndY ) 1539 nWeightY = nMax; 1540 else if( i == 0 ) 1541 nWeightY = nMax - pMapFY[ nTop ]; 1542 else if( nLineRange == 1 ) 1543 nWeightY = pMapFY[ nTop ]; 1544 else if ( nLineRange == i ) 1545 nWeightY = pMapFY[ nBottom ]; 1546 else 1547 nWeightY = nMax; 1548 1549 nWeightY = nWeightY ; 1550 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1551 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1552 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1553 nTotalWeightY += nWeightY; 1554 } 1555 1556 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1557 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1558 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1559 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1560 1561 } 1562 } 1563 } 1564 } 1565 else 1566 { 1567 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1568 { 1569 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1570 { 1571 nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ]; 1572 1573 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1574 { 1575 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ]; 1576 1577 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) ); 1578 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) ); 1579 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 1580 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 1581 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 1582 1583 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) ); 1584 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) ); 1585 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 1586 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 1587 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 1588 1589 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1590 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1591 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1592 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1593 } 1594 } 1595 1596 } 1597 else 1598 { 1599 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1600 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1601 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1602 1603 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1604 { 1605 nTop = bVMirr ? ( nY + 1 ) : nY; 1606 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1607 1608 if( nY ==nEndY ) 1609 { 1610 nLineStart = pMapIY[ nY ]; 1611 nLineRange = 0; 1612 } 1613 else 1614 { 1615 nLineStart = pMapIY[ nTop ] ; 1616 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1617 } 1618 1619 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1620 { 1621 nLeft = bHMirr ? ( nX + 1 ) : nX; 1622 nRight = bHMirr ? nX : ( nX + 1 ) ; 1623 1624 if( nX == nEndX ) 1625 { 1626 nRowStart = pMapIX[ nX ]; 1627 nRowRange = 0; 1628 } 1629 else 1630 { 1631 nRowStart = pMapIX[ nLeft ]; 1632 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1633 } 1634 1635 nSumR = nSumG = nSumB = 0; 1636 nTotalWeightY = 0; 1637 1638 for(int i = 0; i<= nLineRange; i++) 1639 { 1640 nSumRowR = nSumRowG = nSumRowB = 0; 1641 nTotalWeightX = 0; 1642 1643 for(int j = 0; j <= nRowRange; j++) 1644 { 1645 aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) ); 1646 1647 if(nX == nEndX ) 1648 { 1649 1650 nSumRowB += aCol0.GetBlue() << 7L; 1651 nSumRowG += aCol0.GetGreen() << 7L; 1652 nSumRowR += aCol0.GetRed() << 7L; 1653 nTotalWeightX += 1 << 7L; 1654 } 1655 else if( j == 0 ) 1656 { 1657 1658 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1659 nSumRowB += ( nWeightX *aCol0.GetBlue()) ; 1660 nSumRowG += ( nWeightX *aCol0.GetGreen()) ; 1661 nSumRowR += ( nWeightX *aCol0.GetRed()) ; 1662 nTotalWeightX += nWeightX; 1663 } 1664 else if ( nRowRange == j ) 1665 { 1666 1667 nWeightX = pMapFX[ nRight ] ; 1668 nSumRowB += ( nWeightX *aCol0.GetBlue() ); 1669 nSumRowG += ( nWeightX *aCol0.GetGreen() ); 1670 nSumRowR += ( nWeightX *aCol0.GetRed() ); 1671 nTotalWeightX += nWeightX; 1672 } 1673 else 1674 { 1675 1676 nSumRowB += aCol0.GetBlue() << 7L; 1677 nSumRowG += aCol0.GetGreen() << 7L; 1678 nSumRowR += aCol0.GetRed() << 7L; 1679 nTotalWeightX += 1 << 7L; 1680 } 1681 } 1682 1683 if( nY == nEndY ) 1684 nWeightY = nMax; 1685 else if( i == 0 ) 1686 nWeightY = nMax - pMapFY[ nTop ]; 1687 else if( nLineRange == 1 ) 1688 nWeightY = pMapFY[ nTop ]; 1689 else if ( nLineRange == i ) 1690 nWeightY = pMapFY[ nBottom ]; 1691 else 1692 nWeightY = nMax; 1693 1694 nWeightY = nWeightY ; 1695 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1696 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1697 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1698 nTotalWeightY += nWeightY; 1699 } 1700 1701 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1702 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1703 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1704 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1705 } 1706 } 1707 } 1708 } 1709 } 1710 else 1711 { 1712 if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 1713 { 1714 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1715 { 1716 Scanline pLine0, pLine1, pTmp0, pTmp1; 1717 long nOff; 1718 1719 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1720 { 1721 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 1722 pLine0 = pAcc->GetScanline( nTempY ); 1723 pLine1 = pAcc->GetScanline( ++nTempY ); 1724 1725 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1726 { 1727 nOff = 3L * ( nTempX = pMapIX[ nX ] ); 1728 nTempFX = pMapFX[ nX ]; 1729 1730 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; 1731 cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1732 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1733 cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); 1734 1735 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; 1736 cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1737 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1738 cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); 1739 1740 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1741 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1742 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1743 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1744 } 1745 } 1746 } 1747 else 1748 { 1749 Scanline pTmpY, pTmpX; 1750 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1751 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1752 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1753 1754 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1755 { 1756 nTop = bVMirr ? ( nY + 1 ) : nY; 1757 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1758 1759 if( nY ==nEndY ) 1760 { 1761 nLineStart = pMapIY[ nY ]; 1762 nLineRange = 0; 1763 } 1764 else 1765 { 1766 nLineStart = pMapIY[ nTop ] ; 1767 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1768 } 1769 1770 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1771 { 1772 nLeft = bHMirr ? ( nX + 1 ) : nX; 1773 nRight = bHMirr ? nX : ( nX + 1 ) ; 1774 1775 if( nX == nEndX ) 1776 { 1777 nRowStart = pMapIX[ nX ]; 1778 nRowRange = 0; 1779 } 1780 else 1781 { 1782 nRowStart = pMapIX[ nLeft ]; 1783 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1784 } 1785 1786 nSumR = nSumG = nSumB = 0; 1787 nTotalWeightY = 0; 1788 1789 for(int i = 0; i<= nLineRange; i++) 1790 { 1791 pTmpY = pAcc->GetScanline( nLineStart + i ); 1792 pTmpX = pTmpY + 3L * nRowStart; 1793 nSumRowR = nSumRowG = nSumRowB = 0; 1794 nTotalWeightX = 0; 1795 1796 for(int j = 0; j <= nRowRange; j++) 1797 { 1798 if(nX == nEndX ) 1799 { 1800 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1801 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1802 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1803 nTotalWeightX += 1 << 7L; 1804 } 1805 else if( j == 0 ) 1806 { 1807 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1808 nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++; 1809 nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++; 1810 nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++; 1811 nTotalWeightX += nWeightX; 1812 } 1813 else if ( nRowRange == j ) 1814 { 1815 nWeightX = pMapFX[ nRight ] ; 1816 nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++; 1817 nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++; 1818 nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++; 1819 nTotalWeightX += nWeightX; 1820 } 1821 else 1822 { 1823 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1824 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1825 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1826 nTotalWeightX += 1 << 7L; 1827 } 1828 } 1829 1830 if( nY == nEndY ) 1831 nWeightY = nMax; 1832 else if( i == 0 ) 1833 nWeightY = nMax - pMapFY[ nTop ]; 1834 else if( nLineRange == 1 ) 1835 nWeightY = pMapFY[ nTop ]; 1836 else if ( nLineRange == i ) 1837 nWeightY = pMapFY[ nBottom ]; 1838 else 1839 nWeightY = nMax; 1840 1841 nWeightY = nWeightY ; 1842 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1843 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1844 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1845 nTotalWeightY += nWeightY; 1846 } 1847 1848 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1849 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1850 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1851 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1852 1853 } 1854 } 1855 } 1856 } 1857 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ) 1858 { 1859 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 1860 { 1861 Scanline pLine0, pLine1, pTmp0, pTmp1; 1862 long nOff; 1863 1864 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1865 { 1866 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 1867 pLine0 = pAcc->GetScanline( nTempY ); 1868 pLine1 = pAcc->GetScanline( ++nTempY ); 1869 1870 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 1871 { 1872 nOff = 3L * ( nTempX = pMapIX[ nX ] ); 1873 nTempFX = pMapFX[ nX ]; 1874 1875 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L; 1876 cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1877 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1878 cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); 1879 1880 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L; 1881 cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1882 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++; 1883 cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); 1884 1885 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 1886 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 1887 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 1888 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1889 } 1890 } 1891 } 1892 else 1893 { 1894 Scanline pTmpY, pTmpX; 1895 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 1896 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 1897 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 1898 1899 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 1900 { 1901 nTop = bVMirr ? ( nY + 1 ) : nY; 1902 nBottom = bVMirr ? nY : ( nY + 1 ) ; 1903 1904 if( nY ==nEndY ) 1905 { 1906 nLineStart = pMapIY[ nY ]; 1907 nLineRange = 0; 1908 } 1909 else 1910 { 1911 nLineStart = pMapIY[ nTop ] ; 1912 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 1913 } 1914 1915 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 1916 { 1917 nLeft = bHMirr ? ( nX + 1 ) : nX; 1918 nRight = bHMirr ? nX : ( nX + 1 ) ; 1919 1920 if( nX == nEndX ) 1921 { 1922 nRowStart = pMapIX[ nX ]; 1923 nRowRange = 0; 1924 } 1925 else 1926 { 1927 nRowStart = pMapIX[ nLeft ]; 1928 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 1929 } 1930 1931 nSumR = nSumG = nSumB = 0; 1932 nTotalWeightY = 0; 1933 1934 for(int i = 0; i<= nLineRange; i++) 1935 { 1936 pTmpY = pAcc->GetScanline( nLineStart + i ); 1937 pTmpX = pTmpY + 3L * nRowStart; 1938 nSumRowR = nSumRowG = nSumRowB = 0; 1939 nTotalWeightX = 0; 1940 1941 for(int j = 0; j <= nRowRange; j++) 1942 { 1943 if(nX == nEndX ) 1944 { 1945 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1946 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1947 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1948 nTotalWeightX += 1 << 7L; 1949 } 1950 else if( j == 0 ) 1951 { 1952 nWeightX = (nMax- pMapFX[ nLeft ]) ; 1953 nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++; 1954 nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++; 1955 nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++; 1956 nTotalWeightX += nWeightX; 1957 } 1958 else if ( nRowRange == j ) 1959 { 1960 nWeightX = pMapFX[ nRight ] ; 1961 nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++; 1962 nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++; 1963 nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++; 1964 nTotalWeightX += nWeightX; 1965 } 1966 else 1967 { 1968 nSumRowR += ( *pTmpX ) << 7L;pTmpX++; 1969 nSumRowG += ( *pTmpX ) << 7L;pTmpX++; 1970 nSumRowB += ( *pTmpX ) << 7L;pTmpX++; 1971 nTotalWeightX += 1 << 7L; 1972 } 1973 } 1974 1975 if( nY == nEndY ) 1976 nWeightY = nMax; 1977 else if( i == 0 ) 1978 nWeightY = nMax - pMapFY[ nTop ]; 1979 else if( nLineRange == 1 ) 1980 nWeightY = pMapFY[ nTop ]; 1981 else if ( nLineRange == i ) 1982 nWeightY = pMapFY[ nBottom ]; 1983 else 1984 nWeightY = nMax; 1985 1986 nWeightY = nWeightY ; 1987 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 1988 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 1989 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 1990 nTotalWeightY += nWeightY; 1991 } 1992 1993 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 1994 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 1995 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 1996 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 1997 1998 } 1999 } 2000 } 2001 } 2002 else 2003 { 2004 if( scaleX >= fScaleThresh && scaleY >= fScaleThresh ) 2005 { 2006 for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 2007 { 2008 nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ]; 2009 2010 for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ ) 2011 { 2012 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ]; 2013 2014 aCol0 = pAcc->GetPixel( nTempY, nTempX ); 2015 aCol1 = pAcc->GetPixel( nTempY, ++nTempX ); 2016 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 2017 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 2018 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 2019 2020 aCol1 = pAcc->GetPixel( ++nTempY, nTempX ); 2021 aCol0 = pAcc->GetPixel( nTempY--, --nTempX ); 2022 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX ); 2023 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX ); 2024 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX ); 2025 2026 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) ); 2027 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) ); 2028 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) ); 2029 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 2030 } 2031 } 2032 } 2033 else 2034 { 2035 long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ; 2036 long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ; 2037 long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY; 2038 2039 for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ ) 2040 { 2041 nTop = bVMirr ? ( nY + 1 ) : nY; 2042 nBottom = bVMirr ? nY : ( nY + 1 ) ; 2043 2044 if( nY ==nEndY ) 2045 { 2046 nLineStart = pMapIY[ nY ]; 2047 nLineRange = 0; 2048 } 2049 else 2050 { 2051 nLineStart = pMapIY[ nTop ] ; 2052 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] ); 2053 } 2054 2055 for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ ) 2056 { 2057 nLeft = bHMirr ? ( nX + 1 ) : nX; 2058 nRight = bHMirr ? nX : ( nX + 1 ) ; 2059 2060 if( nX == nEndX ) 2061 { 2062 nRowStart = pMapIX[ nX ]; 2063 nRowRange = 0; 2064 } 2065 else 2066 { 2067 nRowStart = pMapIX[ nLeft ]; 2068 nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] ); 2069 } 2070 2071 nSumR = nSumG = nSumB = 0; 2072 nTotalWeightY = 0; 2073 2074 for(int i = 0; i<= nLineRange; i++) 2075 { 2076 nSumRowR = nSumRowG = nSumRowB = 0; 2077 nTotalWeightX = 0; 2078 2079 for(int j = 0; j <= nRowRange; j++) 2080 { 2081 aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j ); 2082 2083 if(nX == nEndX ) 2084 { 2085 2086 nSumRowB += aCol0.GetBlue() << 7L; 2087 nSumRowG += aCol0.GetGreen() << 7L; 2088 nSumRowR += aCol0.GetRed() << 7L; 2089 nTotalWeightX += 1 << 7L; 2090 } 2091 else if( j == 0 ) 2092 { 2093 2094 nWeightX = (nMax- pMapFX[ nLeft ]) ; 2095 nSumRowB += ( nWeightX *aCol0.GetBlue()) ; 2096 nSumRowG += ( nWeightX *aCol0.GetGreen()) ; 2097 nSumRowR += ( nWeightX *aCol0.GetRed()) ; 2098 nTotalWeightX += nWeightX; 2099 } 2100 else if ( nRowRange == j ) 2101 { 2102 2103 nWeightX = pMapFX[ nRight ] ; 2104 nSumRowB += ( nWeightX *aCol0.GetBlue() ); 2105 nSumRowG += ( nWeightX *aCol0.GetGreen() ); 2106 nSumRowR += ( nWeightX *aCol0.GetRed() ); 2107 nTotalWeightX += nWeightX; 2108 } 2109 else 2110 { 2111 nSumRowB += aCol0.GetBlue() << 7L; 2112 nSumRowG += aCol0.GetGreen() << 7L; 2113 nSumRowR += aCol0.GetRed() << 7L; 2114 nTotalWeightX += 1 << 7L; 2115 } 2116 } 2117 2118 if( nY == nEndY ) 2119 nWeightY = nMax; 2120 else if( i == 0 ) 2121 nWeightY = nMax - pMapFY[ nTop ]; 2122 else if( nLineRange == 1 ) 2123 nWeightY = pMapFY[ nTop ]; 2124 else if ( nLineRange == i ) 2125 nWeightY = pMapFY[ nBottom ]; 2126 else 2127 nWeightY = nMax; 2128 2129 nWeightY = nWeightY ; 2130 nSumB += nWeightY * ( nSumRowB / nTotalWeightX ); 2131 nSumG += nWeightY * ( nSumRowG / nTotalWeightX ); 2132 nSumR += nWeightY * ( nSumRowR / nTotalWeightX ); 2133 nTotalWeightY += nWeightY; 2134 } 2135 2136 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) )); 2137 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) )); 2138 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) )); 2139 pWAcc->SetPixel( nYDst, nXDst++, aColRes ); 2140 2141 } 2142 } 2143 } 2144 } 2145 } 2146 2147 bRet = true; 2148 } 2149 2150 delete[] pMapIX; 2151 delete[] pMapIY; 2152 delete[] pMapFX; 2153 delete[] pMapFY; 2154 2155 ReleaseAccess( pAcc ); 2156 aOutBmp.ReleaseAccess( pWAcc ); 2157 2158 if( bRet ) 2159 { 2160 ImplAdaptBitCount(aOutBmp); 2161 ImplAssignWithSize(aOutBmp); 2162 } 2163 2164 if( !bRet ) 2165 bRet = ImplScaleFast( scaleX, scaleY ); 2166 } 2167 2168 return bRet; 2169 } 2170 2171 //----------------------------------------------------------------------------------- 2172 2173 namespace 2174 { 2175 void ImplCalculateContributions( 2176 const sal_uInt32 aSourceSize, 2177 const sal_uInt32 aDestinationSize, 2178 sal_uInt32& aNumberOfContributions, 2179 double*& pWeights, 2180 sal_uInt32*& pPixels, 2181 sal_uInt32*& pCount, 2182 const Kernel& aKernel) 2183 { 2184 const double fSamplingRadius(aKernel.GetWidth()); 2185 const double fScale(aDestinationSize / static_cast< double >(aSourceSize)); 2186 const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius); 2187 const double fFilterFactor((fScale < 1.0) ? fScale : 1.0); 2188 2189 aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1; 2190 const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions); 2191 pWeights = new double[nAllocSize]; 2192 pPixels = new sal_uInt32[nAllocSize]; 2193 pCount = new sal_uInt32[aDestinationSize]; 2194 2195 for(sal_uInt32 i(0); i < aDestinationSize; i++) 2196 { 2197 const sal_uInt32 aIndex(i * aNumberOfContributions); 2198 const double aCenter(i / fScale); 2199 const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius))); 2200 const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius))); 2201 sal_uInt32 aCurrentCount(0); 2202 2203 for(sal_Int32 j(aLeft); j <= aRight; j++) 2204 { 2205 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j)))); 2206 2207 // Reduce calculations with ignoring weights of 0.0 2208 if(fabs(aWeight) < 0.0001) 2209 { 2210 continue; 2211 } 2212 2213 // Handling on edges 2214 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1)); 2215 const sal_uInt32 nIndex(aIndex + aCurrentCount); 2216 2217 pWeights[nIndex] = aWeight; 2218 pPixels[nIndex] = aPixelIndex; 2219 2220 aCurrentCount++; 2221 } 2222 2223 pCount[i] = aCurrentCount; 2224 } 2225 } 2226 2227 sal_Bool ImplScaleConvolutionHor( 2228 Bitmap& rSource, 2229 Bitmap& rTarget, 2230 const double& rScaleX, 2231 const Kernel& aKernel) 2232 { 2233 // Do horizontal filtering 2234 OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)"); 2235 const sal_uInt32 nWidth(rSource.GetSizePixel().Width()); 2236 const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX)); 2237 2238 if(nWidth == nNewWidth) 2239 { 2240 return true; 2241 } 2242 2243 BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess(); 2244 2245 if(pReadAcc) 2246 { 2247 double* pWeights = 0; 2248 sal_uInt32* pPixels = 0; 2249 sal_uInt32* pCount = 0; 2250 sal_uInt32 aNumberOfContributions(0); 2251 2252 const sal_uInt32 nHeight(rSource.GetSizePixel().Height()); 2253 ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel); 2254 rTarget = Bitmap(Size(nNewWidth, nHeight), 24); 2255 BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess(); 2256 bool bResult(0 != pWriteAcc); 2257 2258 if(bResult) 2259 { 2260 for(sal_uInt32 y(0); y < nHeight; y++) 2261 { 2262 for(sal_uInt32 x(0); x < nNewWidth; x++) 2263 { 2264 const sal_uInt32 aBaseIndex(x * aNumberOfContributions); 2265 double aSum(0.0); 2266 double aValueRed(0.0); 2267 double aValueGreen(0.0); 2268 double aValueBlue(0.0); 2269 2270 for(sal_uInt32 j(0); j < pCount[x]; j++) 2271 { 2272 const sal_uInt32 aIndex(aBaseIndex + j); 2273 const double aWeight(pWeights[aIndex]); 2274 BitmapColor aColor; 2275 2276 aSum += aWeight; 2277 2278 if(pReadAcc->HasPalette()) 2279 { 2280 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex])); 2281 } 2282 else 2283 { 2284 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]); 2285 } 2286 2287 aValueRed += aWeight * aColor.GetRed(); 2288 aValueGreen += aWeight * aColor.GetGreen(); 2289 aValueBlue += aWeight * aColor.GetBlue(); 2290 } 2291 2292 const BitmapColor aResultColor( 2293 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)), 2294 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)), 2295 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255))); 2296 2297 pWriteAcc->SetPixel(y, x, aResultColor); 2298 } 2299 } 2300 2301 rTarget.ReleaseAccess(pWriteAcc); 2302 } 2303 2304 rSource.ReleaseAccess(pReadAcc); 2305 delete[] pWeights; 2306 delete[] pCount; 2307 delete[] pPixels; 2308 2309 if(bResult) 2310 { 2311 return true; 2312 } 2313 } 2314 2315 return false; 2316 } 2317 2318 bool ImplScaleConvolutionVer( 2319 Bitmap& rSource, 2320 Bitmap& rTarget, 2321 const double& rScaleY, 2322 const Kernel& aKernel) 2323 { 2324 // Do vertical filtering 2325 OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)"); 2326 const sal_uInt32 nHeight(rSource.GetSizePixel().Height()); 2327 const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY)); 2328 2329 if(nHeight == nNewHeight) 2330 { 2331 return true; 2332 } 2333 2334 BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess(); 2335 2336 if(pReadAcc) 2337 { 2338 double* pWeights = 0; 2339 sal_uInt32* pPixels = 0; 2340 sal_uInt32* pCount = 0; 2341 sal_uInt32 aNumberOfContributions(0); 2342 2343 const sal_uInt32 nWidth(rSource.GetSizePixel().Width()); 2344 ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel); 2345 rTarget = Bitmap(Size(nWidth, nNewHeight), 24); 2346 BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess(); 2347 bool bResult(0 != pWriteAcc); 2348 2349 if(pWriteAcc) 2350 { 2351 for(sal_uInt32 x(0); x < nWidth; x++) 2352 { 2353 for(sal_uInt32 y(0); y < nNewHeight; y++) 2354 { 2355 const sal_uInt32 aBaseIndex(y * aNumberOfContributions); 2356 double aSum(0.0); 2357 double aValueRed(0.0); 2358 double aValueGreen(0.0); 2359 double aValueBlue(0.0); 2360 2361 for(sal_uInt32 j(0); j < pCount[y]; j++) 2362 { 2363 const sal_uInt32 aIndex(aBaseIndex + j); 2364 const double aWeight(pWeights[aIndex]); 2365 BitmapColor aColor; 2366 2367 aSum += aWeight; 2368 2369 if(pReadAcc->HasPalette()) 2370 { 2371 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x)); 2372 } 2373 else 2374 { 2375 aColor = pReadAcc->GetPixel(pPixels[aIndex], x); 2376 } 2377 2378 aValueRed += aWeight * aColor.GetRed(); 2379 aValueGreen += aWeight * aColor.GetGreen(); 2380 aValueBlue += aWeight * aColor.GetBlue(); 2381 } 2382 2383 const BitmapColor aResultColor( 2384 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)), 2385 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)), 2386 static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255))); 2387 2388 if(pWriteAcc->HasPalette()) 2389 { 2390 pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor))); 2391 } 2392 else 2393 { 2394 pWriteAcc->SetPixel(y, x, aResultColor); 2395 } 2396 } 2397 } 2398 } 2399 2400 rTarget.ReleaseAccess(pWriteAcc); 2401 rSource.ReleaseAccess(pReadAcc); 2402 2403 delete[] pWeights; 2404 delete[] pCount; 2405 delete[] pPixels; 2406 2407 if(bResult) 2408 { 2409 return true; 2410 } 2411 } 2412 2413 return false; 2414 } 2415 } 2416 2417 // #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and 2418 // BMP_SCALE_BOX derived from the original commit from Toma� Vajngerl (see 2419 // bugzilla task for deitails) Thanks! 2420 sal_Bool Bitmap::ImplScaleConvolution( 2421 const double& rScaleX, 2422 const double& rScaleY, 2423 const Kernel& aKernel) 2424 { 2425 const bool bMirrorHor(rScaleX < 0.0); 2426 const bool bMirrorVer(rScaleY < 0.0); 2427 const double fScaleX(bMirrorHor ? -rScaleX : rScaleX); 2428 const double fScaleY(bMirrorVer ? -rScaleY : rScaleY); 2429 const sal_uInt32 nWidth(GetSizePixel().Width()); 2430 const sal_uInt32 nHeight(GetSizePixel().Height()); 2431 const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX)); 2432 const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY)); 2433 const bool bScaleHor(nWidth != nNewWidth); 2434 const bool bScaleVer(nHeight != nNewHeight); 2435 const bool bMirror(bMirrorHor || bMirrorVer); 2436 2437 if(!bMirror && !bScaleHor && !bScaleVer) 2438 { 2439 return true; 2440 } 2441 2442 bool bResult(true); 2443 sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE); 2444 bool bMirrorAfter(false); 2445 2446 if(bMirror) 2447 { 2448 if(bMirrorHor) 2449 { 2450 nMirrorFlags |= BMP_MIRROR_HORZ; 2451 } 2452 2453 if(bMirrorVer) 2454 { 2455 nMirrorFlags |= BMP_MIRROR_VERT; 2456 } 2457 2458 const sal_uInt32 nStartSize(nWidth * nHeight); 2459 const sal_uInt32 nEndSize(nNewWidth * nNewHeight); 2460 2461 bMirrorAfter = nStartSize > nEndSize; 2462 2463 if(!bMirrorAfter) 2464 { 2465 bResult = Mirror(nMirrorFlags); 2466 } 2467 } 2468 2469 Bitmap aResult; 2470 2471 if(bResult) 2472 { 2473 const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth); 2474 const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth); 2475 2476 if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst) 2477 { 2478 if(bScaleHor) 2479 { 2480 bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel); 2481 } 2482 2483 if(bResult && bScaleVer) 2484 { 2485 bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel); 2486 } 2487 } 2488 else 2489 { 2490 if(bScaleVer) 2491 { 2492 bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel); 2493 } 2494 2495 if(bResult && bScaleHor) 2496 { 2497 bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel); 2498 } 2499 } 2500 } 2501 2502 if(bResult && bMirrorAfter) 2503 { 2504 bResult = aResult.Mirror(nMirrorFlags); 2505 } 2506 2507 if(bResult) 2508 { 2509 ImplAdaptBitCount(aResult); 2510 *this = aResult; 2511 } 2512 2513 return bResult; 2514 } 2515 2516 // ------------------------------------------------------------------------ 2517 2518 sal_Bool Bitmap::Dither( sal_uLong nDitherFlags ) 2519 { 2520 sal_Bool bRet = sal_False; 2521 2522 const Size aSizePix( GetSizePixel() ); 2523 2524 if( aSizePix.Width() == 1 || aSizePix.Height() == 1 ) 2525 bRet = sal_True; 2526 else if( nDitherFlags & BMP_DITHER_MATRIX ) 2527 bRet = ImplDitherMatrix(); 2528 else if( nDitherFlags & BMP_DITHER_FLOYD ) 2529 bRet = ImplDitherFloyd(); 2530 else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) ) 2531 bRet = ImplDitherFloyd16(); 2532 2533 return bRet; 2534 } 2535 2536 // ------------------------------------------------------------------------ 2537 2538 sal_Bool Bitmap::ImplDitherMatrix() 2539 { 2540 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 2541 Bitmap aNewBmp( GetSizePixel(), 8 ); 2542 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 2543 sal_Bool bRet = sal_False; 2544 2545 if( pReadAcc && pWriteAcc ) 2546 { 2547 const sal_uLong nWidth = pReadAcc->Width(); 2548 const sal_uLong nHeight = pReadAcc->Height(); 2549 BitmapColor aIndex( (sal_uInt8) 0 ); 2550 2551 if( pReadAcc->HasPalette() ) 2552 { 2553 for( sal_uLong nY = 0UL; nY < nHeight; nY++ ) 2554 { 2555 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ ) 2556 { 2557 const BitmapColor aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) ); 2558 const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ]; 2559 const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL; 2560 const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL; 2561 const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL; 2562 2563 aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) ); 2564 pWriteAcc->SetPixel( nY, nX, aIndex ); 2565 } 2566 } 2567 } 2568 else 2569 { 2570 for( sal_uLong nY = 0UL; nY < nHeight; nY++ ) 2571 { 2572 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ ) 2573 { 2574 const BitmapColor aCol( pReadAcc->GetPixel( nY, nX ) ); 2575 const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ]; 2576 const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL; 2577 const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL; 2578 const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL; 2579 2580 aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) ); 2581 pWriteAcc->SetPixel( nY, nX, aIndex ); 2582 } 2583 } 2584 } 2585 2586 bRet = sal_True; 2587 } 2588 2589 ReleaseAccess( pReadAcc ); 2590 aNewBmp.ReleaseAccess( pWriteAcc ); 2591 2592 if( bRet ) 2593 { 2594 const MapMode aMap( maPrefMapMode ); 2595 const Size aSize( maPrefSize ); 2596 2597 *this = aNewBmp; 2598 2599 maPrefMapMode = aMap; 2600 maPrefSize = aSize; 2601 } 2602 2603 return bRet; 2604 } 2605 2606 // ------------------------------------------------------------------------ 2607 2608 sal_Bool Bitmap::ImplDitherFloyd() 2609 { 2610 const Size aSize( GetSizePixel() ); 2611 sal_Bool bRet = sal_False; 2612 2613 if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) ) 2614 { 2615 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 2616 Bitmap aNewBmp( GetSizePixel(), 8 ); 2617 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 2618 2619 if( pReadAcc && pWriteAcc ) 2620 { 2621 BitmapColor aColor; 2622 long nWidth = pReadAcc->Width(); 2623 long nWidth1 = nWidth - 1L; 2624 long nHeight = pReadAcc->Height(); 2625 long nX; 2626 long nW = nWidth * 3L; 2627 long nW2 = nW - 3L; 2628 long nRErr, nGErr, nBErr; 2629 long nRC, nGC, nBC; 2630 long nTemp; 2631 long nZ; 2632 long* p1 = new long[ nW ]; 2633 long* p2 = new long[ nW ]; 2634 long* p1T = p1; 2635 long* p2T = p2; 2636 long* pTmp; 2637 sal_Bool bPal = pReadAcc->HasPalette(); 2638 2639 pTmp = p2T; 2640 2641 if( bPal ) 2642 { 2643 for( nZ = 0; nZ < nWidth; nZ++ ) 2644 { 2645 aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) ); 2646 2647 *pTmp++ = (long) aColor.GetBlue() << 12; 2648 *pTmp++ = (long) aColor.GetGreen() << 12; 2649 *pTmp++ = (long) aColor.GetRed() << 12; 2650 } 2651 } 2652 else 2653 { 2654 for( nZ = 0; nZ < nWidth; nZ++ ) 2655 { 2656 aColor = pReadAcc->GetPixel( 0, nZ ); 2657 2658 *pTmp++ = (long) aColor.GetBlue() << 12; 2659 *pTmp++ = (long) aColor.GetGreen() << 12; 2660 *pTmp++ = (long) aColor.GetRed() << 12; 2661 } 2662 } 2663 2664 for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ ) 2665 { 2666 pTmp = p1T; 2667 p1T = p2T; 2668 p2T = pTmp; 2669 2670 if( nY < nHeight ) 2671 { 2672 if( bPal ) 2673 { 2674 for( nZ = 0; nZ < nWidth; nZ++ ) 2675 { 2676 aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) ); 2677 2678 *pTmp++ = (long) aColor.GetBlue() << 12; 2679 *pTmp++ = (long) aColor.GetGreen() << 12; 2680 *pTmp++ = (long) aColor.GetRed() << 12; 2681 } 2682 } 2683 else 2684 { 2685 for( nZ = 0; nZ < nWidth; nZ++ ) 2686 { 2687 aColor = pReadAcc->GetPixel( nY, nZ ); 2688 2689 *pTmp++ = (long) aColor.GetBlue() << 12; 2690 *pTmp++ = (long) aColor.GetGreen() << 12; 2691 *pTmp++ = (long) aColor.GetRed() << 12; 2692 } 2693 } 2694 } 2695 2696 // erstes Pixel gesondert betrachten 2697 nX = 0; 2698 CALC_ERRORS; 2699 CALC_TABLES7; 2700 nX -= 5; 2701 CALC_TABLES5; 2702 pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) ); 2703 2704 // mittlere Pixel ueber Schleife 2705 long nXAcc; 2706 for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ ) 2707 { 2708 CALC_ERRORS; 2709 CALC_TABLES7; 2710 nX -= 8; 2711 CALC_TABLES3; 2712 CALC_TABLES5; 2713 pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) ); 2714 } 2715 2716 // letztes Pixel gesondert betrachten 2717 CALC_ERRORS; 2718 nX -= 5; 2719 CALC_TABLES3; 2720 CALC_TABLES5; 2721 pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) ); 2722 } 2723 2724 delete[] p1; 2725 delete[] p2; 2726 bRet = sal_True; 2727 } 2728 2729 ReleaseAccess( pReadAcc ); 2730 aNewBmp.ReleaseAccess( pWriteAcc ); 2731 2732 if( bRet ) 2733 { 2734 const MapMode aMap( maPrefMapMode ); 2735 const Size aPrefSize( maPrefSize ); 2736 2737 *this = aNewBmp; 2738 2739 maPrefMapMode = aMap; 2740 maPrefSize = aPrefSize; 2741 } 2742 } 2743 2744 return bRet; 2745 } 2746 2747 // ------------------------------------------------------------------------ 2748 2749 sal_Bool Bitmap::ImplDitherFloyd16() 2750 { 2751 BitmapReadAccess* pReadAcc = AcquireReadAccess(); 2752 Bitmap aNewBmp( GetSizePixel(), 24 ); 2753 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess(); 2754 sal_Bool bRet = sal_False; 2755 2756 if( pReadAcc && pWriteAcc ) 2757 { 2758 const long nWidth = pWriteAcc->Width(); 2759 const long nWidth1 = nWidth - 1L; 2760 const long nHeight = pWriteAcc->Height(); 2761 BitmapColor aColor; 2762 BitmapColor aBestCol; 2763 ImpErrorQuad aErrQuad; 2764 ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ]; 2765 ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ]; 2766 ImpErrorQuad* pQLine1 = pErrQuad1; 2767 ImpErrorQuad* pQLine2 = 0; 2768 long nX, nY; 2769 long nYTmp = 0L; 2770 sal_Bool bQ1 = sal_True; 2771 2772 for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ ) 2773 for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ ) 2774 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX ); 2775 2776 for( nY = 0L; nY < nHeight; nY++, nYTmp++ ) 2777 { 2778 // erstes ZeilenPixel 2779 aBestCol = pQLine1[ 0 ].ImplGetColor(); 2780 aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 ); 2781 aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 ); 2782 aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 ); 2783 pWriteAcc->SetPixel( nY, 0, aBestCol ); 2784 2785 for( nX = 1L; nX < nWidth1; nX++ ) 2786 { 2787 aColor = pQLine1[ nX ].ImplGetColor(); 2788 aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 ); 2789 aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 ); 2790 aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 ); 2791 aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol ); 2792 pQLine1[ ++nX ].ImplAddColorError7( aErrQuad ); 2793 pQLine2[ nX-- ].ImplAddColorError1( aErrQuad ); 2794 pQLine2[ nX-- ].ImplAddColorError5( aErrQuad ); 2795 pQLine2[ nX++ ].ImplAddColorError3( aErrQuad ); 2796 pWriteAcc->SetPixel( nY, nX, aBestCol ); 2797 } 2798 2799 // letztes ZeilenPixel 2800 aBestCol = pQLine1[ nWidth1 ].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, nX, aBestCol ); 2805 2806 // Zeilenpuffer neu fuellen/kopieren 2807 pQLine1 = pQLine2; 2808 pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1; 2809 2810 if( nYTmp < nHeight ) 2811 for( nX = 0L; nX < nWidth; nX++ ) 2812 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX ); 2813 } 2814 2815 // Zeilenpuffer zerstoeren 2816 delete[] pErrQuad1; 2817 delete[] pErrQuad2; 2818 bRet = sal_True; 2819 } 2820 2821 ReleaseAccess( pReadAcc ); 2822 aNewBmp.ReleaseAccess( pWriteAcc ); 2823 2824 if( bRet ) 2825 { 2826 const MapMode aMap( maPrefMapMode ); 2827 const Size aSize( maPrefSize ); 2828 2829 *this = aNewBmp; 2830 2831 maPrefMapMode = aMap; 2832 maPrefSize = aSize; 2833 } 2834 2835 return bRet; 2836 } 2837 2838 // ------------------------------------------------------------------------ 2839 2840 sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce ) 2841 { 2842 sal_Bool bRet; 2843 2844 if( GetColorCount() <= (sal_uLong) nColorCount ) 2845 bRet = sal_True; 2846 else if( nColorCount ) 2847 { 2848 if( BMP_REDUCE_SIMPLE == eReduce ) 2849 bRet = ImplReduceSimple( nColorCount ); 2850 else if( BMP_REDUCE_POPULAR == eReduce ) 2851 bRet = ImplReducePopular( nColorCount ); 2852 else 2853 bRet = ImplReduceMedian( nColorCount ); 2854 } 2855 else 2856 bRet = sal_False; 2857 2858 return bRet; 2859 } 2860 2861 // ------------------------------------------------------------------------ 2862 2863 sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount ) 2864 { 2865 Bitmap aNewBmp; 2866 BitmapReadAccess* pRAcc = AcquireReadAccess(); 2867 const sal_uInt16 nColCount = Min( nColorCount, (sal_uInt16) 256 ); 2868 sal_uInt16 nBitCount; 2869 sal_Bool bRet = sal_False; 2870 2871 if( nColCount <= 2 ) 2872 nBitCount = 1; 2873 else if( nColCount <= 16 ) 2874 nBitCount = 4; 2875 else 2876 nBitCount = 8; 2877 2878 if( pRAcc ) 2879 { 2880 Octree aOct( *pRAcc, nColCount ); 2881 const BitmapPalette& rPal = aOct.GetPalette(); 2882 BitmapWriteAccess* pWAcc; 2883 2884 aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal ); 2885 pWAcc = aNewBmp.AcquireWriteAccess(); 2886 2887 if( pWAcc ) 2888 { 2889 const long nWidth = pRAcc->Width(); 2890 const long nHeight = pRAcc->Height(); 2891 2892 if( pRAcc->HasPalette() ) 2893 { 2894 for( long nY = 0L; nY < nHeight; nY++ ) 2895 for( long nX =0L; nX < nWidth; nX++ ) 2896 pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) ); 2897 } 2898 else 2899 { 2900 for( long nY = 0L; nY < nHeight; nY++ ) 2901 for( long nX =0L; nX < nWidth; nX++ ) 2902 pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) ); 2903 } 2904 2905 aNewBmp.ReleaseAccess( pWAcc ); 2906 bRet = sal_True; 2907 } 2908 2909 ReleaseAccess( pRAcc ); 2910 } 2911 2912 if( bRet ) 2913 { 2914 const MapMode aMap( maPrefMapMode ); 2915 const Size aSize( maPrefSize ); 2916 2917 *this = aNewBmp; 2918 maPrefMapMode = aMap; 2919 maPrefSize = aSize; 2920 } 2921 2922 return bRet; 2923 } 2924 2925 // ------------------------------------------------------------------------ 2926 2927 struct PopularColorCount 2928 { 2929 sal_uInt32 mnIndex; 2930 sal_uInt32 mnCount; 2931 }; 2932 2933 // ------------------------------------------------------------------------ 2934 2935 extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 ) 2936 { 2937 int nRet; 2938 2939 if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount ) 2940 nRet = 1; 2941 else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount ) 2942 nRet = 0; 2943 else 2944 nRet = -1; 2945 2946 return nRet; 2947 } 2948 2949 // ------------------------------------------------------------------------ 2950 2951 sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount ) 2952 { 2953 BitmapReadAccess* pRAcc = AcquireReadAccess(); 2954 sal_uInt16 nBitCount; 2955 sal_Bool bRet = sal_False; 2956 2957 if( nColCount > 256 ) 2958 nColCount = 256; 2959 2960 if( nColCount < 17 ) 2961 nBitCount = 4; 2962 else 2963 nBitCount = 8; 2964 2965 if( pRAcc ) 2966 { 2967 const sal_uInt32 nValidBits = 4; 2968 const sal_uInt32 nRightShiftBits = 8 - nValidBits; 2969 const sal_uInt32 nLeftShiftBits1 = nValidBits; 2970 const sal_uInt32 nLeftShiftBits2 = nValidBits << 1; 2971 const sal_uInt32 nColorsPerComponent = 1 << nValidBits; 2972 const sal_uInt32 nColorOffset = 256 / nColorsPerComponent; 2973 const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent; 2974 const long nWidth = pRAcc->Width(); 2975 const long nHeight = pRAcc->Height(); 2976 PopularColorCount* pCountTable = new PopularColorCount[ nTotalColors ]; 2977 long nX, nY, nR, nG, nB, nIndex; 2978 2979 rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) ); 2980 2981 for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset ) 2982 { 2983 for( nG = 0; nG < 256; nG += nColorOffset ) 2984 { 2985 for( nB = 0; nB < 256; nB += nColorOffset ) 2986 { 2987 pCountTable[ nIndex ].mnIndex = nIndex; 2988 nIndex++; 2989 } 2990 } 2991 } 2992 2993 if( pRAcc->HasPalette() ) 2994 { 2995 for( nY = 0L; nY < nHeight; nY++ ) 2996 { 2997 for( nX = 0L; nX < nWidth; nX++ ) 2998 { 2999 const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ); 3000 pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3001 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3002 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++; 3003 } 3004 } 3005 } 3006 else 3007 { 3008 for( nY = 0L; nY < nHeight; nY++ ) 3009 { 3010 for( nX = 0L; nX < nWidth; nX++ ) 3011 { 3012 const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) ); 3013 pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3014 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3015 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++; 3016 } 3017 } 3018 } 3019 3020 BitmapPalette aNewPal( nColCount ); 3021 3022 qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc ); 3023 3024 for( sal_uInt16 n = 0; n < nColCount; n++ ) 3025 { 3026 const PopularColorCount& rPop = pCountTable[ n ]; 3027 aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ), 3028 (sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ), 3029 (sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) ); 3030 } 3031 3032 Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal ); 3033 BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess(); 3034 3035 if( pWAcc ) 3036 { 3037 BitmapColor aDstCol( (sal_uInt8) 0 ); 3038 sal_uInt8* pIndexMap = new sal_uInt8[ nTotalColors ]; 3039 3040 for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset ) 3041 for( nG = 0; nG < 256; nG += nColorOffset ) 3042 for( nB = 0; nB < 256; nB += nColorOffset ) 3043 pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) ); 3044 3045 if( pRAcc->HasPalette() ) 3046 { 3047 for( nY = 0L; nY < nHeight; nY++ ) 3048 { 3049 for( nX = 0L; nX < nWidth; nX++ ) 3050 { 3051 const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ); 3052 aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3053 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3054 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] ); 3055 pWAcc->SetPixel( nY, nX, aDstCol ); 3056 } 3057 } 3058 } 3059 else 3060 { 3061 for( nY = 0L; nY < nHeight; nY++ ) 3062 { 3063 for( nX = 0L; nX < nWidth; nX++ ) 3064 { 3065 const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) ); 3066 aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) | 3067 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) | 3068 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] ); 3069 pWAcc->SetPixel( nY, nX, aDstCol ); 3070 } 3071 } 3072 } 3073 3074 delete[] pIndexMap; 3075 aNewBmp.ReleaseAccess( pWAcc ); 3076 bRet = sal_True; 3077 } 3078 3079 delete[] pCountTable; 3080 ReleaseAccess( pRAcc ); 3081 3082 if( bRet ) 3083 { 3084 const MapMode aMap( maPrefMapMode ); 3085 const Size aSize( maPrefSize ); 3086 3087 *this = aNewBmp; 3088 maPrefMapMode = aMap; 3089 maPrefSize = aSize; 3090 } 3091 } 3092 3093 return bRet; 3094 } 3095 3096 // ------------------------------------------------------------------------ 3097 3098 sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount ) 3099 { 3100 BitmapReadAccess* pRAcc = AcquireReadAccess(); 3101 sal_uInt16 nBitCount; 3102 sal_Bool bRet = sal_False; 3103 3104 if( nColCount < 17 ) 3105 nBitCount = 4; 3106 else if( nColCount < 257 ) 3107 nBitCount = 8; 3108 else 3109 { 3110 DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" ); 3111 nBitCount = 8; 3112 nColCount = 256; 3113 } 3114 3115 if( pRAcc ) 3116 { 3117 Bitmap aNewBmp( GetSizePixel(), nBitCount ); 3118 BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess(); 3119 3120 if( pWAcc ) 3121 { 3122 const sal_uLong nSize = 32768UL * sizeof( sal_uLong ); 3123 sal_uLong* pColBuf = (sal_uLong*) rtl_allocateMemory( nSize ); 3124 const long nWidth = pWAcc->Width(); 3125 const long nHeight = pWAcc->Height(); 3126 long nIndex = 0L; 3127 3128 memset( (HPBYTE) pColBuf, 0, nSize ); 3129 3130 // create Buffer 3131 if( pRAcc->HasPalette() ) 3132 { 3133 for( long nY = 0L; nY < nHeight; nY++ ) 3134 { 3135 for( long nX = 0L; nX < nWidth; nX++ ) 3136 { 3137 const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ); 3138 pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++; 3139 } 3140 } 3141 } 3142 else 3143 { 3144 for( long nY = 0L; nY < nHeight; nY++ ) 3145 { 3146 for( long nX = 0L; nX < nWidth; nX++ ) 3147 { 3148 const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) ); 3149 pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++; 3150 } 3151 } 3152 } 3153 3154 // create palette via median cut 3155 BitmapPalette aPal( pWAcc->GetPaletteEntryCount() ); 3156 ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31, 3157 nColCount, nWidth * nHeight, nIndex ); 3158 3159 // do mapping of colors to palette 3160 InverseColorMap aMap( aPal ); 3161 pWAcc->SetPalette( aPal ); 3162 for( long nY = 0L; nY < nHeight; nY++ ) 3163 for( long nX = 0L; nX < nWidth; nX++ ) 3164 pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) ); 3165 3166 rtl_freeMemory( pColBuf ); 3167 aNewBmp.ReleaseAccess( pWAcc ); 3168 bRet = sal_True; 3169 } 3170 3171 ReleaseAccess( pRAcc ); 3172 3173 if( bRet ) 3174 { 3175 const MapMode aMap( maPrefMapMode ); 3176 const Size aSize( maPrefSize ); 3177 3178 *this = aNewBmp; 3179 maPrefMapMode = aMap; 3180 maPrefSize = aSize; 3181 } 3182 } 3183 3184 return bRet; 3185 } 3186 3187 // ------------------------------------------------------------------------ 3188 3189 void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal, 3190 long nR1, long nR2, long nG1, long nG2, long nB1, long nB2, 3191 long nColors, long nPixels, long& rIndex ) 3192 { 3193 if( !nPixels ) 3194 return; 3195 3196 BitmapColor aCol; 3197 const long nRLen = nR2 - nR1; 3198 const long nGLen = nG2 - nG1; 3199 const long nBLen = nB2 - nB1; 3200 long nR, nG, nB; 3201 sal_uLong* pBuf = pColBuf; 3202 3203 if( !nRLen && !nGLen && !nBLen ) 3204 { 3205 if( pBuf[ RGB15( nR1, nG1, nB1 ) ] ) 3206 { 3207 aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) ); 3208 aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) ); 3209 aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) ); 3210 rPal[ (sal_uInt16) rIndex++ ] = aCol; 3211 } 3212 } 3213 else 3214 { 3215 if( 1 == nColors || 1 == nPixels ) 3216 { 3217 long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0; 3218 3219 for( nR = nR1; nR <= nR2; nR++ ) 3220 { 3221 for( nG = nG1; nG <= nG2; nG++ ) 3222 { 3223 for( nB = nB1; nB <= nB2; nB++ ) 3224 { 3225 nPixSum = pBuf[ RGB15( nR, nG, nB ) ]; 3226 3227 if( nPixSum ) 3228 { 3229 nRSum += nR * nPixSum; 3230 nGSum += nG * nPixSum; 3231 nBSum += nB * nPixSum; 3232 } 3233 } 3234 } 3235 } 3236 3237 aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) ); 3238 aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) ); 3239 aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) ); 3240 rPal[ (sal_uInt16) rIndex++ ] = aCol; 3241 } 3242 else 3243 { 3244 const long nTest = ( nPixels >> 1 ); 3245 long nPixOld = 0; 3246 long nPixNew = 0; 3247 3248 if( nBLen > nGLen && nBLen > nRLen ) 3249 { 3250 nB = nB1 - 1; 3251 3252 while( nPixNew < nTest ) 3253 { 3254 nB++, nPixOld = nPixNew; 3255 for( nR = nR1; nR <= nR2; nR++ ) 3256 for( nG = nG1; nG <= nG2; nG++ ) 3257 nPixNew += pBuf[ RGB15( nR, nG, nB ) ]; 3258 } 3259 3260 if( nB < nB2 ) 3261 { 3262 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex ); 3263 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex ); 3264 } 3265 else 3266 { 3267 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex ); 3268 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex ); 3269 } 3270 } 3271 else if( nGLen > nRLen ) 3272 { 3273 nG = nG1 - 1; 3274 3275 while( nPixNew < nTest ) 3276 { 3277 nG++, nPixOld = nPixNew; 3278 for( nR = nR1; nR <= nR2; nR++ ) 3279 for( nB = nB1; nB <= nB2; nB++ ) 3280 nPixNew += pBuf[ RGB15( nR, nG, nB ) ]; 3281 } 3282 3283 if( nG < nG2 ) 3284 { 3285 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex ); 3286 ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex ); 3287 } 3288 else 3289 { 3290 ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex ); 3291 ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex ); 3292 } 3293 } 3294 else 3295 { 3296 nR = nR1 - 1; 3297 3298 while( nPixNew < nTest ) 3299 { 3300 nR++, nPixOld = nPixNew; 3301 for( nG = nG1; nG <= nG2; nG++ ) 3302 for( nB = nB1; nB <= nB2; nB++ ) 3303 nPixNew += pBuf[ RGB15( nR, nG, nB ) ]; 3304 } 3305 3306 if( nR < nR2 ) 3307 { 3308 ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex ); 3309 ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex ); 3310 } 3311 else 3312 { 3313 ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex ); 3314 ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex ); 3315 } 3316 } 3317 } 3318 } 3319 } 3320 3321 // ------------------------------------------------------------------------ 3322 3323 sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress ) 3324 { 3325 return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress ); 3326 } 3327 3328 // ------------------------------------------------------------------------ 3329 3330 sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress ) 3331 { 3332 return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress ); 3333 } 3334 3335 // ------------------------------------------------------------------------ 3336 3337 sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent, 3338 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, 3339 double fGamma, sal_Bool bInvert ) 3340 { 3341 sal_Bool bRet = sal_False; 3342 3343 // nothing to do => return quickly 3344 if( !nLuminancePercent && !nContrastPercent && 3345 !nChannelRPercent && !nChannelGPercent && !nChannelBPercent && 3346 ( fGamma == 1.0 ) && !bInvert ) 3347 { 3348 bRet = sal_True; 3349 } 3350 else 3351 { 3352 BitmapWriteAccess* pAcc = AcquireWriteAccess(); 3353 3354 if( pAcc ) 3355 { 3356 BitmapColor aCol; 3357 const long nW = pAcc->Width(); 3358 const long nH = pAcc->Height(); 3359 sal_uInt8* cMapR = new sal_uInt8[ 256 ]; 3360 sal_uInt8* cMapG = new sal_uInt8[ 256 ]; 3361 sal_uInt8* cMapB = new sal_uInt8[ 256 ]; 3362 long nX, nY; 3363 double fM, fROff, fGOff, fBOff, fOff; 3364 3365 // calculate slope 3366 if( nContrastPercent >= 0 ) 3367 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) ); 3368 else 3369 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0; 3370 3371 // total offset = luminance offset + contrast offset 3372 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0; 3373 3374 // channel offset = channel offset + total offset 3375 fROff = nChannelRPercent * 2.55 + fOff; 3376 fGOff = nChannelGPercent * 2.55 + fOff; 3377 fBOff = nChannelBPercent * 2.55 + fOff; 3378 3379 // calculate gamma value 3380 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma ); 3381 const sal_Bool bGamma = ( fGamma != 1.0 ); 3382 3383 // create mapping table 3384 for( nX = 0L; nX < 256L; nX++ ) 3385 { 3386 cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L ); 3387 cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L ); 3388 cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L ); 3389 3390 if( bGamma ) 3391 { 3392 cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma ); 3393 cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma ); 3394 cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma ); 3395 } 3396 3397 if( bInvert ) 3398 { 3399 cMapR[ nX ] = ~cMapR[ nX ]; 3400 cMapG[ nX ] = ~cMapG[ nX ]; 3401 cMapB[ nX ] = ~cMapB[ nX ]; 3402 } 3403 } 3404 3405 // do modifying 3406 if( pAcc->HasPalette() ) 3407 { 3408 BitmapColor aNewCol; 3409 3410 for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ ) 3411 { 3412 const BitmapColor& rCol = pAcc->GetPaletteColor( i ); 3413 aNewCol.SetRed( cMapR[ rCol.GetRed() ] ); 3414 aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] ); 3415 aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] ); 3416 pAcc->SetPaletteColor( i, aNewCol ); 3417 } 3418 } 3419 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 3420 { 3421 for( nY = 0L; nY < nH; nY++ ) 3422 { 3423 Scanline pScan = pAcc->GetScanline( nY ); 3424 3425 for( nX = 0L; nX < nW; nX++ ) 3426 { 3427 *pScan = cMapB[ *pScan ]; pScan++; 3428 *pScan = cMapG[ *pScan ]; pScan++; 3429 *pScan = cMapR[ *pScan ]; pScan++; 3430 } 3431 } 3432 } 3433 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ) 3434 { 3435 for( nY = 0L; nY < nH; nY++ ) 3436 { 3437 Scanline pScan = pAcc->GetScanline( nY ); 3438 3439 for( nX = 0L; nX < nW; nX++ ) 3440 { 3441 *pScan = cMapR[ *pScan ]; pScan++; 3442 *pScan = cMapG[ *pScan ]; pScan++; 3443 *pScan = cMapB[ *pScan ]; pScan++; 3444 } 3445 } 3446 } 3447 else 3448 { 3449 for( nY = 0L; nY < nH; nY++ ) 3450 { 3451 for( nX = 0L; nX < nW; nX++ ) 3452 { 3453 aCol = pAcc->GetPixel( nY, nX ); 3454 aCol.SetRed( cMapR[ aCol.GetRed() ] ); 3455 aCol.SetGreen( cMapG[ aCol.GetGreen() ] ); 3456 aCol.SetBlue( cMapB[ aCol.GetBlue() ] ); 3457 pAcc->SetPixel( nY, nX, aCol ); 3458 } 3459 } 3460 } 3461 3462 delete[] cMapR; 3463 delete[] cMapG; 3464 delete[] cMapB; 3465 ReleaseAccess( pAcc ); 3466 bRet = sal_True; 3467 } 3468 } 3469 3470 return bRet; 3471 } 3472