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