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

Generated by: LCOV version 1.10