xref: /trunk/main/vcl/source/gdi/bitmap3.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <stdlib.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
30cdf0e10cSrcweir #include <vcl/octree.hxx>
31cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
32cdf0e10cSrcweir #include <vcl/bitmap.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <impoct.hxx>
35cdf0e10cSrcweir #include <impvect.hxx>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir // -----------
38cdf0e10cSrcweir // - Defines -
39cdf0e10cSrcweir // -----------
40cdf0e10cSrcweir 
41cdf0e10cSrcweir #define RGB15( _def_cR, _def_cG, _def_cB )  (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
42cdf0e10cSrcweir #define GAMMA( _def_cVal, _def_InvGamma )   ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
4337ab0f2dSArmin Le Grand #define MAP( cVal0, cVal1, nFrac )  ((sal_uInt8)((((long)(cVal0)<<7L)+nFrac*((long)(cVal1)-(cVal0)))>>7L))
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #define CALC_ERRORS                                                             \
46cdf0e10cSrcweir                         nTemp   = p1T[nX++] >> 12;                              \
47cdf0e10cSrcweir                         nBErr = MinMax( nTemp, 0, 255 );                        \
48cdf0e10cSrcweir                         nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
49cdf0e10cSrcweir                         nTemp   = p1T[nX++] >> 12;                              \
50cdf0e10cSrcweir                         nGErr = MinMax( nTemp, 0, 255 );                        \
51cdf0e10cSrcweir                         nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
52cdf0e10cSrcweir                         nTemp   = p1T[nX] >> 12;                                \
53cdf0e10cSrcweir                         nRErr = MinMax( nTemp, 0, 255 );                        \
54cdf0e10cSrcweir                         nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
55cdf0e10cSrcweir 
56cdf0e10cSrcweir #define CALC_TABLES3                                        \
57cdf0e10cSrcweir                         p2T[nX++] += FloydError3[nBErr];    \
58cdf0e10cSrcweir                         p2T[nX++] += FloydError3[nGErr];    \
59cdf0e10cSrcweir                         p2T[nX++] += FloydError3[nRErr];
60cdf0e10cSrcweir 
61cdf0e10cSrcweir #define CALC_TABLES5                                        \
62cdf0e10cSrcweir                         p2T[nX++] += FloydError5[nBErr];    \
63cdf0e10cSrcweir                         p2T[nX++] += FloydError5[nGErr];    \
64cdf0e10cSrcweir                         p2T[nX++] += FloydError5[nRErr];
65cdf0e10cSrcweir 
66cdf0e10cSrcweir #define CALC_TABLES7                                        \
67cdf0e10cSrcweir                         p1T[++nX] += FloydError7[nBErr];    \
68cdf0e10cSrcweir                         p2T[nX++] += FloydError1[nBErr];    \
69cdf0e10cSrcweir                         p1T[nX] += FloydError7[nGErr];      \
70cdf0e10cSrcweir                         p2T[nX++] += FloydError1[nGErr];    \
71cdf0e10cSrcweir                         p1T[nX] += FloydError7[nRErr];      \
72cdf0e10cSrcweir                         p2T[nX] += FloydError1[nRErr];
73cdf0e10cSrcweir 
74cdf0e10cSrcweir // -----------
75cdf0e10cSrcweir // - Statics -
76cdf0e10cSrcweir // -----------
77cdf0e10cSrcweir 
78cdf0e10cSrcweir sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
79cdf0e10cSrcweir sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
80cdf0e10cSrcweir sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
81cdf0e10cSrcweir 
82cdf0e10cSrcweir // ------------------------------------------------------------------------
83cdf0e10cSrcweir 
84cdf0e10cSrcweir sal_uLong nVCLDitherLut[ 256 ] =
85cdf0e10cSrcweir {
86cdf0e10cSrcweir        0, 49152, 12288, 61440,  3072, 52224, 15360, 64512,   768, 49920, 13056,
87cdf0e10cSrcweir    62208,  3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
88cdf0e10cSrcweir    48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
89cdf0e10cSrcweir    57344,  4096, 53248, 11264, 60416,  7168, 56320,  8960, 58112,  4864, 54016,
90cdf0e10cSrcweir    12032, 61184,  7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
91cdf0e10cSrcweir    23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
92cdf0e10cSrcweir    14336, 63488,  1024, 50176, 13312, 62464,  2816, 51968, 15104, 64256,  1792,
93cdf0e10cSrcweir    50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
94cdf0e10cSrcweir    35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392,  6144,
95cdf0e10cSrcweir    55296,  9216, 58368,  5120, 54272, 11008, 60160,  6912, 56064,  9984, 59136,
96cdf0e10cSrcweir     5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
97cdf0e10cSrcweir    27392, 39680, 23296, 42752, 26368, 38656, 22272,   512, 49664, 12800, 61952,
98cdf0e10cSrcweir     3584, 52736, 15872, 65024,   256, 49408, 12544, 61696,  3328, 52480, 15616,
99cdf0e10cSrcweir    64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
100cdf0e10cSrcweir    45312, 28928, 36096, 19712, 48384, 32000,  8704, 57856,  4608, 53760, 11776,
101cdf0e10cSrcweir    60928,  7680, 56832,  8448, 57600,  4352, 53504, 11520, 60672,  7424, 56576,
102cdf0e10cSrcweir    41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
103cdf0e10cSrcweir    20736, 44288, 27904, 40192, 23808,  2560, 51712, 14848, 64000,  1536, 50688,
104cdf0e10cSrcweir    13824, 62976,  2304, 51456, 14592, 63744,  1280, 50432, 13568, 62720, 35328,
105cdf0e10cSrcweir    18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
106cdf0e10cSrcweir    34048, 17664, 46336, 29952, 10752, 59904,  6656, 55808,  9728, 58880,  5632,
107cdf0e10cSrcweir    54784, 10496, 59648,  6400, 55552,  9472, 58624,  5376, 54528, 43520, 27136,
108cdf0e10cSrcweir    39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
109cdf0e10cSrcweir    25856, 38144, 21760
110cdf0e10cSrcweir };
111cdf0e10cSrcweir 
112cdf0e10cSrcweir // ------------------------------------------------------------------------
113cdf0e10cSrcweir 
114cdf0e10cSrcweir sal_uLong nVCLLut[ 256 ] =
115cdf0e10cSrcweir {
116cdf0e10cSrcweir          0,  1286,  2572,  3858,  5144,  6430,  7716,  9002,
117cdf0e10cSrcweir      10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
118cdf0e10cSrcweir      20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
119cdf0e10cSrcweir      30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
120cdf0e10cSrcweir      41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
121cdf0e10cSrcweir      51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
122cdf0e10cSrcweir      61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
123cdf0e10cSrcweir      72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
124cdf0e10cSrcweir      82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
125cdf0e10cSrcweir      92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
126cdf0e10cSrcweir     102880,104166,105452,106738,108024,109310,110596,111882,
127cdf0e10cSrcweir     113168,114454,115740,117026,118312,119598,120884,122170,
128cdf0e10cSrcweir     123456,124742,126028,127314,128600,129886,131172,132458,
129cdf0e10cSrcweir     133744,135030,136316,137602,138888,140174,141460,142746,
130cdf0e10cSrcweir     144032,145318,146604,147890,149176,150462,151748,153034,
131cdf0e10cSrcweir     154320,155606,156892,158178,159464,160750,162036,163322,
132cdf0e10cSrcweir     164608,165894,167180,168466,169752,171038,172324,173610,
133cdf0e10cSrcweir     174896,176182,177468,178754,180040,181326,182612,183898,
134cdf0e10cSrcweir     185184,186470,187756,189042,190328,191614,192900,194186,
135cdf0e10cSrcweir     195472,196758,198044,199330,200616,201902,203188,204474,
136cdf0e10cSrcweir     205760,207046,208332,209618,210904,212190,213476,214762,
137cdf0e10cSrcweir     216048,217334,218620,219906,221192,222478,223764,225050,
138cdf0e10cSrcweir     226336,227622,228908,230194,231480,232766,234052,235338,
139cdf0e10cSrcweir     236624,237910,239196,240482,241768,243054,244340,245626,
140cdf0e10cSrcweir     246912,248198,249484,250770,252056,253342,254628,255914,
141cdf0e10cSrcweir     257200,258486,259772,261058,262344,263630,264916,266202,
142cdf0e10cSrcweir     267488,268774,270060,271346,272632,273918,275204,276490,
143cdf0e10cSrcweir     277776,279062,280348,281634,282920,284206,285492,286778,
144cdf0e10cSrcweir     288064,289350,290636,291922,293208,294494,295780,297066,
145cdf0e10cSrcweir     298352,299638,300924,302210,303496,304782,306068,307354,
146cdf0e10cSrcweir     308640,309926,311212,312498,313784,315070,316356,317642,
147cdf0e10cSrcweir     318928,320214,321500,322786,324072,325358,326644,327930
148cdf0e10cSrcweir };
149cdf0e10cSrcweir 
150cdf0e10cSrcweir // ------------------------------------------------------------------------
151cdf0e10cSrcweir 
152cdf0e10cSrcweir long FloydMap[256] =
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
156cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
157cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
158cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
159cdf0e10cSrcweir     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
160cdf0e10cSrcweir     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
161cdf0e10cSrcweir     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162cdf0e10cSrcweir     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
163cdf0e10cSrcweir     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
164cdf0e10cSrcweir     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
165cdf0e10cSrcweir     3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
166cdf0e10cSrcweir     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
167cdf0e10cSrcweir     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
168cdf0e10cSrcweir     4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
169cdf0e10cSrcweir     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
170cdf0e10cSrcweir };
171cdf0e10cSrcweir 
172cdf0e10cSrcweir // ------------------------------------------------------------------------
173cdf0e10cSrcweir 
174cdf0e10cSrcweir long FloydError1[61] =
175cdf0e10cSrcweir {
176cdf0e10cSrcweir     -7680, -7424, -7168, -6912, -6656, -6400, -6144,
177cdf0e10cSrcweir     -5888, -5632, -5376, -5120, -4864, -4608, -4352,
178cdf0e10cSrcweir     -4096, -3840, -3584, -3328, -3072, -2816, -2560,
179cdf0e10cSrcweir     -2304, -2048, -1792, -1536, -1280, -1024, -768,
180cdf0e10cSrcweir     -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
181cdf0e10cSrcweir     1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
182cdf0e10cSrcweir     3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
183cdf0e10cSrcweir     5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
184cdf0e10cSrcweir };
185cdf0e10cSrcweir 
186cdf0e10cSrcweir // ------------------------------------------------------------------------
187cdf0e10cSrcweir 
188cdf0e10cSrcweir long FloydError3[61] =
189cdf0e10cSrcweir {
190cdf0e10cSrcweir     -23040, -22272, -21504, -20736, -19968, -19200,
191cdf0e10cSrcweir     -18432, -17664, -16896, -16128, -15360, -14592,
192cdf0e10cSrcweir     -13824, -13056, -12288, -11520, -10752, -9984,
193cdf0e10cSrcweir     -9216, -8448, -7680, -6912, -6144, -5376, -4608,
194cdf0e10cSrcweir     -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
195cdf0e10cSrcweir     2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
196cdf0e10cSrcweir     8448, 9216, 9984, 10752, 11520, 12288, 13056,
197cdf0e10cSrcweir     13824, 14592, 15360, 16128, 16896, 17664, 18432,
198cdf0e10cSrcweir     19200, 19968, 20736, 21504, 22272, 23040
199cdf0e10cSrcweir };
200cdf0e10cSrcweir 
201cdf0e10cSrcweir // ------------------------------------------------------------------------
202cdf0e10cSrcweir 
203cdf0e10cSrcweir long FloydError5[61] =
204cdf0e10cSrcweir {
205cdf0e10cSrcweir     -38400, -37120, -35840, -34560, -33280, -32000,
206cdf0e10cSrcweir     -30720, -29440, -28160, -26880, -25600, -24320,
207cdf0e10cSrcweir     -23040, -21760, -20480, -19200, -17920, -16640,
208cdf0e10cSrcweir     -15360, -14080, -12800, -11520, -10240, -8960,
209cdf0e10cSrcweir     -7680, -6400, -5120, -3840, -2560, -1280,   0,
210cdf0e10cSrcweir     1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
211cdf0e10cSrcweir     11520, 12800, 14080, 15360, 16640, 17920, 19200,
212cdf0e10cSrcweir     20480, 21760, 23040, 24320, 25600, 26880, 28160,
213cdf0e10cSrcweir     29440, 30720, 32000, 33280, 34560, 35840, 37120,
214cdf0e10cSrcweir     38400
215cdf0e10cSrcweir };
216cdf0e10cSrcweir 
217cdf0e10cSrcweir // ------------------------------------------------------------------------
218cdf0e10cSrcweir 
219cdf0e10cSrcweir long FloydError7[61] =
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     -53760, -51968, -50176, -48384, -46592, -44800,
222cdf0e10cSrcweir     -43008, -41216, -39424, -37632, -35840, -34048,
223cdf0e10cSrcweir     -32256, -30464, -28672, -26880, -25088, -23296,
224cdf0e10cSrcweir     -21504, -19712, -17920, -16128, -14336, -12544,
225cdf0e10cSrcweir     -10752, -8960, -7168, -5376, -3584, -1792,  0,
226cdf0e10cSrcweir     1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
227cdf0e10cSrcweir     16128, 17920, 19712, 21504, 23296, 25088, 26880,
228cdf0e10cSrcweir     28672, 30464, 32256, 34048, 35840, 37632, 39424,
229cdf0e10cSrcweir     41216, 43008, 44800, 46592, 48384, 50176, 51968,
230cdf0e10cSrcweir     53760
231cdf0e10cSrcweir };
232cdf0e10cSrcweir 
233cdf0e10cSrcweir // ------------------------------------------------------------------------
234cdf0e10cSrcweir 
235cdf0e10cSrcweir long FloydIndexMap[6] =
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     -30,  21, 72, 123, 174, 225
238cdf0e10cSrcweir };
239cdf0e10cSrcweir 
240cdf0e10cSrcweir // --------------------------
241cdf0e10cSrcweir // - ImplCreateDitherMatrix -
242cdf0e10cSrcweir // --------------------------
243cdf0e10cSrcweir 
244cdf0e10cSrcweir void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] )
245cdf0e10cSrcweir {
246cdf0e10cSrcweir     double          fVal = 3.125;
247cdf0e10cSrcweir     const double    fVal16 = fVal / 16.;
248cdf0e10cSrcweir     long            i, j, k, l;
249cdf0e10cSrcweir     sal_uInt16          pMtx[ 16 ][ 16 ];
250cdf0e10cSrcweir     sal_uInt16          nMax = 0;
251cdf0e10cSrcweir     static sal_uInt8    pMagic[4][4] = { { 0, 14,  3, 13, },
252cdf0e10cSrcweir                                      {11,  5,  8,  6, },
253cdf0e10cSrcweir                                      {12,  2, 15,  1, },
254cdf0e10cSrcweir                                      {7,   9,  4, 10 } };
255cdf0e10cSrcweir 
256cdf0e10cSrcweir     // MagicSquare aufbauen
257cdf0e10cSrcweir     for ( i = 0; i < 4; i++ )
258cdf0e10cSrcweir        for ( j = 0; j < 4; j++ )
259cdf0e10cSrcweir            for ( k = 0; k < 4; k++ )
260cdf0e10cSrcweir                 for ( l = 0; l < 4; l++ )
261cdf0e10cSrcweir                     nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
262cdf0e10cSrcweir                     (sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     // auf Intervall [0;254] skalieren
265cdf0e10cSrcweir     for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
266cdf0e10cSrcweir         for( j = 0; j < 16; j++ )
267cdf0e10cSrcweir             (*pDitherMatrix)[i][j] = (sal_uInt8) ( fVal * pMtx[i][j] );
268cdf0e10cSrcweir }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir // ----------
271cdf0e10cSrcweir // - Bitmap -
272cdf0e10cSrcweir // ----------
273cdf0e10cSrcweir 
274cdf0e10cSrcweir sal_Bool Bitmap::Convert( BmpConversion eConversion )
275cdf0e10cSrcweir {
276cdf0e10cSrcweir     const sal_uInt16    nBitCount = GetBitCount();
277cdf0e10cSrcweir     sal_Bool            bRet = sal_False;
278cdf0e10cSrcweir 
279cdf0e10cSrcweir     switch( eConversion )
280cdf0e10cSrcweir     {
281cdf0e10cSrcweir         case( BMP_CONVERSION_1BIT_THRESHOLD ):
282cdf0e10cSrcweir             bRet = ImplMakeMono( 128 );
283cdf0e10cSrcweir         break;
284cdf0e10cSrcweir 
285cdf0e10cSrcweir         case( BMP_CONVERSION_1BIT_MATRIX ):
286cdf0e10cSrcweir             bRet = ImplMakeMonoDither();
287cdf0e10cSrcweir         break;
288cdf0e10cSrcweir 
289cdf0e10cSrcweir         case( BMP_CONVERSION_4BIT_GREYS ):
290cdf0e10cSrcweir             bRet = ImplMakeGreyscales( 16 );
291cdf0e10cSrcweir         break;
292cdf0e10cSrcweir 
293cdf0e10cSrcweir         case( BMP_CONVERSION_4BIT_COLORS ):
294cdf0e10cSrcweir         {
295cdf0e10cSrcweir             if( nBitCount < 4 )
296cdf0e10cSrcweir                 bRet = ImplConvertUp( 4, NULL );
297cdf0e10cSrcweir             else if( nBitCount > 4 )
298cdf0e10cSrcweir                 bRet = ImplConvertDown( 4, NULL );
299cdf0e10cSrcweir             else
300cdf0e10cSrcweir                 bRet = sal_True;
301cdf0e10cSrcweir         }
302cdf0e10cSrcweir         break;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir         case( BMP_CONVERSION_4BIT_TRANS ):
305cdf0e10cSrcweir         {
306cdf0e10cSrcweir             Color aTrans( BMP_COL_TRANS );
307cdf0e10cSrcweir 
308cdf0e10cSrcweir             if( nBitCount < 4 )
309cdf0e10cSrcweir                 bRet = ImplConvertUp( 4, &aTrans );
310cdf0e10cSrcweir             else
311cdf0e10cSrcweir                 bRet = ImplConvertDown( 4, &aTrans );
312cdf0e10cSrcweir         }
313cdf0e10cSrcweir         break;
314cdf0e10cSrcweir 
315cdf0e10cSrcweir         case( BMP_CONVERSION_8BIT_GREYS ):
316cdf0e10cSrcweir             bRet = ImplMakeGreyscales( 256 );
317cdf0e10cSrcweir         break;
318cdf0e10cSrcweir 
319cdf0e10cSrcweir         case( BMP_CONVERSION_8BIT_COLORS ):
320cdf0e10cSrcweir         {
321cdf0e10cSrcweir             if( nBitCount < 8 )
322cdf0e10cSrcweir                 bRet = ImplConvertUp( 8 );
323cdf0e10cSrcweir             else if( nBitCount > 8 )
324cdf0e10cSrcweir                 bRet = ImplConvertDown( 8 );
325cdf0e10cSrcweir             else
326cdf0e10cSrcweir                 bRet = sal_True;
327cdf0e10cSrcweir         }
328cdf0e10cSrcweir         break;
329cdf0e10cSrcweir 
330cdf0e10cSrcweir         case( BMP_CONVERSION_8BIT_TRANS ):
331cdf0e10cSrcweir         {
332cdf0e10cSrcweir             Color aTrans( BMP_COL_TRANS );
333cdf0e10cSrcweir 
334cdf0e10cSrcweir             if( nBitCount < 8 )
335cdf0e10cSrcweir                 bRet = ImplConvertUp( 8, &aTrans );
336cdf0e10cSrcweir             else
337cdf0e10cSrcweir                 bRet = ImplConvertDown( 8, &aTrans );
338cdf0e10cSrcweir         }
339cdf0e10cSrcweir         break;
340cdf0e10cSrcweir 
341cdf0e10cSrcweir         case( BMP_CONVERSION_24BIT ):
342cdf0e10cSrcweir         {
343cdf0e10cSrcweir             if( nBitCount < 24 )
344cdf0e10cSrcweir                 bRet = ImplConvertUp( 24, sal_False );
345cdf0e10cSrcweir             else
346cdf0e10cSrcweir                 bRet = sal_True;
347cdf0e10cSrcweir         }
348cdf0e10cSrcweir         break;
349cdf0e10cSrcweir 
350cdf0e10cSrcweir         case( BMP_CONVERSION_GHOSTED ):
351cdf0e10cSrcweir             bRet = ImplConvertGhosted();
352cdf0e10cSrcweir         break;
353cdf0e10cSrcweir 
354cdf0e10cSrcweir         default:
355cdf0e10cSrcweir             DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
356cdf0e10cSrcweir         break;
357cdf0e10cSrcweir     }
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     return bRet;
360cdf0e10cSrcweir }
361cdf0e10cSrcweir 
362cdf0e10cSrcweir // ------------------------------------------------------------------------
363cdf0e10cSrcweir 
364cdf0e10cSrcweir sal_Bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
367cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
368cdf0e10cSrcweir 
369cdf0e10cSrcweir     if( pReadAcc )
370cdf0e10cSrcweir     {
371cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), 1 );
372cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
373cdf0e10cSrcweir 
374cdf0e10cSrcweir         if( pWriteAcc )
375cdf0e10cSrcweir         {
376cdf0e10cSrcweir             const BitmapColor   aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
377cdf0e10cSrcweir             const BitmapColor   aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
378cdf0e10cSrcweir             const long          nWidth = pWriteAcc->Width();
379cdf0e10cSrcweir             const long          nHeight = pWriteAcc->Height();
380cdf0e10cSrcweir 
381cdf0e10cSrcweir             if( pReadAcc->HasPalette() )
382cdf0e10cSrcweir             {
383cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
384cdf0e10cSrcweir                 {
385cdf0e10cSrcweir                     for( long nX = 0L; nX < nWidth; nX++ )
386cdf0e10cSrcweir                     {
38787bc88d3SHerbert Dürr                         const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
38887bc88d3SHerbert Dürr                         if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >=
389cdf0e10cSrcweir                             cThreshold )
390cdf0e10cSrcweir                         {
391cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aWhite );
392cdf0e10cSrcweir                         }
393cdf0e10cSrcweir                         else
394cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aBlack );
395cdf0e10cSrcweir                     }
396cdf0e10cSrcweir                 }
397cdf0e10cSrcweir             }
398cdf0e10cSrcweir             else
399cdf0e10cSrcweir             {
400cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
401cdf0e10cSrcweir                 {
402cdf0e10cSrcweir                     for( long nX = 0L; nX < nWidth; nX++ )
403cdf0e10cSrcweir                     {
404cdf0e10cSrcweir                         if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
405cdf0e10cSrcweir                             cThreshold )
406cdf0e10cSrcweir                         {
407cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aWhite );
408cdf0e10cSrcweir                         }
409cdf0e10cSrcweir                         else
410cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aBlack );
411cdf0e10cSrcweir                     }
412cdf0e10cSrcweir                 }
413cdf0e10cSrcweir             }
414cdf0e10cSrcweir 
415cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWriteAcc );
416cdf0e10cSrcweir             bRet = sal_True;
417cdf0e10cSrcweir         }
418cdf0e10cSrcweir 
419cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
420cdf0e10cSrcweir 
421cdf0e10cSrcweir         if( bRet )
422cdf0e10cSrcweir         {
423cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
424cdf0e10cSrcweir             const Size      aSize( maPrefSize );
425cdf0e10cSrcweir 
426cdf0e10cSrcweir             *this = aNewBmp;
427cdf0e10cSrcweir 
428cdf0e10cSrcweir             maPrefMapMode = aMap;
429cdf0e10cSrcweir             maPrefSize = aSize;
430cdf0e10cSrcweir         }
431cdf0e10cSrcweir     }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir     return bRet;
434cdf0e10cSrcweir }
435cdf0e10cSrcweir 
436cdf0e10cSrcweir // ------------------------------------------------------------------------
437cdf0e10cSrcweir 
438cdf0e10cSrcweir sal_Bool Bitmap::ImplMakeMonoDither()
439cdf0e10cSrcweir {
440cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
441cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
442cdf0e10cSrcweir 
443cdf0e10cSrcweir     if( pReadAcc )
444cdf0e10cSrcweir     {
445cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), 1 );
446cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
447cdf0e10cSrcweir 
448cdf0e10cSrcweir         if( pWriteAcc )
449cdf0e10cSrcweir         {
450cdf0e10cSrcweir             const BitmapColor   aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
451cdf0e10cSrcweir             const BitmapColor   aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
452cdf0e10cSrcweir             const long          nWidth = pWriteAcc->Width();
453cdf0e10cSrcweir             const long          nHeight = pWriteAcc->Height();
454cdf0e10cSrcweir             sal_uInt8               pDitherMatrix[ 16 ][ 16 ];
455cdf0e10cSrcweir 
456cdf0e10cSrcweir             ImplCreateDitherMatrix( &pDitherMatrix );
457cdf0e10cSrcweir 
458cdf0e10cSrcweir             if( pReadAcc->HasPalette() )
459cdf0e10cSrcweir             {
460cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
461cdf0e10cSrcweir                 {
462cdf0e10cSrcweir                     for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
463cdf0e10cSrcweir                     {
46487bc88d3SHerbert Dürr                         const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
46587bc88d3SHerbert Dürr                         if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >
466cdf0e10cSrcweir                             pDitherMatrix[ nModY ][ nX % 16 ] )
467cdf0e10cSrcweir                         {
468cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aWhite );
469cdf0e10cSrcweir                         }
470cdf0e10cSrcweir                         else
471cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aBlack );
472cdf0e10cSrcweir                     }
473cdf0e10cSrcweir                 }
474cdf0e10cSrcweir             }
475cdf0e10cSrcweir             else
476cdf0e10cSrcweir             {
477cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
478cdf0e10cSrcweir                 {
479cdf0e10cSrcweir                     for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
480cdf0e10cSrcweir                     {
481cdf0e10cSrcweir                         if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
482cdf0e10cSrcweir                             pDitherMatrix[ nModY ][ nX % 16 ]  )
483cdf0e10cSrcweir                         {
484cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aWhite );
485cdf0e10cSrcweir                         }
486cdf0e10cSrcweir                         else
487cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aBlack );
488cdf0e10cSrcweir                     }
489cdf0e10cSrcweir                 }
490cdf0e10cSrcweir             }
491cdf0e10cSrcweir 
492cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWriteAcc );
493cdf0e10cSrcweir             bRet = sal_True;
494cdf0e10cSrcweir         }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
497cdf0e10cSrcweir 
498cdf0e10cSrcweir         if( bRet )
499cdf0e10cSrcweir         {
500cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
501cdf0e10cSrcweir             const Size      aSize( maPrefSize );
502cdf0e10cSrcweir 
503cdf0e10cSrcweir             *this = aNewBmp;
504cdf0e10cSrcweir 
505cdf0e10cSrcweir             maPrefMapMode = aMap;
506cdf0e10cSrcweir             maPrefSize = aSize;
507cdf0e10cSrcweir         }
508cdf0e10cSrcweir     }
509cdf0e10cSrcweir 
510cdf0e10cSrcweir     return bRet;
511cdf0e10cSrcweir }
512cdf0e10cSrcweir 
513cdf0e10cSrcweir // ------------------------------------------------------------------------
514cdf0e10cSrcweir 
515cdf0e10cSrcweir sal_Bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
516cdf0e10cSrcweir {
517cdf0e10cSrcweir     DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" );
518cdf0e10cSrcweir 
519cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
520cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     if( pReadAcc )
523cdf0e10cSrcweir     {
524cdf0e10cSrcweir         const BitmapPalette&    rPal = GetGreyPalette( nGreys );
525cdf0e10cSrcweir         sal_uLong                   nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
526cdf0e10cSrcweir         sal_Bool                    bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
527cdf0e10cSrcweir 
528cdf0e10cSrcweir         if( !bPalDiffers )
529cdf0e10cSrcweir             bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
530cdf0e10cSrcweir 
531cdf0e10cSrcweir         if( bPalDiffers )
532cdf0e10cSrcweir         {
533cdf0e10cSrcweir             Bitmap              aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
534cdf0e10cSrcweir             BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
535cdf0e10cSrcweir 
536cdf0e10cSrcweir             if( pWriteAcc )
537cdf0e10cSrcweir             {
538cdf0e10cSrcweir                 const long  nWidth = pWriteAcc->Width();
539cdf0e10cSrcweir                 const long  nHeight = pWriteAcc->Height();
540cdf0e10cSrcweir 
541cdf0e10cSrcweir                 if( pReadAcc->HasPalette() )
542cdf0e10cSrcweir                 {
543cdf0e10cSrcweir                     for( long nY = 0L; nY < nHeight; nY++ )
544cdf0e10cSrcweir                     {
545cdf0e10cSrcweir                         for( long nX = 0L; nX < nWidth; nX++ )
546cdf0e10cSrcweir                         {
54787bc88d3SHerbert Dürr                             const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
54887bc88d3SHerbert Dürr                             pWriteAcc->SetPixelIndex( nY, nX,
54987bc88d3SHerbert Dürr                                 (pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
550cdf0e10cSrcweir                         }
551cdf0e10cSrcweir                     }
552cdf0e10cSrcweir                 }
553cdf0e10cSrcweir                 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
554cdf0e10cSrcweir                          pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
555cdf0e10cSrcweir                 {
556cdf0e10cSrcweir                     nShift += 8;
557cdf0e10cSrcweir 
558cdf0e10cSrcweir                     for( long nY = 0L; nY < nHeight; nY++ )
559cdf0e10cSrcweir                     {
560cdf0e10cSrcweir                         Scanline pReadScan = pReadAcc->GetScanline( nY );
561cdf0e10cSrcweir                         Scanline pWriteScan = pWriteAcc->GetScanline( nY );
562cdf0e10cSrcweir 
563cdf0e10cSrcweir                         for( long nX = 0L; nX < nWidth; nX++ )
564cdf0e10cSrcweir                         {
565cdf0e10cSrcweir                             const sal_uLong nB = *pReadScan++;
566cdf0e10cSrcweir                             const sal_uLong nG = *pReadScan++;
567cdf0e10cSrcweir                             const sal_uLong nR = *pReadScan++;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir                             *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
570cdf0e10cSrcweir                         }
571cdf0e10cSrcweir                     }
572cdf0e10cSrcweir                 }
573cdf0e10cSrcweir                 else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
574cdf0e10cSrcweir                          pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
575cdf0e10cSrcweir                 {
576cdf0e10cSrcweir                     nShift += 8;
577cdf0e10cSrcweir 
578cdf0e10cSrcweir                     for( long nY = 0L; nY < nHeight; nY++ )
579cdf0e10cSrcweir                     {
580cdf0e10cSrcweir                         Scanline pReadScan = pReadAcc->GetScanline( nY );
581cdf0e10cSrcweir                         Scanline pWriteScan = pWriteAcc->GetScanline( nY );
582cdf0e10cSrcweir 
583cdf0e10cSrcweir                         for( long nX = 0L; nX < nWidth; nX++ )
584cdf0e10cSrcweir                         {
585cdf0e10cSrcweir                             const sal_uLong nR = *pReadScan++;
586cdf0e10cSrcweir                             const sal_uLong nG = *pReadScan++;
587cdf0e10cSrcweir                             const sal_uLong nB = *pReadScan++;
588cdf0e10cSrcweir 
589cdf0e10cSrcweir                             *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
590cdf0e10cSrcweir                         }
591cdf0e10cSrcweir                     }
592cdf0e10cSrcweir                 }
593cdf0e10cSrcweir                 else
594cdf0e10cSrcweir                 {
595cdf0e10cSrcweir                     for( long nY = 0L; nY < nHeight; nY++ )
596cdf0e10cSrcweir                         for( long nX = 0L; nX < nWidth; nX++ )
59787bc88d3SHerbert Dürr                             pWriteAcc->SetPixelIndex( nY, nX, (pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift );
598cdf0e10cSrcweir                 }
599cdf0e10cSrcweir 
600cdf0e10cSrcweir                 aNewBmp.ReleaseAccess( pWriteAcc );
601cdf0e10cSrcweir                 bRet = sal_True;
602cdf0e10cSrcweir             }
603cdf0e10cSrcweir 
604cdf0e10cSrcweir             ReleaseAccess( pReadAcc );
605cdf0e10cSrcweir 
606cdf0e10cSrcweir             if( bRet )
607cdf0e10cSrcweir             {
608cdf0e10cSrcweir                 const MapMode   aMap( maPrefMapMode );
609cdf0e10cSrcweir                 const Size      aSize( maPrefSize );
610cdf0e10cSrcweir 
611cdf0e10cSrcweir                 *this = aNewBmp;
612cdf0e10cSrcweir 
613cdf0e10cSrcweir                 maPrefMapMode = aMap;
614cdf0e10cSrcweir                 maPrefSize = aSize;
615cdf0e10cSrcweir             }
616cdf0e10cSrcweir         }
617cdf0e10cSrcweir         else
618cdf0e10cSrcweir         {
619cdf0e10cSrcweir             ReleaseAccess( pReadAcc );
620cdf0e10cSrcweir             bRet = sal_True;
621cdf0e10cSrcweir         }
622cdf0e10cSrcweir     }
623cdf0e10cSrcweir 
624cdf0e10cSrcweir     return bRet;
625cdf0e10cSrcweir }
626cdf0e10cSrcweir 
627cdf0e10cSrcweir // ------------------------------------------------------------------------
628cdf0e10cSrcweir 
629cdf0e10cSrcweir sal_Bool Bitmap::ImplConvertUp( sal_uInt16 nBitCount, Color* pExtColor )
630cdf0e10cSrcweir {
631cdf0e10cSrcweir     DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
632cdf0e10cSrcweir 
633cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
634cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
635cdf0e10cSrcweir 
636cdf0e10cSrcweir     if( pReadAcc )
637cdf0e10cSrcweir     {
638cdf0e10cSrcweir         BitmapPalette       aPal;
639cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPal );
640cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
641cdf0e10cSrcweir 
642cdf0e10cSrcweir         if( pWriteAcc )
643cdf0e10cSrcweir         {
644cdf0e10cSrcweir             const long  nWidth = pWriteAcc->Width();
645cdf0e10cSrcweir             const long  nHeight = pWriteAcc->Height();
646cdf0e10cSrcweir 
647cdf0e10cSrcweir             if( pWriteAcc->HasPalette() )
648cdf0e10cSrcweir             {
649cdf0e10cSrcweir                 const sal_uInt16            nOldCount = 1 << GetBitCount();
650cdf0e10cSrcweir                 const BitmapPalette&    rOldPal = pReadAcc->GetPalette();
651cdf0e10cSrcweir 
652cdf0e10cSrcweir                 aPal.SetEntryCount( 1 << nBitCount );
653cdf0e10cSrcweir 
654cdf0e10cSrcweir                 for( sal_uInt16 i = 0; i < nOldCount; i++ )
655cdf0e10cSrcweir                     aPal[ i ] = rOldPal[ i ];
656cdf0e10cSrcweir 
657cdf0e10cSrcweir                 if( pExtColor )
658cdf0e10cSrcweir                     aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
659cdf0e10cSrcweir 
660cdf0e10cSrcweir                 pWriteAcc->SetPalette( aPal );
661cdf0e10cSrcweir 
662cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
663cdf0e10cSrcweir                     for( long nX = 0L; nX < nWidth; nX++ )
664cdf0e10cSrcweir                         pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
665cdf0e10cSrcweir             }
666cdf0e10cSrcweir             else
667cdf0e10cSrcweir             {
668cdf0e10cSrcweir                 if( pReadAcc->HasPalette() )
669cdf0e10cSrcweir                 {
670cdf0e10cSrcweir                     for( long nY = 0L; nY < nHeight; nY++ )
671cdf0e10cSrcweir                         for( long nX = 0L; nX < nWidth; nX++ )
67287bc88d3SHerbert Dürr                             pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
673cdf0e10cSrcweir                 }
674cdf0e10cSrcweir                 else
675cdf0e10cSrcweir                 {
676cdf0e10cSrcweir                     for( long nY = 0L; nY < nHeight; nY++ )
677cdf0e10cSrcweir                         for( long nX = 0L; nX < nWidth; nX++ )
678cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
679cdf0e10cSrcweir                 }
680cdf0e10cSrcweir             }
681cdf0e10cSrcweir 
682cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWriteAcc );
683cdf0e10cSrcweir             bRet = sal_True;
684cdf0e10cSrcweir         }
685cdf0e10cSrcweir 
686cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
687cdf0e10cSrcweir 
688cdf0e10cSrcweir         if( bRet )
689cdf0e10cSrcweir         {
690cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
691cdf0e10cSrcweir             const Size      aSize( maPrefSize );
692cdf0e10cSrcweir 
693cdf0e10cSrcweir             *this = aNewBmp;
694cdf0e10cSrcweir 
695cdf0e10cSrcweir             maPrefMapMode = aMap;
696cdf0e10cSrcweir             maPrefSize = aSize;
697cdf0e10cSrcweir         }
698cdf0e10cSrcweir     }
699cdf0e10cSrcweir 
700cdf0e10cSrcweir     return bRet;
701cdf0e10cSrcweir }
702cdf0e10cSrcweir 
703cdf0e10cSrcweir // ------------------------------------------------------------------------
704cdf0e10cSrcweir 
705cdf0e10cSrcweir sal_Bool Bitmap::ImplConvertDown( sal_uInt16 nBitCount, Color* pExtColor )
706cdf0e10cSrcweir {
707cdf0e10cSrcweir     DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
708cdf0e10cSrcweir 
709cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
710cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
711cdf0e10cSrcweir 
712cdf0e10cSrcweir     if( pReadAcc )
713cdf0e10cSrcweir     {
714cdf0e10cSrcweir         BitmapPalette       aPal;
715cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), nBitCount, &aPal );
716cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
717cdf0e10cSrcweir 
718cdf0e10cSrcweir         if( pWriteAcc )
719cdf0e10cSrcweir         {
720cdf0e10cSrcweir             const sal_uInt16    nCount = 1 << nBitCount;
721cdf0e10cSrcweir             const long      nWidth = pWriteAcc->Width();
722cdf0e10cSrcweir             const long      nWidth1 = nWidth - 1L;
723cdf0e10cSrcweir             const long      nHeight = pWriteAcc->Height();
724cdf0e10cSrcweir             Octree          aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
725cdf0e10cSrcweir             InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
726cdf0e10cSrcweir             BitmapColor     aColor;
727cdf0e10cSrcweir             ImpErrorQuad    aErrQuad;
728cdf0e10cSrcweir             ImpErrorQuad*   pErrQuad1 = new ImpErrorQuad[ nWidth ];
729cdf0e10cSrcweir             ImpErrorQuad*   pErrQuad2 = new ImpErrorQuad[ nWidth ];
730cdf0e10cSrcweir             ImpErrorQuad*   pQLine1 = pErrQuad1;
731cdf0e10cSrcweir             ImpErrorQuad*   pQLine2 = 0;
732cdf0e10cSrcweir             long            nX, nY;
733cdf0e10cSrcweir             long            nYTmp = 0L;
734cdf0e10cSrcweir             sal_uInt8           cIndex;
735cdf0e10cSrcweir             sal_Bool            bQ1 = sal_True;
736cdf0e10cSrcweir 
737cdf0e10cSrcweir             if( pExtColor )
738cdf0e10cSrcweir             {
739cdf0e10cSrcweir                 aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
740cdf0e10cSrcweir                 aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
741cdf0e10cSrcweir             }
742cdf0e10cSrcweir 
743cdf0e10cSrcweir             // set Black/White always, if we have enough space
744cdf0e10cSrcweir             if( aPal.GetEntryCount() < ( nCount - 1 ) )
745cdf0e10cSrcweir             {
746cdf0e10cSrcweir                 aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
747cdf0e10cSrcweir                 aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
748cdf0e10cSrcweir                 aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
749cdf0e10cSrcweir             }
750cdf0e10cSrcweir 
751cdf0e10cSrcweir             pWriteAcc->SetPalette( aPal );
752cdf0e10cSrcweir 
753cdf0e10cSrcweir             for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
754cdf0e10cSrcweir             {
755cdf0e10cSrcweir                 for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
756cdf0e10cSrcweir                 {
757cdf0e10cSrcweir                     if( pReadAcc->HasPalette() )
75887bc88d3SHerbert Dürr                         pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) );
759cdf0e10cSrcweir                     else
760cdf0e10cSrcweir                         pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
761cdf0e10cSrcweir                 }
762cdf0e10cSrcweir             }
763cdf0e10cSrcweir 
764cdf0e10cSrcweir             for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
765cdf0e10cSrcweir             {
76687bc88d3SHerbert Dürr                 // first pixel in the line
767cdf0e10cSrcweir                 cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
76887bc88d3SHerbert Dürr                 pWriteAcc->SetPixelIndex( nY, 0, cIndex );
769cdf0e10cSrcweir 
770cdf0e10cSrcweir                 for( nX = 1L; nX < nWidth1; nX++ )
771cdf0e10cSrcweir                 {
772cdf0e10cSrcweir                     cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
773cdf0e10cSrcweir                     aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
774cdf0e10cSrcweir                     pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
775cdf0e10cSrcweir                     pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
776cdf0e10cSrcweir                     pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
777cdf0e10cSrcweir                     pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
77887bc88d3SHerbert Dürr                     pWriteAcc->SetPixelIndex( nY, nX, cIndex );
779cdf0e10cSrcweir                 }
780cdf0e10cSrcweir 
781cdf0e10cSrcweir                 // letztes ZeilenPixel
782cdf0e10cSrcweir                 if( nX < nWidth )
783cdf0e10cSrcweir                 {
784cdf0e10cSrcweir                     cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
78587bc88d3SHerbert Dürr                     pWriteAcc->SetPixelIndex( nY, nX, cIndex );
786cdf0e10cSrcweir                 }
787cdf0e10cSrcweir 
788cdf0e10cSrcweir                 // Zeilenpuffer neu fuellen/kopieren
789cdf0e10cSrcweir                 pQLine1 = pQLine2;
790cdf0e10cSrcweir                 pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir                 if( nYTmp < nHeight )
793cdf0e10cSrcweir                 {
794cdf0e10cSrcweir                     for( nX = 0L; nX < nWidth; nX++ )
795cdf0e10cSrcweir                     {
796cdf0e10cSrcweir                         if( pReadAcc->HasPalette() )
79787bc88d3SHerbert Dürr                             pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) );
798cdf0e10cSrcweir                         else
799cdf0e10cSrcweir                             pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
800cdf0e10cSrcweir                     }
801cdf0e10cSrcweir                 }
802cdf0e10cSrcweir             }
803cdf0e10cSrcweir 
804cdf0e10cSrcweir             // Zeilenpuffer zerstoeren
805cdf0e10cSrcweir             delete[] pErrQuad1;
806cdf0e10cSrcweir             delete[] pErrQuad2;
807cdf0e10cSrcweir 
808cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWriteAcc );
809cdf0e10cSrcweir             bRet = sal_True;
810cdf0e10cSrcweir         }
811cdf0e10cSrcweir 
812cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
813cdf0e10cSrcweir 
814cdf0e10cSrcweir         if( bRet )
815cdf0e10cSrcweir         {
816cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
817cdf0e10cSrcweir             const Size      aSize( maPrefSize );
818cdf0e10cSrcweir 
819cdf0e10cSrcweir             *this = aNewBmp;
820cdf0e10cSrcweir 
821cdf0e10cSrcweir             maPrefMapMode = aMap;
822cdf0e10cSrcweir             maPrefSize = aSize;
823cdf0e10cSrcweir         }
824cdf0e10cSrcweir     }
825cdf0e10cSrcweir 
826cdf0e10cSrcweir     return bRet;
827cdf0e10cSrcweir }
828cdf0e10cSrcweir 
829cdf0e10cSrcweir // ------------------------------------------------------------------------
830cdf0e10cSrcweir 
831cdf0e10cSrcweir sal_Bool Bitmap::ImplConvertGhosted()
832cdf0e10cSrcweir {
833cdf0e10cSrcweir     Bitmap              aNewBmp;
834cdf0e10cSrcweir     BitmapReadAccess*   pR = AcquireReadAccess();
835cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
836cdf0e10cSrcweir 
837cdf0e10cSrcweir     if( pR )
838cdf0e10cSrcweir     {
839cdf0e10cSrcweir         if( pR->HasPalette() )
840cdf0e10cSrcweir         {
841cdf0e10cSrcweir             BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
842cdf0e10cSrcweir 
843cdf0e10cSrcweir             for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
844cdf0e10cSrcweir             {
845cdf0e10cSrcweir                 const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i );
846cdf0e10cSrcweir                 aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
847cdf0e10cSrcweir                                                      ( rOld.GetGreen() >> 1 ) | 0x80,
848cdf0e10cSrcweir                                                      ( rOld.GetBlue() >> 1 ) | 0x80 );
849cdf0e10cSrcweir             }
850cdf0e10cSrcweir 
851cdf0e10cSrcweir             aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
852cdf0e10cSrcweir             BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
853cdf0e10cSrcweir 
854cdf0e10cSrcweir             if( pW )
855cdf0e10cSrcweir             {
856cdf0e10cSrcweir                 pW->CopyBuffer( *pR );
857cdf0e10cSrcweir                 aNewBmp.ReleaseAccess( pW );
858cdf0e10cSrcweir                 bRet = sal_True;
859cdf0e10cSrcweir             }
860cdf0e10cSrcweir         }
861cdf0e10cSrcweir         else
862cdf0e10cSrcweir         {
863cdf0e10cSrcweir             aNewBmp = Bitmap( GetSizePixel(), 24 );
864cdf0e10cSrcweir 
865cdf0e10cSrcweir             BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
866cdf0e10cSrcweir 
867cdf0e10cSrcweir             if( pW )
868cdf0e10cSrcweir             {
869cdf0e10cSrcweir                 const long nWidth = pR->Width(), nHeight = pR->Height();
870cdf0e10cSrcweir 
871cdf0e10cSrcweir                 for( long nY = 0; nY < nHeight; nY++ )
872cdf0e10cSrcweir                 {
873cdf0e10cSrcweir                     for( long nX = 0; nX < nWidth; nX++ )
874cdf0e10cSrcweir                     {
875cdf0e10cSrcweir                         const BitmapColor aOld( pR->GetPixel( nY, nX ) );
876cdf0e10cSrcweir                         pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
877cdf0e10cSrcweir                                                            ( aOld.GetGreen() >> 1 ) | 0x80,
878cdf0e10cSrcweir                                                            ( aOld.GetBlue() >> 1 ) | 0x80 ) );
879cdf0e10cSrcweir 
880cdf0e10cSrcweir                     }
881cdf0e10cSrcweir                 }
882cdf0e10cSrcweir 
883cdf0e10cSrcweir                 aNewBmp.ReleaseAccess( pW );
884cdf0e10cSrcweir                 bRet = sal_True;
885cdf0e10cSrcweir             }
886cdf0e10cSrcweir         }
887cdf0e10cSrcweir 
888cdf0e10cSrcweir         ReleaseAccess( pR );
889cdf0e10cSrcweir     }
890cdf0e10cSrcweir 
891cdf0e10cSrcweir     if( bRet )
892cdf0e10cSrcweir     {
893cdf0e10cSrcweir         const MapMode   aMap( maPrefMapMode );
894cdf0e10cSrcweir         const Size      aSize( maPrefSize );
895cdf0e10cSrcweir 
896cdf0e10cSrcweir         *this = aNewBmp;
897cdf0e10cSrcweir 
898cdf0e10cSrcweir         maPrefMapMode = aMap;
899cdf0e10cSrcweir         maPrefSize = aSize;
900cdf0e10cSrcweir     }
901cdf0e10cSrcweir 
902cdf0e10cSrcweir     return bRet;
903cdf0e10cSrcweir }
904cdf0e10cSrcweir 
905cdf0e10cSrcweir // ------------------------------------------------------------------------
906cdf0e10cSrcweir 
907*54628ca4SArmin Le Grand sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
908cdf0e10cSrcweir {
909*54628ca4SArmin Le Grand     if(basegfx::fTools::equalZero(rScaleX) || basegfx::fTools::equalZero(rScaleY))
910*54628ca4SArmin Le Grand     {
911*54628ca4SArmin Le Grand         // no scale
912*54628ca4SArmin Le Grand         return true;
913*54628ca4SArmin Le Grand     }
914*54628ca4SArmin Le Grand 
915*54628ca4SArmin Le Grand     if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
916*54628ca4SArmin Le Grand     {
917*54628ca4SArmin Le Grand         // no scale
918*54628ca4SArmin Le Grand         return true;
919*54628ca4SArmin Le Grand     }
920e9a409b3SArmin Le Grand 
92137ab0f2dSArmin Le Grand #ifdef DBG_UTIL
92237ab0f2dSArmin Le Grand     // #121233# allow to test the different scalers in debug build with source
92337ab0f2dSArmin Le Grand     // level debugger (change nNumber to desired action)
92437ab0f2dSArmin Le Grand     static sal_uInt16 nNumber(0);
925e9a409b3SArmin Le Grand     const sal_uInt16 nStartCount(GetBitCount());
926cdf0e10cSrcweir 
92737ab0f2dSArmin Le Grand     switch(nNumber)
928cdf0e10cSrcweir     {
92937ab0f2dSArmin Le Grand         case 0 : break;
93037ab0f2dSArmin Le Grand         case 1: nScaleFlag = BMP_SCALE_FAST; break;
93137ab0f2dSArmin Le Grand         case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break;
93237ab0f2dSArmin Le Grand         case 3: nScaleFlag = BMP_SCALE_SUPER; break;
93337ab0f2dSArmin Le Grand         case 4: nScaleFlag = BMP_SCALE_LANCZOS; break;
93437ab0f2dSArmin Le Grand         case 5: nScaleFlag = BMP_SCALE_BICUBIC; break;
93537ab0f2dSArmin Le Grand         case 6: nScaleFlag = BMP_SCALE_BILINEAR; break;
93637ab0f2dSArmin Le Grand         case 7: nScaleFlag = BMP_SCALE_BOX; break;
93737ab0f2dSArmin Le Grand         case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break;
93837ab0f2dSArmin Le Grand         case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break;
93937ab0f2dSArmin Le Grand     }
94037ab0f2dSArmin Le Grand #endif // DBG_UTIL
94137ab0f2dSArmin Le Grand 
942*54628ca4SArmin Le Grand     bool bRetval(false);
943*54628ca4SArmin Le Grand 
94437ab0f2dSArmin Le Grand     if(BMP_SCALE_BESTQUALITY == nScaleFlag)
94537ab0f2dSArmin Le Grand     {
94637ab0f2dSArmin Le Grand         // Use LANCZOS when best quality is requested
94737ab0f2dSArmin Le Grand         nScaleFlag = BMP_SCALE_LANCZOS;
94837ab0f2dSArmin Le Grand     }
94937ab0f2dSArmin Le Grand     else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag)
95037ab0f2dSArmin Le Grand     {
95137ab0f2dSArmin Le Grand         // Use BMP_SCALE_SUPER when speed is requested, but not worst quality
95237ab0f2dSArmin Le Grand         nScaleFlag = BMP_SCALE_SUPER;
95337ab0f2dSArmin Le Grand     }
954cdf0e10cSrcweir 
95537ab0f2dSArmin Le Grand     switch(nScaleFlag)
95637ab0f2dSArmin Le Grand     {
95737ab0f2dSArmin Le Grand         default:
95837ab0f2dSArmin Le Grand         case BMP_SCALE_NONE :
95937ab0f2dSArmin Le Grand         {
960e9a409b3SArmin Le Grand             bRetval = false;
96137ab0f2dSArmin Le Grand             break;
96237ab0f2dSArmin Le Grand         }
96337ab0f2dSArmin Le Grand         case BMP_SCALE_FAST :
96437ab0f2dSArmin Le Grand         {
965e9a409b3SArmin Le Grand             bRetval = ImplScaleFast( rScaleX, rScaleY );
96637ab0f2dSArmin Le Grand             break;
96737ab0f2dSArmin Le Grand         }
96837ab0f2dSArmin Le Grand         case BMP_SCALE_INTERPOLATE :
96937ab0f2dSArmin Le Grand         {
970e9a409b3SArmin Le Grand             bRetval = ImplScaleInterpolate( rScaleX, rScaleY );
97137ab0f2dSArmin Le Grand             break;
97237ab0f2dSArmin Le Grand         }
97337ab0f2dSArmin Le Grand         case BMP_SCALE_SUPER :
97437ab0f2dSArmin Le Grand         {
97537ab0f2dSArmin Le Grand             if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
97637ab0f2dSArmin Le Grand             {
97737ab0f2dSArmin Le Grand                 // fallback to ImplScaleFast
978e9a409b3SArmin Le Grand                 bRetval = ImplScaleFast( rScaleX, rScaleY );
97937ab0f2dSArmin Le Grand             }
98037ab0f2dSArmin Le Grand             else
98137ab0f2dSArmin Le Grand             {
98237ab0f2dSArmin Le Grand                 // #121233# use method from symphony
983e9a409b3SArmin Le Grand                 bRetval = ImplScaleSuper( rScaleX, rScaleY );
98437ab0f2dSArmin Le Grand             }
98537ab0f2dSArmin Le Grand             break;
98637ab0f2dSArmin Le Grand         }
98737ab0f2dSArmin Le Grand         case BMP_SCALE_LANCZOS :
98837ab0f2dSArmin Le Grand         {
98937ab0f2dSArmin Le Grand             const Lanczos3Kernel kernel;
99037ab0f2dSArmin Le Grand 
991e9a409b3SArmin Le Grand             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel);
99237ab0f2dSArmin Le Grand             break;
99337ab0f2dSArmin Le Grand         }
99437ab0f2dSArmin Le Grand         case BMP_SCALE_BICUBIC :
99537ab0f2dSArmin Le Grand         {
99637ab0f2dSArmin Le Grand             const BicubicKernel kernel;
99737ab0f2dSArmin Le Grand 
998e9a409b3SArmin Le Grand             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
99937ab0f2dSArmin Le Grand             break;
100037ab0f2dSArmin Le Grand         }
100137ab0f2dSArmin Le Grand         case BMP_SCALE_BILINEAR :
100237ab0f2dSArmin Le Grand         {
100337ab0f2dSArmin Le Grand             const BilinearKernel kernel;
100437ab0f2dSArmin Le Grand 
1005e9a409b3SArmin Le Grand             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
100637ab0f2dSArmin Le Grand             break;
100737ab0f2dSArmin Le Grand         }
100837ab0f2dSArmin Le Grand         case BMP_SCALE_BOX :
100937ab0f2dSArmin Le Grand         {
101037ab0f2dSArmin Le Grand             const BoxKernel kernel;
101137ab0f2dSArmin Le Grand 
1012e9a409b3SArmin Le Grand             bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
101337ab0f2dSArmin Le Grand             break;
101437ab0f2dSArmin Le Grand         }
101537ab0f2dSArmin Le Grand     }
101637ab0f2dSArmin Le Grand 
1017e9a409b3SArmin Le Grand #ifdef DBG_UTIL
1018e9a409b3SArmin Le Grand     if(bRetval && nStartCount != GetBitCount())
1019e9a409b3SArmin Le Grand     {
1020e9a409b3SArmin Le Grand         OSL_ENSURE(false, "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
1021e9a409b3SArmin Le Grand     }
1022e9a409b3SArmin Le Grand #endif
1023e9a409b3SArmin Le Grand 
1024e9a409b3SArmin Le Grand     return bRetval;
1025cdf0e10cSrcweir }
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir // ------------------------------------------------------------------------
1028cdf0e10cSrcweir 
1029*54628ca4SArmin Le Grand sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
1030cdf0e10cSrcweir {
1031cdf0e10cSrcweir     const Size  aSize( GetSizePixel() );
1032cdf0e10cSrcweir     sal_Bool        bRet;
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir     if( aSize.Width() && aSize.Height() )
1035cdf0e10cSrcweir     {
1036cdf0e10cSrcweir         bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
1037cdf0e10cSrcweir                       (double) rNewSize.Height() / aSize.Height(),
1038cdf0e10cSrcweir                       nScaleFlag );
1039cdf0e10cSrcweir     }
1040cdf0e10cSrcweir     else
1041cdf0e10cSrcweir         bRet = sal_True;
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir     return bRet;
1044cdf0e10cSrcweir }
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir // ------------------------------------------------------------------------
1047cdf0e10cSrcweir 
1048c2821885SArmin Le Grand void Bitmap::AdaptBitCount(Bitmap& rNew) const
1049c2821885SArmin Le Grand {
1050c2821885SArmin Le Grand     ImplAdaptBitCount(rNew);
1051c2821885SArmin Le Grand }
1052c2821885SArmin Le Grand 
1053c2821885SArmin Le Grand // ------------------------------------------------------------------------
1054c2821885SArmin Le Grand 
1055c2821885SArmin Le Grand void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const
105637ab0f2dSArmin Le Grand {
105737ab0f2dSArmin Le Grand     // aNew is the result of some operation; adapt it's BitCount to the original (this)
105837ab0f2dSArmin Le Grand     if(GetBitCount() != rNew.GetBitCount())
105937ab0f2dSArmin Le Grand     {
106037ab0f2dSArmin Le Grand         switch(GetBitCount())
106137ab0f2dSArmin Le Grand         {
106237ab0f2dSArmin Le Grand             case 1:
106337ab0f2dSArmin Le Grand             {
106437ab0f2dSArmin Le Grand                 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
106537ab0f2dSArmin Le Grand                 break;
106637ab0f2dSArmin Le Grand             }
106737ab0f2dSArmin Le Grand             case 4:
106837ab0f2dSArmin Le Grand             {
106937ab0f2dSArmin Le Grand                 if(HasGreyPalette())
107037ab0f2dSArmin Le Grand                 {
107137ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
107237ab0f2dSArmin Le Grand                 }
107337ab0f2dSArmin Le Grand                 else
107437ab0f2dSArmin Le Grand                 {
107537ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
107637ab0f2dSArmin Le Grand                 }
107737ab0f2dSArmin Le Grand                 break;
107837ab0f2dSArmin Le Grand             }
107937ab0f2dSArmin Le Grand             case 8:
108037ab0f2dSArmin Le Grand             {
108137ab0f2dSArmin Le Grand                 if(HasGreyPalette())
108237ab0f2dSArmin Le Grand                 {
108337ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
108437ab0f2dSArmin Le Grand                 }
108537ab0f2dSArmin Le Grand                 else
108637ab0f2dSArmin Le Grand                 {
108737ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
108837ab0f2dSArmin Le Grand                 }
108937ab0f2dSArmin Le Grand                 break;
109037ab0f2dSArmin Le Grand             }
109137ab0f2dSArmin Le Grand             case 24:
109237ab0f2dSArmin Le Grand             {
109337ab0f2dSArmin Le Grand                 rNew.Convert(BMP_CONVERSION_24BIT);
109437ab0f2dSArmin Le Grand                 break;
109537ab0f2dSArmin Le Grand             }
109637ab0f2dSArmin Le Grand             default:
109737ab0f2dSArmin Le Grand             {
109837ab0f2dSArmin Le Grand                 OSL_ENSURE(false, "BitDepth adaption failed (!)");
109937ab0f2dSArmin Le Grand                 break;
110037ab0f2dSArmin Le Grand             }
110137ab0f2dSArmin Le Grand         }
110237ab0f2dSArmin Le Grand     }
110337ab0f2dSArmin Le Grand }
110437ab0f2dSArmin Le Grand 
110537ab0f2dSArmin Le Grand // ------------------------------------------------------------------------
110637ab0f2dSArmin Le Grand 
1107cdf0e10cSrcweir sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
1108cdf0e10cSrcweir {
1109cdf0e10cSrcweir     const Size  aSizePix( GetSizePixel() );
1110cdf0e10cSrcweir     const long  nNewWidth = FRound( aSizePix.Width() * rScaleX );
1111cdf0e10cSrcweir     const long  nNewHeight = FRound( aSizePix.Height() * rScaleY );
1112cdf0e10cSrcweir     sal_Bool        bRet = sal_False;
1113cdf0e10cSrcweir 
1114cdf0e10cSrcweir     if( nNewWidth && nNewHeight )
1115cdf0e10cSrcweir     {
1116cdf0e10cSrcweir         BitmapReadAccess*   pReadAcc = AcquireReadAccess();
11170f740837SAriel Constenla-Haile         if ( !pReadAcc )
11180f740837SAriel Constenla-Haile             return sal_False;
11190f740837SAriel Constenla-Haile 
1120cdf0e10cSrcweir         Bitmap              aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
1121cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
1122cdf0e10cSrcweir 
11230f740837SAriel Constenla-Haile         if( pWriteAcc )
1124cdf0e10cSrcweir         {
1125cdf0e10cSrcweir             const long  nScanlineSize = pWriteAcc->GetScanlineSize();
1126cdf0e10cSrcweir             const long  nNewWidth1 = nNewWidth - 1L;
1127cdf0e10cSrcweir             const long  nNewHeight1 = nNewHeight - 1L;
1128cdf0e10cSrcweir             const long  nWidth = pReadAcc->Width();
1129cdf0e10cSrcweir             const long  nHeight = pReadAcc->Height();
1130cdf0e10cSrcweir             long*       pLutX = new long[ nNewWidth ];
1131cdf0e10cSrcweir             long*       pLutY = new long[ nNewHeight ];
1132cdf0e10cSrcweir             long        nX, nY, nMapY, nActY = 0L;
1133cdf0e10cSrcweir 
1134cdf0e10cSrcweir             if( nNewWidth1 && nNewHeight1 )
1135cdf0e10cSrcweir             {
1136cdf0e10cSrcweir                 for( nX = 0L; nX < nNewWidth; nX++ )
1137cdf0e10cSrcweir                     pLutX[ nX ] = nX * nWidth / nNewWidth;
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir                 for( nY = 0L; nY < nNewHeight; nY++ )
1140cdf0e10cSrcweir                     pLutY[ nY ] = nY * nHeight / nNewHeight;
1141cdf0e10cSrcweir 
1142cdf0e10cSrcweir                 while( nActY < nNewHeight )
1143cdf0e10cSrcweir                 {
1144cdf0e10cSrcweir                     nMapY = pLutY[ nActY ];
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir                     for( nX = 0L; nX < nNewWidth; nX++ )
1147cdf0e10cSrcweir                         pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
1148cdf0e10cSrcweir 
1149cdf0e10cSrcweir                     while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
1150cdf0e10cSrcweir                     {
1151cdf0e10cSrcweir                         memcpy( pWriteAcc->GetScanline( nActY + 1L ),
1152cdf0e10cSrcweir                                  pWriteAcc->GetScanline( nActY ), nScanlineSize );
1153cdf0e10cSrcweir                         nActY++;
1154cdf0e10cSrcweir                     }
1155cdf0e10cSrcweir 
1156cdf0e10cSrcweir                     nActY++;
1157cdf0e10cSrcweir                 }
1158cdf0e10cSrcweir 
1159cdf0e10cSrcweir                 bRet = sal_True;
1160cdf0e10cSrcweir             }
1161cdf0e10cSrcweir 
1162cdf0e10cSrcweir             delete[] pLutX;
1163cdf0e10cSrcweir             delete[] pLutY;
1164cdf0e10cSrcweir         }
1165cdf0e10cSrcweir 
1166cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
1167cdf0e10cSrcweir         aNewBmp.ReleaseAccess( pWriteAcc );
1168cdf0e10cSrcweir 
1169cdf0e10cSrcweir         if( bRet )
1170cdf0e10cSrcweir             ImplAssignWithSize( aNewBmp );
1171cdf0e10cSrcweir     }
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir     return bRet;
1174cdf0e10cSrcweir }
1175cdf0e10cSrcweir 
1176cdf0e10cSrcweir // ------------------------------------------------------------------------
1177cdf0e10cSrcweir 
1178cdf0e10cSrcweir sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1179cdf0e10cSrcweir {
1180cdf0e10cSrcweir     const Size  aSizePix( GetSizePixel() );
1181cdf0e10cSrcweir     const long  nNewWidth = FRound( aSizePix.Width() * rScaleX );
1182cdf0e10cSrcweir     const long  nNewHeight = FRound( aSizePix.Height() * rScaleY );
1183cdf0e10cSrcweir     sal_Bool        bRet = sal_False;
1184cdf0e10cSrcweir 
1185cdf0e10cSrcweir     if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1186cdf0e10cSrcweir     {
1187cdf0e10cSrcweir         BitmapColor         aCol0;
1188cdf0e10cSrcweir         BitmapColor         aCol1;
1189cdf0e10cSrcweir         BitmapReadAccess*   pReadAcc = AcquireReadAccess();
1190cdf0e10cSrcweir         long                nWidth = pReadAcc->Width();
1191cdf0e10cSrcweir         long                nHeight = pReadAcc->Height();
1192cdf0e10cSrcweir         Bitmap              aNewBmp( Size( nNewWidth, nHeight ), 24 );
1193cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
1194cdf0e10cSrcweir         long*               pLutInt;
1195cdf0e10cSrcweir         long*               pLutFrac;
1196cdf0e10cSrcweir         long                nX, nY;
1197cdf0e10cSrcweir         long                lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1198cdf0e10cSrcweir         double              fTemp;
1199cdf0e10cSrcweir         long                nTemp;
1200cdf0e10cSrcweir 
1201cdf0e10cSrcweir         if( pReadAcc && pWriteAcc )
1202cdf0e10cSrcweir         {
1203cdf0e10cSrcweir             const long      nNewWidth1 = nNewWidth - 1L;
1204cdf0e10cSrcweir             const long      nWidth1 = pReadAcc->Width() - 1L;
1205cdf0e10cSrcweir             const double    fRevScaleX = (double) nWidth1 / nNewWidth1;
1206cdf0e10cSrcweir 
1207cdf0e10cSrcweir             pLutInt = new long[ nNewWidth ];
1208cdf0e10cSrcweir             pLutFrac = new long[ nNewWidth ];
1209cdf0e10cSrcweir 
1210cdf0e10cSrcweir             for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1211cdf0e10cSrcweir             {
1212cdf0e10cSrcweir                 fTemp = nX * fRevScaleX;
1213cdf0e10cSrcweir                 pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1214cdf0e10cSrcweir                 fTemp -= pLutInt[ nX ];
1215cdf0e10cSrcweir                 pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1216cdf0e10cSrcweir             }
1217cdf0e10cSrcweir 
1218c2821885SArmin Le Grand             for( nY = 0L; nY < nHeight; nY++ )
1219c2821885SArmin Le Grand             {
1220c2821885SArmin Le Grand                 if( 1 == nWidth )
1221c2821885SArmin Le Grand                 {
1222cdf0e10cSrcweir                     if( pReadAcc->HasPalette() )
1223cdf0e10cSrcweir                     {
122487bc88d3SHerbert Dürr                         aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) );
1225cdf0e10cSrcweir                     }
1226cdf0e10cSrcweir                     else
1227cdf0e10cSrcweir                     {
1228cdf0e10cSrcweir                         aCol0 = pReadAcc->GetPixel( nY, 0 );
1229c2821885SArmin Le Grand                     }
1230cdf0e10cSrcweir 
1231cdf0e10cSrcweir                     for( nX = 0L; nX < nNewWidth; nX++ )
1232c2821885SArmin Le Grand                     {
1233cdf0e10cSrcweir                         pWriteAcc->SetPixel( nY, nX, aCol0 );
1234cdf0e10cSrcweir                     }
1235c2821885SArmin Le Grand                 }
1236cdf0e10cSrcweir                 else
1237cdf0e10cSrcweir                 {
1238cdf0e10cSrcweir                     for( nX = 0L; nX < nNewWidth; nX++ )
1239cdf0e10cSrcweir                     {
1240cdf0e10cSrcweir                         nTemp = pLutInt[ nX ];
1241cdf0e10cSrcweir 
1242c2821885SArmin Le Grand                         if( pReadAcc->HasPalette() )
1243c2821885SArmin Le Grand                         {
1244c2821885SArmin Le Grand                             aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) );
1245c2821885SArmin Le Grand                             aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) );
1246c2821885SArmin Le Grand                         }
1247c2821885SArmin Le Grand                         else
1248c2821885SArmin Le Grand                         {
1249cdf0e10cSrcweir                             aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1250cdf0e10cSrcweir                             aCol1 = pReadAcc->GetPixel( nY, nTemp );
1251c2821885SArmin Le Grand                         }
1252cdf0e10cSrcweir 
1253cdf0e10cSrcweir                         nTemp = pLutFrac[ nX ];
1254cdf0e10cSrcweir 
1255cdf0e10cSrcweir                         lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1256cdf0e10cSrcweir                         lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1257cdf0e10cSrcweir                         lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1258cdf0e10cSrcweir 
1259cdf0e10cSrcweir                         aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1260cdf0e10cSrcweir                         aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1261cdf0e10cSrcweir                         aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir                         pWriteAcc->SetPixel( nY, nX, aCol0 );
1264cdf0e10cSrcweir                     }
1265cdf0e10cSrcweir                 }
1266cdf0e10cSrcweir             }
1267cdf0e10cSrcweir 
1268cdf0e10cSrcweir             delete[] pLutInt;
1269cdf0e10cSrcweir             delete[] pLutFrac;
1270cdf0e10cSrcweir             bRet = sal_True;
1271cdf0e10cSrcweir         }
1272cdf0e10cSrcweir 
1273cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
1274cdf0e10cSrcweir         aNewBmp.ReleaseAccess( pWriteAcc );
1275cdf0e10cSrcweir 
1276cdf0e10cSrcweir         if( bRet )
1277cdf0e10cSrcweir         {
1278cdf0e10cSrcweir             bRet = sal_False;
1279561c4886SArmin Le Grand             const Bitmap aOriginal(*this);
1280c2821885SArmin Le Grand             *this = aNewBmp;
1281cdf0e10cSrcweir             aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1282c2821885SArmin Le Grand             pReadAcc = AcquireReadAccess();
1283cdf0e10cSrcweir             pWriteAcc = aNewBmp.AcquireWriteAccess();
1284cdf0e10cSrcweir 
1285cdf0e10cSrcweir             if( pReadAcc && pWriteAcc )
1286cdf0e10cSrcweir             {
1287cdf0e10cSrcweir                 const long      nNewHeight1 = nNewHeight - 1L;
1288cdf0e10cSrcweir                 const long      nHeight1 = pReadAcc->Height() - 1L;
1289cdf0e10cSrcweir                 const double    fRevScaleY = (double) nHeight1 / nNewHeight1;
1290cdf0e10cSrcweir 
1291cdf0e10cSrcweir                 pLutInt = new long[ nNewHeight ];
1292cdf0e10cSrcweir                 pLutFrac = new long[ nNewHeight ];
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir                 for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1295cdf0e10cSrcweir                 {
1296cdf0e10cSrcweir                     fTemp = nY * fRevScaleY;
1297cdf0e10cSrcweir                     pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1298cdf0e10cSrcweir                     fTemp -= pLutInt[ nY ];
1299cdf0e10cSrcweir                     pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1300cdf0e10cSrcweir                 }
1301cdf0e10cSrcweir 
1302c2821885SArmin Le Grand                 // after 1st step, bitmap *is* 24bit format (see above)
1303c2821885SArmin Le Grand                 OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)");
1304cdf0e10cSrcweir 
1305cdf0e10cSrcweir                 for( nX = 0L; nX < nNewWidth; nX++ )
1306cdf0e10cSrcweir                 {
1307cdf0e10cSrcweir                     if( 1 == nHeight )
1308cdf0e10cSrcweir                     {
1309cdf0e10cSrcweir                         aCol0 = pReadAcc->GetPixel( 0, nX );
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir                         for( nY = 0L; nY < nNewHeight; nY++ )
1312c2821885SArmin Le Grand                         {
1313cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aCol0 );
1314cdf0e10cSrcweir                         }
1315c2821885SArmin Le Grand                     }
1316cdf0e10cSrcweir                     else
1317cdf0e10cSrcweir                     {
1318cdf0e10cSrcweir                         for( nY = 0L; nY < nNewHeight; nY++ )
1319cdf0e10cSrcweir                         {
1320cdf0e10cSrcweir                             nTemp = pLutInt[ nY ];
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir                             aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1323cdf0e10cSrcweir                             aCol1 = pReadAcc->GetPixel( nTemp, nX );
1324cdf0e10cSrcweir 
1325cdf0e10cSrcweir                             nTemp = pLutFrac[ nY ];
1326cdf0e10cSrcweir 
1327cdf0e10cSrcweir                             lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1328cdf0e10cSrcweir                             lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1329cdf0e10cSrcweir                             lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1330cdf0e10cSrcweir 
1331cdf0e10cSrcweir                             aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1332cdf0e10cSrcweir                             aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1333cdf0e10cSrcweir                             aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1334cdf0e10cSrcweir 
1335cdf0e10cSrcweir                             pWriteAcc->SetPixel( nY, nX, aCol0 );
1336cdf0e10cSrcweir                         }
1337cdf0e10cSrcweir                     }
1338cdf0e10cSrcweir                 }
1339cdf0e10cSrcweir 
1340cdf0e10cSrcweir                 delete[] pLutInt;
1341cdf0e10cSrcweir                 delete[] pLutFrac;
1342cdf0e10cSrcweir                 bRet = sal_True;
1343cdf0e10cSrcweir             }
1344cdf0e10cSrcweir 
1345cdf0e10cSrcweir             ReleaseAccess( pReadAcc );
1346cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWriteAcc );
1347cdf0e10cSrcweir 
1348cdf0e10cSrcweir             if( bRet )
134937ab0f2dSArmin Le Grand             {
1350561c4886SArmin Le Grand                 aOriginal.ImplAdaptBitCount(aNewBmp);
1351c2821885SArmin Le Grand                 *this = aNewBmp;
1352cdf0e10cSrcweir             }
1353cdf0e10cSrcweir         }
135437ab0f2dSArmin Le Grand     }
1355cdf0e10cSrcweir 
1356cdf0e10cSrcweir     if( !bRet )
1357c2821885SArmin Le Grand     {
1358cdf0e10cSrcweir         bRet = ImplScaleFast( rScaleX, rScaleY );
1359c2821885SArmin Le Grand     }
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir     return bRet;
1362cdf0e10cSrcweir }
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir // ------------------------------------------------------------------------
136537ab0f2dSArmin Le Grand // #121233# Added BMP_SCALE_SUPER from symphony code
136637ab0f2dSArmin Le Grand 
136737ab0f2dSArmin Le Grand sal_Bool Bitmap::ImplScaleSuper(
136837ab0f2dSArmin Le Grand     const double& rScaleX,
136937ab0f2dSArmin Le Grand     const double& rScaleY )
137037ab0f2dSArmin Le Grand {
137137ab0f2dSArmin Le Grand     const Size  aSizePix( GetSizePixel() );
137237ab0f2dSArmin Le Grand     bool   bHMirr = ( rScaleX < 0 );
137337ab0f2dSArmin Le Grand     bool   bVMirr = ( rScaleY < 0 );
137437ab0f2dSArmin Le Grand     double scaleX = bHMirr ? -rScaleX : rScaleX;
137537ab0f2dSArmin Le Grand     double scaleY = bVMirr ? -rScaleY : rScaleY;
137637ab0f2dSArmin Le Grand     const long  nDstW = FRound( aSizePix.Width() * scaleX );
137737ab0f2dSArmin Le Grand     const long  nDstH = FRound( aSizePix.Height() * scaleY );
137837ab0f2dSArmin Le Grand     const double fScaleThresh = 0.6;
137937ab0f2dSArmin Le Grand     bool bRet = false;
138037ab0f2dSArmin Le Grand 
138137ab0f2dSArmin Le Grand     if( ( nDstW > 1L ) && ( nDstH > 1L ) )
138237ab0f2dSArmin Le Grand     {
138337ab0f2dSArmin Le Grand         BitmapColor         aCol0, aCol1, aColRes;
138437ab0f2dSArmin Le Grand         BitmapReadAccess*   pAcc = AcquireReadAccess();
138537ab0f2dSArmin Le Grand         long                nW = pAcc->Width() ;
138637ab0f2dSArmin Le Grand         long                nH = pAcc->Height() ;
138737ab0f2dSArmin Le Grand         Bitmap              aOutBmp( Size( nDstW, nDstH ), 24 );
138837ab0f2dSArmin Le Grand         BitmapWriteAccess*  pWAcc = aOutBmp.AcquireWriteAccess();
138937ab0f2dSArmin Le Grand         long*               pMapIX = new long[ nDstW ];
139037ab0f2dSArmin Le Grand         long*               pMapIY = new long[ nDstH ];
139137ab0f2dSArmin Le Grand         long*               pMapFX = new long[ nDstW ];
139237ab0f2dSArmin Le Grand         long*               pMapFY = new long[ nDstH ];
139337ab0f2dSArmin Le Grand         long                nX, nY, nXDst, nYDst;;
139437ab0f2dSArmin Le Grand         double              fTemp;
139537ab0f2dSArmin Le Grand         long                nTemp , nTempX, nTempY, nTempFX, nTempFY;
139637ab0f2dSArmin Le Grand         sal_uInt8           cR0, cG0, cB0, cR1, cG1, cB1;
139737ab0f2dSArmin Le Grand         long                nStartX = 0 , nStartY = 0;
139837ab0f2dSArmin Le Grand         long                nEndX = nDstW - 1L;
139937ab0f2dSArmin Le Grand         long                nEndY = nDstH - 1L;
140037ab0f2dSArmin Le Grand         long                nMax = 1 << 7L;
140137ab0f2dSArmin Le Grand 
140237ab0f2dSArmin Le Grand         if( pAcc && pWAcc )
140337ab0f2dSArmin Le Grand         {
140437ab0f2dSArmin Le Grand             const double    fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0;
140537ab0f2dSArmin Le Grand             const double    fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0;
140637ab0f2dSArmin Le Grand 
140737ab0f2dSArmin Le Grand             // create horizontal mapping table
140837ab0f2dSArmin Le Grand             for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ )
140937ab0f2dSArmin Le Grand             {
141037ab0f2dSArmin Le Grand                 fTemp = nX * fRevScaleX;
141137ab0f2dSArmin Le Grand 
141237ab0f2dSArmin Le Grand                 if( bHMirr )
141337ab0f2dSArmin Le Grand                     fTemp = nTempX - fTemp;
141437ab0f2dSArmin Le Grand 
141537ab0f2dSArmin Le Grand                 pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
141637ab0f2dSArmin Le Grand             }
141737ab0f2dSArmin Le Grand 
141837ab0f2dSArmin Le Grand             // create vertical mapping table
141937ab0f2dSArmin Le Grand             for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ )
142037ab0f2dSArmin Le Grand             {
142137ab0f2dSArmin Le Grand                 fTemp = nY * fRevScaleY;
142237ab0f2dSArmin Le Grand 
142337ab0f2dSArmin Le Grand                 if( bVMirr )
142437ab0f2dSArmin Le Grand                     fTemp = nTempY - fTemp;
142537ab0f2dSArmin Le Grand 
142637ab0f2dSArmin Le Grand                 pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
142737ab0f2dSArmin Le Grand             }
142837ab0f2dSArmin Le Grand 
142937ab0f2dSArmin Le Grand             if( pAcc->HasPalette() )
143037ab0f2dSArmin Le Grand             {
143137ab0f2dSArmin Le Grand                 if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
143237ab0f2dSArmin Le Grand                 {
143337ab0f2dSArmin Le Grand                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
143437ab0f2dSArmin Le Grand                     {
143537ab0f2dSArmin Le Grand                         Scanline pLine0, pLine1;
143637ab0f2dSArmin Le Grand 
143737ab0f2dSArmin Le Grand                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
143837ab0f2dSArmin Le Grand                         {
143937ab0f2dSArmin Le Grand                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
144037ab0f2dSArmin Le Grand                             pLine0 = pAcc->GetScanline( nTempY );
144137ab0f2dSArmin Le Grand                             pLine1 = pAcc->GetScanline( ++nTempY );
144237ab0f2dSArmin Le Grand 
144337ab0f2dSArmin Le Grand                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
144437ab0f2dSArmin Le Grand                             {
144537ab0f2dSArmin Le Grand                                 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
144637ab0f2dSArmin Le Grand 
144737ab0f2dSArmin Le Grand                                 const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] );
144837ab0f2dSArmin Le Grand                                 const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
144937ab0f2dSArmin Le Grand                                 const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] );
145037ab0f2dSArmin Le Grand                                 const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
145137ab0f2dSArmin Le Grand 
145237ab0f2dSArmin Le Grand                                 cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
145337ab0f2dSArmin Le Grand                                 cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
145437ab0f2dSArmin Le Grand                                 cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
145537ab0f2dSArmin Le Grand 
145637ab0f2dSArmin Le Grand                                 cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
145737ab0f2dSArmin Le Grand                                 cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
145837ab0f2dSArmin Le Grand                                 cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
145937ab0f2dSArmin Le Grand 
146037ab0f2dSArmin Le Grand                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
146137ab0f2dSArmin Le Grand                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
146237ab0f2dSArmin Le Grand                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
146337ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
146437ab0f2dSArmin Le Grand                             }
146537ab0f2dSArmin Le Grand                         }
146637ab0f2dSArmin Le Grand                     }
146737ab0f2dSArmin Le Grand                     else
146837ab0f2dSArmin Le Grand                     {
146937ab0f2dSArmin Le Grand                         Scanline    pTmpY;
147037ab0f2dSArmin Le Grand                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
147137ab0f2dSArmin Le Grand                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
147237ab0f2dSArmin Le Grand                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
147337ab0f2dSArmin Le Grand 
147437ab0f2dSArmin Le Grand                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
147537ab0f2dSArmin Le Grand                         {
147637ab0f2dSArmin Le Grand                             nTop = bVMirr ? ( nY + 1 ) : nY;
147737ab0f2dSArmin Le Grand                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
147837ab0f2dSArmin Le Grand 
147937ab0f2dSArmin Le Grand                             if( nY ==nEndY )
148037ab0f2dSArmin Le Grand                             {
148137ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nY ];
148237ab0f2dSArmin Le Grand                                 nLineRange = 0;
148337ab0f2dSArmin Le Grand                             }
148437ab0f2dSArmin Le Grand                             else
148537ab0f2dSArmin Le Grand                             {
148637ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nTop ] ;
148737ab0f2dSArmin Le Grand                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
148837ab0f2dSArmin Le Grand                             }
148937ab0f2dSArmin Le Grand 
149037ab0f2dSArmin Le Grand                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
149137ab0f2dSArmin Le Grand                             {
149237ab0f2dSArmin Le Grand                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
149337ab0f2dSArmin Le Grand                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
149437ab0f2dSArmin Le Grand 
149537ab0f2dSArmin Le Grand                                 if( nX == nEndX )
149637ab0f2dSArmin Le Grand                                 {
149737ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nX ];
149837ab0f2dSArmin Le Grand                                     nRowRange = 0;
149937ab0f2dSArmin Le Grand                                 }
150037ab0f2dSArmin Le Grand                                 else
150137ab0f2dSArmin Le Grand                                 {
150237ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nLeft ];
150337ab0f2dSArmin Le Grand                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
150437ab0f2dSArmin Le Grand                                 }
150537ab0f2dSArmin Le Grand 
150637ab0f2dSArmin Le Grand                                 nSumR = nSumG = nSumB = 0;
150737ab0f2dSArmin Le Grand                                 nTotalWeightY = 0;
150837ab0f2dSArmin Le Grand 
150937ab0f2dSArmin Le Grand                                 for(int i = 0; i<= nLineRange; i++)
151037ab0f2dSArmin Le Grand                                 {
151137ab0f2dSArmin Le Grand                                     pTmpY = pAcc->GetScanline( nLineStart + i );
151237ab0f2dSArmin Le Grand                                     nSumRowR = nSumRowG = nSumRowB = 0;
151337ab0f2dSArmin Le Grand                                     nTotalWeightX = 0;
151437ab0f2dSArmin Le Grand 
151537ab0f2dSArmin Le Grand                                     for(int j = 0; j <= nRowRange; j++)
151637ab0f2dSArmin Le Grand                                     {
151737ab0f2dSArmin Le Grand                                         const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] );
151837ab0f2dSArmin Le Grand 
151937ab0f2dSArmin Le Grand                                         if(nX == nEndX )
152037ab0f2dSArmin Le Grand                                         {
152137ab0f2dSArmin Le Grand                                             nSumRowB += rCol.GetBlue() << 7L;
152237ab0f2dSArmin Le Grand                                             nSumRowG += rCol.GetGreen() << 7L;
152337ab0f2dSArmin Le Grand                                             nSumRowR += rCol.GetRed() << 7L;
152437ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
152537ab0f2dSArmin Le Grand                                         }
152637ab0f2dSArmin Le Grand                                         else if( j == 0 )
152737ab0f2dSArmin Le Grand                                         {
152837ab0f2dSArmin Le Grand                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
152937ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *rCol.GetBlue()) ;
153037ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *rCol.GetGreen()) ;
153137ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *rCol.GetRed()) ;
153237ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
153337ab0f2dSArmin Le Grand                                         }
153437ab0f2dSArmin Le Grand                                         else if ( nRowRange == j )
153537ab0f2dSArmin Le Grand                                         {
153637ab0f2dSArmin Le Grand                                             nWeightX = pMapFX[ nRight ] ;
153737ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *rCol.GetBlue() );
153837ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *rCol.GetGreen() );
153937ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *rCol.GetRed() );
154037ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
154137ab0f2dSArmin Le Grand                                         }
154237ab0f2dSArmin Le Grand                                         else
154337ab0f2dSArmin Le Grand                                         {
154437ab0f2dSArmin Le Grand                                             nSumRowB += rCol.GetBlue() << 7L;
154537ab0f2dSArmin Le Grand                                             nSumRowG += rCol.GetGreen() << 7L;
154637ab0f2dSArmin Le Grand                                             nSumRowR += rCol.GetRed() << 7L;
154737ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
154837ab0f2dSArmin Le Grand                                         }
154937ab0f2dSArmin Le Grand                                     }
155037ab0f2dSArmin Le Grand 
155137ab0f2dSArmin Le Grand                                     if( nY == nEndY )
155237ab0f2dSArmin Le Grand                                         nWeightY = nMax;
155337ab0f2dSArmin Le Grand                                     else if( i == 0 )
155437ab0f2dSArmin Le Grand                                         nWeightY = nMax - pMapFY[ nTop ];
155537ab0f2dSArmin Le Grand                                     else if( nLineRange == 1 )
155637ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nTop ];
155737ab0f2dSArmin Le Grand                                     else if ( nLineRange == i )
155837ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nBottom ];
155937ab0f2dSArmin Le Grand                                     else
156037ab0f2dSArmin Le Grand                                         nWeightY = nMax;
156137ab0f2dSArmin Le Grand 
156237ab0f2dSArmin Le Grand                                     nWeightY = nWeightY ;
156337ab0f2dSArmin Le Grand                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
156437ab0f2dSArmin Le Grand                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
156537ab0f2dSArmin Le Grand                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
156637ab0f2dSArmin Le Grand                                     nTotalWeightY += nWeightY;
156737ab0f2dSArmin Le Grand                                 }
156837ab0f2dSArmin Le Grand 
156937ab0f2dSArmin Le Grand                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
157037ab0f2dSArmin Le Grand                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
157137ab0f2dSArmin Le Grand                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
157237ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
157337ab0f2dSArmin Le Grand 
157437ab0f2dSArmin Le Grand                             }
157537ab0f2dSArmin Le Grand                         }
157637ab0f2dSArmin Le Grand                     }
157737ab0f2dSArmin Le Grand }
157837ab0f2dSArmin Le Grand                 else
157937ab0f2dSArmin Le Grand                 {
158037ab0f2dSArmin Le Grand                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
158137ab0f2dSArmin Le Grand                     {
158237ab0f2dSArmin Le Grand                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
158337ab0f2dSArmin Le Grand                         {
158437ab0f2dSArmin Le Grand                             nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ];
158537ab0f2dSArmin Le Grand 
158637ab0f2dSArmin Le Grand                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
158737ab0f2dSArmin Le Grand                             {
158837ab0f2dSArmin Le Grand                                 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
158937ab0f2dSArmin Le Grand 
159037ab0f2dSArmin Le Grand                                 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) );
159137ab0f2dSArmin Le Grand                                 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) );
159237ab0f2dSArmin Le Grand                                 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
159337ab0f2dSArmin Le Grand                                 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
159437ab0f2dSArmin Le Grand                                 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
159537ab0f2dSArmin Le Grand 
159637ab0f2dSArmin Le Grand                                 aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) );
159737ab0f2dSArmin Le Grand                                 aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) );
159837ab0f2dSArmin Le Grand                                 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
159937ab0f2dSArmin Le Grand                                 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
160037ab0f2dSArmin Le Grand                                 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
160137ab0f2dSArmin Le Grand 
160237ab0f2dSArmin Le Grand                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
160337ab0f2dSArmin Le Grand                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
160437ab0f2dSArmin Le Grand                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
160537ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
160637ab0f2dSArmin Le Grand                             }
160737ab0f2dSArmin Le Grand                         }
160837ab0f2dSArmin Le Grand 
160937ab0f2dSArmin Le Grand                     }
161037ab0f2dSArmin Le Grand                     else
161137ab0f2dSArmin Le Grand                     {
161237ab0f2dSArmin Le Grand                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
161337ab0f2dSArmin Le Grand                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
161437ab0f2dSArmin Le Grand                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
161537ab0f2dSArmin Le Grand 
161637ab0f2dSArmin Le Grand                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
161737ab0f2dSArmin Le Grand                         {
161837ab0f2dSArmin Le Grand                             nTop = bVMirr ? ( nY + 1 ) : nY;
161937ab0f2dSArmin Le Grand                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
162037ab0f2dSArmin Le Grand 
162137ab0f2dSArmin Le Grand                             if( nY ==nEndY )
162237ab0f2dSArmin Le Grand                             {
162337ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nY ];
162437ab0f2dSArmin Le Grand                                 nLineRange = 0;
162537ab0f2dSArmin Le Grand                             }
162637ab0f2dSArmin Le Grand                             else
162737ab0f2dSArmin Le Grand                             {
162837ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nTop ] ;
162937ab0f2dSArmin Le Grand                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
163037ab0f2dSArmin Le Grand                             }
163137ab0f2dSArmin Le Grand 
163237ab0f2dSArmin Le Grand                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
163337ab0f2dSArmin Le Grand                             {
163437ab0f2dSArmin Le Grand                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
163537ab0f2dSArmin Le Grand                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
163637ab0f2dSArmin Le Grand 
163737ab0f2dSArmin Le Grand                                 if( nX == nEndX )
163837ab0f2dSArmin Le Grand                                 {
163937ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nX ];
164037ab0f2dSArmin Le Grand                                     nRowRange = 0;
164137ab0f2dSArmin Le Grand                                 }
164237ab0f2dSArmin Le Grand                                 else
164337ab0f2dSArmin Le Grand                                 {
164437ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nLeft ];
164537ab0f2dSArmin Le Grand                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
164637ab0f2dSArmin Le Grand                                 }
164737ab0f2dSArmin Le Grand 
164837ab0f2dSArmin Le Grand                                 nSumR = nSumG = nSumB = 0;
164937ab0f2dSArmin Le Grand                                 nTotalWeightY = 0;
165037ab0f2dSArmin Le Grand 
165137ab0f2dSArmin Le Grand                                 for(int i = 0; i<= nLineRange; i++)
165237ab0f2dSArmin Le Grand                                 {
165337ab0f2dSArmin Le Grand                                     nSumRowR = nSumRowG = nSumRowB = 0;
165437ab0f2dSArmin Le Grand                                     nTotalWeightX = 0;
165537ab0f2dSArmin Le Grand 
165637ab0f2dSArmin Le Grand                                     for(int j = 0; j <= nRowRange; j++)
165737ab0f2dSArmin Le Grand                                     {
165837ab0f2dSArmin Le Grand                                         aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
165937ab0f2dSArmin Le Grand 
166037ab0f2dSArmin Le Grand                                         if(nX == nEndX )
166137ab0f2dSArmin Le Grand                                         {
166237ab0f2dSArmin Le Grand 
166337ab0f2dSArmin Le Grand                                             nSumRowB += aCol0.GetBlue() << 7L;
166437ab0f2dSArmin Le Grand                                             nSumRowG += aCol0.GetGreen() << 7L;
166537ab0f2dSArmin Le Grand                                             nSumRowR += aCol0.GetRed() << 7L;
166637ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
166737ab0f2dSArmin Le Grand                                         }
166837ab0f2dSArmin Le Grand                                         else if( j == 0 )
166937ab0f2dSArmin Le Grand                                         {
167037ab0f2dSArmin Le Grand 
167137ab0f2dSArmin Le Grand                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
167237ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
167337ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
167437ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *aCol0.GetRed()) ;
167537ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
167637ab0f2dSArmin Le Grand                                         }
167737ab0f2dSArmin Le Grand                                         else if ( nRowRange == j )
167837ab0f2dSArmin Le Grand                                         {
167937ab0f2dSArmin Le Grand 
168037ab0f2dSArmin Le Grand                                             nWeightX = pMapFX[ nRight ] ;
168137ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *aCol0.GetBlue() );
168237ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *aCol0.GetGreen() );
168337ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *aCol0.GetRed() );
168437ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
168537ab0f2dSArmin Le Grand                                         }
168637ab0f2dSArmin Le Grand                                         else
168737ab0f2dSArmin Le Grand                                         {
168837ab0f2dSArmin Le Grand 
168937ab0f2dSArmin Le Grand                                             nSumRowB += aCol0.GetBlue() << 7L;
169037ab0f2dSArmin Le Grand                                             nSumRowG += aCol0.GetGreen() << 7L;
169137ab0f2dSArmin Le Grand                                             nSumRowR += aCol0.GetRed() << 7L;
169237ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
169337ab0f2dSArmin Le Grand                                         }
169437ab0f2dSArmin Le Grand                                     }
169537ab0f2dSArmin Le Grand 
169637ab0f2dSArmin Le Grand                                     if( nY == nEndY )
169737ab0f2dSArmin Le Grand                                         nWeightY = nMax;
169837ab0f2dSArmin Le Grand                                     else if( i == 0 )
169937ab0f2dSArmin Le Grand                                         nWeightY = nMax - pMapFY[ nTop ];
170037ab0f2dSArmin Le Grand                                     else if( nLineRange == 1 )
170137ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nTop ];
170237ab0f2dSArmin Le Grand                                     else if ( nLineRange == i )
170337ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nBottom ];
170437ab0f2dSArmin Le Grand                                     else
170537ab0f2dSArmin Le Grand                                         nWeightY = nMax;
170637ab0f2dSArmin Le Grand 
170737ab0f2dSArmin Le Grand                                     nWeightY = nWeightY ;
170837ab0f2dSArmin Le Grand                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
170937ab0f2dSArmin Le Grand                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
171037ab0f2dSArmin Le Grand                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
171137ab0f2dSArmin Le Grand                                     nTotalWeightY += nWeightY;
171237ab0f2dSArmin Le Grand                                 }
171337ab0f2dSArmin Le Grand 
171437ab0f2dSArmin Le Grand                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
171537ab0f2dSArmin Le Grand                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
171637ab0f2dSArmin Le Grand                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
171737ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
171837ab0f2dSArmin Le Grand                             }
171937ab0f2dSArmin Le Grand                         }
172037ab0f2dSArmin Le Grand                     }
172137ab0f2dSArmin Le Grand                 }
172237ab0f2dSArmin Le Grand             }
172337ab0f2dSArmin Le Grand             else
172437ab0f2dSArmin Le Grand             {
172537ab0f2dSArmin Le Grand                 if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
172637ab0f2dSArmin Le Grand                 {
172737ab0f2dSArmin Le Grand                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
172837ab0f2dSArmin Le Grand                     {
172937ab0f2dSArmin Le Grand                         Scanline    pLine0, pLine1, pTmp0, pTmp1;
173037ab0f2dSArmin Le Grand                         long        nOff;
173137ab0f2dSArmin Le Grand 
173237ab0f2dSArmin Le Grand                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
173337ab0f2dSArmin Le Grand                         {
173437ab0f2dSArmin Le Grand                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
173537ab0f2dSArmin Le Grand                             pLine0 = pAcc->GetScanline( nTempY );
173637ab0f2dSArmin Le Grand                             pLine1 = pAcc->GetScanline( ++nTempY );
173737ab0f2dSArmin Le Grand 
173837ab0f2dSArmin Le Grand                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
173937ab0f2dSArmin Le Grand                             {
174037ab0f2dSArmin Le Grand                                 nOff = 3L * ( nTempX = pMapIX[ nX ] );
174137ab0f2dSArmin Le Grand                                 nTempFX = pMapFX[ nX ];
174237ab0f2dSArmin Le Grand 
174337ab0f2dSArmin Le Grand                                 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
174437ab0f2dSArmin Le Grand                                 cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
174537ab0f2dSArmin Le Grand                                 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
174637ab0f2dSArmin Le Grand                                 cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
174737ab0f2dSArmin Le Grand 
174837ab0f2dSArmin Le Grand                                 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
174937ab0f2dSArmin Le Grand                                 cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
175037ab0f2dSArmin Le Grand                                 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
175137ab0f2dSArmin Le Grand                                 cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
175237ab0f2dSArmin Le Grand 
175337ab0f2dSArmin Le Grand                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
175437ab0f2dSArmin Le Grand                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
175537ab0f2dSArmin Le Grand                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
175637ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
175737ab0f2dSArmin Le Grand                             }
175837ab0f2dSArmin Le Grand                         }
175937ab0f2dSArmin Le Grand                     }
176037ab0f2dSArmin Le Grand                     else
176137ab0f2dSArmin Le Grand                     {
176237ab0f2dSArmin Le Grand                         Scanline    pTmpY, pTmpX;
176337ab0f2dSArmin Le Grand                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
176437ab0f2dSArmin Le Grand                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
176537ab0f2dSArmin Le Grand                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
176637ab0f2dSArmin Le Grand 
176737ab0f2dSArmin Le Grand                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
176837ab0f2dSArmin Le Grand                         {
176937ab0f2dSArmin Le Grand                             nTop = bVMirr ? ( nY + 1 ) : nY;
177037ab0f2dSArmin Le Grand                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
177137ab0f2dSArmin Le Grand 
177237ab0f2dSArmin Le Grand                             if( nY ==nEndY )
177337ab0f2dSArmin Le Grand                             {
177437ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nY ];
177537ab0f2dSArmin Le Grand                                 nLineRange = 0;
177637ab0f2dSArmin Le Grand                             }
177737ab0f2dSArmin Le Grand                             else
177837ab0f2dSArmin Le Grand                             {
177937ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nTop ] ;
178037ab0f2dSArmin Le Grand                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
178137ab0f2dSArmin Le Grand                             }
178237ab0f2dSArmin Le Grand 
178337ab0f2dSArmin Le Grand                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
178437ab0f2dSArmin Le Grand                             {
178537ab0f2dSArmin Le Grand                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
178637ab0f2dSArmin Le Grand                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
178737ab0f2dSArmin Le Grand 
178837ab0f2dSArmin Le Grand                                 if( nX == nEndX  )
178937ab0f2dSArmin Le Grand                                 {
179037ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nX ];
179137ab0f2dSArmin Le Grand                                     nRowRange = 0;
179237ab0f2dSArmin Le Grand                                 }
179337ab0f2dSArmin Le Grand                                 else
179437ab0f2dSArmin Le Grand                                 {
179537ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nLeft ];
179637ab0f2dSArmin Le Grand                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
179737ab0f2dSArmin Le Grand                                 }
179837ab0f2dSArmin Le Grand 
179937ab0f2dSArmin Le Grand                                 nSumR = nSumG = nSumB = 0;
180037ab0f2dSArmin Le Grand                                 nTotalWeightY = 0;
180137ab0f2dSArmin Le Grand 
180237ab0f2dSArmin Le Grand                                 for(int i = 0; i<= nLineRange; i++)
180337ab0f2dSArmin Le Grand                                 {
180437ab0f2dSArmin Le Grand                                     pTmpY = pAcc->GetScanline( nLineStart + i );
180537ab0f2dSArmin Le Grand                                     pTmpX = pTmpY + 3L * nRowStart;
180637ab0f2dSArmin Le Grand                                     nSumRowR = nSumRowG = nSumRowB = 0;
180737ab0f2dSArmin Le Grand                                     nTotalWeightX = 0;
180837ab0f2dSArmin Le Grand 
180937ab0f2dSArmin Le Grand                                     for(int j = 0; j <= nRowRange; j++)
181037ab0f2dSArmin Le Grand                                     {
181137ab0f2dSArmin Le Grand                                         if(nX == nEndX )
181237ab0f2dSArmin Le Grand                                         {
181337ab0f2dSArmin Le Grand                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
181437ab0f2dSArmin Le Grand                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
181537ab0f2dSArmin Le Grand                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
181637ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
181737ab0f2dSArmin Le Grand                                         }
181837ab0f2dSArmin Le Grand                                         else if( j == 0 )
181937ab0f2dSArmin Le Grand                                         {
182037ab0f2dSArmin Le Grand                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
182137ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
182237ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
182337ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
182437ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
182537ab0f2dSArmin Le Grand                                         }
182637ab0f2dSArmin Le Grand                                         else if ( nRowRange == j )
182737ab0f2dSArmin Le Grand                                         {
182837ab0f2dSArmin Le Grand                                             nWeightX = pMapFX[ nRight ] ;
182937ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
183037ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
183137ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
183237ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
183337ab0f2dSArmin Le Grand                                         }
183437ab0f2dSArmin Le Grand                                         else
183537ab0f2dSArmin Le Grand                                         {
183637ab0f2dSArmin Le Grand                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
183737ab0f2dSArmin Le Grand                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
183837ab0f2dSArmin Le Grand                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
183937ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
184037ab0f2dSArmin Le Grand                                         }
184137ab0f2dSArmin Le Grand                                     }
184237ab0f2dSArmin Le Grand 
184337ab0f2dSArmin Le Grand                                     if( nY == nEndY )
184437ab0f2dSArmin Le Grand                                         nWeightY = nMax;
184537ab0f2dSArmin Le Grand                                     else if( i == 0 )
184637ab0f2dSArmin Le Grand                                         nWeightY = nMax - pMapFY[ nTop ];
184737ab0f2dSArmin Le Grand                                     else if( nLineRange == 1 )
184837ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nTop ];
184937ab0f2dSArmin Le Grand                                     else if ( nLineRange == i )
185037ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nBottom ];
185137ab0f2dSArmin Le Grand                                     else
185237ab0f2dSArmin Le Grand                                         nWeightY = nMax;
185337ab0f2dSArmin Le Grand 
185437ab0f2dSArmin Le Grand                                     nWeightY = nWeightY ;
185537ab0f2dSArmin Le Grand                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
185637ab0f2dSArmin Le Grand                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
185737ab0f2dSArmin Le Grand                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
185837ab0f2dSArmin Le Grand                                     nTotalWeightY += nWeightY;
185937ab0f2dSArmin Le Grand                                 }
186037ab0f2dSArmin Le Grand 
186137ab0f2dSArmin Le Grand                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
186237ab0f2dSArmin Le Grand                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
186337ab0f2dSArmin Le Grand                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
186437ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
186537ab0f2dSArmin Le Grand 
186637ab0f2dSArmin Le Grand                             }
186737ab0f2dSArmin Le Grand                         }
186837ab0f2dSArmin Le Grand                     }
186937ab0f2dSArmin Le Grand                 }
187037ab0f2dSArmin Le Grand                 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
187137ab0f2dSArmin Le Grand                 {
187237ab0f2dSArmin Le Grand                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
187337ab0f2dSArmin Le Grand                     {
187437ab0f2dSArmin Le Grand                         Scanline    pLine0, pLine1, pTmp0, pTmp1;
187537ab0f2dSArmin Le Grand                         long        nOff;
187637ab0f2dSArmin Le Grand 
187737ab0f2dSArmin Le Grand                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
187837ab0f2dSArmin Le Grand                         {
187937ab0f2dSArmin Le Grand                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
188037ab0f2dSArmin Le Grand                             pLine0 = pAcc->GetScanline( nTempY );
188137ab0f2dSArmin Le Grand                             pLine1 = pAcc->GetScanline( ++nTempY );
188237ab0f2dSArmin Le Grand 
188337ab0f2dSArmin Le Grand                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
188437ab0f2dSArmin Le Grand                             {
188537ab0f2dSArmin Le Grand                                 nOff = 3L * ( nTempX = pMapIX[ nX ] );
188637ab0f2dSArmin Le Grand                                 nTempFX = pMapFX[ nX ];
188737ab0f2dSArmin Le Grand 
188837ab0f2dSArmin Le Grand                                 pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
188937ab0f2dSArmin Le Grand                                 cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
189037ab0f2dSArmin Le Grand                                 cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
189137ab0f2dSArmin Le Grand                                 cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
189237ab0f2dSArmin Le Grand 
189337ab0f2dSArmin Le Grand                                 pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
189437ab0f2dSArmin Le Grand                                 cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
189537ab0f2dSArmin Le Grand                                 cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
189637ab0f2dSArmin Le Grand                                 cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
189737ab0f2dSArmin Le Grand 
189837ab0f2dSArmin Le Grand                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
189937ab0f2dSArmin Le Grand                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
190037ab0f2dSArmin Le Grand                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
190137ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
190237ab0f2dSArmin Le Grand                             }
190337ab0f2dSArmin Le Grand                         }
190437ab0f2dSArmin Le Grand                     }
190537ab0f2dSArmin Le Grand                     else
190637ab0f2dSArmin Le Grand                     {
190737ab0f2dSArmin Le Grand                         Scanline    pTmpY, pTmpX;
190837ab0f2dSArmin Le Grand                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
190937ab0f2dSArmin Le Grand                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
191037ab0f2dSArmin Le Grand                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
191137ab0f2dSArmin Le Grand 
191237ab0f2dSArmin Le Grand                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
191337ab0f2dSArmin Le Grand                         {
191437ab0f2dSArmin Le Grand                             nTop = bVMirr ? ( nY + 1 ) : nY;
191537ab0f2dSArmin Le Grand                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
191637ab0f2dSArmin Le Grand 
191737ab0f2dSArmin Le Grand                             if( nY ==nEndY )
191837ab0f2dSArmin Le Grand                             {
191937ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nY ];
192037ab0f2dSArmin Le Grand                                 nLineRange = 0;
192137ab0f2dSArmin Le Grand                             }
192237ab0f2dSArmin Le Grand                             else
192337ab0f2dSArmin Le Grand                             {
192437ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nTop ] ;
192537ab0f2dSArmin Le Grand                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
192637ab0f2dSArmin Le Grand                             }
192737ab0f2dSArmin Le Grand 
192837ab0f2dSArmin Le Grand                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
192937ab0f2dSArmin Le Grand                             {
193037ab0f2dSArmin Le Grand                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
193137ab0f2dSArmin Le Grand                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
193237ab0f2dSArmin Le Grand 
193337ab0f2dSArmin Le Grand                                 if( nX == nEndX )
193437ab0f2dSArmin Le Grand                                 {
193537ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nX ];
193637ab0f2dSArmin Le Grand                                     nRowRange = 0;
193737ab0f2dSArmin Le Grand                                 }
193837ab0f2dSArmin Le Grand                                 else
193937ab0f2dSArmin Le Grand                                 {
194037ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nLeft ];
194137ab0f2dSArmin Le Grand                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
194237ab0f2dSArmin Le Grand                                 }
194337ab0f2dSArmin Le Grand 
194437ab0f2dSArmin Le Grand                                 nSumR = nSumG = nSumB = 0;
194537ab0f2dSArmin Le Grand                                 nTotalWeightY = 0;
194637ab0f2dSArmin Le Grand 
194737ab0f2dSArmin Le Grand                                 for(int i = 0; i<= nLineRange; i++)
194837ab0f2dSArmin Le Grand                                 {
194937ab0f2dSArmin Le Grand                                     pTmpY = pAcc->GetScanline( nLineStart + i );
195037ab0f2dSArmin Le Grand                                     pTmpX = pTmpY + 3L * nRowStart;
195137ab0f2dSArmin Le Grand                                     nSumRowR = nSumRowG = nSumRowB = 0;
195237ab0f2dSArmin Le Grand                                     nTotalWeightX = 0;
195337ab0f2dSArmin Le Grand 
195437ab0f2dSArmin Le Grand                                     for(int j = 0; j <= nRowRange; j++)
195537ab0f2dSArmin Le Grand                                     {
195637ab0f2dSArmin Le Grand                                         if(nX == nEndX )
195737ab0f2dSArmin Le Grand                                         {
195837ab0f2dSArmin Le Grand                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
195937ab0f2dSArmin Le Grand                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
196037ab0f2dSArmin Le Grand                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
196137ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
196237ab0f2dSArmin Le Grand                                         }
196337ab0f2dSArmin Le Grand                                         else if( j == 0 )
196437ab0f2dSArmin Le Grand                                         {
196537ab0f2dSArmin Le Grand                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
196637ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
196737ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
196837ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
196937ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
197037ab0f2dSArmin Le Grand                                         }
197137ab0f2dSArmin Le Grand                                         else if ( nRowRange == j )
197237ab0f2dSArmin Le Grand                                         {
197337ab0f2dSArmin Le Grand                                             nWeightX = pMapFX[ nRight ] ;
197437ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
197537ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
197637ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
197737ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
197837ab0f2dSArmin Le Grand                                         }
197937ab0f2dSArmin Le Grand                                         else
198037ab0f2dSArmin Le Grand                                         {
198137ab0f2dSArmin Le Grand                                             nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
198237ab0f2dSArmin Le Grand                                             nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
198337ab0f2dSArmin Le Grand                                             nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
198437ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
198537ab0f2dSArmin Le Grand                                         }
198637ab0f2dSArmin Le Grand                                     }
198737ab0f2dSArmin Le Grand 
198837ab0f2dSArmin Le Grand                                     if( nY == nEndY )
198937ab0f2dSArmin Le Grand                                         nWeightY = nMax;
199037ab0f2dSArmin Le Grand                                     else if( i == 0 )
199137ab0f2dSArmin Le Grand                                         nWeightY = nMax - pMapFY[ nTop ];
199237ab0f2dSArmin Le Grand                                     else if( nLineRange == 1 )
199337ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nTop ];
199437ab0f2dSArmin Le Grand                                     else if ( nLineRange == i )
199537ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nBottom ];
199637ab0f2dSArmin Le Grand                                     else
199737ab0f2dSArmin Le Grand                                         nWeightY = nMax;
199837ab0f2dSArmin Le Grand 
199937ab0f2dSArmin Le Grand                                     nWeightY = nWeightY ;
200037ab0f2dSArmin Le Grand                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
200137ab0f2dSArmin Le Grand                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
200237ab0f2dSArmin Le Grand                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
200337ab0f2dSArmin Le Grand                                     nTotalWeightY += nWeightY;
200437ab0f2dSArmin Le Grand                                 }
200537ab0f2dSArmin Le Grand 
200637ab0f2dSArmin Le Grand                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
200737ab0f2dSArmin Le Grand                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
200837ab0f2dSArmin Le Grand                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
200937ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
201037ab0f2dSArmin Le Grand 
201137ab0f2dSArmin Le Grand                             }
201237ab0f2dSArmin Le Grand                         }
201337ab0f2dSArmin Le Grand                     }
201437ab0f2dSArmin Le Grand                 }
201537ab0f2dSArmin Le Grand                 else
201637ab0f2dSArmin Le Grand                 {
201737ab0f2dSArmin Le Grand                     if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
201837ab0f2dSArmin Le Grand                     {
201937ab0f2dSArmin Le Grand                         for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
202037ab0f2dSArmin Le Grand                         {
202137ab0f2dSArmin Le Grand                             nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
202237ab0f2dSArmin Le Grand 
202337ab0f2dSArmin Le Grand                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
202437ab0f2dSArmin Le Grand                             {
202537ab0f2dSArmin Le Grand                                 nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
202637ab0f2dSArmin Le Grand 
202737ab0f2dSArmin Le Grand                                 aCol0 = pAcc->GetPixel( nTempY, nTempX );
202837ab0f2dSArmin Le Grand                                 aCol1 = pAcc->GetPixel( nTempY, ++nTempX );
202937ab0f2dSArmin Le Grand                                 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
203037ab0f2dSArmin Le Grand                                 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
203137ab0f2dSArmin Le Grand                                 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
203237ab0f2dSArmin Le Grand 
203337ab0f2dSArmin Le Grand                                 aCol1 = pAcc->GetPixel( ++nTempY, nTempX );
203437ab0f2dSArmin Le Grand                                 aCol0 = pAcc->GetPixel( nTempY--, --nTempX );
203537ab0f2dSArmin Le Grand                                 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
203637ab0f2dSArmin Le Grand                                 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
203737ab0f2dSArmin Le Grand                                 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
203837ab0f2dSArmin Le Grand 
203937ab0f2dSArmin Le Grand                                 aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
204037ab0f2dSArmin Le Grand                                 aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
204137ab0f2dSArmin Le Grand                                 aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
204237ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
204337ab0f2dSArmin Le Grand                             }
204437ab0f2dSArmin Le Grand                         }
204537ab0f2dSArmin Le Grand                     }
204637ab0f2dSArmin Le Grand                     else
204737ab0f2dSArmin Le Grand                     {
204837ab0f2dSArmin Le Grand                         long        nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
204937ab0f2dSArmin Le Grand                         long        nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
205037ab0f2dSArmin Le Grand                         long        nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
205137ab0f2dSArmin Le Grand 
205237ab0f2dSArmin Le Grand                         for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
205337ab0f2dSArmin Le Grand                         {
205437ab0f2dSArmin Le Grand                             nTop = bVMirr ? ( nY + 1 ) : nY;
205537ab0f2dSArmin Le Grand                             nBottom = bVMirr ? nY : ( nY + 1 ) ;
205637ab0f2dSArmin Le Grand 
205737ab0f2dSArmin Le Grand                             if( nY ==nEndY )
205837ab0f2dSArmin Le Grand                             {
205937ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nY ];
206037ab0f2dSArmin Le Grand                                 nLineRange = 0;
206137ab0f2dSArmin Le Grand                             }
206237ab0f2dSArmin Le Grand                             else
206337ab0f2dSArmin Le Grand                             {
206437ab0f2dSArmin Le Grand                                 nLineStart = pMapIY[ nTop ] ;
206537ab0f2dSArmin Le Grand                                 nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
206637ab0f2dSArmin Le Grand                             }
206737ab0f2dSArmin Le Grand 
206837ab0f2dSArmin Le Grand                             for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
206937ab0f2dSArmin Le Grand                             {
207037ab0f2dSArmin Le Grand                                 nLeft = bHMirr ? ( nX + 1 ) : nX;
207137ab0f2dSArmin Le Grand                                 nRight = bHMirr ? nX : ( nX + 1 ) ;
207237ab0f2dSArmin Le Grand 
207337ab0f2dSArmin Le Grand                                 if( nX == nEndX )
207437ab0f2dSArmin Le Grand                                 {
207537ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nX ];
207637ab0f2dSArmin Le Grand                                     nRowRange = 0;
207737ab0f2dSArmin Le Grand                                 }
207837ab0f2dSArmin Le Grand                                 else
207937ab0f2dSArmin Le Grand                                 {
208037ab0f2dSArmin Le Grand                                     nRowStart = pMapIX[ nLeft ];
208137ab0f2dSArmin Le Grand                                     nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
208237ab0f2dSArmin Le Grand                                 }
208337ab0f2dSArmin Le Grand 
208437ab0f2dSArmin Le Grand                                 nSumR = nSumG = nSumB = 0;
208537ab0f2dSArmin Le Grand                                 nTotalWeightY = 0;
208637ab0f2dSArmin Le Grand 
208737ab0f2dSArmin Le Grand                                 for(int i = 0; i<= nLineRange; i++)
208837ab0f2dSArmin Le Grand                                 {
208937ab0f2dSArmin Le Grand                                     nSumRowR = nSumRowG = nSumRowB = 0;
209037ab0f2dSArmin Le Grand                                     nTotalWeightX = 0;
209137ab0f2dSArmin Le Grand 
209237ab0f2dSArmin Le Grand                                     for(int j = 0; j <= nRowRange; j++)
209337ab0f2dSArmin Le Grand                                     {
209437ab0f2dSArmin Le Grand                                         aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j );
209537ab0f2dSArmin Le Grand 
209637ab0f2dSArmin Le Grand                                         if(nX == nEndX )
209737ab0f2dSArmin Le Grand                                         {
209837ab0f2dSArmin Le Grand 
209937ab0f2dSArmin Le Grand                                             nSumRowB += aCol0.GetBlue() << 7L;
210037ab0f2dSArmin Le Grand                                             nSumRowG += aCol0.GetGreen() << 7L;
210137ab0f2dSArmin Le Grand                                             nSumRowR += aCol0.GetRed() << 7L;
210237ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
210337ab0f2dSArmin Le Grand                                         }
210437ab0f2dSArmin Le Grand                                         else if( j == 0 )
210537ab0f2dSArmin Le Grand                                         {
210637ab0f2dSArmin Le Grand 
210737ab0f2dSArmin Le Grand                                             nWeightX = (nMax- pMapFX[ nLeft ]) ;
210837ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
210937ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
211037ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *aCol0.GetRed()) ;
211137ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
211237ab0f2dSArmin Le Grand                                         }
211337ab0f2dSArmin Le Grand                                         else if ( nRowRange == j )
211437ab0f2dSArmin Le Grand                                         {
211537ab0f2dSArmin Le Grand 
211637ab0f2dSArmin Le Grand                                             nWeightX = pMapFX[ nRight ] ;
211737ab0f2dSArmin Le Grand                                             nSumRowB += ( nWeightX *aCol0.GetBlue() );
211837ab0f2dSArmin Le Grand                                             nSumRowG += ( nWeightX *aCol0.GetGreen() );
211937ab0f2dSArmin Le Grand                                             nSumRowR += ( nWeightX *aCol0.GetRed() );
212037ab0f2dSArmin Le Grand                                             nTotalWeightX += nWeightX;
212137ab0f2dSArmin Le Grand                                         }
212237ab0f2dSArmin Le Grand                                         else
212337ab0f2dSArmin Le Grand                                         {
212437ab0f2dSArmin Le Grand                                             nSumRowB += aCol0.GetBlue() << 7L;
212537ab0f2dSArmin Le Grand                                             nSumRowG += aCol0.GetGreen() << 7L;
212637ab0f2dSArmin Le Grand                                             nSumRowR += aCol0.GetRed() << 7L;
212737ab0f2dSArmin Le Grand                                             nTotalWeightX += 1 << 7L;
212837ab0f2dSArmin Le Grand                                         }
212937ab0f2dSArmin Le Grand                                     }
213037ab0f2dSArmin Le Grand 
213137ab0f2dSArmin Le Grand                                     if( nY == nEndY )
213237ab0f2dSArmin Le Grand                                         nWeightY = nMax;
213337ab0f2dSArmin Le Grand                                     else if( i == 0 )
213437ab0f2dSArmin Le Grand                                         nWeightY = nMax - pMapFY[ nTop ];
213537ab0f2dSArmin Le Grand                                     else if( nLineRange == 1 )
213637ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nTop ];
213737ab0f2dSArmin Le Grand                                     else if ( nLineRange == i )
213837ab0f2dSArmin Le Grand                                         nWeightY = pMapFY[ nBottom ];
213937ab0f2dSArmin Le Grand                                     else
214037ab0f2dSArmin Le Grand                                         nWeightY = nMax;
214137ab0f2dSArmin Le Grand 
214237ab0f2dSArmin Le Grand                                     nWeightY = nWeightY ;
214337ab0f2dSArmin Le Grand                                     nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
214437ab0f2dSArmin Le Grand                                     nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
214537ab0f2dSArmin Le Grand                                     nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
214637ab0f2dSArmin Le Grand                                     nTotalWeightY += nWeightY;
214737ab0f2dSArmin Le Grand                                 }
214837ab0f2dSArmin Le Grand 
214937ab0f2dSArmin Le Grand                                 aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
215037ab0f2dSArmin Le Grand                                 aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
215137ab0f2dSArmin Le Grand                                 aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
215237ab0f2dSArmin Le Grand                                 pWAcc->SetPixel( nYDst, nXDst++, aColRes );
215337ab0f2dSArmin Le Grand 
215437ab0f2dSArmin Le Grand                             }
215537ab0f2dSArmin Le Grand                         }
215637ab0f2dSArmin Le Grand                     }
215737ab0f2dSArmin Le Grand                 }
215837ab0f2dSArmin Le Grand             }
215937ab0f2dSArmin Le Grand 
216037ab0f2dSArmin Le Grand             bRet = true;
216137ab0f2dSArmin Le Grand         }
216237ab0f2dSArmin Le Grand 
216337ab0f2dSArmin Le Grand         delete[] pMapIX;
216437ab0f2dSArmin Le Grand         delete[] pMapIY;
216537ab0f2dSArmin Le Grand         delete[] pMapFX;
216637ab0f2dSArmin Le Grand         delete[] pMapFY;
216737ab0f2dSArmin Le Grand 
216837ab0f2dSArmin Le Grand         ReleaseAccess( pAcc );
216937ab0f2dSArmin Le Grand         aOutBmp.ReleaseAccess( pWAcc );
217037ab0f2dSArmin Le Grand 
217137ab0f2dSArmin Le Grand         if( bRet )
217237ab0f2dSArmin Le Grand         {
217337ab0f2dSArmin Le Grand             ImplAdaptBitCount(aOutBmp);
217437ab0f2dSArmin Le Grand             ImplAssignWithSize(aOutBmp);
217537ab0f2dSArmin Le Grand         }
217637ab0f2dSArmin Le Grand 
217737ab0f2dSArmin Le Grand         if( !bRet )
217837ab0f2dSArmin Le Grand             bRet = ImplScaleFast( scaleX, scaleY );
217937ab0f2dSArmin Le Grand     }
218037ab0f2dSArmin Le Grand 
218137ab0f2dSArmin Le Grand     return bRet;
218237ab0f2dSArmin Le Grand }
218337ab0f2dSArmin Le Grand 
218437ab0f2dSArmin Le Grand //-----------------------------------------------------------------------------------
218537ab0f2dSArmin Le Grand 
218637ab0f2dSArmin Le Grand namespace
218737ab0f2dSArmin Le Grand {
218837ab0f2dSArmin Le Grand     void ImplCalculateContributions(
218937ab0f2dSArmin Le Grand         const sal_uInt32 aSourceSize,
219037ab0f2dSArmin Le Grand         const sal_uInt32 aDestinationSize,
219137ab0f2dSArmin Le Grand         sal_uInt32& aNumberOfContributions,
219237ab0f2dSArmin Le Grand         double*& pWeights,
219337ab0f2dSArmin Le Grand         sal_uInt32*& pPixels,
219437ab0f2dSArmin Le Grand         sal_uInt32*& pCount,
219537ab0f2dSArmin Le Grand         const Kernel& aKernel)
219637ab0f2dSArmin Le Grand     {
219737ab0f2dSArmin Le Grand         const double fSamplingRadius(aKernel.GetWidth());
219837ab0f2dSArmin Le Grand         const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
219937ab0f2dSArmin Le Grand         const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
220037ab0f2dSArmin Le Grand         const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
220137ab0f2dSArmin Le Grand 
220237ab0f2dSArmin Le Grand         aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
220337ab0f2dSArmin Le Grand         const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
220437ab0f2dSArmin Le Grand         pWeights = new double[nAllocSize];
220537ab0f2dSArmin Le Grand         pPixels = new sal_uInt32[nAllocSize];
220637ab0f2dSArmin Le Grand         pCount = new sal_uInt32[aDestinationSize];
220737ab0f2dSArmin Le Grand 
220837ab0f2dSArmin Le Grand         for(sal_uInt32 i(0); i < aDestinationSize; i++)
220937ab0f2dSArmin Le Grand         {
221037ab0f2dSArmin Le Grand             const sal_uInt32 aIndex(i * aNumberOfContributions);
221137ab0f2dSArmin Le Grand             const double aCenter(i / fScale);
221237ab0f2dSArmin Le Grand             const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
221337ab0f2dSArmin Le Grand             const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
221437ab0f2dSArmin Le Grand             sal_uInt32 aCurrentCount(0);
221537ab0f2dSArmin Le Grand 
221637ab0f2dSArmin Le Grand             for(sal_Int32 j(aLeft); j <= aRight; j++)
221737ab0f2dSArmin Le Grand             {
221837ab0f2dSArmin Le Grand                 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
221937ab0f2dSArmin Le Grand 
222037ab0f2dSArmin Le Grand                 // Reduce calculations with ignoring weights of 0.0
222137ab0f2dSArmin Le Grand                 if(fabs(aWeight) < 0.0001)
222237ab0f2dSArmin Le Grand                 {
222337ab0f2dSArmin Le Grand                     continue;
222437ab0f2dSArmin Le Grand                 }
222537ab0f2dSArmin Le Grand 
222637ab0f2dSArmin Le Grand                 // Handling on edges
222737ab0f2dSArmin Le Grand                 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
222837ab0f2dSArmin Le Grand                 const sal_uInt32 nIndex(aIndex + aCurrentCount);
222937ab0f2dSArmin Le Grand 
223037ab0f2dSArmin Le Grand                 pWeights[nIndex] = aWeight;
223137ab0f2dSArmin Le Grand                 pPixels[nIndex] = aPixelIndex;
223237ab0f2dSArmin Le Grand 
223337ab0f2dSArmin Le Grand                 aCurrentCount++;
223437ab0f2dSArmin Le Grand             }
223537ab0f2dSArmin Le Grand 
223637ab0f2dSArmin Le Grand             pCount[i] = aCurrentCount;
223737ab0f2dSArmin Le Grand         }
223837ab0f2dSArmin Le Grand     }
223937ab0f2dSArmin Le Grand 
224037ab0f2dSArmin Le Grand     sal_Bool ImplScaleConvolutionHor(
224137ab0f2dSArmin Le Grand         Bitmap& rSource,
224237ab0f2dSArmin Le Grand         Bitmap& rTarget,
224337ab0f2dSArmin Le Grand         const double& rScaleX,
224437ab0f2dSArmin Le Grand         const Kernel& aKernel)
224537ab0f2dSArmin Le Grand     {
224637ab0f2dSArmin Le Grand         // Do horizontal filtering
224737ab0f2dSArmin Le Grand         OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
224837ab0f2dSArmin Le Grand         const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
224937ab0f2dSArmin Le Grand         const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
225037ab0f2dSArmin Le Grand 
225137ab0f2dSArmin Le Grand         if(nWidth == nNewWidth)
225237ab0f2dSArmin Le Grand         {
225337ab0f2dSArmin Le Grand             return true;
225437ab0f2dSArmin Le Grand         }
225537ab0f2dSArmin Le Grand 
225637ab0f2dSArmin Le Grand         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
225737ab0f2dSArmin Le Grand 
225837ab0f2dSArmin Le Grand         if(pReadAcc)
225937ab0f2dSArmin Le Grand         {
226037ab0f2dSArmin Le Grand             double* pWeights = 0;
226137ab0f2dSArmin Le Grand             sal_uInt32* pPixels = 0;
226237ab0f2dSArmin Le Grand             sal_uInt32* pCount = 0;
226337ab0f2dSArmin Le Grand             sal_uInt32 aNumberOfContributions(0);
226437ab0f2dSArmin Le Grand 
226537ab0f2dSArmin Le Grand             const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
226637ab0f2dSArmin Le Grand             ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
226737ab0f2dSArmin Le Grand             rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
226837ab0f2dSArmin Le Grand             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
226937ab0f2dSArmin Le Grand             bool bResult(0 != pWriteAcc);
227037ab0f2dSArmin Le Grand 
227137ab0f2dSArmin Le Grand             if(bResult)
227237ab0f2dSArmin Le Grand             {
227337ab0f2dSArmin Le Grand                 for(sal_uInt32 y(0); y < nHeight; y++)
227437ab0f2dSArmin Le Grand                 {
227537ab0f2dSArmin Le Grand                     for(sal_uInt32 x(0); x < nNewWidth; x++)
227637ab0f2dSArmin Le Grand                     {
227737ab0f2dSArmin Le Grand                         const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
227837ab0f2dSArmin Le Grand                         double aSum(0.0);
227937ab0f2dSArmin Le Grand                         double aValueRed(0.0);
228037ab0f2dSArmin Le Grand                         double aValueGreen(0.0);
228137ab0f2dSArmin Le Grand                         double aValueBlue(0.0);
228237ab0f2dSArmin Le Grand 
228337ab0f2dSArmin Le Grand                         for(sal_uInt32 j(0); j < pCount[x]; j++)
228437ab0f2dSArmin Le Grand                         {
228537ab0f2dSArmin Le Grand                             const sal_uInt32 aIndex(aBaseIndex + j);
228637ab0f2dSArmin Le Grand                             const double aWeight(pWeights[aIndex]);
228737ab0f2dSArmin Le Grand                             BitmapColor aColor;
228837ab0f2dSArmin Le Grand 
228937ab0f2dSArmin Le Grand                             aSum += aWeight;
229037ab0f2dSArmin Le Grand 
229137ab0f2dSArmin Le Grand                             if(pReadAcc->HasPalette())
229237ab0f2dSArmin Le Grand                             {
229337ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
229437ab0f2dSArmin Le Grand                             }
229537ab0f2dSArmin Le Grand                             else
229637ab0f2dSArmin Le Grand                             {
229737ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
229837ab0f2dSArmin Le Grand                             }
229937ab0f2dSArmin Le Grand 
230037ab0f2dSArmin Le Grand                             aValueRed += aWeight * aColor.GetRed();
230137ab0f2dSArmin Le Grand                             aValueGreen += aWeight * aColor.GetGreen();
230237ab0f2dSArmin Le Grand                             aValueBlue += aWeight * aColor.GetBlue();
230337ab0f2dSArmin Le Grand                         }
230437ab0f2dSArmin Le Grand 
230537ab0f2dSArmin Le Grand                         const BitmapColor aResultColor(
230637ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
230737ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
230837ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
230937ab0f2dSArmin Le Grand 
231037ab0f2dSArmin Le Grand                         pWriteAcc->SetPixel(y, x, aResultColor);
231137ab0f2dSArmin Le Grand                     }
231237ab0f2dSArmin Le Grand                 }
231337ab0f2dSArmin Le Grand 
231437ab0f2dSArmin Le Grand                 rTarget.ReleaseAccess(pWriteAcc);
231537ab0f2dSArmin Le Grand             }
231637ab0f2dSArmin Le Grand 
231737ab0f2dSArmin Le Grand             rSource.ReleaseAccess(pReadAcc);
231837ab0f2dSArmin Le Grand             delete[] pWeights;
231937ab0f2dSArmin Le Grand             delete[] pCount;
232037ab0f2dSArmin Le Grand             delete[] pPixels;
232137ab0f2dSArmin Le Grand 
232237ab0f2dSArmin Le Grand             if(bResult)
232337ab0f2dSArmin Le Grand             {
232437ab0f2dSArmin Le Grand                 return true;
232537ab0f2dSArmin Le Grand             }
232637ab0f2dSArmin Le Grand         }
232737ab0f2dSArmin Le Grand 
232837ab0f2dSArmin Le Grand         return false;
232937ab0f2dSArmin Le Grand     }
233037ab0f2dSArmin Le Grand 
233137ab0f2dSArmin Le Grand     bool ImplScaleConvolutionVer(
233237ab0f2dSArmin Le Grand         Bitmap& rSource,
233337ab0f2dSArmin Le Grand         Bitmap& rTarget,
233437ab0f2dSArmin Le Grand         const double& rScaleY,
233537ab0f2dSArmin Le Grand         const Kernel& aKernel)
233637ab0f2dSArmin Le Grand     {
233737ab0f2dSArmin Le Grand         // Do vertical filtering
233837ab0f2dSArmin Le Grand         OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
233937ab0f2dSArmin Le Grand         const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
234037ab0f2dSArmin Le Grand         const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
234137ab0f2dSArmin Le Grand 
234237ab0f2dSArmin Le Grand         if(nHeight == nNewHeight)
234337ab0f2dSArmin Le Grand         {
234437ab0f2dSArmin Le Grand             return true;
234537ab0f2dSArmin Le Grand         }
234637ab0f2dSArmin Le Grand 
234737ab0f2dSArmin Le Grand         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
234837ab0f2dSArmin Le Grand 
234937ab0f2dSArmin Le Grand         if(pReadAcc)
235037ab0f2dSArmin Le Grand         {
235137ab0f2dSArmin Le Grand             double* pWeights = 0;
235237ab0f2dSArmin Le Grand             sal_uInt32* pPixels = 0;
235337ab0f2dSArmin Le Grand             sal_uInt32* pCount = 0;
235437ab0f2dSArmin Le Grand             sal_uInt32 aNumberOfContributions(0);
235537ab0f2dSArmin Le Grand 
235637ab0f2dSArmin Le Grand             const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
235737ab0f2dSArmin Le Grand             ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
235837ab0f2dSArmin Le Grand             rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
235937ab0f2dSArmin Le Grand             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
236037ab0f2dSArmin Le Grand             bool bResult(0 != pWriteAcc);
236137ab0f2dSArmin Le Grand 
236237ab0f2dSArmin Le Grand             if(pWriteAcc)
236337ab0f2dSArmin Le Grand             {
236437ab0f2dSArmin Le Grand                 for(sal_uInt32 x(0); x < nWidth; x++)
236537ab0f2dSArmin Le Grand                 {
236637ab0f2dSArmin Le Grand                     for(sal_uInt32 y(0); y < nNewHeight; y++)
236737ab0f2dSArmin Le Grand                     {
236837ab0f2dSArmin Le Grand                         const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
236937ab0f2dSArmin Le Grand                         double aSum(0.0);
237037ab0f2dSArmin Le Grand                         double aValueRed(0.0);
237137ab0f2dSArmin Le Grand                         double aValueGreen(0.0);
237237ab0f2dSArmin Le Grand                         double aValueBlue(0.0);
237337ab0f2dSArmin Le Grand 
237437ab0f2dSArmin Le Grand                         for(sal_uInt32 j(0); j < pCount[y]; j++)
237537ab0f2dSArmin Le Grand                         {
237637ab0f2dSArmin Le Grand                             const sal_uInt32 aIndex(aBaseIndex + j);
237737ab0f2dSArmin Le Grand                             const double aWeight(pWeights[aIndex]);
237837ab0f2dSArmin Le Grand                             BitmapColor aColor;
237937ab0f2dSArmin Le Grand 
238037ab0f2dSArmin Le Grand                             aSum += aWeight;
238137ab0f2dSArmin Le Grand 
238237ab0f2dSArmin Le Grand                             if(pReadAcc->HasPalette())
238337ab0f2dSArmin Le Grand                             {
238437ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
238537ab0f2dSArmin Le Grand                             }
238637ab0f2dSArmin Le Grand                             else
238737ab0f2dSArmin Le Grand                             {
238837ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
238937ab0f2dSArmin Le Grand                             }
239037ab0f2dSArmin Le Grand 
239137ab0f2dSArmin Le Grand                             aValueRed += aWeight * aColor.GetRed();
239237ab0f2dSArmin Le Grand                             aValueGreen += aWeight * aColor.GetGreen();
239337ab0f2dSArmin Le Grand                             aValueBlue += aWeight * aColor.GetBlue();
239437ab0f2dSArmin Le Grand                         }
239537ab0f2dSArmin Le Grand 
239637ab0f2dSArmin Le Grand                         const BitmapColor aResultColor(
239737ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
239837ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
239937ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
240037ab0f2dSArmin Le Grand 
240137ab0f2dSArmin Le Grand                         if(pWriteAcc->HasPalette())
240237ab0f2dSArmin Le Grand                         {
240337ab0f2dSArmin Le Grand                             pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
240437ab0f2dSArmin Le Grand                         }
240537ab0f2dSArmin Le Grand                         else
240637ab0f2dSArmin Le Grand                         {
240737ab0f2dSArmin Le Grand                             pWriteAcc->SetPixel(y, x, aResultColor);
240837ab0f2dSArmin Le Grand                         }
240937ab0f2dSArmin Le Grand                     }
241037ab0f2dSArmin Le Grand                 }
241137ab0f2dSArmin Le Grand             }
241237ab0f2dSArmin Le Grand 
241337ab0f2dSArmin Le Grand             rTarget.ReleaseAccess(pWriteAcc);
241437ab0f2dSArmin Le Grand             rSource.ReleaseAccess(pReadAcc);
241537ab0f2dSArmin Le Grand 
241637ab0f2dSArmin Le Grand             delete[] pWeights;
241737ab0f2dSArmin Le Grand             delete[] pCount;
241837ab0f2dSArmin Le Grand             delete[] pPixels;
241937ab0f2dSArmin Le Grand 
242037ab0f2dSArmin Le Grand             if(bResult)
242137ab0f2dSArmin Le Grand             {
242237ab0f2dSArmin Le Grand                 return true;
242337ab0f2dSArmin Le Grand             }
242437ab0f2dSArmin Le Grand         }
242537ab0f2dSArmin Le Grand 
242637ab0f2dSArmin Le Grand         return false;
242737ab0f2dSArmin Le Grand     }
242837ab0f2dSArmin Le Grand }
242937ab0f2dSArmin Le Grand 
243037ab0f2dSArmin Le Grand // #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and
243137ab0f2dSArmin Le Grand // BMP_SCALE_BOX derived from the original commit from Toma� Vajngerl (see
243237ab0f2dSArmin Le Grand // bugzilla task for deitails) Thanks!
243337ab0f2dSArmin Le Grand sal_Bool Bitmap::ImplScaleConvolution(
243437ab0f2dSArmin Le Grand     const double& rScaleX,
243537ab0f2dSArmin Le Grand     const double& rScaleY,
243637ab0f2dSArmin Le Grand     const Kernel& aKernel)
243737ab0f2dSArmin Le Grand {
243837ab0f2dSArmin Le Grand     const bool bMirrorHor(rScaleX < 0.0);
243937ab0f2dSArmin Le Grand     const bool bMirrorVer(rScaleY < 0.0);
244037ab0f2dSArmin Le Grand     const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
244137ab0f2dSArmin Le Grand     const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
244237ab0f2dSArmin Le Grand     const sal_uInt32 nWidth(GetSizePixel().Width());
244337ab0f2dSArmin Le Grand     const sal_uInt32 nHeight(GetSizePixel().Height());
244437ab0f2dSArmin Le Grand     const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
244537ab0f2dSArmin Le Grand     const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
244637ab0f2dSArmin Le Grand     const bool bScaleHor(nWidth != nNewWidth);
244737ab0f2dSArmin Le Grand     const bool bScaleVer(nHeight != nNewHeight);
244837ab0f2dSArmin Le Grand     const bool bMirror(bMirrorHor || bMirrorVer);
244937ab0f2dSArmin Le Grand 
245037ab0f2dSArmin Le Grand     if(!bMirror && !bScaleHor && !bScaleVer)
245137ab0f2dSArmin Le Grand     {
245237ab0f2dSArmin Le Grand         return true;
245337ab0f2dSArmin Le Grand     }
245437ab0f2dSArmin Le Grand 
245537ab0f2dSArmin Le Grand     bool bResult(true);
245637ab0f2dSArmin Le Grand     sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
245737ab0f2dSArmin Le Grand     bool bMirrorAfter(false);
245837ab0f2dSArmin Le Grand 
245937ab0f2dSArmin Le Grand     if(bMirror)
246037ab0f2dSArmin Le Grand     {
246137ab0f2dSArmin Le Grand         if(bMirrorHor)
246237ab0f2dSArmin Le Grand         {
246337ab0f2dSArmin Le Grand             nMirrorFlags |= BMP_MIRROR_HORZ;
246437ab0f2dSArmin Le Grand         }
246537ab0f2dSArmin Le Grand 
246637ab0f2dSArmin Le Grand         if(bMirrorVer)
246737ab0f2dSArmin Le Grand         {
246837ab0f2dSArmin Le Grand             nMirrorFlags |= BMP_MIRROR_VERT;
246937ab0f2dSArmin Le Grand         }
247037ab0f2dSArmin Le Grand 
247137ab0f2dSArmin Le Grand         const sal_uInt32 nStartSize(nWidth * nHeight);
247237ab0f2dSArmin Le Grand         const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
247337ab0f2dSArmin Le Grand 
247437ab0f2dSArmin Le Grand         bMirrorAfter = nStartSize > nEndSize;
247537ab0f2dSArmin Le Grand 
247637ab0f2dSArmin Le Grand         if(!bMirrorAfter)
247737ab0f2dSArmin Le Grand         {
247837ab0f2dSArmin Le Grand             bResult = Mirror(nMirrorFlags);
247937ab0f2dSArmin Le Grand         }
248037ab0f2dSArmin Le Grand     }
248137ab0f2dSArmin Le Grand 
248237ab0f2dSArmin Le Grand     Bitmap aResult;
248337ab0f2dSArmin Le Grand 
248437ab0f2dSArmin Le Grand     if(bResult)
248537ab0f2dSArmin Le Grand     {
248637ab0f2dSArmin Le Grand         const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
248737ab0f2dSArmin Le Grand         const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
24881a517a07SArmin Le Grand         Bitmap aSource(*this);
248937ab0f2dSArmin Le Grand 
249037ab0f2dSArmin Le Grand         if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
249137ab0f2dSArmin Le Grand         {
249237ab0f2dSArmin Le Grand             if(bScaleHor)
249337ab0f2dSArmin Le Grand             {
24941a517a07SArmin Le Grand                 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
249537ab0f2dSArmin Le Grand             }
249637ab0f2dSArmin Le Grand 
249737ab0f2dSArmin Le Grand             if(bResult && bScaleVer)
249837ab0f2dSArmin Le Grand             {
24991a517a07SArmin Le Grand                 if(bScaleHor)
25001a517a07SArmin Le Grand                 {
25011a517a07SArmin Le Grand                     // copy partial result, independent of color depth
25021a517a07SArmin Le Grand                     aSource = aResult;
25031a517a07SArmin Le Grand                 }
25041a517a07SArmin Le Grand 
25051a517a07SArmin Le Grand                 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
250637ab0f2dSArmin Le Grand             }
250737ab0f2dSArmin Le Grand         }
250837ab0f2dSArmin Le Grand         else
250937ab0f2dSArmin Le Grand         {
251037ab0f2dSArmin Le Grand             if(bScaleVer)
251137ab0f2dSArmin Le Grand             {
25121a517a07SArmin Le Grand                 bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
251337ab0f2dSArmin Le Grand             }
251437ab0f2dSArmin Le Grand 
251537ab0f2dSArmin Le Grand             if(bResult && bScaleHor)
251637ab0f2dSArmin Le Grand             {
25171a517a07SArmin Le Grand                 if(bScaleVer)
25181a517a07SArmin Le Grand                 {
25191a517a07SArmin Le Grand                     // copy partial result, independent of color depth
25201a517a07SArmin Le Grand                     aSource = aResult;
25211a517a07SArmin Le Grand                 }
25221a517a07SArmin Le Grand 
25231a517a07SArmin Le Grand                 bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
252437ab0f2dSArmin Le Grand             }
252537ab0f2dSArmin Le Grand         }
252637ab0f2dSArmin Le Grand     }
252737ab0f2dSArmin Le Grand 
252837ab0f2dSArmin Le Grand     if(bResult && bMirrorAfter)
252937ab0f2dSArmin Le Grand     {
253037ab0f2dSArmin Le Grand         bResult = aResult.Mirror(nMirrorFlags);
253137ab0f2dSArmin Le Grand     }
253237ab0f2dSArmin Le Grand 
253337ab0f2dSArmin Le Grand     if(bResult)
253437ab0f2dSArmin Le Grand     {
253537ab0f2dSArmin Le Grand         ImplAdaptBitCount(aResult);
253637ab0f2dSArmin Le Grand         *this = aResult;
253737ab0f2dSArmin Le Grand     }
253837ab0f2dSArmin Le Grand 
253937ab0f2dSArmin Le Grand     return bResult;
254037ab0f2dSArmin Le Grand }
254137ab0f2dSArmin Le Grand 
254237ab0f2dSArmin Le Grand // ------------------------------------------------------------------------
2543cdf0e10cSrcweir 
2544cdf0e10cSrcweir sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
2545cdf0e10cSrcweir {
2546cdf0e10cSrcweir     sal_Bool bRet = sal_False;
2547cdf0e10cSrcweir 
2548cdf0e10cSrcweir     const Size aSizePix( GetSizePixel() );
2549cdf0e10cSrcweir 
2550cdf0e10cSrcweir     if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
2551cdf0e10cSrcweir         bRet = sal_True;
2552cdf0e10cSrcweir     else if( nDitherFlags & BMP_DITHER_MATRIX )
2553cdf0e10cSrcweir         bRet = ImplDitherMatrix();
2554cdf0e10cSrcweir     else if( nDitherFlags & BMP_DITHER_FLOYD )
2555cdf0e10cSrcweir         bRet = ImplDitherFloyd();
2556cdf0e10cSrcweir     else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
2557cdf0e10cSrcweir         bRet = ImplDitherFloyd16();
2558cdf0e10cSrcweir 
2559cdf0e10cSrcweir     return bRet;
2560cdf0e10cSrcweir }
2561cdf0e10cSrcweir 
2562cdf0e10cSrcweir // ------------------------------------------------------------------------
2563cdf0e10cSrcweir 
2564cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherMatrix()
2565cdf0e10cSrcweir {
2566cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
2567cdf0e10cSrcweir     Bitmap              aNewBmp( GetSizePixel(), 8 );
2568cdf0e10cSrcweir     BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
2569cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
2570cdf0e10cSrcweir 
2571cdf0e10cSrcweir     if( pReadAcc && pWriteAcc )
2572cdf0e10cSrcweir     {
2573cdf0e10cSrcweir         const sal_uLong nWidth = pReadAcc->Width();
2574cdf0e10cSrcweir         const sal_uLong nHeight = pReadAcc->Height();
2575cdf0e10cSrcweir         BitmapColor aIndex( (sal_uInt8) 0 );
2576cdf0e10cSrcweir 
2577cdf0e10cSrcweir         if( pReadAcc->HasPalette() )
2578cdf0e10cSrcweir         {
2579cdf0e10cSrcweir             for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2580cdf0e10cSrcweir             {
2581cdf0e10cSrcweir                 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2582cdf0e10cSrcweir                 {
258387bc88d3SHerbert Dürr                     const BitmapColor   aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
2584cdf0e10cSrcweir                     const sal_uLong         nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2585cdf0e10cSrcweir                     const sal_uLong         nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2586cdf0e10cSrcweir                     const sal_uLong         nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2587cdf0e10cSrcweir                     const sal_uLong         nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2588cdf0e10cSrcweir 
2589cdf0e10cSrcweir                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2590cdf0e10cSrcweir                     pWriteAcc->SetPixel( nY, nX, aIndex );
2591cdf0e10cSrcweir                 }
2592cdf0e10cSrcweir             }
2593cdf0e10cSrcweir         }
2594cdf0e10cSrcweir         else
2595cdf0e10cSrcweir         {
2596cdf0e10cSrcweir             for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2597cdf0e10cSrcweir             {
2598cdf0e10cSrcweir                 for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2599cdf0e10cSrcweir                 {
2600cdf0e10cSrcweir                     const BitmapColor   aCol( pReadAcc->GetPixel( nY, nX ) );
2601cdf0e10cSrcweir                     const sal_uLong         nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2602cdf0e10cSrcweir                     const sal_uLong         nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2603cdf0e10cSrcweir                     const sal_uLong         nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2604cdf0e10cSrcweir                     const sal_uLong         nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2605cdf0e10cSrcweir 
2606cdf0e10cSrcweir                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2607cdf0e10cSrcweir                     pWriteAcc->SetPixel( nY, nX, aIndex );
2608cdf0e10cSrcweir                 }
2609cdf0e10cSrcweir             }
2610cdf0e10cSrcweir         }
2611cdf0e10cSrcweir 
2612cdf0e10cSrcweir         bRet = sal_True;
2613cdf0e10cSrcweir     }
2614cdf0e10cSrcweir 
2615cdf0e10cSrcweir     ReleaseAccess( pReadAcc );
2616cdf0e10cSrcweir     aNewBmp.ReleaseAccess( pWriteAcc );
2617cdf0e10cSrcweir 
2618cdf0e10cSrcweir     if( bRet )
2619cdf0e10cSrcweir     {
2620cdf0e10cSrcweir         const MapMode   aMap( maPrefMapMode );
2621cdf0e10cSrcweir         const Size      aSize( maPrefSize );
2622cdf0e10cSrcweir 
2623cdf0e10cSrcweir         *this = aNewBmp;
2624cdf0e10cSrcweir 
2625cdf0e10cSrcweir         maPrefMapMode = aMap;
2626cdf0e10cSrcweir         maPrefSize = aSize;
2627cdf0e10cSrcweir     }
2628cdf0e10cSrcweir 
2629cdf0e10cSrcweir     return bRet;
2630cdf0e10cSrcweir }
2631cdf0e10cSrcweir 
2632cdf0e10cSrcweir // ------------------------------------------------------------------------
2633cdf0e10cSrcweir 
2634cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherFloyd()
2635cdf0e10cSrcweir {
2636cdf0e10cSrcweir     const Size  aSize( GetSizePixel() );
2637cdf0e10cSrcweir     sal_Bool        bRet = sal_False;
2638cdf0e10cSrcweir 
2639cdf0e10cSrcweir     if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
2640cdf0e10cSrcweir     {
2641cdf0e10cSrcweir         BitmapReadAccess*   pReadAcc = AcquireReadAccess();
2642cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), 8 );
2643cdf0e10cSrcweir         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
2644cdf0e10cSrcweir 
2645cdf0e10cSrcweir         if( pReadAcc && pWriteAcc )
2646cdf0e10cSrcweir         {
2647cdf0e10cSrcweir             BitmapColor aColor;
2648cdf0e10cSrcweir             long        nWidth = pReadAcc->Width();
2649cdf0e10cSrcweir             long        nWidth1 = nWidth - 1L;
2650cdf0e10cSrcweir             long        nHeight = pReadAcc->Height();
2651cdf0e10cSrcweir             long        nX;
2652cdf0e10cSrcweir             long        nW = nWidth * 3L;
2653cdf0e10cSrcweir             long        nW2 = nW - 3L;
2654cdf0e10cSrcweir             long        nRErr, nGErr, nBErr;
2655cdf0e10cSrcweir             long        nRC, nGC, nBC;
2656cdf0e10cSrcweir             long        nTemp;
2657cdf0e10cSrcweir             long        nZ;
2658cdf0e10cSrcweir             long*       p1 = new long[ nW ];
2659cdf0e10cSrcweir             long*       p2 = new long[ nW ];
2660cdf0e10cSrcweir             long*       p1T = p1;
2661cdf0e10cSrcweir             long*       p2T = p2;
2662cdf0e10cSrcweir             long*       pTmp;
2663cdf0e10cSrcweir             sal_Bool        bPal = pReadAcc->HasPalette();
2664cdf0e10cSrcweir 
2665cdf0e10cSrcweir             pTmp = p2T;
2666cdf0e10cSrcweir 
2667cdf0e10cSrcweir             if( bPal )
2668cdf0e10cSrcweir             {
2669cdf0e10cSrcweir                 for( nZ = 0; nZ < nWidth; nZ++ )
2670cdf0e10cSrcweir                 {
267187bc88d3SHerbert Dürr                     aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) );
2672cdf0e10cSrcweir 
2673cdf0e10cSrcweir                     *pTmp++ = (long) aColor.GetBlue() << 12;
2674cdf0e10cSrcweir                     *pTmp++ = (long) aColor.GetGreen() << 12;
2675cdf0e10cSrcweir                     *pTmp++ = (long) aColor.GetRed() << 12;
2676cdf0e10cSrcweir                 }
2677cdf0e10cSrcweir             }
2678cdf0e10cSrcweir             else
2679cdf0e10cSrcweir             {
2680cdf0e10cSrcweir                 for( nZ = 0; nZ < nWidth; nZ++ )
2681cdf0e10cSrcweir                 {
2682cdf0e10cSrcweir                     aColor = pReadAcc->GetPixel( 0, nZ );
2683cdf0e10cSrcweir 
2684cdf0e10cSrcweir                     *pTmp++ = (long) aColor.GetBlue() << 12;
2685cdf0e10cSrcweir                     *pTmp++ = (long) aColor.GetGreen() << 12;
2686cdf0e10cSrcweir                     *pTmp++ = (long) aColor.GetRed() << 12;
2687cdf0e10cSrcweir                 }
2688cdf0e10cSrcweir             }
2689cdf0e10cSrcweir 
2690cdf0e10cSrcweir             for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
2691cdf0e10cSrcweir             {
2692cdf0e10cSrcweir                 pTmp = p1T;
2693cdf0e10cSrcweir                 p1T = p2T;
2694cdf0e10cSrcweir                 p2T = pTmp;
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir                 if( nY < nHeight )
2697cdf0e10cSrcweir                 {
2698cdf0e10cSrcweir                     if( bPal )
2699cdf0e10cSrcweir                     {
2700cdf0e10cSrcweir                         for( nZ = 0; nZ < nWidth; nZ++ )
2701cdf0e10cSrcweir                         {
270287bc88d3SHerbert Dürr                             aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) );
2703cdf0e10cSrcweir 
2704cdf0e10cSrcweir                             *pTmp++ = (long) aColor.GetBlue() << 12;
2705cdf0e10cSrcweir                             *pTmp++ = (long) aColor.GetGreen() << 12;
2706cdf0e10cSrcweir                             *pTmp++ = (long) aColor.GetRed() << 12;
2707cdf0e10cSrcweir                         }
2708cdf0e10cSrcweir                     }
2709cdf0e10cSrcweir                     else
2710cdf0e10cSrcweir                     {
2711cdf0e10cSrcweir                         for( nZ = 0; nZ < nWidth; nZ++ )
2712cdf0e10cSrcweir                         {
2713cdf0e10cSrcweir                             aColor = pReadAcc->GetPixel( nY, nZ );
2714cdf0e10cSrcweir 
2715cdf0e10cSrcweir                             *pTmp++ = (long) aColor.GetBlue() << 12;
2716cdf0e10cSrcweir                             *pTmp++ = (long) aColor.GetGreen() << 12;
2717cdf0e10cSrcweir                             *pTmp++ = (long) aColor.GetRed() << 12;
2718cdf0e10cSrcweir                         }
2719cdf0e10cSrcweir                     }
2720cdf0e10cSrcweir                 }
2721cdf0e10cSrcweir 
2722cdf0e10cSrcweir                 // erstes Pixel gesondert betrachten
2723cdf0e10cSrcweir                 nX = 0;
2724cdf0e10cSrcweir                 CALC_ERRORS;
2725cdf0e10cSrcweir                 CALC_TABLES7;
2726cdf0e10cSrcweir                 nX -= 5;
2727cdf0e10cSrcweir                 CALC_TABLES5;
272887bc88d3SHerbert Dürr                 pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2729cdf0e10cSrcweir 
2730cdf0e10cSrcweir                 // mittlere Pixel ueber Schleife
2731cdf0e10cSrcweir                 long nXAcc;
2732cdf0e10cSrcweir                 for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
2733cdf0e10cSrcweir                 {
2734cdf0e10cSrcweir                     CALC_ERRORS;
2735cdf0e10cSrcweir                     CALC_TABLES7;
2736cdf0e10cSrcweir                     nX -= 8;
2737cdf0e10cSrcweir                     CALC_TABLES3;
2738cdf0e10cSrcweir                     CALC_TABLES5;
273987bc88d3SHerbert Dürr                     pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2740cdf0e10cSrcweir                 }
2741cdf0e10cSrcweir 
2742cdf0e10cSrcweir                 // letztes Pixel gesondert betrachten
2743cdf0e10cSrcweir                 CALC_ERRORS;
2744cdf0e10cSrcweir                 nX -= 5;
2745cdf0e10cSrcweir                 CALC_TABLES3;
2746cdf0e10cSrcweir                 CALC_TABLES5;
274787bc88d3SHerbert Dürr                 pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2748cdf0e10cSrcweir             }
2749cdf0e10cSrcweir 
2750cdf0e10cSrcweir             delete[] p1;
2751cdf0e10cSrcweir             delete[] p2;
2752cdf0e10cSrcweir             bRet = sal_True;
2753cdf0e10cSrcweir         }
2754cdf0e10cSrcweir 
2755cdf0e10cSrcweir         ReleaseAccess( pReadAcc );
2756cdf0e10cSrcweir         aNewBmp.ReleaseAccess( pWriteAcc );
2757cdf0e10cSrcweir 
2758cdf0e10cSrcweir         if( bRet )
2759cdf0e10cSrcweir         {
2760cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
2761cdf0e10cSrcweir             const Size      aPrefSize( maPrefSize );
2762cdf0e10cSrcweir 
2763cdf0e10cSrcweir             *this = aNewBmp;
2764cdf0e10cSrcweir 
2765cdf0e10cSrcweir             maPrefMapMode = aMap;
2766cdf0e10cSrcweir             maPrefSize = aPrefSize;
2767cdf0e10cSrcweir         }
2768cdf0e10cSrcweir     }
2769cdf0e10cSrcweir 
2770cdf0e10cSrcweir     return bRet;
2771cdf0e10cSrcweir }
2772cdf0e10cSrcweir 
2773cdf0e10cSrcweir // ------------------------------------------------------------------------
2774cdf0e10cSrcweir 
2775cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherFloyd16()
2776cdf0e10cSrcweir {
2777cdf0e10cSrcweir     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
2778cdf0e10cSrcweir     Bitmap              aNewBmp( GetSizePixel(), 24 );
2779cdf0e10cSrcweir     BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
2780cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
2781cdf0e10cSrcweir 
2782cdf0e10cSrcweir     if( pReadAcc && pWriteAcc )
2783cdf0e10cSrcweir     {
2784cdf0e10cSrcweir         const long      nWidth = pWriteAcc->Width();
2785cdf0e10cSrcweir         const long      nWidth1 = nWidth - 1L;
2786cdf0e10cSrcweir         const long      nHeight = pWriteAcc->Height();
2787cdf0e10cSrcweir         BitmapColor     aColor;
2788cdf0e10cSrcweir         BitmapColor     aBestCol;
2789cdf0e10cSrcweir         ImpErrorQuad    aErrQuad;
2790cdf0e10cSrcweir         ImpErrorQuad*   pErrQuad1 = new ImpErrorQuad[ nWidth ];
2791cdf0e10cSrcweir         ImpErrorQuad*   pErrQuad2 = new ImpErrorQuad[ nWidth ];
2792cdf0e10cSrcweir         ImpErrorQuad*   pQLine1 = pErrQuad1;
2793cdf0e10cSrcweir         ImpErrorQuad*   pQLine2 = 0;
2794cdf0e10cSrcweir         long            nX, nY;
2795cdf0e10cSrcweir         long            nYTmp = 0L;
2796cdf0e10cSrcweir         sal_Bool            bQ1 = sal_True;
2797cdf0e10cSrcweir 
2798cdf0e10cSrcweir         for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
2799cdf0e10cSrcweir             for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
2800cdf0e10cSrcweir                 pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2801cdf0e10cSrcweir 
2802cdf0e10cSrcweir         for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
2803cdf0e10cSrcweir         {
2804cdf0e10cSrcweir             // erstes ZeilenPixel
2805cdf0e10cSrcweir             aBestCol = pQLine1[ 0 ].ImplGetColor();
2806cdf0e10cSrcweir             aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2807cdf0e10cSrcweir             aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2808cdf0e10cSrcweir             aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2809cdf0e10cSrcweir             pWriteAcc->SetPixel( nY, 0, aBestCol );
2810cdf0e10cSrcweir 
2811cdf0e10cSrcweir             for( nX = 1L; nX < nWidth1; nX++ )
2812cdf0e10cSrcweir             {
2813cdf0e10cSrcweir                 aColor = pQLine1[ nX ].ImplGetColor();
2814cdf0e10cSrcweir                 aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
2815cdf0e10cSrcweir                 aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
2816cdf0e10cSrcweir                 aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
2817cdf0e10cSrcweir                 aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
2818cdf0e10cSrcweir                 pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
2819cdf0e10cSrcweir                 pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
2820cdf0e10cSrcweir                 pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
2821cdf0e10cSrcweir                 pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
2822cdf0e10cSrcweir                 pWriteAcc->SetPixel( nY, nX, aBestCol );
2823cdf0e10cSrcweir             }
2824cdf0e10cSrcweir 
2825cdf0e10cSrcweir             // letztes ZeilenPixel
2826cdf0e10cSrcweir             aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
2827cdf0e10cSrcweir             aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2828cdf0e10cSrcweir             aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2829cdf0e10cSrcweir             aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2830cdf0e10cSrcweir             pWriteAcc->SetPixel( nY, nX, aBestCol );
2831cdf0e10cSrcweir 
2832cdf0e10cSrcweir             // Zeilenpuffer neu fuellen/kopieren
2833cdf0e10cSrcweir             pQLine1 = pQLine2;
2834cdf0e10cSrcweir             pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
2835cdf0e10cSrcweir 
2836cdf0e10cSrcweir             if( nYTmp < nHeight )
2837cdf0e10cSrcweir                 for( nX = 0L; nX < nWidth; nX++ )
2838cdf0e10cSrcweir                     pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2839cdf0e10cSrcweir         }
2840cdf0e10cSrcweir 
2841cdf0e10cSrcweir         // Zeilenpuffer zerstoeren
2842cdf0e10cSrcweir         delete[] pErrQuad1;
2843cdf0e10cSrcweir         delete[] pErrQuad2;
2844cdf0e10cSrcweir         bRet = sal_True;
2845cdf0e10cSrcweir     }
2846cdf0e10cSrcweir 
2847cdf0e10cSrcweir     ReleaseAccess( pReadAcc );
2848cdf0e10cSrcweir     aNewBmp.ReleaseAccess( pWriteAcc );
2849cdf0e10cSrcweir 
2850cdf0e10cSrcweir     if( bRet )
2851cdf0e10cSrcweir     {
2852cdf0e10cSrcweir         const MapMode   aMap( maPrefMapMode );
2853cdf0e10cSrcweir         const Size      aSize( maPrefSize );
2854cdf0e10cSrcweir 
2855cdf0e10cSrcweir         *this = aNewBmp;
2856cdf0e10cSrcweir 
2857cdf0e10cSrcweir         maPrefMapMode = aMap;
2858cdf0e10cSrcweir         maPrefSize = aSize;
2859cdf0e10cSrcweir     }
2860cdf0e10cSrcweir 
2861cdf0e10cSrcweir     return bRet;
2862cdf0e10cSrcweir }
2863cdf0e10cSrcweir 
2864cdf0e10cSrcweir // ------------------------------------------------------------------------
2865cdf0e10cSrcweir 
2866cdf0e10cSrcweir sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
2867cdf0e10cSrcweir {
2868cdf0e10cSrcweir     sal_Bool bRet;
2869cdf0e10cSrcweir 
2870cdf0e10cSrcweir     if( GetColorCount() <= (sal_uLong) nColorCount )
2871cdf0e10cSrcweir         bRet = sal_True;
2872cdf0e10cSrcweir     else if( nColorCount )
2873cdf0e10cSrcweir     {
2874cdf0e10cSrcweir         if( BMP_REDUCE_SIMPLE == eReduce )
2875cdf0e10cSrcweir             bRet = ImplReduceSimple( nColorCount );
2876cdf0e10cSrcweir         else if( BMP_REDUCE_POPULAR == eReduce )
2877cdf0e10cSrcweir             bRet = ImplReducePopular( nColorCount );
2878cdf0e10cSrcweir         else
2879cdf0e10cSrcweir             bRet = ImplReduceMedian( nColorCount );
2880cdf0e10cSrcweir     }
2881cdf0e10cSrcweir     else
2882cdf0e10cSrcweir         bRet = sal_False;
2883cdf0e10cSrcweir 
2884cdf0e10cSrcweir     return bRet;
2885cdf0e10cSrcweir }
2886cdf0e10cSrcweir 
2887cdf0e10cSrcweir // ------------------------------------------------------------------------
2888cdf0e10cSrcweir 
2889cdf0e10cSrcweir sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
2890cdf0e10cSrcweir {
2891cdf0e10cSrcweir     Bitmap              aNewBmp;
2892cdf0e10cSrcweir     BitmapReadAccess*   pRAcc = AcquireReadAccess();
2893cdf0e10cSrcweir     const sal_uInt16        nColCount = Min( nColorCount, (sal_uInt16) 256 );
2894cdf0e10cSrcweir     sal_uInt16              nBitCount;
2895cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
2896cdf0e10cSrcweir 
2897cdf0e10cSrcweir     if( nColCount <= 2 )
2898cdf0e10cSrcweir         nBitCount = 1;
2899cdf0e10cSrcweir     else if( nColCount <= 16 )
2900cdf0e10cSrcweir         nBitCount = 4;
2901cdf0e10cSrcweir     else
2902cdf0e10cSrcweir         nBitCount = 8;
2903cdf0e10cSrcweir 
2904cdf0e10cSrcweir     if( pRAcc )
2905cdf0e10cSrcweir     {
2906cdf0e10cSrcweir         Octree                  aOct( *pRAcc, nColCount );
2907cdf0e10cSrcweir         const BitmapPalette&    rPal = aOct.GetPalette();
2908cdf0e10cSrcweir         BitmapWriteAccess*      pWAcc;
2909cdf0e10cSrcweir 
2910cdf0e10cSrcweir         aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
2911cdf0e10cSrcweir         pWAcc = aNewBmp.AcquireWriteAccess();
2912cdf0e10cSrcweir 
2913cdf0e10cSrcweir         if( pWAcc )
2914cdf0e10cSrcweir         {
2915cdf0e10cSrcweir             const long nWidth = pRAcc->Width();
2916cdf0e10cSrcweir             const long nHeight = pRAcc->Height();
2917cdf0e10cSrcweir 
2918cdf0e10cSrcweir             if( pRAcc->HasPalette() )
2919cdf0e10cSrcweir             {
2920cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
2921cdf0e10cSrcweir                     for( long nX =0L; nX < nWidth; nX++ )
292287bc88d3SHerbert Dürr                         pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) );
2923cdf0e10cSrcweir             }
2924cdf0e10cSrcweir             else
2925cdf0e10cSrcweir             {
2926cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
2927cdf0e10cSrcweir                     for( long nX =0L; nX < nWidth; nX++ )
292887bc88d3SHerbert Dürr                         pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) );
2929cdf0e10cSrcweir             }
2930cdf0e10cSrcweir 
2931cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWAcc );
2932cdf0e10cSrcweir             bRet = sal_True;
2933cdf0e10cSrcweir         }
2934cdf0e10cSrcweir 
2935cdf0e10cSrcweir         ReleaseAccess( pRAcc );
2936cdf0e10cSrcweir     }
2937cdf0e10cSrcweir 
2938cdf0e10cSrcweir     if( bRet )
2939cdf0e10cSrcweir     {
2940cdf0e10cSrcweir         const MapMode   aMap( maPrefMapMode );
2941cdf0e10cSrcweir         const Size      aSize( maPrefSize );
2942cdf0e10cSrcweir 
2943cdf0e10cSrcweir         *this = aNewBmp;
2944cdf0e10cSrcweir         maPrefMapMode = aMap;
2945cdf0e10cSrcweir         maPrefSize = aSize;
2946cdf0e10cSrcweir     }
2947cdf0e10cSrcweir 
2948cdf0e10cSrcweir     return bRet;
2949cdf0e10cSrcweir }
2950cdf0e10cSrcweir 
2951cdf0e10cSrcweir // ------------------------------------------------------------------------
2952cdf0e10cSrcweir 
2953cdf0e10cSrcweir struct PopularColorCount
2954cdf0e10cSrcweir {
2955cdf0e10cSrcweir     sal_uInt32  mnIndex;
2956cdf0e10cSrcweir     sal_uInt32  mnCount;
2957cdf0e10cSrcweir };
2958cdf0e10cSrcweir 
2959cdf0e10cSrcweir // ------------------------------------------------------------------------
2960cdf0e10cSrcweir 
2961cdf0e10cSrcweir extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
2962cdf0e10cSrcweir {
2963cdf0e10cSrcweir     int nRet;
2964cdf0e10cSrcweir 
2965cdf0e10cSrcweir     if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
2966cdf0e10cSrcweir         nRet = 1;
2967cdf0e10cSrcweir     else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
2968cdf0e10cSrcweir         nRet = 0;
2969cdf0e10cSrcweir     else
2970cdf0e10cSrcweir         nRet = -1;
2971cdf0e10cSrcweir 
2972cdf0e10cSrcweir     return nRet;
2973cdf0e10cSrcweir }
2974cdf0e10cSrcweir 
2975cdf0e10cSrcweir // ------------------------------------------------------------------------
2976cdf0e10cSrcweir 
2977cdf0e10cSrcweir sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
2978cdf0e10cSrcweir {
2979cdf0e10cSrcweir     BitmapReadAccess*   pRAcc = AcquireReadAccess();
2980cdf0e10cSrcweir     sal_uInt16              nBitCount;
2981cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
2982cdf0e10cSrcweir 
2983cdf0e10cSrcweir     if( nColCount > 256 )
2984cdf0e10cSrcweir         nColCount = 256;
2985cdf0e10cSrcweir 
2986cdf0e10cSrcweir     if( nColCount < 17 )
2987cdf0e10cSrcweir         nBitCount = 4;
2988cdf0e10cSrcweir     else
2989cdf0e10cSrcweir         nBitCount = 8;
2990cdf0e10cSrcweir 
2991cdf0e10cSrcweir     if( pRAcc )
2992cdf0e10cSrcweir     {
2993cdf0e10cSrcweir         const sal_uInt32    nValidBits = 4;
2994cdf0e10cSrcweir         const sal_uInt32    nRightShiftBits = 8 - nValidBits;
2995cdf0e10cSrcweir         const sal_uInt32    nLeftShiftBits1 = nValidBits;
2996cdf0e10cSrcweir         const sal_uInt32    nLeftShiftBits2 = nValidBits << 1;
2997cdf0e10cSrcweir         const sal_uInt32    nColorsPerComponent = 1 << nValidBits;
2998cdf0e10cSrcweir         const sal_uInt32    nColorOffset = 256 / nColorsPerComponent;
2999cdf0e10cSrcweir         const sal_uInt32    nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
3000cdf0e10cSrcweir         const long          nWidth = pRAcc->Width();
3001cdf0e10cSrcweir         const long          nHeight = pRAcc->Height();
3002cdf0e10cSrcweir         PopularColorCount*  pCountTable = new PopularColorCount[ nTotalColors ];
3003cdf0e10cSrcweir         long                nX, nY, nR, nG, nB, nIndex;
3004cdf0e10cSrcweir 
3005cdf0e10cSrcweir         rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
3006cdf0e10cSrcweir 
3007cdf0e10cSrcweir         for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3008cdf0e10cSrcweir         {
3009cdf0e10cSrcweir             for( nG = 0; nG < 256; nG += nColorOffset )
3010cdf0e10cSrcweir             {
3011cdf0e10cSrcweir                 for( nB = 0; nB < 256; nB += nColorOffset )
3012cdf0e10cSrcweir                 {
3013cdf0e10cSrcweir                     pCountTable[ nIndex ].mnIndex = nIndex;
3014cdf0e10cSrcweir                     nIndex++;
3015cdf0e10cSrcweir                 }
3016cdf0e10cSrcweir             }
3017cdf0e10cSrcweir         }
3018cdf0e10cSrcweir 
3019cdf0e10cSrcweir         if( pRAcc->HasPalette() )
3020cdf0e10cSrcweir         {
3021cdf0e10cSrcweir             for( nY = 0L; nY < nHeight; nY++ )
3022cdf0e10cSrcweir             {
3023cdf0e10cSrcweir                 for( nX = 0L; nX < nWidth; nX++ )
3024cdf0e10cSrcweir                 {
302587bc88d3SHerbert Dürr                     const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3026cdf0e10cSrcweir                     pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3027cdf0e10cSrcweir                                  ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3028cdf0e10cSrcweir                                  ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3029cdf0e10cSrcweir                 }
3030cdf0e10cSrcweir             }
3031cdf0e10cSrcweir         }
3032cdf0e10cSrcweir         else
3033cdf0e10cSrcweir         {
3034cdf0e10cSrcweir             for( nY = 0L; nY < nHeight; nY++ )
3035cdf0e10cSrcweir             {
3036cdf0e10cSrcweir                 for( nX = 0L; nX < nWidth; nX++ )
3037cdf0e10cSrcweir                 {
3038cdf0e10cSrcweir                     const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3039cdf0e10cSrcweir                     pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3040cdf0e10cSrcweir                                  ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3041cdf0e10cSrcweir                                  ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3042cdf0e10cSrcweir                 }
3043cdf0e10cSrcweir             }
3044cdf0e10cSrcweir         }
3045cdf0e10cSrcweir 
3046cdf0e10cSrcweir         BitmapPalette aNewPal( nColCount );
3047cdf0e10cSrcweir 
3048cdf0e10cSrcweir         qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
3049cdf0e10cSrcweir 
3050cdf0e10cSrcweir         for( sal_uInt16 n = 0; n < nColCount; n++ )
3051cdf0e10cSrcweir         {
3052cdf0e10cSrcweir             const PopularColorCount& rPop = pCountTable[ n ];
3053cdf0e10cSrcweir             aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
3054cdf0e10cSrcweir                                         (sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
3055cdf0e10cSrcweir                                         (sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
3056cdf0e10cSrcweir         }
3057cdf0e10cSrcweir 
3058cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
3059cdf0e10cSrcweir         BitmapWriteAccess*  pWAcc = aNewBmp.AcquireWriteAccess();
3060cdf0e10cSrcweir 
3061cdf0e10cSrcweir         if( pWAcc )
3062cdf0e10cSrcweir         {
3063cdf0e10cSrcweir             BitmapColor aDstCol( (sal_uInt8) 0 );
3064cdf0e10cSrcweir             sal_uInt8*      pIndexMap = new sal_uInt8[ nTotalColors ];
3065cdf0e10cSrcweir 
3066cdf0e10cSrcweir             for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3067cdf0e10cSrcweir                 for( nG = 0; nG < 256; nG += nColorOffset )
3068cdf0e10cSrcweir                     for( nB = 0; nB < 256; nB += nColorOffset )
3069cdf0e10cSrcweir                         pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
3070cdf0e10cSrcweir 
3071cdf0e10cSrcweir             if( pRAcc->HasPalette() )
3072cdf0e10cSrcweir             {
3073cdf0e10cSrcweir                 for( nY = 0L; nY < nHeight; nY++ )
3074cdf0e10cSrcweir                 {
3075cdf0e10cSrcweir                     for( nX = 0L; nX < nWidth; nX++ )
3076cdf0e10cSrcweir                     {
307787bc88d3SHerbert Dürr                         const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3078cdf0e10cSrcweir                         aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3079cdf0e10cSrcweir                                                      ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3080cdf0e10cSrcweir                                                      ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
3081cdf0e10cSrcweir                         pWAcc->SetPixel( nY, nX, aDstCol );
3082cdf0e10cSrcweir                     }
3083cdf0e10cSrcweir                 }
3084cdf0e10cSrcweir             }
3085cdf0e10cSrcweir             else
3086cdf0e10cSrcweir             {
3087cdf0e10cSrcweir                 for( nY = 0L; nY < nHeight; nY++ )
3088cdf0e10cSrcweir                 {
3089cdf0e10cSrcweir                     for( nX = 0L; nX < nWidth; nX++ )
3090cdf0e10cSrcweir                     {
3091cdf0e10cSrcweir                         const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3092cdf0e10cSrcweir                         aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3093cdf0e10cSrcweir                                                      ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3094cdf0e10cSrcweir                                                      ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
3095cdf0e10cSrcweir                         pWAcc->SetPixel( nY, nX, aDstCol );
3096cdf0e10cSrcweir                     }
3097cdf0e10cSrcweir                 }
3098cdf0e10cSrcweir             }
3099cdf0e10cSrcweir 
3100cdf0e10cSrcweir             delete[] pIndexMap;
3101cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWAcc );
3102cdf0e10cSrcweir             bRet = sal_True;
3103cdf0e10cSrcweir         }
3104cdf0e10cSrcweir 
3105cdf0e10cSrcweir         delete[] pCountTable;
3106cdf0e10cSrcweir         ReleaseAccess( pRAcc );
3107cdf0e10cSrcweir 
3108cdf0e10cSrcweir         if( bRet )
3109cdf0e10cSrcweir         {
3110cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
3111cdf0e10cSrcweir             const Size      aSize( maPrefSize );
3112cdf0e10cSrcweir 
3113cdf0e10cSrcweir             *this = aNewBmp;
3114cdf0e10cSrcweir             maPrefMapMode = aMap;
3115cdf0e10cSrcweir             maPrefSize = aSize;
3116cdf0e10cSrcweir         }
3117cdf0e10cSrcweir     }
3118cdf0e10cSrcweir 
3119cdf0e10cSrcweir     return bRet;
3120cdf0e10cSrcweir }
3121cdf0e10cSrcweir 
3122cdf0e10cSrcweir // ------------------------------------------------------------------------
3123cdf0e10cSrcweir 
3124cdf0e10cSrcweir sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
3125cdf0e10cSrcweir {
3126cdf0e10cSrcweir     BitmapReadAccess*   pRAcc = AcquireReadAccess();
3127cdf0e10cSrcweir     sal_uInt16              nBitCount;
3128cdf0e10cSrcweir     sal_Bool                bRet = sal_False;
3129cdf0e10cSrcweir 
3130cdf0e10cSrcweir     if( nColCount < 17 )
3131cdf0e10cSrcweir         nBitCount = 4;
3132cdf0e10cSrcweir     else if( nColCount < 257 )
3133cdf0e10cSrcweir         nBitCount = 8;
3134cdf0e10cSrcweir     else
3135cdf0e10cSrcweir     {
3136cdf0e10cSrcweir         DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
3137cdf0e10cSrcweir         nBitCount = 8;
3138cdf0e10cSrcweir         nColCount = 256;
3139cdf0e10cSrcweir     }
3140cdf0e10cSrcweir 
3141cdf0e10cSrcweir     if( pRAcc )
3142cdf0e10cSrcweir     {
3143cdf0e10cSrcweir         Bitmap              aNewBmp( GetSizePixel(), nBitCount );
3144cdf0e10cSrcweir         BitmapWriteAccess*  pWAcc = aNewBmp.AcquireWriteAccess();
3145cdf0e10cSrcweir 
3146cdf0e10cSrcweir         if( pWAcc )
3147cdf0e10cSrcweir         {
3148cdf0e10cSrcweir             const sal_uLong nSize = 32768UL * sizeof( sal_uLong );
3149cdf0e10cSrcweir             sal_uLong*      pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
3150cdf0e10cSrcweir             const long  nWidth = pWAcc->Width();
3151cdf0e10cSrcweir             const long  nHeight = pWAcc->Height();
3152cdf0e10cSrcweir             long        nIndex = 0L;
3153cdf0e10cSrcweir 
3154cdf0e10cSrcweir             memset( (HPBYTE) pColBuf, 0, nSize );
3155cdf0e10cSrcweir 
3156cdf0e10cSrcweir             // create Buffer
3157cdf0e10cSrcweir             if( pRAcc->HasPalette() )
3158cdf0e10cSrcweir             {
3159cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
3160cdf0e10cSrcweir                 {
3161cdf0e10cSrcweir                     for( long nX = 0L; nX < nWidth; nX++ )
3162cdf0e10cSrcweir                     {
316387bc88d3SHerbert Dürr                         const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3164cdf0e10cSrcweir                         pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
3165cdf0e10cSrcweir                     }
3166cdf0e10cSrcweir                 }
3167cdf0e10cSrcweir             }
3168cdf0e10cSrcweir             else
3169cdf0e10cSrcweir             {
3170cdf0e10cSrcweir                 for( long nY = 0L; nY < nHeight; nY++ )
3171cdf0e10cSrcweir                 {
3172cdf0e10cSrcweir                     for( long nX = 0L; nX < nWidth; nX++ )
3173cdf0e10cSrcweir                     {
3174cdf0e10cSrcweir                         const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3175cdf0e10cSrcweir                         pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
3176cdf0e10cSrcweir                     }
3177cdf0e10cSrcweir                 }
3178cdf0e10cSrcweir             }
3179cdf0e10cSrcweir 
3180cdf0e10cSrcweir             // create palette via median cut
3181cdf0e10cSrcweir             BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
3182cdf0e10cSrcweir             ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
3183cdf0e10cSrcweir                            nColCount, nWidth * nHeight, nIndex );
3184cdf0e10cSrcweir 
3185cdf0e10cSrcweir             // do mapping of colors to palette
3186cdf0e10cSrcweir             InverseColorMap aMap( aPal );
3187cdf0e10cSrcweir             pWAcc->SetPalette( aPal );
3188cdf0e10cSrcweir             for( long nY = 0L; nY < nHeight; nY++ )
3189cdf0e10cSrcweir                 for( long nX = 0L; nX < nWidth; nX++ )
319087bc88d3SHerbert Dürr                     pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) );
3191cdf0e10cSrcweir 
3192cdf0e10cSrcweir             rtl_freeMemory( pColBuf );
3193cdf0e10cSrcweir             aNewBmp.ReleaseAccess( pWAcc );
3194cdf0e10cSrcweir             bRet = sal_True;
3195cdf0e10cSrcweir         }
3196cdf0e10cSrcweir 
3197cdf0e10cSrcweir         ReleaseAccess( pRAcc );
3198cdf0e10cSrcweir 
3199cdf0e10cSrcweir         if( bRet )
3200cdf0e10cSrcweir         {
3201cdf0e10cSrcweir             const MapMode   aMap( maPrefMapMode );
3202cdf0e10cSrcweir             const Size      aSize( maPrefSize );
3203cdf0e10cSrcweir 
3204cdf0e10cSrcweir             *this = aNewBmp;
3205cdf0e10cSrcweir             maPrefMapMode = aMap;
3206cdf0e10cSrcweir             maPrefSize = aSize;
3207cdf0e10cSrcweir         }
3208cdf0e10cSrcweir     }
3209cdf0e10cSrcweir 
3210cdf0e10cSrcweir     return bRet;
3211cdf0e10cSrcweir }
3212cdf0e10cSrcweir 
3213cdf0e10cSrcweir // ------------------------------------------------------------------------
3214cdf0e10cSrcweir 
3215cdf0e10cSrcweir void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
3216cdf0e10cSrcweir                             long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
3217cdf0e10cSrcweir                             long nColors, long nPixels, long& rIndex )
3218cdf0e10cSrcweir {
3219cdf0e10cSrcweir     if( !nPixels )
3220cdf0e10cSrcweir         return;
3221cdf0e10cSrcweir 
3222cdf0e10cSrcweir     BitmapColor aCol;
3223cdf0e10cSrcweir     const long  nRLen = nR2 - nR1;
3224cdf0e10cSrcweir     const long  nGLen = nG2 - nG1;
3225cdf0e10cSrcweir     const long  nBLen = nB2 - nB1;
3226cdf0e10cSrcweir     long        nR, nG, nB;
3227cdf0e10cSrcweir     sal_uLong*      pBuf = pColBuf;
3228cdf0e10cSrcweir 
3229cdf0e10cSrcweir     if( !nRLen && !nGLen && !nBLen )
3230cdf0e10cSrcweir     {
3231cdf0e10cSrcweir         if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
3232cdf0e10cSrcweir         {
3233cdf0e10cSrcweir             aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
3234cdf0e10cSrcweir             aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
3235cdf0e10cSrcweir             aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
3236cdf0e10cSrcweir             rPal[ (sal_uInt16) rIndex++ ] = aCol;
3237cdf0e10cSrcweir         }
3238cdf0e10cSrcweir     }
3239cdf0e10cSrcweir     else
3240cdf0e10cSrcweir     {
3241cdf0e10cSrcweir         if( 1 == nColors || 1 == nPixels )
3242cdf0e10cSrcweir         {
3243cdf0e10cSrcweir             long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
3244cdf0e10cSrcweir 
3245cdf0e10cSrcweir             for( nR = nR1; nR <= nR2; nR++ )
3246cdf0e10cSrcweir             {
3247cdf0e10cSrcweir                 for( nG = nG1; nG <= nG2; nG++ )
3248cdf0e10cSrcweir                 {
3249cdf0e10cSrcweir                     for( nB = nB1; nB <= nB2; nB++ )
3250cdf0e10cSrcweir                     {
3251cdf0e10cSrcweir                         nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
3252cdf0e10cSrcweir 
3253cdf0e10cSrcweir                         if( nPixSum )
3254cdf0e10cSrcweir                         {
3255cdf0e10cSrcweir                             nRSum += nR * nPixSum;
3256cdf0e10cSrcweir                             nGSum += nG * nPixSum;
3257cdf0e10cSrcweir                             nBSum += nB * nPixSum;
3258cdf0e10cSrcweir                         }
3259cdf0e10cSrcweir                     }
3260cdf0e10cSrcweir                 }
3261cdf0e10cSrcweir             }
3262cdf0e10cSrcweir 
3263cdf0e10cSrcweir             aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
3264cdf0e10cSrcweir             aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
3265cdf0e10cSrcweir             aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
3266cdf0e10cSrcweir             rPal[ (sal_uInt16) rIndex++ ] = aCol;
3267cdf0e10cSrcweir         }
3268cdf0e10cSrcweir         else
3269cdf0e10cSrcweir         {
3270cdf0e10cSrcweir             const long  nTest = ( nPixels >> 1 );
3271cdf0e10cSrcweir             long        nPixOld = 0;
3272cdf0e10cSrcweir             long        nPixNew = 0;
3273cdf0e10cSrcweir 
3274cdf0e10cSrcweir             if( nBLen > nGLen && nBLen > nRLen )
3275cdf0e10cSrcweir             {
3276cdf0e10cSrcweir                 nB = nB1 - 1;
3277cdf0e10cSrcweir 
3278cdf0e10cSrcweir                 while( nPixNew < nTest )
3279cdf0e10cSrcweir                 {
3280cdf0e10cSrcweir                     nB++, nPixOld = nPixNew;
3281cdf0e10cSrcweir                     for( nR = nR1; nR <= nR2; nR++ )
3282cdf0e10cSrcweir                         for( nG = nG1; nG <= nG2; nG++ )
3283cdf0e10cSrcweir                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3284cdf0e10cSrcweir                 }
3285cdf0e10cSrcweir 
3286cdf0e10cSrcweir                 if( nB < nB2 )
3287cdf0e10cSrcweir                 {
3288cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
3289cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3290cdf0e10cSrcweir                 }
3291cdf0e10cSrcweir                 else
3292cdf0e10cSrcweir                 {
3293cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
3294cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3295cdf0e10cSrcweir                 }
3296cdf0e10cSrcweir             }
3297cdf0e10cSrcweir             else if( nGLen > nRLen )
3298cdf0e10cSrcweir             {
3299cdf0e10cSrcweir                 nG = nG1 - 1;
3300cdf0e10cSrcweir 
3301cdf0e10cSrcweir                 while( nPixNew < nTest )
3302cdf0e10cSrcweir                 {
3303cdf0e10cSrcweir                     nG++, nPixOld = nPixNew;
3304cdf0e10cSrcweir                     for( nR = nR1; nR <= nR2; nR++ )
3305cdf0e10cSrcweir                         for( nB = nB1; nB <= nB2; nB++ )
3306cdf0e10cSrcweir                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3307cdf0e10cSrcweir                 }
3308cdf0e10cSrcweir 
3309cdf0e10cSrcweir                 if( nG < nG2 )
3310cdf0e10cSrcweir                 {
3311cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3312cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3313cdf0e10cSrcweir                 }
3314cdf0e10cSrcweir                 else
3315cdf0e10cSrcweir                 {
3316cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3317cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3318cdf0e10cSrcweir                 }
3319cdf0e10cSrcweir             }
3320cdf0e10cSrcweir             else
3321cdf0e10cSrcweir             {
3322cdf0e10cSrcweir                 nR = nR1 - 1;
3323cdf0e10cSrcweir 
3324cdf0e10cSrcweir                 while( nPixNew < nTest )
3325cdf0e10cSrcweir                 {
3326cdf0e10cSrcweir                     nR++, nPixOld = nPixNew;
3327cdf0e10cSrcweir                     for( nG = nG1; nG <= nG2; nG++ )
3328cdf0e10cSrcweir                         for( nB = nB1; nB <= nB2; nB++ )
3329cdf0e10cSrcweir                             nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3330cdf0e10cSrcweir                 }
3331cdf0e10cSrcweir 
3332cdf0e10cSrcweir                 if( nR < nR2 )
3333cdf0e10cSrcweir                 {
3334cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3335cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3336cdf0e10cSrcweir                 }
3337cdf0e10cSrcweir                 else
3338cdf0e10cSrcweir                 {
3339cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3340cdf0e10cSrcweir                     ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3341cdf0e10cSrcweir                 }
3342cdf0e10cSrcweir             }
3343cdf0e10cSrcweir         }
3344cdf0e10cSrcweir     }
3345cdf0e10cSrcweir }
3346cdf0e10cSrcweir 
3347cdf0e10cSrcweir // ------------------------------------------------------------------------
3348cdf0e10cSrcweir 
3349cdf0e10cSrcweir sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
3350cdf0e10cSrcweir {
3351cdf0e10cSrcweir     return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
3352cdf0e10cSrcweir }
3353cdf0e10cSrcweir 
3354cdf0e10cSrcweir // ------------------------------------------------------------------------
3355cdf0e10cSrcweir 
3356cdf0e10cSrcweir sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
3357cdf0e10cSrcweir {
3358cdf0e10cSrcweir     return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
3359cdf0e10cSrcweir }
3360cdf0e10cSrcweir 
3361cdf0e10cSrcweir // ------------------------------------------------------------------------
3362cdf0e10cSrcweir 
3363cdf0e10cSrcweir sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
3364cdf0e10cSrcweir                      short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
3365cdf0e10cSrcweir                      double fGamma, sal_Bool bInvert )
3366cdf0e10cSrcweir {
3367cdf0e10cSrcweir     sal_Bool bRet = sal_False;
3368cdf0e10cSrcweir 
3369cdf0e10cSrcweir     // nothing to do => return quickly
3370cdf0e10cSrcweir     if( !nLuminancePercent && !nContrastPercent &&
3371cdf0e10cSrcweir         !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
3372cdf0e10cSrcweir         ( fGamma == 1.0 ) && !bInvert )
3373cdf0e10cSrcweir     {
3374cdf0e10cSrcweir         bRet = sal_True;
3375cdf0e10cSrcweir     }
3376cdf0e10cSrcweir     else
3377cdf0e10cSrcweir     {
3378cdf0e10cSrcweir         BitmapWriteAccess* pAcc = AcquireWriteAccess();
3379cdf0e10cSrcweir 
3380cdf0e10cSrcweir         if( pAcc )
3381cdf0e10cSrcweir         {
3382cdf0e10cSrcweir             BitmapColor     aCol;
3383cdf0e10cSrcweir             const long      nW = pAcc->Width();
3384cdf0e10cSrcweir             const long      nH = pAcc->Height();
3385cdf0e10cSrcweir             sal_uInt8*          cMapR = new sal_uInt8[ 256 ];
3386cdf0e10cSrcweir             sal_uInt8*          cMapG = new sal_uInt8[ 256 ];
3387cdf0e10cSrcweir             sal_uInt8*          cMapB = new sal_uInt8[ 256 ];
3388cdf0e10cSrcweir             long            nX, nY;
3389cdf0e10cSrcweir             double          fM, fROff, fGOff, fBOff, fOff;
3390cdf0e10cSrcweir 
3391cdf0e10cSrcweir             // calculate slope
3392cdf0e10cSrcweir             if( nContrastPercent >= 0 )
3393cdf0e10cSrcweir                 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
3394cdf0e10cSrcweir             else
3395cdf0e10cSrcweir                 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
3396cdf0e10cSrcweir 
3397cdf0e10cSrcweir             // total offset = luminance offset + contrast offset
3398cdf0e10cSrcweir             fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
3399cdf0e10cSrcweir 
3400cdf0e10cSrcweir             // channel offset = channel offset  + total offset
3401cdf0e10cSrcweir             fROff = nChannelRPercent * 2.55 + fOff;
3402cdf0e10cSrcweir             fGOff = nChannelGPercent * 2.55 + fOff;
3403cdf0e10cSrcweir             fBOff = nChannelBPercent * 2.55 + fOff;
3404cdf0e10cSrcweir 
3405cdf0e10cSrcweir             // calculate gamma value
3406cdf0e10cSrcweir             fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
3407cdf0e10cSrcweir             const sal_Bool bGamma = ( fGamma != 1.0 );
3408cdf0e10cSrcweir 
3409cdf0e10cSrcweir             // create mapping table
3410cdf0e10cSrcweir             for( nX = 0L; nX < 256L; nX++ )
3411cdf0e10cSrcweir             {
3412cdf0e10cSrcweir                 cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
3413cdf0e10cSrcweir                 cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
3414cdf0e10cSrcweir                 cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
3415cdf0e10cSrcweir 
3416cdf0e10cSrcweir                 if( bGamma )
3417cdf0e10cSrcweir                 {
3418cdf0e10cSrcweir                     cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
3419cdf0e10cSrcweir                     cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
3420cdf0e10cSrcweir                     cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
3421cdf0e10cSrcweir                 }
3422cdf0e10cSrcweir 
3423cdf0e10cSrcweir                 if( bInvert )
3424cdf0e10cSrcweir                 {
3425cdf0e10cSrcweir                     cMapR[ nX ] = ~cMapR[ nX ];
3426cdf0e10cSrcweir                     cMapG[ nX ] = ~cMapG[ nX ];
3427cdf0e10cSrcweir                     cMapB[ nX ] = ~cMapB[ nX ];
3428cdf0e10cSrcweir                 }
3429cdf0e10cSrcweir             }
3430cdf0e10cSrcweir 
3431cdf0e10cSrcweir             // do modifying
3432cdf0e10cSrcweir             if( pAcc->HasPalette() )
3433cdf0e10cSrcweir             {
3434cdf0e10cSrcweir                 BitmapColor aNewCol;
3435cdf0e10cSrcweir 
3436cdf0e10cSrcweir                 for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
3437cdf0e10cSrcweir                 {
3438cdf0e10cSrcweir                     const BitmapColor& rCol = pAcc->GetPaletteColor( i );
3439cdf0e10cSrcweir                     aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
3440cdf0e10cSrcweir                     aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
3441cdf0e10cSrcweir                     aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
3442cdf0e10cSrcweir                     pAcc->SetPaletteColor( i, aNewCol );
3443cdf0e10cSrcweir                 }
3444cdf0e10cSrcweir             }
3445cdf0e10cSrcweir             else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
3446cdf0e10cSrcweir             {
3447cdf0e10cSrcweir                 for( nY = 0L; nY < nH; nY++ )
3448cdf0e10cSrcweir                 {
3449cdf0e10cSrcweir                     Scanline pScan = pAcc->GetScanline( nY );
3450cdf0e10cSrcweir 
3451cdf0e10cSrcweir                     for( nX = 0L; nX < nW; nX++ )
3452cdf0e10cSrcweir                     {
3453cdf0e10cSrcweir                         *pScan = cMapB[ *pScan ]; pScan++;
3454cdf0e10cSrcweir                         *pScan = cMapG[ *pScan ]; pScan++;
3455cdf0e10cSrcweir                         *pScan = cMapR[ *pScan ]; pScan++;
3456cdf0e10cSrcweir                     }
3457cdf0e10cSrcweir                 }
3458cdf0e10cSrcweir             }
3459cdf0e10cSrcweir             else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
3460cdf0e10cSrcweir             {
3461cdf0e10cSrcweir                 for( nY = 0L; nY < nH; nY++ )
3462cdf0e10cSrcweir                 {
3463cdf0e10cSrcweir                     Scanline pScan = pAcc->GetScanline( nY );
3464cdf0e10cSrcweir 
3465cdf0e10cSrcweir                     for( nX = 0L; nX < nW; nX++ )
3466cdf0e10cSrcweir                     {
3467cdf0e10cSrcweir                         *pScan = cMapR[ *pScan ]; pScan++;
3468cdf0e10cSrcweir                         *pScan = cMapG[ *pScan ]; pScan++;
3469cdf0e10cSrcweir                         *pScan = cMapB[ *pScan ]; pScan++;
3470cdf0e10cSrcweir                     }
3471cdf0e10cSrcweir                 }
3472cdf0e10cSrcweir             }
3473cdf0e10cSrcweir             else
3474cdf0e10cSrcweir             {
3475cdf0e10cSrcweir                 for( nY = 0L; nY < nH; nY++ )
3476cdf0e10cSrcweir                 {
3477cdf0e10cSrcweir                     for( nX = 0L; nX < nW; nX++ )
3478cdf0e10cSrcweir                     {
3479cdf0e10cSrcweir                         aCol = pAcc->GetPixel( nY, nX );
3480cdf0e10cSrcweir                         aCol.SetRed( cMapR[ aCol.GetRed() ] );
3481cdf0e10cSrcweir                         aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
3482cdf0e10cSrcweir                         aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
3483cdf0e10cSrcweir                         pAcc->SetPixel( nY, nX, aCol );
3484cdf0e10cSrcweir                     }
3485cdf0e10cSrcweir                 }
3486cdf0e10cSrcweir             }
3487cdf0e10cSrcweir 
3488cdf0e10cSrcweir             delete[] cMapR;
3489cdf0e10cSrcweir             delete[] cMapG;
3490cdf0e10cSrcweir             delete[] cMapB;
3491cdf0e10cSrcweir             ReleaseAccess( pAcc );
3492cdf0e10cSrcweir             bRet = sal_True;
3493cdf0e10cSrcweir         }
3494cdf0e10cSrcweir     }
3495cdf0e10cSrcweir 
3496cdf0e10cSrcweir     return bRet;
3497cdf0e10cSrcweir }
3498