LCOV - code coverage report
Current view: top level - vcl/source/gdi - bitmap3.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 580 1272 45.6 %
Date: 2015-06-13 12:38:46 Functions: 17 33 51.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <math.h>
      21             : #include <stdlib.h>
      22             : 
      23             : #include <vcl/bmpacc.hxx>
      24             : #include <vcl/bitmapex.hxx>
      25             : #include <vcl/bitmap.hxx>
      26             : #include <vcl/bitmapscalesuper.hxx>
      27             : #include <vcl/opengl/OpenGLHelper.hxx>
      28             : 
      29             : #include <boost/scoped_array.hpp>
      30             : 
      31             : #include <impbmp.hxx>
      32             : #include <impoct.hxx>
      33             : #include <impvect.hxx>
      34             : 
      35             : #include "octree.hxx"
      36             : 
      37             : #define RGB15( _def_cR, _def_cG, _def_cB )  (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
      38             : #define GAMMA( _def_cVal, _def_InvGamma )   ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
      39             : 
      40             : #define CALC_ERRORS                                                             \
      41             :                         nTemp = p1T[nX++] >> 12;                              \
      42             :                         nBErr = MinMax( nTemp, 0, 255 );                        \
      43             :                         nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
      44             :                         nTemp = p1T[nX++] >> 12;                              \
      45             :                         nGErr = MinMax( nTemp, 0, 255 );                        \
      46             :                         nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
      47             :                         nTemp = p1T[nX] >> 12;                                \
      48             :                         nRErr = MinMax( nTemp, 0, 255 );                        \
      49             :                         nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
      50             : 
      51             : #define CALC_TABLES3                                        \
      52             :                         p2T[nX++] += FloydError3[nBErr];    \
      53             :                         p2T[nX++] += FloydError3[nGErr];    \
      54             :                         p2T[nX++] += FloydError3[nRErr];
      55             : 
      56             : #define CALC_TABLES5                                        \
      57             :                         p2T[nX++] += FloydError5[nBErr];    \
      58             :                         p2T[nX++] += FloydError5[nGErr];    \
      59             :                         p2T[nX++] += FloydError5[nRErr];
      60             : 
      61             : #define CALC_TABLES7                                        \
      62             :                         p1T[++nX] += FloydError7[nBErr];    \
      63             :                         p2T[nX++] += FloydError1[nBErr];    \
      64             :                         p1T[nX] += FloydError7[nGErr];      \
      65             :                         p2T[nX++] += FloydError1[nGErr];    \
      66             :                         p1T[nX] += FloydError7[nRErr];      \
      67             :                         p2T[nX] += FloydError1[nRErr];
      68             : 
      69             : const extern sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
      70             : const extern sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
      71             : const extern sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
      72             : 
      73             : const extern sal_uLong nVCLDitherLut[ 256 ] =
      74             : {
      75             :        0, 49152, 12288, 61440,  3072, 52224, 15360, 64512,   768, 49920, 13056,
      76             :    62208,  3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
      77             :    48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
      78             :    57344,  4096, 53248, 11264, 60416,  7168, 56320,  8960, 58112,  4864, 54016,
      79             :    12032, 61184,  7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
      80             :    23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
      81             :    14336, 63488,  1024, 50176, 13312, 62464,  2816, 51968, 15104, 64256,  1792,
      82             :    50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
      83             :    35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392,  6144,
      84             :    55296,  9216, 58368,  5120, 54272, 11008, 60160,  6912, 56064,  9984, 59136,
      85             :     5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
      86             :    27392, 39680, 23296, 42752, 26368, 38656, 22272,   512, 49664, 12800, 61952,
      87             :     3584, 52736, 15872, 65024,   256, 49408, 12544, 61696,  3328, 52480, 15616,
      88             :    64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
      89             :    45312, 28928, 36096, 19712, 48384, 32000,  8704, 57856,  4608, 53760, 11776,
      90             :    60928,  7680, 56832,  8448, 57600,  4352, 53504, 11520, 60672,  7424, 56576,
      91             :    41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
      92             :    20736, 44288, 27904, 40192, 23808,  2560, 51712, 14848, 64000,  1536, 50688,
      93             :    13824, 62976,  2304, 51456, 14592, 63744,  1280, 50432, 13568, 62720, 35328,
      94             :    18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
      95             :    34048, 17664, 46336, 29952, 10752, 59904,  6656, 55808,  9728, 58880,  5632,
      96             :    54784, 10496, 59648,  6400, 55552,  9472, 58624,  5376, 54528, 43520, 27136,
      97             :    39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
      98             :    25856, 38144, 21760
      99             : };
     100             : 
     101             : const extern sal_uLong nVCLLut[ 256 ] =
     102             : {
     103             :          0,  1286,  2572,  3858,  5144,  6430,  7716,  9002,
     104             :      10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
     105             :      20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
     106             :      30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
     107             :      41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
     108             :      51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
     109             :      61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
     110             :      72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
     111             :      82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
     112             :      92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
     113             :     102880,104166,105452,106738,108024,109310,110596,111882,
     114             :     113168,114454,115740,117026,118312,119598,120884,122170,
     115             :     123456,124742,126028,127314,128600,129886,131172,132458,
     116             :     133744,135030,136316,137602,138888,140174,141460,142746,
     117             :     144032,145318,146604,147890,149176,150462,151748,153034,
     118             :     154320,155606,156892,158178,159464,160750,162036,163322,
     119             :     164608,165894,167180,168466,169752,171038,172324,173610,
     120             :     174896,176182,177468,178754,180040,181326,182612,183898,
     121             :     185184,186470,187756,189042,190328,191614,192900,194186,
     122             :     195472,196758,198044,199330,200616,201902,203188,204474,
     123             :     205760,207046,208332,209618,210904,212190,213476,214762,
     124             :     216048,217334,218620,219906,221192,222478,223764,225050,
     125             :     226336,227622,228908,230194,231480,232766,234052,235338,
     126             :     236624,237910,239196,240482,241768,243054,244340,245626,
     127             :     246912,248198,249484,250770,252056,253342,254628,255914,
     128             :     257200,258486,259772,261058,262344,263630,264916,266202,
     129             :     267488,268774,270060,271346,272632,273918,275204,276490,
     130             :     277776,279062,280348,281634,282920,284206,285492,286778,
     131             :     288064,289350,290636,291922,293208,294494,295780,297066,
     132             :     298352,299638,300924,302210,303496,304782,306068,307354,
     133             :     308640,309926,311212,312498,313784,315070,316356,317642,
     134             :     318928,320214,321500,322786,324072,325358,326644,327930
     135             : };
     136             : 
     137             : const long FloydMap[256] =
     138             : {
     139             :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     140             :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
     141             :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     142             :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     143             :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
     144             :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     145             :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     146             :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     147             :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
     148             :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
     149             :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
     150             :     3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
     151             :     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
     152             :     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
     153             :     4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
     154             :     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
     155             : };
     156             : 
     157             : const long FloydError1[61] =
     158             : {
     159             :     -7680, -7424, -7168, -6912, -6656, -6400, -6144,
     160             :     -5888, -5632, -5376, -5120, -4864, -4608, -4352,
     161             :     -4096, -3840, -3584, -3328, -3072, -2816, -2560,
     162             :     -2304, -2048, -1792, -1536, -1280, -1024, -768,
     163             :     -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
     164             :     1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
     165             :     3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
     166             :     5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
     167             : };
     168             : 
     169             : const long FloydError3[61] =
     170             : {
     171             :     -23040, -22272, -21504, -20736, -19968, -19200,
     172             :     -18432, -17664, -16896, -16128, -15360, -14592,
     173             :     -13824, -13056, -12288, -11520, -10752, -9984,
     174             :     -9216, -8448, -7680, -6912, -6144, -5376, -4608,
     175             :     -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
     176             :     2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
     177             :     8448, 9216, 9984, 10752, 11520, 12288, 13056,
     178             :     13824, 14592, 15360, 16128, 16896, 17664, 18432,
     179             :     19200, 19968, 20736, 21504, 22272, 23040
     180             : };
     181             : 
     182             : const long FloydError5[61] =
     183             : {
     184             :     -38400, -37120, -35840, -34560, -33280, -32000,
     185             :     -30720, -29440, -28160, -26880, -25600, -24320,
     186             :     -23040, -21760, -20480, -19200, -17920, -16640,
     187             :     -15360, -14080, -12800, -11520, -10240, -8960,
     188             :     -7680, -6400, -5120, -3840, -2560, -1280,   0,
     189             :     1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
     190             :     11520, 12800, 14080, 15360, 16640, 17920, 19200,
     191             :     20480, 21760, 23040, 24320, 25600, 26880, 28160,
     192             :     29440, 30720, 32000, 33280, 34560, 35840, 37120,
     193             :     38400
     194             : };
     195             : 
     196             : const long FloydError7[61] =
     197             : {
     198             :     -53760, -51968, -50176, -48384, -46592, -44800,
     199             :     -43008, -41216, -39424, -37632, -35840, -34048,
     200             :     -32256, -30464, -28672, -26880, -25088, -23296,
     201             :     -21504, -19712, -17920, -16128, -14336, -12544,
     202             :     -10752, -8960, -7168, -5376, -3584, -1792,  0,
     203             :     1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
     204             :     16128, 17920, 19712, 21504, 23296, 25088, 26880,
     205             :     28672, 30464, 32256, 34048, 35840, 37632, 39424,
     206             :     41216, 43008, 44800, 46592, 48384, 50176, 51968,
     207             :     53760
     208             : };
     209             : 
     210             : const long FloydIndexMap[6] =
     211             : {
     212             :     -30,  21, 72, 123, 174, 225
     213             : };
     214             : 
     215           0 : void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] )
     216             : {
     217           0 :     const double fVal = 3.125;
     218           0 :     const double fVal16 = fVal / 16.;
     219           0 :     const double fValScale = 254.;
     220             :     sal_uInt16 pMtx[ 16 ][ 16 ];
     221           0 :     sal_uInt16 nMax = 0;
     222             :     static const sal_uInt8 pMagic[4][4] = { { 0, 14,  3, 13, },
     223             :                                      {11,  5,  8,  6, },
     224             :                                      {12,  2, 15,  1, },
     225             :                                      {7,   9,  4, 10 } };
     226             : 
     227             :     // Build MagicSquare
     228           0 :     for ( long i = 0; i < 4; i++ )
     229           0 :        for ( long j = 0; j < 4; j++ )
     230           0 :            for ( long k = 0; k < 4; k++ )
     231           0 :                 for ( long l = 0; l < 4; l++ )
     232             :                 {
     233           0 :                     pMtx[ (k<<2) + i][(l<<2 ) + j ] = (sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 );
     234           0 :                     nMax = std::max ( pMtx[ (k<<2) + i][(l<<2 ) + j], nMax );
     235             :                 }
     236             : 
     237             :     // Scale to interval [0;254]
     238           0 :     double tmp = fValScale / nMax;
     239           0 :     for ( long i = 0; i < 16; i++ )
     240           0 :         for( long j = 0; j < 16; j++ )
     241           0 :             (*pDitherMatrix)[i][j] = (sal_uInt8) ( tmp * pMtx[i][j] );
     242           0 : }
     243             : 
     244      192472 : bool Bitmap::Convert( BmpConversion eConversion )
     245             : {
     246      192472 :     const sal_uInt16 nBitCount = GetBitCount ();
     247      192472 :     bool bRet = false;
     248             : 
     249      192472 :     switch( eConversion )
     250             :     {
     251             :         case( BMP_CONVERSION_1BIT_THRESHOLD ):
     252           0 :             bRet = ImplMakeMono( 128 );
     253           0 :         break;
     254             : 
     255             :         case( BMP_CONVERSION_1BIT_MATRIX ):
     256           0 :             bRet = ImplMakeMonoDither();
     257           0 :         break;
     258             : 
     259             :         case( BMP_CONVERSION_4BIT_GREYS ):
     260           0 :             bRet = ImplMakeGreyscales( 16 );
     261           0 :         break;
     262             : 
     263             :         case( BMP_CONVERSION_4BIT_COLORS ):
     264             :         {
     265           2 :             if( nBitCount < 4 )
     266           0 :                 bRet = ImplConvertUp( 4, NULL );
     267           2 :             else if( nBitCount > 4 )
     268           2 :                 bRet = ImplConvertDown( 4, NULL );
     269             :             else
     270           0 :                 bRet = true;
     271             :         }
     272           2 :         break;
     273             : 
     274             :         case( BMP_CONVERSION_4BIT_TRANS ):
     275             :         {
     276           0 :             Color aTrans( BMP_COL_TRANS );
     277             : 
     278           0 :             if( nBitCount < 4 )
     279           0 :                 bRet = ImplConvertUp( 4, &aTrans );
     280             :             else
     281           0 :                 bRet = ImplConvertDown( 4, &aTrans );
     282             :         }
     283           0 :         break;
     284             : 
     285             :         case( BMP_CONVERSION_8BIT_GREYS ):
     286      191827 :             bRet = ImplMakeGreyscales( 256 );
     287      191827 :         break;
     288             : 
     289             :         case( BMP_CONVERSION_8BIT_COLORS ):
     290             :         {
     291         564 :             if( nBitCount < 8 )
     292           0 :                 bRet = ImplConvertUp( 8 );
     293         564 :             else if( nBitCount > 8 )
     294         553 :                 bRet = ImplConvertDown( 8 );
     295             :             else
     296          11 :                 bRet = true;
     297             :         }
     298         564 :         break;
     299             : 
     300             :         case( BMP_CONVERSION_8BIT_TRANS ):
     301             :         {
     302           4 :             Color aTrans( BMP_COL_TRANS );
     303             : 
     304           4 :             if( nBitCount < 8 )
     305           0 :                 bRet = ImplConvertUp( 8, &aTrans );
     306             :             else
     307           4 :                 bRet = ImplConvertDown( 8, &aTrans );
     308             :         }
     309           4 :         break;
     310             : 
     311             :         case( BMP_CONVERSION_24BIT ):
     312             :         {
     313          75 :             if( nBitCount < 24 )
     314          70 :                 bRet = ImplConvertUp( 24, NULL );
     315             :             else
     316           5 :                 bRet = true;
     317             :         }
     318          75 :         break;
     319             : 
     320             :         case( BMP_CONVERSION_GHOSTED ):
     321           0 :             bRet = ImplConvertGhosted();
     322           0 :         break;
     323             : 
     324             :         default:
     325             :             OSL_FAIL( "Bitmap::Convert(): Unsupported conversion" );
     326           0 :         break;
     327             :     }
     328             : 
     329      192472 :     return bRet;
     330             : }
     331             : 
     332          39 : bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold )
     333             : {
     334          39 :     BitmapReadAccess* pReadAcc = AcquireReadAccess();
     335          39 :     bool bRet = false;
     336             : 
     337          39 :     if( pReadAcc )
     338             :     {
     339          39 :         Bitmap aNewBmp( GetSizePixel(), 1 );
     340          39 :         BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
     341             : 
     342          39 :         if( pWriteAcc )
     343             :         {
     344          39 :             const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
     345          78 :             const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
     346          39 :             const long nWidth = pWriteAcc->Width();
     347          39 :             const long nHeight = pWriteAcc->Height();
     348             : 
     349          39 :             if( pReadAcc->HasPalette() )
     350             :             {
     351        1730 :                 for( long nY = 0L; nY < nHeight; nY++ )
     352             :                 {
     353     1449418 :                     for( long nX = 0L; nX < nWidth; nX++ )
     354             :                     {
     355     1447698 :                         const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
     356     1447698 :                         if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >=
     357             :                             cThreshold )
     358             :                         {
     359       12410 :                             pWriteAcc->SetPixel( nY, nX, aWhite );
     360             :                         }
     361             :                         else
     362     1435288 :                             pWriteAcc->SetPixel( nY, nX, aBlack );
     363             :                     }
     364             :                 }
     365             :             }
     366             :             else
     367             :             {
     368        1070 :                 for( long nY = 0L; nY < nHeight; nY++ )
     369             :                 {
     370      388710 :                     for( long nX = 0L; nX < nWidth; nX++ )
     371             :                     {
     372      387669 :                         if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
     373             :                             cThreshold )
     374             :                         {
     375      378042 :                             pWriteAcc->SetPixel( nY, nX, aWhite );
     376             :                         }
     377             :                         else
     378        9627 :                             pWriteAcc->SetPixel( nY, nX, aBlack );
     379             :                     }
     380             :                 }
     381             :             }
     382             : 
     383          39 :             ReleaseAccess( pWriteAcc );
     384          78 :             bRet = true;
     385             :         }
     386             : 
     387          39 :         ReleaseAccess( pReadAcc );
     388             : 
     389          39 :         if( bRet )
     390             :         {
     391          39 :             const MapMode aMap( maPrefMapMode );
     392          39 :             const Size aSize( maPrefSize );
     393             : 
     394          39 :             *this = aNewBmp;
     395             : 
     396          39 :             maPrefMapMode = aMap;
     397          39 :             maPrefSize = aSize;
     398          39 :         }
     399             :     }
     400             : 
     401          39 :     return bRet;
     402             : }
     403             : 
     404           0 : bool Bitmap::ImplMakeMonoDither()
     405             : {
     406           0 :     BitmapReadAccess* pReadAcc = AcquireReadAccess();
     407           0 :     bool bRet = false;
     408             : 
     409           0 :     if( pReadAcc )
     410             :     {
     411           0 :         Bitmap aNewBmp( GetSizePixel(), 1 );
     412           0 :         BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
     413             : 
     414           0 :         if( pWriteAcc )
     415             :         {
     416           0 :             const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
     417           0 :             const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
     418           0 :             const long nWidth = pWriteAcc->Width();
     419           0 :             const long nHeight = pWriteAcc->Height();
     420             :             sal_uInt8 pDitherMatrix[ 16 ][ 16 ];
     421             : 
     422           0 :             ImplCreateDitherMatrix( &pDitherMatrix );
     423             : 
     424           0 :             if( pReadAcc->HasPalette() )
     425             :             {
     426           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
     427             :                 {
     428           0 :                     for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
     429             :                     {
     430           0 :                         const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
     431           0 :                         if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >
     432           0 :                             pDitherMatrix[ nModY ][ nX % 16 ] )
     433             :                         {
     434           0 :                             pWriteAcc->SetPixel( nY, nX, aWhite );
     435             :                         }
     436             :                         else
     437           0 :                             pWriteAcc->SetPixel( nY, nX, aBlack );
     438             :                     }
     439             :                 }
     440             :             }
     441             :             else
     442             :             {
     443           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
     444             :                 {
     445           0 :                     for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
     446             :                     {
     447           0 :                         if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
     448           0 :                             pDitherMatrix[ nModY ][ nX % 16 ] )
     449             :                         {
     450           0 :                             pWriteAcc->SetPixel( nY, nX, aWhite );
     451             :                         }
     452             :                         else
     453           0 :                             pWriteAcc->SetPixel( nY, nX, aBlack );
     454             :                     }
     455             :                 }
     456             :             }
     457             : 
     458           0 :             ReleaseAccess( pWriteAcc );
     459           0 :             bRet = true;
     460             :         }
     461             : 
     462           0 :         ReleaseAccess( pReadAcc );
     463             : 
     464           0 :         if( bRet )
     465             :         {
     466           0 :             const MapMode aMap( maPrefMapMode );
     467           0 :             const Size aSize( maPrefSize );
     468             : 
     469           0 :             *this = aNewBmp;
     470             : 
     471           0 :             maPrefMapMode = aMap;
     472           0 :             maPrefSize = aSize;
     473           0 :         }
     474             :     }
     475             : 
     476           0 :     return bRet;
     477             : }
     478             : 
     479      191827 : bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
     480             : {
     481             :     DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" );
     482             : 
     483      191827 :     BitmapReadAccess* pReadAcc = AcquireReadAccess();
     484      191827 :     bool bRet = false;
     485             : 
     486      191827 :     if( pReadAcc )
     487             :     {
     488      191827 :         const BitmapPalette& rPal = GetGreyPalette( nGreys );
     489      191827 :         sal_uLong nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
     490      191827 :         bool bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
     491             : 
     492      191827 :         if( !bPalDiffers )
     493      175763 :             bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
     494             : 
     495      191827 :         if( bPalDiffers )
     496             :         {
     497       16064 :             Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
     498       16064 :             BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
     499             : 
     500       16064 :             if( pWriteAcc )
     501             :             {
     502       16064 :                 const long nWidth = pWriteAcc->Width();
     503       16064 :                 const long nHeight = pWriteAcc->Height();
     504             : 
     505       16064 :                 if( pReadAcc->HasPalette() )
     506             :                 {
     507        5730 :                     for( long nY = 0L; nY < nHeight; nY++ )
     508             :                     {
     509      100128 :                         for( long nX = 0L; nX < nWidth; nX++ )
     510             :                         {
     511       94720 :                             const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
     512             :                             pWriteAcc->SetPixelIndex( nY, nX,
     513       94720 :                                 (pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
     514             :                         }
     515             :                     }
     516             :                 }
     517       15742 :                 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
     518           0 :                          pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
     519             :                 {
     520           0 :                     nShift += 8;
     521             : 
     522           0 :                     for( long nY = 0L; nY < nHeight; nY++ )
     523             :                     {
     524           0 :                         Scanline pReadScan = pReadAcc->GetScanline( nY );
     525           0 :                         Scanline pWriteScan = pWriteAcc->GetScanline( nY );
     526             : 
     527           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     528             :                         {
     529           0 :                             const sal_uLong nB = *pReadScan++;
     530           0 :                             const sal_uLong nG = *pReadScan++;
     531           0 :                             const sal_uLong nR = *pReadScan++;
     532             : 
     533           0 :                             *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
     534             :                         }
     535             :                     }
     536             :                 }
     537       15742 :                 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
     538           0 :                          pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
     539             :                 {
     540           0 :                     nShift += 8;
     541             : 
     542           0 :                     for( long nY = 0L; nY < nHeight; nY++ )
     543             :                     {
     544           0 :                         Scanline pReadScan = pReadAcc->GetScanline( nY );
     545           0 :                         Scanline pWriteScan = pWriteAcc->GetScanline( nY );
     546             : 
     547           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     548             :                         {
     549           0 :                             const sal_uLong nR = *pReadScan++;
     550           0 :                             const sal_uLong nG = *pReadScan++;
     551           0 :                             const sal_uLong nB = *pReadScan++;
     552             : 
     553           0 :                             *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
     554             :                         }
     555             :                     }
     556             :                 }
     557             :                 else
     558             :                 {
     559     1595781 :                     for( long nY = 0L; nY < nHeight; nY++ )
     560   231574554 :                         for( long nX = 0L; nX < nWidth; nX++ )
     561   229994515 :                             pWriteAcc->SetPixelIndex( nY, nX, (pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift );
     562             :                 }
     563             : 
     564       16064 :                 ReleaseAccess( pWriteAcc );
     565       16064 :                 bRet = true;
     566             :             }
     567             : 
     568       16064 :             ReleaseAccess( pReadAcc );
     569             : 
     570       16064 :             if( bRet )
     571             :             {
     572       16064 :                 const MapMode aMap( maPrefMapMode );
     573       16064 :                 const Size aSize( maPrefSize );
     574             : 
     575       16064 :                 *this = aNewBmp;
     576             : 
     577       16064 :                 maPrefMapMode = aMap;
     578       16064 :                 maPrefSize = aSize;
     579       16064 :             }
     580             :         }
     581             :         else
     582             :         {
     583      175763 :             ReleaseAccess( pReadAcc );
     584      175763 :             bRet = true;
     585             :         }
     586             :     }
     587             : 
     588      191827 :     return bRet;
     589             : }
     590             : 
     591          70 : bool Bitmap::ImplConvertUp(sal_uInt16 nBitCount, Color* pExtColor)
     592             : {
     593             :     DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
     594             : 
     595          70 :     Bitmap::ScopedReadAccess pReadAcc(*this);
     596          70 :     bool bRet = false;
     597             : 
     598          70 :     if (pReadAcc)
     599             :     {
     600          70 :         BitmapPalette aPalette;
     601         140 :         Bitmap aNewBmp(GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPalette);
     602         140 :         Bitmap::ScopedWriteAccess pWriteAcc(aNewBmp);
     603             : 
     604          70 :         if (pWriteAcc)
     605             :         {
     606          70 :             const long nWidth = pWriteAcc->Width();
     607          70 :             const long nHeight = pWriteAcc->Height();
     608             : 
     609          70 :             if (pWriteAcc->HasPalette())
     610             :             {
     611           0 :                 const sal_uInt16 nOldCount = 1 << GetBitCount();
     612           0 :                 const BitmapPalette& rOldPalette = pReadAcc->GetPalette();
     613             : 
     614           0 :                 aPalette.SetEntryCount(1 << nBitCount);
     615             : 
     616           0 :                 for (sal_uInt16 i = 0; i < nOldCount; i++)
     617           0 :                     aPalette[i] = rOldPalette[i];
     618             : 
     619           0 :                 if (pExtColor)
     620           0 :                     aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
     621             : 
     622           0 :                 pWriteAcc->SetPalette(aPalette);
     623             : 
     624           0 :                 for (long nY = 0L; nY < nHeight; nY++)
     625             :                 {
     626           0 :                     for (long nX = 0L; nX < nWidth; nX++)
     627             :                     {
     628           0 :                         pWriteAcc->SetPixel(nY, nX, pReadAcc->GetPixel(nY, nX));
     629             :                     }
     630             :                 }
     631             :             }
     632             :             else
     633             :             {
     634          70 :                 if (pReadAcc->HasPalette())
     635             :                 {
     636        2212 :                     for (long nY = 0L; nY < nHeight; nY++)
     637             :                     {
     638      145640 :                         for (long nX = 0L; nX < nWidth; nX++)
     639             :                         {
     640      143498 :                             pWriteAcc->SetPixel(nY, nX, pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(nY, nX)));
     641             :                         }
     642             :                     }
     643             :                 }
     644             :                 else
     645             :                 {
     646           0 :                     for (long nY = 0L; nY < nHeight; nY++)
     647             :                     {
     648           0 :                         for (long nX = 0L; nX < nWidth; nX++)
     649             :                         {
     650           0 :                             pWriteAcc->SetPixel(nY, nX, pReadAcc->GetPixel(nY, nX));
     651             :                         }
     652             :                     }
     653             :                 }
     654             :             }
     655          70 :             bRet = true;
     656             :         }
     657             : 
     658          70 :         if (bRet)
     659             :         {
     660          70 :             const MapMode aMap(maPrefMapMode);
     661          70 :             const Size aSize(maPrefSize);
     662             : 
     663          70 :             *this = aNewBmp;
     664             : 
     665          70 :             maPrefMapMode = aMap;
     666          70 :             maPrefSize = aSize;
     667          70 :         }
     668             :     }
     669             : 
     670          70 :     return bRet;
     671             : }
     672             : 
     673         559 : bool Bitmap::ImplConvertDown(sal_uInt16 nBitCount, Color* pExtColor)
     674             : {
     675             :     DBG_ASSERT(nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!");
     676             : 
     677         559 :     Bitmap::ScopedReadAccess pReadAcc(*this);
     678         559 :     bool bRet = false;
     679             : 
     680         559 :     if (pReadAcc)
     681             :     {
     682         559 :         BitmapPalette aPalette;
     683        1118 :         Bitmap aNewBmp(GetSizePixel(), nBitCount, &aPalette);
     684        1118 :         Bitmap::ScopedWriteAccess pWriteAcc(aNewBmp);
     685             : 
     686         559 :         if (pWriteAcc)
     687             :         {
     688         559 :             const sal_uInt16 nCount = 1 << nBitCount;
     689         559 :             const long nWidth = pWriteAcc->Width();
     690         559 :             const long nWidth1 = nWidth - 1L;
     691         559 :             const long nHeight = pWriteAcc->Height();
     692         559 :             Octree aOctree(*pReadAcc, pExtColor ? (nCount - 1) : nCount);
     693         559 :             aPalette = aOctree.GetPalette();
     694        1118 :             InverseColorMap aColorMap(aPalette);
     695        1118 :             BitmapColor aColor;
     696         559 :             ImpErrorQuad aErrQuad;
     697        1118 :             std::vector<ImpErrorQuad> pErrQuad1(nWidth);
     698        1118 :             std::vector<ImpErrorQuad> pErrQuad2(nWidth);
     699         559 :             ImpErrorQuad* pQLine1 = pErrQuad1.data();
     700         559 :             ImpErrorQuad* pQLine2 = NULL;
     701         559 :             long nYTmp = 0L;
     702             :             sal_uInt8 cIndex;
     703         559 :             bool bQ1 = true;
     704             : 
     705         559 :             if (pExtColor)
     706             :             {
     707           4 :                 aPalette.SetEntryCount(aPalette.GetEntryCount() + 1);
     708           4 :                 aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
     709             :             }
     710             : 
     711             :             // set Black/White always, if we have enough space
     712         559 :             if (aPalette.GetEntryCount() < (nCount - 1))
     713             :             {
     714         447 :                 aPalette.SetEntryCount(aPalette.GetEntryCount() + 2);
     715         447 :                 aPalette[aPalette.GetEntryCount() - 2] = Color(COL_BLACK);
     716         447 :                 aPalette[aPalette.GetEntryCount() - 1] = Color(COL_WHITE);
     717             :             }
     718             : 
     719         559 :             pWriteAcc->SetPalette(aPalette);
     720             : 
     721        1677 :             for (long nY = 0L; nY < std::min(nHeight, 2L); nY++, nYTmp++)
     722             :             {
     723        1118 :                 pQLine2 = !nY ? pErrQuad1.data() : pErrQuad2.data();
     724      106784 :                 for (long nX = 0L; nX < nWidth; nX++)
     725             :                 {
     726      105666 :                     if (pReadAcc->HasPalette())
     727         104 :                         pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(nYTmp, nX));
     728             :                     else
     729      105562 :                         pQLine2[nX] = pReadAcc->GetPixel(nYTmp, nX);
     730             :                 }
     731             :             }
     732             : 
     733       54328 :             for (long nY = 0L; nY < nHeight; nY++, nYTmp++)
     734             :             {
     735             :                 // first pixel in the line
     736       53769 :                 cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex(pQLine1[0].ImplGetColor());
     737       53769 :                 pWriteAcc->SetPixelIndex(nY, 0, cIndex);
     738             : 
     739             :                 long nX;
     740     7155406 :                 for (nX = 1L; nX < nWidth1; nX++)
     741             :                 {
     742     7101637 :                     aColor = pQLine1[nX].ImplGetColor();
     743     7101637 :                     cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(aColor));
     744     7101637 :                     aErrQuad = (ImpErrorQuad(aColor) -= pWriteAcc->GetPaletteColor(cIndex));
     745     7101637 :                     pQLine1[++nX].ImplAddColorError7(aErrQuad);
     746     7101637 :                     pQLine2[nX--].ImplAddColorError1(aErrQuad);
     747     7101637 :                     pQLine2[nX--].ImplAddColorError5(aErrQuad);
     748     7101637 :                     pQLine2[nX++].ImplAddColorError3(aErrQuad);
     749     7101637 :                     pWriteAcc->SetPixelIndex(nY, nX, cIndex);
     750             :                 }
     751             : 
     752             :                 // Last RowPixel
     753       53769 :                 if (nX < nWidth)
     754             :                 {
     755       53769 :                     cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[nWidth1].ImplGetColor()));
     756       53769 :                     pWriteAcc->SetPixelIndex(nY, nX, cIndex);
     757             :                 }
     758             : 
     759             :                 // Refill/copy row buffer
     760       53769 :                 pQLine1 = pQLine2;
     761       53769 :                 pQLine2 = (bQ1 = !bQ1) ? pErrQuad2.data() : pErrQuad1.data();
     762             : 
     763       53769 :                 if (nYTmp < nHeight)
     764             :                 {
     765     7156160 :                     for (nX = 0L; nX < nWidth; nX++)
     766             :                     {
     767     7103509 :                         if (pReadAcc->HasPalette())
     768         584 :                             pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(nYTmp, nX));
     769             :                         else
     770     7102925 :                             pQLine2[nX] = pReadAcc->GetPixel(nYTmp, nX);
     771             :                     }
     772             :                 }
     773             :             }
     774             : 
     775        1118 :             bRet = true;
     776             :         }
     777             : 
     778         559 :         if(bRet)
     779             :         {
     780         559 :             const MapMode aMap(maPrefMapMode);
     781         559 :             const Size aSize(maPrefSize);
     782             : 
     783         559 :             *this = aNewBmp;
     784             : 
     785         559 :             maPrefMapMode = aMap;
     786         559 :             maPrefSize = aSize;
     787         559 :         }
     788             :     }
     789             : 
     790         559 :     return bRet;
     791             : }
     792             : 
     793           0 : bool Bitmap::ImplConvertGhosted()
     794             : {
     795           0 :     Bitmap aNewBmp;
     796           0 :     BitmapReadAccess* pR = AcquireReadAccess();
     797           0 :     bool bRet = false;
     798             : 
     799           0 :     if( pR )
     800             :     {
     801           0 :         if( pR->HasPalette() )
     802             :         {
     803           0 :             BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
     804             : 
     805           0 :             for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
     806             :             {
     807           0 :                 const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i );
     808           0 :                 aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
     809           0 :                                                      ( rOld.GetGreen() >> 1 ) | 0x80,
     810           0 :                                                      ( rOld.GetBlue() >> 1 ) | 0x80 );
     811             :             }
     812             : 
     813           0 :             aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
     814           0 :             BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
     815             : 
     816           0 :             if( pW )
     817             :             {
     818           0 :                 pW->CopyBuffer( *pR );
     819           0 :                 ReleaseAccess( pW );
     820           0 :                 bRet = true;
     821           0 :             }
     822             :         }
     823             :         else
     824             :         {
     825           0 :             aNewBmp = Bitmap( GetSizePixel(), 24 );
     826             : 
     827           0 :             BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
     828             : 
     829           0 :             if( pW )
     830             :             {
     831           0 :                 const long nWidth = pR->Width(), nHeight = pR->Height();
     832             : 
     833           0 :                 for( long nY = 0; nY < nHeight; nY++ )
     834             :                 {
     835           0 :                     for( long nX = 0; nX < nWidth; nX++ )
     836             :                     {
     837           0 :                         const BitmapColor aOld( pR->GetPixel( nY, nX ) );
     838           0 :                         pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
     839           0 :                                                            ( aOld.GetGreen() >> 1 ) | 0x80,
     840           0 :                                                            ( aOld.GetBlue() >> 1 ) | 0x80 ) );
     841             : 
     842           0 :                     }
     843             :                 }
     844             : 
     845           0 :                 ReleaseAccess( pW );
     846           0 :                 bRet = true;
     847             :             }
     848             :         }
     849             : 
     850           0 :         ReleaseAccess( pR );
     851             :     }
     852             : 
     853           0 :     if( bRet )
     854             :     {
     855           0 :         const MapMode aMap( maPrefMapMode );
     856           0 :         const Size aSize( maPrefSize );
     857             : 
     858           0 :         *this = aNewBmp;
     859             : 
     860           0 :         maPrefMapMode = aMap;
     861           0 :         maPrefSize = aSize;
     862             :     }
     863             : 
     864           0 :     return bRet;
     865             : }
     866             : 
     867        4620 : bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
     868             : {
     869        4620 :     bool bRetval(false);
     870             : 
     871        4620 :     const sal_uInt16 nStartCount(GetBitCount());
     872             : 
     873        4620 :     if(basegfx::fTools::equalZero(rScaleX) || basegfx::fTools::equalZero(rScaleY))
     874             :     {
     875             :         // no scale
     876           0 :         bRetval = true;
     877             :     }
     878             : 
     879        4620 :     if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
     880             :     {
     881             :         // no scale
     882         658 :         bRetval = true;
     883             :     }
     884             : 
     885        4620 :     if( mpImpBmp )
     886             :     {
     887             :         // implementation specific scaling
     888        4620 :         ImpBitmap* pImpBmp = new ImpBitmap;
     889             : 
     890        4620 :         if( pImpBmp->ImplCreate( *mpImpBmp ) && pImpBmp->ImplScale( rScaleX, rScaleY, nScaleFlag ) )
     891             :         {
     892           0 :             ImplSetImpBitmap( pImpBmp );
     893             :             SAL_INFO( "vcl.opengl", "Ref count: " << mpImpBmp->ImplGetRefCount() );
     894           0 :             maPrefMapMode = MapMode( MAP_PIXEL );
     895           0 :             maPrefSize = pImpBmp->ImplGetSize();
     896           0 :             return true;
     897             :         }
     898             :         else
     899             :         {
     900        4620 :             delete pImpBmp;
     901             :         }
     902             :     }
     903             : 
     904             :     //fdo#33455
     905             :     //
     906             :     //If we start with a 1 bit image, then after scaling it in any mode except
     907             :     //BmpScaleFlag::Fast we have a 24bit image which is perfectly correct, but we
     908             :     //are going to down-shift it to mono again and Bitmap::ImplMakeMono just
     909             :     //has "Bitmap aNewBmp( GetSizePixel(), 1 );" to create a 1 bit bitmap which
     910             :     //will default to black/white and the colors mapped to which ever is closer
     911             :     //to black/white
     912             :     //
     913             :     //So the easiest thing to do to retain the colors of 1 bit bitmaps is to
     914             :     //just use the fast scale rather than attempting to count unique colors in
     915             :     //the other converters and pass all the info down through
     916             :     //Bitmap::ImplMakeMono
     917        4620 :     if (nStartCount == 1 && nScaleFlag != BmpScaleFlag::NONE)
     918           2 :         nScaleFlag = BmpScaleFlag::Fast;
     919             : 
     920        4620 :     switch(nScaleFlag)
     921             :     {
     922             :         case BmpScaleFlag::NONE :
     923             :         {
     924           0 :             bRetval = false;
     925           0 :             break;
     926             :         }
     927             :         case BmpScaleFlag::Fast :
     928             :         {
     929         572 :             bRetval = ImplScaleFast( rScaleX, rScaleY );
     930         572 :             break;
     931             :         }
     932             :         case BmpScaleFlag::Interpolate :
     933             :         {
     934         295 :             bRetval = ImplScaleInterpolate( rScaleX, rScaleY );
     935         295 :             break;
     936             :         }
     937             :         case BmpScaleFlag::Super:
     938             :         case BmpScaleFlag::Default:
     939             :         {
     940        2716 :             if (GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
     941             :             {
     942             :                 // fallback to ImplScaleFast
     943        1920 :                 bRetval = ImplScaleFast( rScaleX, rScaleY );
     944             :             }
     945             :             else
     946             :             {
     947         796 :                 BitmapScaleSuper aScaleSuper(rScaleX, rScaleY);
     948         796 :                 bRetval = aScaleSuper.filter(*this);
     949             :             }
     950        2716 :             break;
     951             :         }
     952             :         case BmpScaleFlag::Lanczos :
     953             :         case BmpScaleFlag::BestQuality:
     954             :         {
     955        1034 :             const Lanczos3Kernel kernel;
     956             : 
     957        1034 :             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
     958        1034 :             break;
     959             :         }
     960             :         case BmpScaleFlag::BiCubic :
     961             :         {
     962           1 :             const BicubicKernel kernel;
     963             : 
     964           1 :             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
     965           1 :             break;
     966             :         }
     967             :         case BmpScaleFlag::BiLinear :
     968             :         {
     969           1 :             const BilinearKernel kernel;
     970             : 
     971           1 :             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
     972           1 :             break;
     973             :         }
     974             :         case BmpScaleFlag::Box :
     975             :         {
     976           1 :             const BoxKernel kernel;
     977             : 
     978           1 :             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
     979           1 :             break;
     980             :         }
     981             :     }
     982             : 
     983             :     OSL_ENSURE(!bRetval || nStartCount == GetBitCount(), "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
     984        4620 :     return bRetval;
     985             : }
     986             : 
     987          89 : bool Bitmap::Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag )
     988             : {
     989          89 :     const Size aSize( GetSizePixel() );
     990             :     bool bRet;
     991             : 
     992          89 :     if( aSize.Width() && aSize.Height() )
     993             :     {
     994          89 :         bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
     995          89 :                       (double) rNewSize.Height() / aSize.Height(),
     996         178 :                       nScaleFlag );
     997             :     }
     998             :     else
     999           0 :         bRet = true;
    1000             : 
    1001          89 :     return bRet;
    1002             : }
    1003             : 
    1004         129 : bool Bitmap::HasFastScale()
    1005             : {
    1006         129 :     return OpenGLHelper::isVCLOpenGLEnabled();
    1007             : }
    1008             : 
    1009         864 : void Bitmap::AdaptBitCount(Bitmap& rNew) const
    1010             : {
    1011         864 :     ImplAdaptBitCount(rNew);
    1012         864 : }
    1013             : 
    1014        2196 : void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const
    1015             : {
    1016             :     // aNew is the result of some operation; adapt it's BitCount to the original (this)
    1017        2196 :     if(GetBitCount() != rNew.GetBitCount())
    1018             :     {
    1019         895 :         switch(GetBitCount())
    1020             :         {
    1021             :             case 1:
    1022             :             {
    1023           0 :                 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
    1024           0 :                 break;
    1025             :             }
    1026             :             case 4:
    1027             :             {
    1028           2 :                 if(HasGreyPalette())
    1029             :                 {
    1030           0 :                     rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
    1031             :                 }
    1032             :                 else
    1033             :                 {
    1034           2 :                     rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
    1035             :                 }
    1036           2 :                 break;
    1037             :             }
    1038             :             case 8:
    1039             :             {
    1040         893 :                 if(HasGreyPalette())
    1041             :                 {
    1042         870 :                     rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
    1043             :                 }
    1044             :                 else
    1045             :                 {
    1046          23 :                     rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
    1047             :                 }
    1048         893 :                 break;
    1049             :             }
    1050             :             case 24:
    1051             :             {
    1052           0 :                 rNew.Convert(BMP_CONVERSION_24BIT);
    1053           0 :                 break;
    1054             :             }
    1055             :             default:
    1056             :             {
    1057             :                 OSL_ENSURE(false, "BitDepth adaption failed (!)");
    1058           0 :                 break;
    1059             :             }
    1060             :         }
    1061             :     }
    1062        2196 : }
    1063             : 
    1064        2492 : bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
    1065             : {
    1066        2492 :     const Size aSizePix( GetSizePixel() );
    1067        2492 :     const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
    1068        2492 :     const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
    1069        2492 :     bool bRet = false;
    1070             : 
    1071        2492 :     if( nNewWidth && nNewHeight )
    1072             :     {
    1073        2492 :         BitmapReadAccess* pReadAcc = AcquireReadAccess();
    1074             : 
    1075        2492 :         if(pReadAcc)
    1076             :         {
    1077        2492 :             Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
    1078        2492 :             BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
    1079             : 
    1080        2492 :             if( pWriteAcc )
    1081             :             {
    1082        2492 :                 const long nScanlineSize = pWriteAcc->GetScanlineSize();
    1083        2492 :                 const long nNewWidth1 = nNewWidth - 1L;
    1084        2492 :                 const long nNewHeight1 = nNewHeight - 1L;
    1085             : 
    1086        2492 :                 if( nNewWidth1 && nNewHeight1 )
    1087             :                 {
    1088        2492 :                     const double nWidth = pReadAcc->Width();
    1089        2492 :                     const double nHeight = pReadAcc->Height();
    1090        2492 :                     boost::scoped_array<long> pLutX(new long[ nNewWidth ]);
    1091        4984 :                     boost::scoped_array<long> pLutY(new long[ nNewHeight ]);
    1092             : 
    1093      377508 :                     for( long nX = 0L; nX < nNewWidth; nX++ )
    1094      375016 :                         pLutX[ nX ] = long(nX * nWidth / nNewWidth);
    1095             : 
    1096      496943 :                     for( long nY = 0L; nY < nNewHeight; nY++ )
    1097      494451 :                         pLutY[ nY ] = long(nY * nHeight / nNewHeight);
    1098             : 
    1099        2492 :                     long nActY = 0L;
    1100      127357 :                     while( nActY < nNewHeight )
    1101             :                     {
    1102      122373 :                         long nMapY = pLutY[ nActY ];
    1103             : 
    1104     3972989 :                         for( long nX = 0L; nX < nNewWidth; nX++ )
    1105     3850616 :                             pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
    1106             : 
    1107      616824 :                         while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
    1108             :                         {
    1109      372078 :                             memcpy( pWriteAcc->GetScanline( nActY + 1L ),
    1110      744156 :                                     pWriteAcc->GetScanline( nActY ), nScanlineSize );
    1111      372078 :                             nActY++;
    1112             :                         }
    1113      122373 :                         nActY++;
    1114             :                     }
    1115             : 
    1116        2492 :                     bRet = true;
    1117        4984 :                     ReleaseAccess( pWriteAcc );
    1118             :                 }
    1119             :             }
    1120        2492 :             ReleaseAccess( pReadAcc );
    1121             : 
    1122        2492 :             if( bRet )
    1123        2492 :                 ImplAssignWithSize( aNewBmp );
    1124             :         }
    1125             :     }
    1126             : 
    1127        2492 :     return bRet;
    1128             : }
    1129             : 
    1130         295 : bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
    1131             : {
    1132         295 :     const Size aSizePix( GetSizePixel() );
    1133         295 :     const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
    1134         295 :     const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
    1135         295 :     bool bRet = false;
    1136             : 
    1137         295 :     if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
    1138             :     {
    1139         295 :         BitmapReadAccess* pReadAcc = AcquireReadAccess();
    1140         295 :         if( pReadAcc )
    1141             :         {
    1142         295 :             long nWidth = pReadAcc->Width();
    1143         295 :             long nHeight = pReadAcc->Height();
    1144         295 :             Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 );
    1145         295 :             BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
    1146             : 
    1147         295 :             if( pWriteAcc )
    1148             :             {
    1149         295 :                 const long nNewWidth1 = nNewWidth - 1L;
    1150         295 :                 const long nWidth1 = pReadAcc->Width() - 1L;
    1151         295 :                 const double fRevScaleX = (double) nWidth1 / nNewWidth1;
    1152             : 
    1153         295 :                 boost::scoped_array<long> pLutInt(new long[ nNewWidth ]);
    1154         590 :                 boost::scoped_array<long> pLutFrac(new long[ nNewWidth ]);
    1155             : 
    1156        3609 :                 for( long nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
    1157             :                 {
    1158        3314 :                     double fTemp = nX * fRevScaleX;
    1159        3314 :                     pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
    1160        3314 :                     fTemp -= pLutInt[ nX ];
    1161        3314 :                     pLutFrac[ nX ] = (long) ( fTemp * 1024. );
    1162             :                 }
    1163             : 
    1164        3056 :                 for( long nY = 0L; nY < nHeight; nY++ )
    1165             :                 {
    1166        2761 :                     if( 1 == nWidth )
    1167             :                     {
    1168           0 :                         BitmapColor aCol0;
    1169           0 :                         if( pReadAcc->HasPalette() )
    1170             :                         {
    1171           0 :                             aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) );
    1172             :                         }
    1173             :                         else
    1174             :                         {
    1175           0 :                             aCol0 = pReadAcc->GetPixel( nY, 0 );
    1176             :                         }
    1177             : 
    1178           0 :                         for( long nX = 0L; nX < nNewWidth; nX++ )
    1179             :                         {
    1180           0 :                             pWriteAcc->SetPixel( nY, nX, aCol0 );
    1181           0 :                         }
    1182             :                     }
    1183             :                     else
    1184             :                     {
    1185       61353 :                         for( long nX = 0L; nX < nNewWidth; nX++ )
    1186             :                         {
    1187       58592 :                             long nTemp = pLutInt[ nX ];
    1188             : 
    1189      117184 :                             BitmapColor aCol0, aCol1;
    1190       58592 :                             if( pReadAcc->HasPalette() )
    1191             :                             {
    1192           0 :                                 aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) );
    1193           0 :                                 aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) );
    1194             :                             }
    1195             :                             else
    1196             :                             {
    1197       58592 :                                 aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
    1198       58592 :                                 aCol1 = pReadAcc->GetPixel( nY, nTemp );
    1199             :                             }
    1200             : 
    1201       58592 :                             nTemp = pLutFrac[ nX ];
    1202             : 
    1203       58592 :                             long lXR0 = aCol0.GetRed();
    1204       58592 :                             long lXG0 = aCol0.GetGreen();
    1205       58592 :                             long lXB0 = aCol0.GetBlue();
    1206       58592 :                             long lXR1 = aCol1.GetRed() - lXR0;
    1207       58592 :                             long lXG1 = aCol1.GetGreen() - lXG0;
    1208       58592 :                             long lXB1 = aCol1.GetBlue() - lXB0;
    1209             : 
    1210       58592 :                             aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
    1211       58592 :                             aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
    1212       58592 :                             aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
    1213             : 
    1214       58592 :                             pWriteAcc->SetPixel( nY, nX, aCol0 );
    1215       58592 :                         }
    1216             :                     }
    1217             :                 }
    1218             : 
    1219         590 :                 bRet = true;
    1220             :             }
    1221             : 
    1222         295 :             ReleaseAccess( pReadAcc );
    1223         295 :             ReleaseAccess( pWriteAcc );
    1224             : 
    1225         295 :             if( bRet )
    1226             :             {
    1227         295 :                 bRet = false;
    1228         295 :                 const Bitmap aOriginal(*this);
    1229         295 :                 *this = aNewBmp;
    1230         295 :                 aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
    1231         295 :                 pReadAcc = AcquireReadAccess();
    1232         295 :                 pWriteAcc = aNewBmp.AcquireWriteAccess();
    1233             : 
    1234         295 :                 if( pReadAcc && pWriteAcc )
    1235             :                 {
    1236         295 :                     const long nNewHeight1 = nNewHeight - 1L;
    1237         295 :                     const long nHeight1 = pReadAcc->Height() - 1L;
    1238         295 :                     const double fRevScaleY = (double) nHeight1 / nNewHeight1;
    1239             : 
    1240         295 :                     boost::scoped_array<long> pLutInt(new long[ nNewHeight ]);
    1241         590 :                     boost::scoped_array<long> pLutFrac(new long[ nNewHeight ]);
    1242             : 
    1243        3902 :                     for( long nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
    1244             :                     {
    1245        3607 :                         double fTemp = nY * fRevScaleY;
    1246        3607 :                         pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
    1247        3607 :                         fTemp -= pLutInt[ nY ];
    1248        3607 :                         pLutFrac[ nY ] = (long) ( fTemp * 1024. );
    1249             :                     }
    1250             : 
    1251             :                     // after 1st step, bitmap *is* 24bit format (see above)
    1252             :                     OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)");
    1253             : 
    1254        3609 :                     for( long nX = 0L; nX < nNewWidth; nX++ )
    1255             :                     {
    1256        3314 :                         if( 1 == nHeight )
    1257             :                         {
    1258           0 :                             BitmapColor aCol0 = pReadAcc->GetPixel( 0, nX );
    1259             : 
    1260           0 :                             for( long nY = 0L; nY < nNewHeight; nY++ )
    1261             :                             {
    1262           0 :                                 pWriteAcc->SetPixel( nY, nX, aCol0 );
    1263           0 :                             }
    1264             :                         }
    1265             :                         else
    1266             :                         {
    1267       48442 :                             for( long nY = 0L; nY < nNewHeight; nY++ )
    1268             :                             {
    1269       45128 :                                 long nTemp = pLutInt[ nY ];
    1270             : 
    1271       45128 :                                 BitmapColor aCol0 = pReadAcc->GetPixel( nTemp++, nX );
    1272       90256 :                                 BitmapColor aCol1 = pReadAcc->GetPixel( nTemp, nX );
    1273             : 
    1274       45128 :                                 nTemp = pLutFrac[ nY ];
    1275             : 
    1276       45128 :                                 long lXR0 = aCol0.GetRed();
    1277       45128 :                                 long lXG0 = aCol0.GetGreen();
    1278       45128 :                                 long lXB0 = aCol0.GetBlue();
    1279       45128 :                                 long lXR1 = aCol1.GetRed() - lXR0;
    1280       45128 :                                 long lXG1 = aCol1.GetGreen() - lXG0;
    1281       45128 :                                 long lXB1 = aCol1.GetBlue() - lXB0;
    1282             : 
    1283       45128 :                                 aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
    1284       45128 :                                 aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
    1285       45128 :                                 aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
    1286             : 
    1287       45128 :                                 pWriteAcc->SetPixel( nY, nX, aCol0 );
    1288       45128 :                             }
    1289             :                         }
    1290             :                     }
    1291             : 
    1292         590 :                     bRet = true;
    1293             :                 }
    1294             : 
    1295         295 :                 ReleaseAccess( pReadAcc );
    1296         295 :                 ReleaseAccess( pWriteAcc );
    1297             : 
    1298         295 :                 if( bRet )
    1299             :                 {
    1300         295 :                     aOriginal.ImplAdaptBitCount(aNewBmp);
    1301         295 :                     *this = aNewBmp;
    1302         295 :                 }
    1303         295 :             }
    1304             :         }
    1305             :     }
    1306             : 
    1307         295 :     if( !bRet )
    1308             :     {
    1309           0 :         bRet = ImplScaleFast( rScaleX, rScaleY );
    1310             :     }
    1311             : 
    1312         295 :     return bRet;
    1313             : }
    1314             : 
    1315             : namespace
    1316             : {
    1317        1968 :     void ImplCalculateContributions(
    1318             :         const sal_uInt32 aSourceSize,
    1319             :         const sal_uInt32 aDestinationSize,
    1320             :         sal_uInt32& aNumberOfContributions,
    1321             :         double*& pWeights,
    1322             :         sal_uInt32*& pPixels,
    1323             :         sal_uInt32*& pCount,
    1324             :         const Kernel& aKernel)
    1325             :     {
    1326        1968 :         const double fSamplingRadius(aKernel.GetWidth());
    1327        1968 :         const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
    1328        1968 :         const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
    1329        1968 :         const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
    1330             : 
    1331        1968 :         aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
    1332        1968 :         const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
    1333        1968 :         pWeights = new double[nAllocSize];
    1334        1968 :         pPixels = new sal_uInt32[nAllocSize];
    1335        1968 :         pCount = new sal_uInt32[aDestinationSize];
    1336             : 
    1337      174461 :         for(sal_uInt32 i(0); i < aDestinationSize; i++)
    1338             :         {
    1339      172493 :             const sal_uInt32 aIndex(i * aNumberOfContributions);
    1340      172493 :             const double aCenter(i / fScale);
    1341      172493 :             const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
    1342      172493 :             const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
    1343      172493 :             sal_uInt32 aCurrentCount(0);
    1344             : 
    1345     3974508 :             for(sal_Int32 j(aLeft); j <= aRight; j++)
    1346             :             {
    1347     3802015 :                 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
    1348             : 
    1349             :                 // Reduce calculations with ignoring weights of 0.0
    1350     3802015 :                 if(fabs(aWeight) < 0.0001)
    1351             :                 {
    1352      426451 :                     continue;
    1353             :                 }
    1354             : 
    1355             :                 // Handling on edges
    1356     3375564 :                 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
    1357     3375564 :                 const sal_uInt32 nIndex(aIndex + aCurrentCount);
    1358             : 
    1359     3375564 :                 pWeights[nIndex] = aWeight;
    1360     3375564 :                 pPixels[nIndex] = aPixelIndex;
    1361             : 
    1362     3375564 :                 aCurrentCount++;
    1363             :             }
    1364             : 
    1365      172493 :             pCount[i] = aCurrentCount;
    1366             :         }
    1367        1968 :     }
    1368             : 
    1369        1005 :     bool ImplScaleConvolutionHor(
    1370             :         Bitmap& rSource,
    1371             :         Bitmap& rTarget,
    1372             :         const double& rScaleX,
    1373             :         const Kernel& aKernel)
    1374             :     {
    1375             :         // Do horizontal filtering
    1376             :         OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
    1377        1005 :         const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
    1378        1005 :         const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
    1379             : 
    1380        1005 :         if(nWidth == nNewWidth)
    1381             :         {
    1382           0 :             return true;
    1383             :         }
    1384             : 
    1385        1005 :         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
    1386             : 
    1387        1005 :         if(pReadAcc)
    1388             :         {
    1389        1005 :             double* pWeights = 0;
    1390        1005 :             sal_uInt32* pPixels = 0;
    1391        1005 :             sal_uInt32* pCount = 0;
    1392        1005 :             sal_uInt32 aNumberOfContributions(0);
    1393             : 
    1394        1005 :             const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
    1395        1005 :             ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
    1396        1005 :             rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
    1397        1005 :             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
    1398        1005 :             bool bResult(0 != pWriteAcc);
    1399             : 
    1400        1005 :             if(bResult)
    1401             :             {
    1402      160822 :                 for(sal_uInt32 y(0); y < nHeight; y++)
    1403             :                 {
    1404    16803519 :                     for(sal_uInt32 x(0); x < nNewWidth; x++)
    1405             :                     {
    1406    16643702 :                         const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
    1407    16643702 :                         double aSum(0.0);
    1408    16643702 :                         double aValueRed(0.0);
    1409    16643702 :                         double aValueGreen(0.0);
    1410    16643702 :                         double aValueBlue(0.0);
    1411             : 
    1412   334942633 :                         for(sal_uInt32 j(0); j < pCount[x]; j++)
    1413             :                         {
    1414   318298931 :                             const sal_uInt32 aIndex(aBaseIndex + j);
    1415   318298931 :                             const double aWeight(pWeights[aIndex]);
    1416   318298931 :                             BitmapColor aColor;
    1417             : 
    1418   318298931 :                             aSum += aWeight;
    1419             : 
    1420   318298931 :                             if(pReadAcc->HasPalette())
    1421             :                             {
    1422   121686457 :                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
    1423             :                             }
    1424             :                             else
    1425             :                             {
    1426   196612474 :                                 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
    1427             :                             }
    1428             : 
    1429   318298931 :                             aValueRed += aWeight * aColor.GetRed();
    1430   318298931 :                             aValueGreen += aWeight * aColor.GetGreen();
    1431   318298931 :                             aValueBlue += aWeight * aColor.GetBlue();
    1432   318298931 :                         }
    1433             : 
    1434             :                         const BitmapColor aResultColor(
    1435    16643702 :                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
    1436    16643702 :                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
    1437    49931106 :                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
    1438             : 
    1439    16643702 :                         pWriteAcc->SetPixel(y, x, aResultColor);
    1440    16643702 :                     }
    1441             :                 }
    1442             : 
    1443        1005 :                 Bitmap::ReleaseAccess(pWriteAcc);
    1444             :             }
    1445             : 
    1446        1005 :             Bitmap::ReleaseAccess(pReadAcc);
    1447        1005 :             delete[] pWeights;
    1448        1005 :             delete[] pCount;
    1449        1005 :             delete[] pPixels;
    1450             : 
    1451        1005 :             if(bResult)
    1452             :             {
    1453        1005 :                 return true;
    1454             :             }
    1455             :         }
    1456             : 
    1457           0 :         return false;
    1458             :     }
    1459             : 
    1460         963 :     bool ImplScaleConvolutionVer(
    1461             :         Bitmap& rSource,
    1462             :         Bitmap& rTarget,
    1463             :         const double& rScaleY,
    1464             :         const Kernel& aKernel)
    1465             :     {
    1466             :         // Do vertical filtering
    1467             :         OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
    1468         963 :         const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
    1469         963 :         const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
    1470             : 
    1471         963 :         if(nHeight == nNewHeight)
    1472             :         {
    1473           0 :             return true;
    1474             :         }
    1475             : 
    1476         963 :         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
    1477             : 
    1478         963 :         if(pReadAcc)
    1479             :         {
    1480         963 :             double* pWeights = 0;
    1481         963 :             sal_uInt32* pPixels = 0;
    1482         963 :             sal_uInt32* pCount = 0;
    1483         963 :             sal_uInt32 aNumberOfContributions(0);
    1484             : 
    1485         963 :             const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
    1486         963 :             ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
    1487         963 :             rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
    1488         963 :             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
    1489         963 :             bool bResult(0 != pWriteAcc);
    1490             : 
    1491         963 :             if(pWriteAcc)
    1492             :             {
    1493      239048 :                 for(sal_uInt32 x(0); x < nWidth; x++)
    1494             :                 {
    1495    17224530 :                     for(sal_uInt32 y(0); y < nNewHeight; y++)
    1496             :                     {
    1497    16986445 :                         const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
    1498    16986445 :                         double aSum(0.0);
    1499    16986445 :                         double aValueRed(0.0);
    1500    16986445 :                         double aValueGreen(0.0);
    1501    16986445 :                         double aValueBlue(0.0);
    1502             : 
    1503   510729986 :                         for(sal_uInt32 j(0); j < pCount[y]; j++)
    1504             :                         {
    1505   493743541 :                             const sal_uInt32 aIndex(aBaseIndex + j);
    1506   493743541 :                             const double aWeight(pWeights[aIndex]);
    1507   493743541 :                             BitmapColor aColor;
    1508             : 
    1509   493743541 :                             aSum += aWeight;
    1510             : 
    1511   493743541 :                             if(pReadAcc->HasPalette())
    1512             :                             {
    1513   222664893 :                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
    1514             :                             }
    1515             :                             else
    1516             :                             {
    1517   271078648 :                                 aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
    1518             :                             }
    1519             : 
    1520   493743541 :                             aValueRed += aWeight * aColor.GetRed();
    1521   493743541 :                             aValueGreen += aWeight * aColor.GetGreen();
    1522   493743541 :                             aValueBlue += aWeight * aColor.GetBlue();
    1523   493743541 :                         }
    1524             : 
    1525             :                         const BitmapColor aResultColor(
    1526    16986445 :                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
    1527    16986445 :                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
    1528    50959335 :                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
    1529             : 
    1530    16986445 :                         if(pWriteAcc->HasPalette())
    1531             :                         {
    1532           0 :                             pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
    1533             :                         }
    1534             :                         else
    1535             :                         {
    1536    16986445 :                             pWriteAcc->SetPixel(y, x, aResultColor);
    1537             :                         }
    1538    16986445 :                     }
    1539             :                 }
    1540             :             }
    1541             : 
    1542         963 :             Bitmap::ReleaseAccess(pWriteAcc);
    1543         963 :             Bitmap::ReleaseAccess(pReadAcc);
    1544             : 
    1545         963 :             delete[] pWeights;
    1546         963 :             delete[] pCount;
    1547         963 :             delete[] pPixels;
    1548             : 
    1549         963 :             if(bResult)
    1550             :             {
    1551         963 :                 return true;
    1552             :             }
    1553             :         }
    1554             : 
    1555           0 :         return false;
    1556             :     }
    1557             : }
    1558             : 
    1559             : // #i121233# Added BmpScaleFlag::Lanczos, BmpScaleFlag::BiCubic, BmpScaleFlag::BiLinear and
    1560             : // BmpScaleFlag::Box derived from the original commit from Tomas Vajngerl (see
    1561             : // bugzilla task for deitails) Thanks!
    1562        1037 : bool Bitmap::ImplScaleConvolution(
    1563             :     const double& rScaleX,
    1564             :     const double& rScaleY,
    1565             :     const Kernel& aKernel)
    1566             : {
    1567        1037 :     const bool bMirrorHor(rScaleX < 0.0);
    1568        1037 :     const bool bMirrorVer(rScaleY < 0.0);
    1569        1037 :     const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
    1570        1037 :     const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
    1571        1037 :     const sal_uInt32 nWidth(GetSizePixel().Width());
    1572        1037 :     const sal_uInt32 nHeight(GetSizePixel().Height());
    1573        1037 :     const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
    1574        1037 :     const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
    1575        1037 :     const bool bScaleHor(nWidth != nNewWidth);
    1576        1037 :     const bool bScaleVer(nHeight != nNewHeight);
    1577        1037 :     const bool bMirror(bMirrorHor || bMirrorVer);
    1578             : 
    1579        1037 :     if(!bMirror && !bScaleHor && !bScaleVer)
    1580             :     {
    1581           0 :         return true;
    1582             :     }
    1583             : 
    1584        1037 :     bool bResult(true);
    1585        1037 :     BmpMirrorFlags nMirrorFlags(BmpMirrorFlags::NONE);
    1586        1037 :     bool bMirrorAfter(false);
    1587             : 
    1588        1037 :     if(bMirror)
    1589             :     {
    1590           0 :         if(bMirrorHor)
    1591             :         {
    1592           0 :             nMirrorFlags |= BmpMirrorFlags::Horizontal;
    1593             :         }
    1594             : 
    1595           0 :         if(bMirrorVer)
    1596             :         {
    1597           0 :             nMirrorFlags |= BmpMirrorFlags::Vertical;
    1598             :         }
    1599             : 
    1600           0 :         const sal_uInt32 nStartSize(nWidth * nHeight);
    1601           0 :         const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
    1602             : 
    1603           0 :         bMirrorAfter = nStartSize > nEndSize;
    1604             : 
    1605           0 :         if(!bMirrorAfter)
    1606             :         {
    1607           0 :             bResult = Mirror(nMirrorFlags);
    1608             :         }
    1609             :     }
    1610             : 
    1611        1037 :     Bitmap aResult;
    1612             : 
    1613        1037 :     if(bResult)
    1614             :     {
    1615        1037 :         const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
    1616        1037 :         const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
    1617        1037 :         Bitmap aSource(*this);
    1618             : 
    1619        1037 :         if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
    1620             :         {
    1621         322 :             if(bScaleHor)
    1622             :             {
    1623         322 :                 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
    1624             :             }
    1625             : 
    1626         322 :             if(bResult && bScaleVer)
    1627             :             {
    1628         248 :                 if(bScaleHor)
    1629             :                 {
    1630             :                     // copy partial result, independent of color depth
    1631         248 :                     aSource = aResult;
    1632             :                 }
    1633             : 
    1634         248 :                 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
    1635             :             }
    1636             :         }
    1637             :         else
    1638             :         {
    1639         715 :             if(bScaleVer)
    1640             :             {
    1641         715 :                 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
    1642             :             }
    1643             : 
    1644         715 :             if(bResult && bScaleHor)
    1645             :             {
    1646         683 :                 if(bScaleVer)
    1647             :                 {
    1648             :                     // copy partial result, independent of color depth
    1649         683 :                     aSource = aResult;
    1650             :                 }
    1651             : 
    1652         683 :                 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
    1653             :             }
    1654        1037 :         }
    1655             :     }
    1656             : 
    1657        1037 :     if(bResult && bMirrorAfter)
    1658             :     {
    1659           0 :         bResult = aResult.Mirror(nMirrorFlags);
    1660             :     }
    1661             : 
    1662        1037 :     if(bResult)
    1663             :     {
    1664        1037 :         ImplAdaptBitCount(aResult);
    1665        1037 :         *this = aResult;
    1666             :     }
    1667             : 
    1668        1037 :     return bResult;
    1669             : }
    1670             : 
    1671           0 : bool Bitmap::Dither( BmpDitherFlags nDitherFlags )
    1672             : {
    1673           0 :     bool bRet = false;
    1674             : 
    1675           0 :     const Size aSizePix( GetSizePixel() );
    1676             : 
    1677           0 :     if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
    1678           0 :         bRet = true;
    1679           0 :     else if( nDitherFlags & BmpDitherFlags::Matrix )
    1680           0 :         bRet = ImplDitherMatrix();
    1681           0 :     else if( nDitherFlags & BmpDitherFlags::Floyd )
    1682           0 :         bRet = ImplDitherFloyd();
    1683           0 :     else if( ( nDitherFlags & BmpDitherFlags::Floyd16 ) && ( GetBitCount() == 24 ) )
    1684           0 :         bRet = ImplDitherFloyd16();
    1685             : 
    1686           0 :     return bRet;
    1687             : }
    1688             : 
    1689           0 : bool Bitmap::ImplDitherMatrix()
    1690             : {
    1691           0 :     BitmapReadAccess* pReadAcc = AcquireReadAccess();
    1692           0 :     Bitmap aNewBmp( GetSizePixel(), 8 );
    1693           0 :     BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
    1694           0 :     bool bRet = false;
    1695             : 
    1696           0 :     if( pReadAcc && pWriteAcc )
    1697             :     {
    1698           0 :         const sal_uLong nWidth = pReadAcc->Width();
    1699           0 :         const sal_uLong nHeight = pReadAcc->Height();
    1700           0 :         BitmapColor aIndex( (sal_uInt8) 0 );
    1701             : 
    1702           0 :         if( pReadAcc->HasPalette() )
    1703             :         {
    1704           0 :             for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
    1705             :             {
    1706           0 :                 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
    1707             :                 {
    1708           0 :                     const BitmapColor aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
    1709           0 :                     const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
    1710           0 :                     const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
    1711           0 :                     const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
    1712           0 :                     const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
    1713             : 
    1714           0 :                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
    1715           0 :                     pWriteAcc->SetPixel( nY, nX, aIndex );
    1716           0 :                 }
    1717             :             }
    1718             :         }
    1719             :         else
    1720             :         {
    1721           0 :             for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
    1722             :             {
    1723           0 :                 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
    1724             :                 {
    1725           0 :                     const BitmapColor aCol( pReadAcc->GetPixel( nY, nX ) );
    1726           0 :                     const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
    1727           0 :                     const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
    1728           0 :                     const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
    1729           0 :                     const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
    1730             : 
    1731           0 :                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
    1732           0 :                     pWriteAcc->SetPixel( nY, nX, aIndex );
    1733           0 :                 }
    1734             :             }
    1735             :         }
    1736             : 
    1737           0 :         bRet = true;
    1738             :     }
    1739             : 
    1740           0 :     ReleaseAccess( pReadAcc );
    1741           0 :     ReleaseAccess( pWriteAcc );
    1742             : 
    1743           0 :     if( bRet )
    1744             :     {
    1745           0 :         const MapMode aMap( maPrefMapMode );
    1746           0 :         const Size aSize( maPrefSize );
    1747             : 
    1748           0 :         *this = aNewBmp;
    1749             : 
    1750           0 :         maPrefMapMode = aMap;
    1751           0 :         maPrefSize = aSize;
    1752             :     }
    1753             : 
    1754           0 :     return bRet;
    1755             : }
    1756             : 
    1757           0 : bool Bitmap::ImplDitherFloyd()
    1758             : {
    1759           0 :     const Size aSize( GetSizePixel() );
    1760           0 :     bool bRet = false;
    1761             : 
    1762           0 :     if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
    1763             :     {
    1764           0 :         BitmapReadAccess* pReadAcc = AcquireReadAccess();
    1765           0 :         Bitmap aNewBmp( GetSizePixel(), 8 );
    1766           0 :         BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
    1767             : 
    1768           0 :         if( pReadAcc && pWriteAcc )
    1769             :         {
    1770           0 :             BitmapColor aColor;
    1771           0 :             long nWidth = pReadAcc->Width();
    1772           0 :             long nWidth1 = nWidth - 1L;
    1773           0 :             long nHeight = pReadAcc->Height();
    1774             :             long nX;
    1775           0 :             long nW = nWidth * 3L;
    1776           0 :             long nW2 = nW - 3L;
    1777             :             long nRErr, nGErr, nBErr;
    1778             :             long nRC, nGC, nBC;
    1779           0 :             boost::scoped_array<long> p1(new long[ nW ]);
    1780           0 :             boost::scoped_array<long> p2(new long[ nW ]);
    1781           0 :             long* p1T = p1.get();
    1782           0 :             long* p2T = p2.get();
    1783             :             long* pTmp;
    1784           0 :             bool bPal = pReadAcc->HasPalette();
    1785             : 
    1786           0 :             pTmp = p2T;
    1787             : 
    1788           0 :             if( bPal )
    1789             :             {
    1790           0 :                 for( long nZ = 0; nZ < nWidth; nZ++ )
    1791             :                 {
    1792           0 :                     aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) );
    1793             : 
    1794           0 :                     *pTmp++ = (long) aColor.GetBlue() << 12;
    1795           0 :                     *pTmp++ = (long) aColor.GetGreen() << 12;
    1796           0 :                     *pTmp++ = (long) aColor.GetRed() << 12;
    1797             :                 }
    1798             :             }
    1799             :             else
    1800             :             {
    1801           0 :                 for( long nZ = 0; nZ < nWidth; nZ++ )
    1802             :                 {
    1803           0 :                     aColor = pReadAcc->GetPixel( 0, nZ );
    1804             : 
    1805           0 :                     *pTmp++ = (long) aColor.GetBlue() << 12;
    1806           0 :                     *pTmp++ = (long) aColor.GetGreen() << 12;
    1807           0 :                     *pTmp++ = (long) aColor.GetRed() << 12;
    1808             :                 }
    1809             :             }
    1810             : 
    1811           0 :             for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
    1812             :             {
    1813           0 :                 pTmp = p1T;
    1814           0 :                 p1T = p2T;
    1815           0 :                 p2T = pTmp;
    1816             : 
    1817           0 :                 if( nY < nHeight )
    1818             :                 {
    1819           0 :                     if( bPal )
    1820             :                     {
    1821           0 :                         for( long nZ = 0; nZ < nWidth; nZ++ )
    1822             :                         {
    1823           0 :                             aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) );
    1824             : 
    1825           0 :                             *pTmp++ = (long) aColor.GetBlue() << 12;
    1826           0 :                             *pTmp++ = (long) aColor.GetGreen() << 12;
    1827           0 :                             *pTmp++ = (long) aColor.GetRed() << 12;
    1828             :                         }
    1829             :                     }
    1830             :                     else
    1831             :                     {
    1832           0 :                         for( long nZ = 0; nZ < nWidth; nZ++ )
    1833             :                         {
    1834           0 :                             aColor = pReadAcc->GetPixel( nY, nZ );
    1835             : 
    1836           0 :                             *pTmp++ = (long) aColor.GetBlue() << 12;
    1837           0 :                             *pTmp++ = (long) aColor.GetGreen() << 12;
    1838           0 :                             *pTmp++ = (long) aColor.GetRed() << 12;
    1839             :                         }
    1840             :                     }
    1841             :                 }
    1842             : 
    1843             :                 // Examine first Pixel separately
    1844           0 :                 nX = 0;
    1845             :                 long nTemp;
    1846           0 :                 CALC_ERRORS;
    1847           0 :                 CALC_TABLES7;
    1848           0 :                 nX -= 5;
    1849           0 :                 CALC_TABLES5;
    1850           0 :                 pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
    1851             : 
    1852             :                 // Get middle Pixels using a loop
    1853             :                 long nXAcc;
    1854           0 :                 for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
    1855             :                 {
    1856           0 :                     CALC_ERRORS;
    1857           0 :                     CALC_TABLES7;
    1858           0 :                     nX -= 8;
    1859           0 :                     CALC_TABLES3;
    1860           0 :                     CALC_TABLES5;
    1861           0 :                     pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
    1862             :                 }
    1863             : 
    1864             :                 // Treat last Pixel separately
    1865           0 :                 CALC_ERRORS;
    1866           0 :                 nX -= 5;
    1867           0 :                 CALC_TABLES3;
    1868           0 :                 CALC_TABLES5;
    1869           0 :                 pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
    1870             :             }
    1871             : 
    1872           0 :             bRet = true;
    1873             :         }
    1874             : 
    1875           0 :         ReleaseAccess( pReadAcc );
    1876           0 :         ReleaseAccess( pWriteAcc );
    1877             : 
    1878           0 :         if( bRet )
    1879             :         {
    1880           0 :             const MapMode aMap( maPrefMapMode );
    1881           0 :             const Size aPrefSize( maPrefSize );
    1882             : 
    1883           0 :             *this = aNewBmp;
    1884             : 
    1885           0 :             maPrefMapMode = aMap;
    1886           0 :             maPrefSize = aPrefSize;
    1887           0 :         }
    1888             :     }
    1889             : 
    1890           0 :     return bRet;
    1891             : }
    1892             : 
    1893           0 : bool Bitmap::ImplDitherFloyd16()
    1894             : {
    1895           0 :     BitmapReadAccess* pReadAcc = AcquireReadAccess();
    1896           0 :     Bitmap aNewBmp( GetSizePixel(), 24 );
    1897           0 :     BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
    1898           0 :     bool bRet = false;
    1899             : 
    1900           0 :     if( pReadAcc && pWriteAcc )
    1901             :     {
    1902           0 :         const long nWidth = pWriteAcc->Width();
    1903           0 :         const long nWidth1 = nWidth - 1L;
    1904           0 :         const long nHeight = pWriteAcc->Height();
    1905           0 :         BitmapColor aColor;
    1906           0 :         BitmapColor aBestCol;
    1907           0 :         ImpErrorQuad aErrQuad;
    1908           0 :         boost::scoped_array<ImpErrorQuad> pErrQuad1(new ImpErrorQuad[ nWidth ]);
    1909           0 :         boost::scoped_array<ImpErrorQuad> pErrQuad2(new ImpErrorQuad[ nWidth ]);
    1910           0 :         ImpErrorQuad* pQLine1 = pErrQuad1.get();
    1911           0 :         ImpErrorQuad* pQLine2 = 0;
    1912           0 :         long nYTmp = 0L;
    1913           0 :         bool bQ1 = true;
    1914             : 
    1915           0 :         for( long nY = 0L; nY < std::min( nHeight, 2L ); nY++, nYTmp++ )
    1916             :         {
    1917           0 :             pQLine2 = !nY ? pErrQuad1.get() : pErrQuad2.get();
    1918           0 :             for( long nX = 0L; nX < nWidth; nX++ )
    1919           0 :                 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
    1920             :         }
    1921             : 
    1922           0 :         for( long nY = 0L; nY < nHeight; nY++, nYTmp++ )
    1923             :         {
    1924             :             // First RowPixel
    1925           0 :             aBestCol = pQLine1[ 0 ].ImplGetColor();
    1926           0 :             aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
    1927           0 :             aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
    1928           0 :             aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
    1929           0 :             pWriteAcc->SetPixel( nY, 0, aBestCol );
    1930             : 
    1931             :             long nX;
    1932           0 :             for( nX = 1L; nX < nWidth1; nX++ )
    1933             :             {
    1934           0 :                 aColor = pQLine1[ nX ].ImplGetColor();
    1935           0 :                 aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
    1936           0 :                 aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
    1937           0 :                 aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
    1938           0 :                 aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
    1939           0 :                 pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
    1940           0 :                 pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
    1941           0 :                 pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
    1942           0 :                 pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
    1943           0 :                 pWriteAcc->SetPixel( nY, nX, aBestCol );
    1944             :             }
    1945             : 
    1946             :             // Last RowPixel
    1947           0 :             aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
    1948           0 :             aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
    1949           0 :             aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
    1950           0 :             aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
    1951           0 :             pWriteAcc->SetPixel( nY, nX, aBestCol );
    1952             : 
    1953             :             // Refill/copy row buffer
    1954           0 :             pQLine1 = pQLine2;
    1955           0 :             pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2.get() : pErrQuad1.get();
    1956             : 
    1957           0 :             if( nYTmp < nHeight )
    1958           0 :                 for( nX = 0L; nX < nWidth; nX++ )
    1959           0 :                     pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
    1960             :         }
    1961             : 
    1962           0 :         bRet = true;
    1963             :     }
    1964             : 
    1965           0 :     ReleaseAccess( pReadAcc );
    1966           0 :     ReleaseAccess( pWriteAcc );
    1967             : 
    1968           0 :     if( bRet )
    1969             :     {
    1970           0 :         const MapMode aMap( maPrefMapMode );
    1971           0 :         const Size aSize( maPrefSize );
    1972             : 
    1973           0 :         *this = aNewBmp;
    1974             : 
    1975           0 :         maPrefMapMode = aMap;
    1976           0 :         maPrefSize = aSize;
    1977             :     }
    1978             : 
    1979           0 :     return bRet;
    1980             : }
    1981             : 
    1982           0 : bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
    1983             : {
    1984             :     bool bRet;
    1985             : 
    1986           0 :     if( GetColorCount() <= (sal_uLong) nColorCount )
    1987           0 :         bRet = true;
    1988           0 :     else if( nColorCount )
    1989             :     {
    1990           0 :         if( BMP_REDUCE_SIMPLE == eReduce )
    1991           0 :             bRet = ImplReduceSimple( nColorCount );
    1992           0 :         else if( BMP_REDUCE_POPULAR == eReduce )
    1993           0 :             bRet = ImplReducePopular( nColorCount );
    1994             :         else
    1995           0 :             bRet = ImplReduceMedian( nColorCount );
    1996             :     }
    1997             :     else
    1998           0 :         bRet = false;
    1999             : 
    2000           0 :     return bRet;
    2001             : }
    2002             : 
    2003           0 : bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
    2004             : {
    2005           0 :     Bitmap aNewBmp;
    2006           0 :     BitmapReadAccess* pRAcc = AcquireReadAccess();
    2007           0 :     const sal_uInt16 nColCount = std::min( nColorCount, (sal_uInt16) 256 );
    2008             :     sal_uInt16 nBitCount;
    2009           0 :     bool bRet = false;
    2010             : 
    2011           0 :     if( nColCount <= 2 )
    2012           0 :         nBitCount = 1;
    2013           0 :     else if( nColCount <= 16 )
    2014           0 :         nBitCount = 4;
    2015             :     else
    2016           0 :         nBitCount = 8;
    2017             : 
    2018           0 :     if( pRAcc )
    2019             :     {
    2020           0 :         Octree aOct( *pRAcc, nColCount );
    2021           0 :         const BitmapPalette& rPal = aOct.GetPalette();
    2022             :         BitmapWriteAccess* pWAcc;
    2023             : 
    2024           0 :         aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
    2025           0 :         pWAcc = aNewBmp.AcquireWriteAccess();
    2026             : 
    2027           0 :         if( pWAcc )
    2028             :         {
    2029           0 :             const long nWidth = pRAcc->Width();
    2030           0 :             const long nHeight = pRAcc->Height();
    2031             : 
    2032           0 :             if( pRAcc->HasPalette() )
    2033             :             {
    2034           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
    2035           0 :                     for( long nX =0L; nX < nWidth; nX++ )
    2036           0 :                         pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) );
    2037             :             }
    2038             :             else
    2039             :             {
    2040           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
    2041           0 :                     for( long nX =0L; nX < nWidth; nX++ )
    2042           0 :                         pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) );
    2043             :             }
    2044             : 
    2045           0 :             ReleaseAccess( pWAcc );
    2046           0 :             bRet = true;
    2047             :         }
    2048             : 
    2049           0 :         ReleaseAccess( pRAcc );
    2050             :     }
    2051             : 
    2052           0 :     if( bRet )
    2053             :     {
    2054           0 :         const MapMode aMap( maPrefMapMode );
    2055           0 :         const Size aSize( maPrefSize );
    2056             : 
    2057           0 :         *this = aNewBmp;
    2058           0 :         maPrefMapMode = aMap;
    2059           0 :         maPrefSize = aSize;
    2060             :     }
    2061             : 
    2062           0 :     return bRet;
    2063             : }
    2064             : 
    2065             : struct PopularColorCount
    2066             : {
    2067             :     sal_uInt32 mnIndex;
    2068             :     sal_uInt32 mnCount;
    2069             : };
    2070             : 
    2071           0 : extern "C" int SAL_CALL ImplPopularCmpFnc( const void* p1, const void* p2 )
    2072             : {
    2073             :     int nRet;
    2074             : 
    2075           0 :     if( static_cast<PopularColorCount const *>(p1)->mnCount < static_cast<PopularColorCount const *>(p2)->mnCount )
    2076           0 :         nRet = 1;
    2077           0 :     else if( static_cast<PopularColorCount const *>(p1)->mnCount == static_cast<PopularColorCount const *>(p2)->mnCount )
    2078           0 :         nRet = 0;
    2079             :     else
    2080           0 :         nRet = -1;
    2081             : 
    2082           0 :     return nRet;
    2083             : }
    2084             : 
    2085           0 : bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
    2086             : {
    2087           0 :     BitmapReadAccess* pRAcc = AcquireReadAccess();
    2088             :     sal_uInt16 nBitCount;
    2089           0 :     bool bRet = false;
    2090             : 
    2091           0 :     if( nColCount > 256 )
    2092           0 :         nColCount = 256;
    2093             : 
    2094           0 :     if( nColCount < 17 )
    2095           0 :         nBitCount = 4;
    2096             :     else
    2097           0 :         nBitCount = 8;
    2098             : 
    2099           0 :     if( pRAcc )
    2100             :     {
    2101           0 :         const sal_uInt32 nValidBits = 4;
    2102           0 :         const sal_uInt32 nRightShiftBits = 8 - nValidBits;
    2103           0 :         const sal_uInt32 nLeftShiftBits1 = nValidBits;
    2104           0 :         const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
    2105           0 :         const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
    2106           0 :         const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
    2107           0 :         const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
    2108           0 :         const long nWidth = pRAcc->Width();
    2109           0 :         const long nHeight = pRAcc->Height();
    2110           0 :         boost::scoped_array<PopularColorCount> pCountTable(new PopularColorCount[ nTotalColors ]);
    2111             : 
    2112           0 :         memset( pCountTable.get(), 0, nTotalColors * sizeof( PopularColorCount ) );
    2113             : 
    2114           0 :         for( long nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
    2115             :         {
    2116           0 :             for( long nG = 0; nG < 256; nG += nColorOffset )
    2117             :             {
    2118           0 :                 for( long nB = 0; nB < 256; nB += nColorOffset )
    2119             :                 {
    2120           0 :                     pCountTable[ nIndex ].mnIndex = nIndex;
    2121           0 :                     nIndex++;
    2122             :                 }
    2123             :             }
    2124             :         }
    2125             : 
    2126           0 :         if( pRAcc->HasPalette() )
    2127             :         {
    2128           0 :             for( long nY = 0L; nY < nHeight; nY++ )
    2129             :             {
    2130           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
    2131             :                 {
    2132           0 :                     const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
    2133           0 :                     pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
    2134           0 :                                  ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
    2135           0 :                                  ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
    2136             :                 }
    2137             :             }
    2138             :         }
    2139             :         else
    2140             :         {
    2141           0 :             for( long nY = 0L; nY < nHeight; nY++ )
    2142             :             {
    2143           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
    2144             :                 {
    2145           0 :                     const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
    2146           0 :                     pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
    2147           0 :                                  ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
    2148           0 :                                  ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
    2149           0 :                 }
    2150             :             }
    2151             :         }
    2152             : 
    2153           0 :         BitmapPalette aNewPal( nColCount );
    2154             : 
    2155           0 :         qsort( pCountTable.get(), nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
    2156             : 
    2157           0 :         for( sal_uInt16 n = 0; n < nColCount; n++ )
    2158             :         {
    2159           0 :             const PopularColorCount& rPop = pCountTable[ n ];
    2160           0 :             aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
    2161             :                                         (sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
    2162           0 :                                         (sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
    2163             :         }
    2164             : 
    2165           0 :         Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
    2166           0 :         BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
    2167             : 
    2168           0 :         if( pWAcc )
    2169             :         {
    2170           0 :             BitmapColor aDstCol( (sal_uInt8) 0 );
    2171           0 :             boost::scoped_array<sal_uInt8> pIndexMap(new sal_uInt8[ nTotalColors ]);
    2172             : 
    2173           0 :             for( long nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
    2174           0 :                 for( long nG = 0; nG < 256; nG += nColorOffset )
    2175           0 :                     for( long nB = 0; nB < 256; nB += nColorOffset )
    2176           0 :                         pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
    2177             : 
    2178           0 :             if( pRAcc->HasPalette() )
    2179             :             {
    2180           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
    2181             :                 {
    2182           0 :                     for( long nX = 0L; nX < nWidth; nX++ )
    2183             :                     {
    2184           0 :                         const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
    2185           0 :                         aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
    2186           0 :                                                      ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
    2187           0 :                                                      ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
    2188           0 :                         pWAcc->SetPixel( nY, nX, aDstCol );
    2189             :                     }
    2190             :                 }
    2191             :             }
    2192             :             else
    2193             :             {
    2194           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
    2195             :                 {
    2196           0 :                     for( long nX = 0L; nX < nWidth; nX++ )
    2197             :                     {
    2198           0 :                         const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
    2199           0 :                         aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
    2200           0 :                                                      ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
    2201           0 :                                                      ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
    2202           0 :                         pWAcc->SetPixel( nY, nX, aDstCol );
    2203           0 :                     }
    2204             :                 }
    2205             :             }
    2206             : 
    2207           0 :             ReleaseAccess( pWAcc );
    2208           0 :             bRet = true;
    2209             :         }
    2210             : 
    2211           0 :         pCountTable.reset();
    2212           0 :         ReleaseAccess( pRAcc );
    2213             : 
    2214           0 :         if( bRet )
    2215             :         {
    2216           0 :             const MapMode aMap( maPrefMapMode );
    2217           0 :             const Size aSize( maPrefSize );
    2218             : 
    2219           0 :             *this = aNewBmp;
    2220           0 :             maPrefMapMode = aMap;
    2221           0 :             maPrefSize = aSize;
    2222           0 :         }
    2223             :     }
    2224             : 
    2225           0 :     return bRet;
    2226             : }
    2227             : 
    2228           0 : bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
    2229             : {
    2230           0 :     BitmapReadAccess* pRAcc = AcquireReadAccess();
    2231             :     sal_uInt16 nBitCount;
    2232           0 :     bool bRet = false;
    2233             : 
    2234           0 :     if( nColCount < 17 )
    2235           0 :         nBitCount = 4;
    2236           0 :     else if( nColCount < 257 )
    2237           0 :         nBitCount = 8;
    2238             :     else
    2239             :     {
    2240             :         OSL_FAIL( "Bitmap::ImplReduceMedian(): invalid color count!" );
    2241           0 :         nBitCount = 8;
    2242           0 :         nColCount = 256;
    2243             :     }
    2244             : 
    2245           0 :     if( pRAcc )
    2246             :     {
    2247           0 :         Bitmap aNewBmp( GetSizePixel(), nBitCount );
    2248           0 :         BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
    2249             : 
    2250           0 :         if( pWAcc )
    2251             :         {
    2252           0 :             const sal_uLong nSize = 32768UL * sizeof( sal_uLong );
    2253           0 :             sal_uLong* pColBuf = static_cast<sal_uLong*>(rtl_allocateMemory( nSize ));
    2254           0 :             const long nWidth = pWAcc->Width();
    2255           0 :             const long nHeight = pWAcc->Height();
    2256           0 :             long nIndex = 0L;
    2257             : 
    2258           0 :             memset( pColBuf, 0, nSize );
    2259             : 
    2260             :             // create Buffer
    2261           0 :             if( pRAcc->HasPalette() )
    2262             :             {
    2263           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
    2264             :                 {
    2265           0 :                     for( long nX = 0L; nX < nWidth; nX++ )
    2266             :                     {
    2267           0 :                         const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
    2268           0 :                         pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
    2269             :                     }
    2270             :                 }
    2271             :             }
    2272             :             else
    2273             :             {
    2274           0 :                 for( long nY = 0L; nY < nHeight; nY++ )
    2275             :                 {
    2276           0 :                     for( long nX = 0L; nX < nWidth; nX++ )
    2277             :                     {
    2278           0 :                         const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
    2279           0 :                         pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
    2280           0 :                     }
    2281             :                 }
    2282             :             }
    2283             : 
    2284             :             // create palette via median cut
    2285           0 :             BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
    2286             :             ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
    2287           0 :                            nColCount, nWidth * nHeight, nIndex );
    2288             : 
    2289             :             // do mapping of colors to palette
    2290           0 :             InverseColorMap aMap( aPal );
    2291           0 :             pWAcc->SetPalette( aPal );
    2292           0 :             for( long nY = 0L; nY < nHeight; nY++ )
    2293           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
    2294           0 :                     pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) );
    2295             : 
    2296           0 :             rtl_freeMemory( pColBuf );
    2297           0 :             ReleaseAccess( pWAcc );
    2298           0 :             bRet = true;
    2299             :         }
    2300             : 
    2301           0 :         ReleaseAccess( pRAcc );
    2302             : 
    2303           0 :         if( bRet )
    2304             :         {
    2305           0 :             const MapMode aMap( maPrefMapMode );
    2306           0 :             const Size aSize( maPrefSize );
    2307             : 
    2308           0 :             *this = aNewBmp;
    2309           0 :             maPrefMapMode = aMap;
    2310           0 :             maPrefSize = aSize;
    2311           0 :         }
    2312             :     }
    2313             : 
    2314           0 :     return bRet;
    2315             : }
    2316             : 
    2317           0 : void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
    2318             :                             long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
    2319             :                             long nColors, long nPixels, long& rIndex )
    2320             : {
    2321           0 :     if( !nPixels )
    2322           0 :         return;
    2323             : 
    2324           0 :     BitmapColor aCol;
    2325           0 :     const long nRLen = nR2 - nR1;
    2326           0 :     const long nGLen = nG2 - nG1;
    2327           0 :     const long nBLen = nB2 - nB1;
    2328           0 :     sal_uLong* pBuf = pColBuf;
    2329             : 
    2330           0 :     if( !nRLen && !nGLen && !nBLen )
    2331             :     {
    2332           0 :         if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
    2333             :         {
    2334           0 :             aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
    2335           0 :             aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
    2336           0 :             aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
    2337           0 :             rPal[ (sal_uInt16) rIndex++ ] = aCol;
    2338             :         }
    2339             :     }
    2340             :     else
    2341             :     {
    2342           0 :         if( 1 == nColors || 1 == nPixels )
    2343             :         {
    2344           0 :             long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
    2345             : 
    2346           0 :             for( long nR = nR1; nR <= nR2; nR++ )
    2347             :             {
    2348           0 :                 for( long nG = nG1; nG <= nG2; nG++ )
    2349             :                 {
    2350           0 :                     for( long nB = nB1; nB <= nB2; nB++ )
    2351             :                     {
    2352           0 :                         nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
    2353             : 
    2354           0 :                         if( nPixSum )
    2355             :                         {
    2356           0 :                             nRSum += nR * nPixSum;
    2357           0 :                             nGSum += nG * nPixSum;
    2358           0 :                             nBSum += nB * nPixSum;
    2359             :                         }
    2360             :                     }
    2361             :                 }
    2362             :             }
    2363             : 
    2364           0 :             aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
    2365           0 :             aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
    2366           0 :             aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
    2367           0 :             rPal[ (sal_uInt16) rIndex++ ] = aCol;
    2368             :         }
    2369             :         else
    2370             :         {
    2371           0 :             const long nTest = ( nPixels >> 1 );
    2372           0 :             long nPixOld = 0;
    2373           0 :             long nPixNew = 0;
    2374             : 
    2375           0 :             if( nBLen > nGLen && nBLen > nRLen )
    2376             :             {
    2377           0 :                 long nB = nB1 - 1;
    2378             : 
    2379           0 :                 while( nPixNew < nTest )
    2380             :                 {
    2381           0 :                     nB++, nPixOld = nPixNew;
    2382           0 :                     for( long nR = nR1; nR <= nR2; nR++ )
    2383           0 :                         for( long nG = nG1; nG <= nG2; nG++ )
    2384           0 :                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
    2385             :                 }
    2386             : 
    2387           0 :                 if( nB < nB2 )
    2388             :                 {
    2389           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
    2390           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
    2391             :                 }
    2392             :                 else
    2393             :                 {
    2394           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
    2395           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
    2396           0 :                 }
    2397             :             }
    2398           0 :             else if( nGLen > nRLen )
    2399             :             {
    2400           0 :                 long nG = nG1 - 1;
    2401             : 
    2402           0 :                 while( nPixNew < nTest )
    2403             :                 {
    2404           0 :                     nG++, nPixOld = nPixNew;
    2405           0 :                     for( long nR = nR1; nR <= nR2; nR++ )
    2406           0 :                         for( long nB = nB1; nB <= nB2; nB++ )
    2407           0 :                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
    2408             :                 }
    2409             : 
    2410           0 :                 if( nG < nG2 )
    2411             :                 {
    2412           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
    2413           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
    2414             :                 }
    2415             :                 else
    2416             :                 {
    2417           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
    2418           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
    2419             :                 }
    2420             :             }
    2421             :             else
    2422             :             {
    2423           0 :                 long nR = nR1 - 1;
    2424             : 
    2425           0 :                 while( nPixNew < nTest )
    2426             :                 {
    2427           0 :                     nR++, nPixOld = nPixNew;
    2428           0 :                     for( long nG = nG1; nG <= nG2; nG++ )
    2429           0 :                         for( long nB = nB1; nB <= nB2; nB++ )
    2430           0 :                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
    2431             :                 }
    2432             : 
    2433           0 :                 if( nR < nR2 )
    2434             :                 {
    2435           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
    2436           0 :                     ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
    2437             :                 }
    2438             :                 else
    2439             :                 {
    2440           0 :                     ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
    2441           0 :                     ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
    2442             :                 }
    2443             :             }
    2444             :         }
    2445           0 :     }
    2446             : }
    2447             : 
    2448           0 : bool Bitmap::Vectorize( tools::PolyPolygon& rPolyPoly, BmpVectorizeFlags nFlags, const Link<>* pProgress )
    2449             : {
    2450           0 :     return ImplVectorizer::ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
    2451             : }
    2452             : 
    2453           0 : bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, BmpVectorizeFlags nFlags, const Link<>* pProgress )
    2454             : {
    2455           0 :     return ImplVectorizer::ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
    2456             : }
    2457             : 
    2458           4 : bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
    2459             :                      short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
    2460             :                      double fGamma, bool bInvert, bool msoBrightness )
    2461             : {
    2462           4 :     bool bRet = false;
    2463             : 
    2464             :     // nothing to do => return quickly
    2465           4 :     if( !nLuminancePercent && !nContrastPercent &&
    2466           0 :         !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
    2467           0 :         ( fGamma == 1.0 ) && !bInvert )
    2468             :     {
    2469           0 :         bRet = true;
    2470             :     }
    2471             :     else
    2472             :     {
    2473           4 :         BitmapWriteAccess* pAcc = AcquireWriteAccess();
    2474             : 
    2475           4 :         if( pAcc )
    2476             :         {
    2477           4 :             BitmapColor aCol;
    2478           4 :             const long nW = pAcc->Width();
    2479           4 :             const long nH = pAcc->Height();
    2480           8 :             boost::scoped_array<sal_uInt8> cMapR(new sal_uInt8[ 256 ]);
    2481           8 :             boost::scoped_array<sal_uInt8> cMapG(new sal_uInt8[ 256 ]);
    2482           8 :             boost::scoped_array<sal_uInt8> cMapB(new sal_uInt8[ 256 ]);
    2483             :             double fM, fROff, fGOff, fBOff, fOff;
    2484             : 
    2485             :             // calculate slope
    2486           4 :             if( nContrastPercent >= 0 )
    2487           0 :                 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
    2488             :             else
    2489           4 :                 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
    2490             : 
    2491           4 :             if(!msoBrightness)
    2492             :                 // total offset = luminance offset + contrast offset
    2493           0 :                 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
    2494             :             else
    2495           4 :                 fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55;
    2496             : 
    2497             :             // channel offset = channel offset + total offset
    2498           4 :             fROff = nChannelRPercent * 2.55 + fOff;
    2499           4 :             fGOff = nChannelGPercent * 2.55 + fOff;
    2500           4 :             fBOff = nChannelBPercent * 2.55 + fOff;
    2501             : 
    2502             :             // calculate gamma value
    2503           4 :             fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
    2504           4 :             const bool bGamma = ( fGamma != 1.0 );
    2505             : 
    2506             :             // create mapping table
    2507        1028 :             for( long nX = 0L; nX < 256L; nX++ )
    2508             :             {
    2509        1024 :                 if(!msoBrightness)
    2510             :                 {
    2511           0 :                     cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
    2512           0 :                     cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
    2513           0 :                     cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
    2514             :                 }
    2515             :                 else
    2516             :                 {
    2517             :                     // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128"
    2518             :                     // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason,
    2519             :                     // use neither first, but apparently it applies half of brightness before contrast and half afterwards.
    2520        1024 :                     cMapR[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0L, 255L );
    2521        1024 :                     cMapG[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0L, 255L );
    2522        1024 :                     cMapB[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0L, 255L );
    2523             :                 }
    2524        1024 :                 if( bGamma )
    2525             :                 {
    2526           0 :                     cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
    2527           0 :                     cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
    2528           0 :                     cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
    2529             :                 }
    2530             : 
    2531        1024 :                 if( bInvert )
    2532             :                 {
    2533           0 :                     cMapR[ nX ] = ~cMapR[ nX ];
    2534           0 :                     cMapG[ nX ] = ~cMapG[ nX ];
    2535           0 :                     cMapB[ nX ] = ~cMapB[ nX ];
    2536             :                 }
    2537             :             }
    2538             : 
    2539             :             // do modifying
    2540           4 :             if( pAcc->HasPalette() )
    2541             :             {
    2542           0 :                 BitmapColor aNewCol;
    2543             : 
    2544           0 :                 for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
    2545             :                 {
    2546           0 :                     const BitmapColor& rCol = pAcc->GetPaletteColor( i );
    2547           0 :                     aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
    2548           0 :                     aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
    2549           0 :                     aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
    2550           0 :                     pAcc->SetPaletteColor( i, aNewCol );
    2551           0 :                 }
    2552             :             }
    2553           4 :             else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
    2554             :             {
    2555           0 :                 for( long nY = 0L; nY < nH; nY++ )
    2556             :                 {
    2557           0 :                     Scanline pScan = pAcc->GetScanline( nY );
    2558             : 
    2559           0 :                     for( long nX = 0L; nX < nW; nX++ )
    2560             :                     {
    2561           0 :                         *pScan = cMapB[ *pScan ]; pScan++;
    2562           0 :                         *pScan = cMapG[ *pScan ]; pScan++;
    2563           0 :                         *pScan = cMapR[ *pScan ]; pScan++;
    2564             :                     }
    2565             :                 }
    2566             :             }
    2567           4 :             else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
    2568             :             {
    2569           0 :                 for( long nY = 0L; nY < nH; nY++ )
    2570             :                 {
    2571           0 :                     Scanline pScan = pAcc->GetScanline( nY );
    2572             : 
    2573           0 :                     for( long nX = 0L; nX < nW; nX++ )
    2574             :                     {
    2575           0 :                         *pScan = cMapR[ *pScan ]; pScan++;
    2576           0 :                         *pScan = cMapG[ *pScan ]; pScan++;
    2577           0 :                         *pScan = cMapB[ *pScan ]; pScan++;
    2578             :                     }
    2579             :                 }
    2580             :             }
    2581             :             else
    2582             :             {
    2583        1395 :                 for( long nY = 0L; nY < nH; nY++ )
    2584             :                 {
    2585     1408342 :                     for( long nX = 0L; nX < nW; nX++ )
    2586             :                     {
    2587     1406951 :                         aCol = pAcc->GetPixel( nY, nX );
    2588     1406951 :                         aCol.SetRed( cMapR[ aCol.GetRed() ] );
    2589     1406951 :                         aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
    2590     1406951 :                         aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
    2591     1406951 :                         pAcc->SetPixel( nY, nX, aCol );
    2592             :                     }
    2593             :                 }
    2594             :             }
    2595             : 
    2596           4 :             ReleaseAccess( pAcc );
    2597           8 :             bRet = true;
    2598             :         }
    2599             :     }
    2600             : 
    2601           4 :     return bRet;
    2602             : }
    2603             : 
    2604           0 : bool Bitmap::ImplConvolutionPass(Bitmap& aNewBitmap, BitmapReadAccess* pReadAcc, int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount)
    2605             : {
    2606           0 :     BitmapWriteAccess* pWriteAcc = aNewBitmap.AcquireWriteAccess();
    2607             : 
    2608           0 :     if (!pReadAcc || !pWriteAcc)
    2609           0 :         return false;
    2610             : 
    2611           0 :     const int nHeight = GetSizePixel().Height();
    2612             :     assert(GetSizePixel().Height() == aNewBitmap.GetSizePixel().Width());
    2613           0 :     const int nWidth = GetSizePixel().Width();
    2614             :     assert(GetSizePixel().Width() == aNewBitmap.GetSizePixel().Height());
    2615             : 
    2616           0 :     BitmapColor aColor;
    2617             :     double aValueRed, aValueGreen, aValueBlue;
    2618             :     double aSum, aWeight;
    2619             :     int aBaseIndex, aIndex;
    2620             : 
    2621           0 :     for (int nSourceY = 0; nSourceY < nHeight; ++nSourceY)
    2622             :     {
    2623           0 :         for (int nSourceX = 0; nSourceX < nWidth; ++nSourceX)
    2624             :         {
    2625           0 :             aBaseIndex = nSourceX * aNumberOfContributions;
    2626           0 :             aSum = aValueRed = aValueGreen = aValueBlue = 0.0;
    2627             : 
    2628           0 :             for (int j = 0; j < pCount[nSourceX]; ++j)
    2629             :             {
    2630           0 :                 aIndex = aBaseIndex + j;
    2631           0 :                 aSum += aWeight = pWeights[ aIndex ];
    2632             : 
    2633           0 :                 aColor = pReadAcc->GetColor(nSourceY, pPixels[aIndex]);
    2634             : 
    2635           0 :                 aValueRed += aWeight * aColor.GetRed();
    2636           0 :                 aValueGreen += aWeight * aColor.GetGreen();
    2637           0 :                 aValueBlue += aWeight * aColor.GetBlue();
    2638             :             }
    2639             : 
    2640             :             BitmapColor aResultColor(
    2641           0 :                 (sal_uInt8) MinMax( aValueRed / aSum, 0, 255 ),
    2642           0 :                 (sal_uInt8) MinMax( aValueGreen / aSum, 0, 255 ),
    2643           0 :                 (sal_uInt8) MinMax( aValueBlue / aSum, 0, 255 ) );
    2644             : 
    2645           0 :             int nDestX = nSourceY;
    2646           0 :             int nDestY = nSourceX;
    2647             : 
    2648           0 :             pWriteAcc->SetPixel(nDestY, nDestX, aResultColor);
    2649           0 :         }
    2650             :     }
    2651           0 :     ReleaseAccess( pWriteAcc );
    2652           0 :     return true;
    2653             : }
    2654             : 
    2655             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11