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