xref: /aoo41x/main/vcl/source/gdi/bitmap3.cxx (revision 561c4886)
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
109f62ea84SAndrew Rist  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist  *
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.
199f62ea84SAndrew Rist  *
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 
907cdf0e10cSrcweir sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
908cdf0e10cSrcweir {
90937ab0f2dSArmin Le Grand #ifdef DBG_UTIL
91037ab0f2dSArmin Le Grand     // #121233# allow to test the different scalers in debug build with source
91137ab0f2dSArmin Le Grand     // level debugger (change nNumber to desired action)
91237ab0f2dSArmin Le Grand     static sal_uInt16 nNumber(0);
91337ab0f2dSArmin Le Grand 
91437ab0f2dSArmin Le Grand     switch(nNumber)
91537ab0f2dSArmin Le Grand     {
91637ab0f2dSArmin Le Grand         case 0 : break;
91737ab0f2dSArmin Le Grand         case 1: nScaleFlag = BMP_SCALE_FAST; break;
91837ab0f2dSArmin Le Grand         case 2: nScaleFlag = BMP_SCALE_INTERPOLATE; break;
91937ab0f2dSArmin Le Grand         case 3: nScaleFlag = BMP_SCALE_SUPER; break;
92037ab0f2dSArmin Le Grand         case 4: nScaleFlag = BMP_SCALE_LANCZOS; break;
92137ab0f2dSArmin Le Grand         case 5: nScaleFlag = BMP_SCALE_BICUBIC; break;
92237ab0f2dSArmin Le Grand         case 6: nScaleFlag = BMP_SCALE_BILINEAR; break;
92337ab0f2dSArmin Le Grand         case 7: nScaleFlag = BMP_SCALE_BOX; break;
92437ab0f2dSArmin Le Grand         case 8: nScaleFlag = BMP_SCALE_BESTQUALITY; break;
92537ab0f2dSArmin Le Grand         case 9: nScaleFlag = BMP_SCALE_FASTESTINTERPOLATE; break;
92637ab0f2dSArmin Le Grand     }
92737ab0f2dSArmin Le Grand #endif // DBG_UTIL
92837ab0f2dSArmin Le Grand 
92937ab0f2dSArmin Le Grand     if(basegfx::fTools::equalZero(rScaleX) && basegfx::fTools::equalZero(rScaleY))
93037ab0f2dSArmin Le Grand     {
93137ab0f2dSArmin Le Grand         // no scale
93237ab0f2dSArmin Le Grand         return true;
93337ab0f2dSArmin Le Grand     }
93437ab0f2dSArmin Le Grand     else
93537ab0f2dSArmin Le Grand     {
93637ab0f2dSArmin Le Grand         if(BMP_SCALE_BESTQUALITY == nScaleFlag)
93737ab0f2dSArmin Le Grand         {
93837ab0f2dSArmin Le Grand             // Use LANCZOS when best quality is requested
93937ab0f2dSArmin Le Grand             nScaleFlag = BMP_SCALE_LANCZOS;
94037ab0f2dSArmin Le Grand         }
94137ab0f2dSArmin Le Grand         else if(BMP_SCALE_FASTESTINTERPOLATE == nScaleFlag)
94237ab0f2dSArmin Le Grand         {
94337ab0f2dSArmin Le Grand             // Use BMP_SCALE_SUPER when speed is requested, but not worst quality
94437ab0f2dSArmin Le Grand             nScaleFlag = BMP_SCALE_SUPER;
94537ab0f2dSArmin Le Grand         }
94637ab0f2dSArmin Le Grand 
94737ab0f2dSArmin Le Grand         switch(nScaleFlag)
94837ab0f2dSArmin Le Grand         {
94937ab0f2dSArmin Le Grand             default:
95037ab0f2dSArmin Le Grand             case BMP_SCALE_NONE :
95137ab0f2dSArmin Le Grand             {
95237ab0f2dSArmin Le Grand                 return false;
95337ab0f2dSArmin Le Grand                 break;
95437ab0f2dSArmin Le Grand             }
95537ab0f2dSArmin Le Grand             case BMP_SCALE_FAST :
95637ab0f2dSArmin Le Grand             {
95737ab0f2dSArmin Le Grand                 return ImplScaleFast( rScaleX, rScaleY );
95837ab0f2dSArmin Le Grand                 break;
95937ab0f2dSArmin Le Grand             }
96037ab0f2dSArmin Le Grand             case BMP_SCALE_INTERPOLATE :
96137ab0f2dSArmin Le Grand             {
96237ab0f2dSArmin Le Grand                 return ImplScaleInterpolate( rScaleX, rScaleY );
96337ab0f2dSArmin Le Grand                 break;
96437ab0f2dSArmin Le Grand             }
96537ab0f2dSArmin Le Grand             case BMP_SCALE_SUPER :
96637ab0f2dSArmin Le Grand             {
96737ab0f2dSArmin Le Grand                 if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
96837ab0f2dSArmin Le Grand                 {
96937ab0f2dSArmin Le Grand                     // fallback to ImplScaleFast
97037ab0f2dSArmin Le Grand                     return ImplScaleFast( rScaleX, rScaleY );
97137ab0f2dSArmin Le Grand                 }
97237ab0f2dSArmin Le Grand                 else
97337ab0f2dSArmin Le Grand                 {
97437ab0f2dSArmin Le Grand                     // #121233# use method from symphony
97537ab0f2dSArmin Le Grand                     return ImplScaleSuper( rScaleX, rScaleY );
97637ab0f2dSArmin Le Grand                 }
97737ab0f2dSArmin Le Grand                 break;
97837ab0f2dSArmin Le Grand             }
97937ab0f2dSArmin Le Grand             case BMP_SCALE_LANCZOS :
98037ab0f2dSArmin Le Grand             {
98137ab0f2dSArmin Le Grand                 const Lanczos3Kernel kernel;
98237ab0f2dSArmin Le Grand 
98337ab0f2dSArmin Le Grand                 return ImplScaleConvolution( rScaleX, rScaleY, kernel);
98437ab0f2dSArmin Le Grand                 break;
98537ab0f2dSArmin Le Grand             }
98637ab0f2dSArmin Le Grand             case BMP_SCALE_BICUBIC :
98737ab0f2dSArmin Le Grand             {
98837ab0f2dSArmin Le Grand                 const BicubicKernel kernel;
98937ab0f2dSArmin Le Grand 
99037ab0f2dSArmin Le Grand                 return ImplScaleConvolution( rScaleX, rScaleY, kernel );
99137ab0f2dSArmin Le Grand                 break;
99237ab0f2dSArmin Le Grand             }
99337ab0f2dSArmin Le Grand             case BMP_SCALE_BILINEAR :
99437ab0f2dSArmin Le Grand             {
99537ab0f2dSArmin Le Grand                 const BilinearKernel kernel;
99637ab0f2dSArmin Le Grand 
99737ab0f2dSArmin Le Grand                 return ImplScaleConvolution( rScaleX, rScaleY, kernel );
99837ab0f2dSArmin Le Grand                 break;
99937ab0f2dSArmin Le Grand             }
100037ab0f2dSArmin Le Grand             case BMP_SCALE_BOX :
100137ab0f2dSArmin Le Grand             {
100237ab0f2dSArmin Le Grand                 const BoxKernel kernel;
100337ab0f2dSArmin Le Grand 
100437ab0f2dSArmin Le Grand                 return ImplScaleConvolution( rScaleX, rScaleY, kernel );
100537ab0f2dSArmin Le Grand                 break;
100637ab0f2dSArmin Le Grand             }
100737ab0f2dSArmin Le Grand         }
100837ab0f2dSArmin Le Grand     }
100937ab0f2dSArmin Le Grand 
101037ab0f2dSArmin Le Grand     // should not happen
101137ab0f2dSArmin Le Grand     return false;
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir // ------------------------------------------------------------------------
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
1017cdf0e10cSrcweir {
1018cdf0e10cSrcweir 	const Size	aSize( GetSizePixel() );
1019cdf0e10cSrcweir 	sal_Bool		bRet;
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir 	if( aSize.Width() && aSize.Height() )
1022cdf0e10cSrcweir 	{
1023cdf0e10cSrcweir 		bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
1024cdf0e10cSrcweir 					  (double) rNewSize.Height() / aSize.Height(),
1025cdf0e10cSrcweir 					  nScaleFlag );
1026cdf0e10cSrcweir 	}
1027cdf0e10cSrcweir 	else
1028cdf0e10cSrcweir 		bRet = sal_True;
1029cdf0e10cSrcweir 
1030cdf0e10cSrcweir 	return bRet;
1031cdf0e10cSrcweir }
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir // ------------------------------------------------------------------------
1034cdf0e10cSrcweir 
1035c2821885SArmin Le Grand void Bitmap::AdaptBitCount(Bitmap& rNew) const
1036c2821885SArmin Le Grand {
1037c2821885SArmin Le Grand     ImplAdaptBitCount(rNew);
1038c2821885SArmin Le Grand }
1039c2821885SArmin Le Grand 
1040c2821885SArmin Le Grand // ------------------------------------------------------------------------
1041c2821885SArmin Le Grand 
1042c2821885SArmin Le Grand void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const
104337ab0f2dSArmin Le Grand {
104437ab0f2dSArmin Le Grand     // aNew is the result of some operation; adapt it's BitCount to the original (this)
104537ab0f2dSArmin Le Grand     if(GetBitCount() != rNew.GetBitCount())
104637ab0f2dSArmin Le Grand     {
104737ab0f2dSArmin Le Grand         switch(GetBitCount())
104837ab0f2dSArmin Le Grand         {
104937ab0f2dSArmin Le Grand             case 1:
105037ab0f2dSArmin Le Grand             {
105137ab0f2dSArmin Le Grand                 rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
105237ab0f2dSArmin Le Grand                 break;
105337ab0f2dSArmin Le Grand             }
105437ab0f2dSArmin Le Grand             case 4:
105537ab0f2dSArmin Le Grand             {
105637ab0f2dSArmin Le Grand                 if(HasGreyPalette())
105737ab0f2dSArmin Le Grand                 {
105837ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
105937ab0f2dSArmin Le Grand                 }
106037ab0f2dSArmin Le Grand                 else
106137ab0f2dSArmin Le Grand                 {
106237ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
106337ab0f2dSArmin Le Grand                 }
106437ab0f2dSArmin Le Grand                 break;
106537ab0f2dSArmin Le Grand             }
106637ab0f2dSArmin Le Grand             case 8:
106737ab0f2dSArmin Le Grand             {
106837ab0f2dSArmin Le Grand                 if(HasGreyPalette())
106937ab0f2dSArmin Le Grand                 {
107037ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
107137ab0f2dSArmin Le Grand                 }
107237ab0f2dSArmin Le Grand                 else
107337ab0f2dSArmin Le Grand                 {
107437ab0f2dSArmin Le Grand                     rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
107537ab0f2dSArmin Le Grand                 }
107637ab0f2dSArmin Le Grand                 break;
107737ab0f2dSArmin Le Grand             }
107837ab0f2dSArmin Le Grand             case 24:
107937ab0f2dSArmin Le Grand             {
108037ab0f2dSArmin Le Grand                 rNew.Convert(BMP_CONVERSION_24BIT);
108137ab0f2dSArmin Le Grand                 break;
108237ab0f2dSArmin Le Grand             }
108337ab0f2dSArmin Le Grand             default:
108437ab0f2dSArmin Le Grand             {
108537ab0f2dSArmin Le Grand                 OSL_ENSURE(false, "BitDepth adaption failed (!)");
108637ab0f2dSArmin Le Grand                 break;
108737ab0f2dSArmin Le Grand             }
108837ab0f2dSArmin Le Grand         }
108937ab0f2dSArmin Le Grand     }
109037ab0f2dSArmin Le Grand }
109137ab0f2dSArmin Le Grand 
109237ab0f2dSArmin Le Grand // ------------------------------------------------------------------------
109337ab0f2dSArmin Le Grand 
1094cdf0e10cSrcweir sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
1095cdf0e10cSrcweir {
1096cdf0e10cSrcweir 	const Size	aSizePix( GetSizePixel() );
1097cdf0e10cSrcweir 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
1098cdf0e10cSrcweir 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
1099cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir 	if( nNewWidth && nNewHeight )
1102cdf0e10cSrcweir 	{
1103cdf0e10cSrcweir 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
11040f740837SAriel Constenla-Haile         if ( !pReadAcc )
11050f740837SAriel Constenla-Haile             return sal_False;
11060f740837SAriel Constenla-Haile 
1107cdf0e10cSrcweir 		Bitmap				aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
1108cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1109cdf0e10cSrcweir 
11100f740837SAriel Constenla-Haile 		if( pWriteAcc )
1111cdf0e10cSrcweir 		{
1112cdf0e10cSrcweir 			const long	nScanlineSize = pWriteAcc->GetScanlineSize();
1113cdf0e10cSrcweir 			const long	nNewWidth1 = nNewWidth - 1L;
1114cdf0e10cSrcweir 			const long	nNewHeight1 = nNewHeight - 1L;
1115cdf0e10cSrcweir 			const long	nWidth = pReadAcc->Width();
1116cdf0e10cSrcweir 			const long	nHeight = pReadAcc->Height();
1117cdf0e10cSrcweir 			long*		pLutX = new long[ nNewWidth ];
1118cdf0e10cSrcweir 			long*		pLutY = new long[ nNewHeight ];
1119cdf0e10cSrcweir 			long		nX, nY, nMapY, nActY = 0L;
1120cdf0e10cSrcweir 
1121cdf0e10cSrcweir 			if( nNewWidth1 && nNewHeight1 )
1122cdf0e10cSrcweir 			{
1123cdf0e10cSrcweir 				for( nX = 0L; nX < nNewWidth; nX++ )
1124cdf0e10cSrcweir 					pLutX[ nX ] = nX * nWidth / nNewWidth;
1125cdf0e10cSrcweir 
1126cdf0e10cSrcweir 				for( nY = 0L; nY < nNewHeight; nY++ )
1127cdf0e10cSrcweir 					pLutY[ nY ] = nY * nHeight / nNewHeight;
1128cdf0e10cSrcweir 
1129cdf0e10cSrcweir 				while( nActY < nNewHeight )
1130cdf0e10cSrcweir 				{
1131cdf0e10cSrcweir 					nMapY = pLutY[ nActY ];
1132cdf0e10cSrcweir 
1133cdf0e10cSrcweir 					for( nX = 0L; nX < nNewWidth; nX++ )
1134cdf0e10cSrcweir 						pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir 					while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
1137cdf0e10cSrcweir 					{
1138cdf0e10cSrcweir 						memcpy( pWriteAcc->GetScanline( nActY + 1L ),
1139cdf0e10cSrcweir 								 pWriteAcc->GetScanline( nActY ), nScanlineSize );
1140cdf0e10cSrcweir 						nActY++;
1141cdf0e10cSrcweir 					}
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir 					nActY++;
1144cdf0e10cSrcweir 				}
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir 				bRet = sal_True;
1147cdf0e10cSrcweir 			}
1148cdf0e10cSrcweir 
1149cdf0e10cSrcweir 			delete[] pLutX;
1150cdf0e10cSrcweir 			delete[] pLutY;
1151cdf0e10cSrcweir 		}
1152cdf0e10cSrcweir 
1153cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
1154cdf0e10cSrcweir 		aNewBmp.ReleaseAccess( pWriteAcc );
1155cdf0e10cSrcweir 
1156cdf0e10cSrcweir 		if( bRet )
1157cdf0e10cSrcweir 			ImplAssignWithSize( aNewBmp );
1158cdf0e10cSrcweir 	}
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir 	return bRet;
1161cdf0e10cSrcweir }
1162cdf0e10cSrcweir 
1163cdf0e10cSrcweir // ------------------------------------------------------------------------
1164cdf0e10cSrcweir 
1165cdf0e10cSrcweir sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1166cdf0e10cSrcweir {
1167cdf0e10cSrcweir 	const Size	aSizePix( GetSizePixel() );
1168cdf0e10cSrcweir 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
1169cdf0e10cSrcweir 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
1170cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
1171cdf0e10cSrcweir 
1172cdf0e10cSrcweir 	if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1173cdf0e10cSrcweir 	{
1174cdf0e10cSrcweir 		BitmapColor 		aCol0;
1175cdf0e10cSrcweir 		BitmapColor 		aCol1;
1176cdf0e10cSrcweir 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1177cdf0e10cSrcweir 		long				nWidth = pReadAcc->Width();
1178cdf0e10cSrcweir 		long				nHeight = pReadAcc->Height();
1179cdf0e10cSrcweir 		Bitmap				aNewBmp( Size( nNewWidth, nHeight ), 24 );
1180cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1181cdf0e10cSrcweir 		long*				pLutInt;
1182cdf0e10cSrcweir 		long*				pLutFrac;
1183cdf0e10cSrcweir 		long				nX, nY;
1184cdf0e10cSrcweir 		long				lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1185cdf0e10cSrcweir 		double				fTemp;
1186cdf0e10cSrcweir 		long				nTemp;
1187cdf0e10cSrcweir 
1188cdf0e10cSrcweir 		if( pReadAcc && pWriteAcc )
1189cdf0e10cSrcweir 		{
1190cdf0e10cSrcweir 			const long		nNewWidth1 = nNewWidth - 1L;
1191cdf0e10cSrcweir 			const long		nWidth1 = pReadAcc->Width() - 1L;
1192cdf0e10cSrcweir 			const double	fRevScaleX = (double) nWidth1 / nNewWidth1;
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir 			pLutInt = new long[ nNewWidth ];
1195cdf0e10cSrcweir 			pLutFrac = new long[ nNewWidth ];
1196cdf0e10cSrcweir 
1197cdf0e10cSrcweir 			for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1198cdf0e10cSrcweir 			{
1199cdf0e10cSrcweir 				fTemp = nX * fRevScaleX;
1200cdf0e10cSrcweir 				pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1201cdf0e10cSrcweir 				fTemp -= pLutInt[ nX ];
1202cdf0e10cSrcweir 				pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1203cdf0e10cSrcweir 			}
1204cdf0e10cSrcweir 
1205c2821885SArmin Le Grand 			for( nY = 0L; nY < nHeight; nY++ )
1206cdf0e10cSrcweir 			{
1207c2821885SArmin Le Grand 				if( 1 == nWidth )
1208cdf0e10cSrcweir 				{
1209c2821885SArmin Le Grand 			        if( pReadAcc->HasPalette() )
1210c2821885SArmin Le Grand 			        {
1211c2821885SArmin Le Grand     					aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) );
1212c2821885SArmin Le Grand                     }
1213c2821885SArmin Le Grand                     else
1214c2821885SArmin Le Grand                     {
1215c2821885SArmin Le Grand     					aCol0 = pReadAcc->GetPixel( nY, 0 );
1216c2821885SArmin Le Grand                     }
1217cdf0e10cSrcweir 
1218c2821885SArmin Le Grand 					for( nX = 0L; nX < nNewWidth; nX++ )
1219c2821885SArmin Le Grand                     {
1220c2821885SArmin Le Grand 						pWriteAcc->SetPixel( nY, nX, aCol0 );
1221c2821885SArmin Le Grand                     }
1222cdf0e10cSrcweir 				}
1223c2821885SArmin Le Grand 				else
1224cdf0e10cSrcweir 				{
1225c2821885SArmin Le Grand 					for( nX = 0L; nX < nNewWidth; nX++ )
1226cdf0e10cSrcweir 					{
1227c2821885SArmin Le Grand 						nTemp = pLutInt[ nX ];
1228cdf0e10cSrcweir 
1229c2821885SArmin Le Grand 			            if( pReadAcc->HasPalette() )
1230c2821885SArmin Le Grand 			            {
1231c2821885SArmin Le Grand 							aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) );
1232c2821885SArmin Le Grand 							aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) );
1233c2821885SArmin Le Grand                         }
1234c2821885SArmin Le Grand                         else
1235c2821885SArmin Le Grand                         {
1236cdf0e10cSrcweir 							aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1237cdf0e10cSrcweir 							aCol1 = pReadAcc->GetPixel( nY, nTemp );
1238c2821885SArmin Le Grand                         }
1239cdf0e10cSrcweir 
1240c2821885SArmin Le Grand 						nTemp = pLutFrac[ nX ];
1241cdf0e10cSrcweir 
1242c2821885SArmin Le Grand 						lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1243c2821885SArmin Le Grand 						lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1244c2821885SArmin Le Grand 						lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1245cdf0e10cSrcweir 
1246c2821885SArmin Le Grand 						aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1247c2821885SArmin Le Grand 						aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1248c2821885SArmin Le Grand 						aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1249cdf0e10cSrcweir 
1250c2821885SArmin Le Grand 						pWriteAcc->SetPixel( nY, nX, aCol0 );
1251cdf0e10cSrcweir 					}
1252cdf0e10cSrcweir 				}
1253cdf0e10cSrcweir 			}
1254cdf0e10cSrcweir 
1255cdf0e10cSrcweir 			delete[] pLutInt;
1256cdf0e10cSrcweir 			delete[] pLutFrac;
1257cdf0e10cSrcweir 			bRet = sal_True;
1258cdf0e10cSrcweir 		}
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
1261cdf0e10cSrcweir 		aNewBmp.ReleaseAccess( pWriteAcc );
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir 		if( bRet )
1264cdf0e10cSrcweir 		{
1265cdf0e10cSrcweir 			bRet = sal_False;
1266*561c4886SArmin Le Grand             const Bitmap aOriginal(*this);
1267c2821885SArmin Le Grand             *this = aNewBmp;
1268cdf0e10cSrcweir 			aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1269c2821885SArmin Le Grand 			pReadAcc = AcquireReadAccess();
1270cdf0e10cSrcweir 			pWriteAcc = aNewBmp.AcquireWriteAccess();
1271cdf0e10cSrcweir 
1272cdf0e10cSrcweir 			if( pReadAcc && pWriteAcc )
1273cdf0e10cSrcweir 			{
1274cdf0e10cSrcweir 				const long		nNewHeight1 = nNewHeight - 1L;
1275cdf0e10cSrcweir 				const long		nHeight1 = pReadAcc->Height() - 1L;
1276cdf0e10cSrcweir 				const double	fRevScaleY = (double) nHeight1 / nNewHeight1;
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir 				pLutInt = new long[ nNewHeight ];
1279cdf0e10cSrcweir 				pLutFrac = new long[ nNewHeight ];
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir 				for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1282cdf0e10cSrcweir 				{
1283cdf0e10cSrcweir 					fTemp = nY * fRevScaleY;
1284cdf0e10cSrcweir 					pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1285cdf0e10cSrcweir 					fTemp -= pLutInt[ nY ];
1286cdf0e10cSrcweir 					pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1287cdf0e10cSrcweir 				}
1288cdf0e10cSrcweir 
1289c2821885SArmin Le Grand                 // after 1st step, bitmap *is* 24bit format (see above)
1290c2821885SArmin Le Grand 				OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)");
1291c2821885SArmin Le Grand 
1292c2821885SArmin Le Grand 				for( nX = 0L; nX < nNewWidth; nX++ )
1293cdf0e10cSrcweir 				{
1294c2821885SArmin Le Grand 					if( 1 == nHeight )
1295cdf0e10cSrcweir 					{
1296c2821885SArmin Le Grand 						aCol0 = pReadAcc->GetPixel( 0, nX );
1297cdf0e10cSrcweir 
1298c2821885SArmin Le Grand 						for( nY = 0L; nY < nNewHeight; nY++ )
1299c2821885SArmin Le Grand                         {
1300c2821885SArmin Le Grand 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1301c2821885SArmin Le Grand                         }
1302cdf0e10cSrcweir 					}
1303c2821885SArmin Le Grand 					else
1304cdf0e10cSrcweir 					{
1305c2821885SArmin Le Grand 						for( nY = 0L; nY < nNewHeight; nY++ )
1306cdf0e10cSrcweir 						{
1307c2821885SArmin Le Grand 							nTemp = pLutInt[ nY ];
1308cdf0e10cSrcweir 
1309c2821885SArmin Le Grand 							aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1310c2821885SArmin Le Grand 							aCol1 = pReadAcc->GetPixel( nTemp, nX );
1311cdf0e10cSrcweir 
1312c2821885SArmin Le Grand 							nTemp = pLutFrac[ nY ];
1313cdf0e10cSrcweir 
1314c2821885SArmin Le Grand 							lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1315c2821885SArmin Le Grand 							lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1316c2821885SArmin Le Grand 							lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1317cdf0e10cSrcweir 
1318c2821885SArmin Le Grand 							aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1319c2821885SArmin Le Grand 							aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1320c2821885SArmin Le Grand 							aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1321cdf0e10cSrcweir 
1322c2821885SArmin Le Grand 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1323cdf0e10cSrcweir 						}
1324cdf0e10cSrcweir 					}
1325cdf0e10cSrcweir 				}
1326cdf0e10cSrcweir 
1327cdf0e10cSrcweir 				delete[] pLutInt;
1328cdf0e10cSrcweir 				delete[] pLutFrac;
1329cdf0e10cSrcweir 				bRet = sal_True;
1330cdf0e10cSrcweir 			}
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir 			ReleaseAccess( pReadAcc );
1333cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWriteAcc );
1334cdf0e10cSrcweir 
1335cdf0e10cSrcweir 			if( bRet )
133637ab0f2dSArmin Le Grand             {
1337*561c4886SArmin Le Grand                 aOriginal.ImplAdaptBitCount(aNewBmp);
1338c2821885SArmin Le Grand 				*this = aNewBmp;
133937ab0f2dSArmin Le Grand             }
1340cdf0e10cSrcweir 		}
1341cdf0e10cSrcweir 	}
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir 	if( !bRet )
1344c2821885SArmin Le Grand     {
1345cdf0e10cSrcweir 		bRet = ImplScaleFast( rScaleX, rScaleY );
1346c2821885SArmin Le Grand     }
1347cdf0e10cSrcweir 
1348cdf0e10cSrcweir 	return bRet;
1349cdf0e10cSrcweir }
1350cdf0e10cSrcweir 
135137ab0f2dSArmin Le Grand // ------------------------------------------------------------------------
135237ab0f2dSArmin Le Grand // #121233# Added BMP_SCALE_SUPER from symphony code
135337ab0f2dSArmin Le Grand 
135437ab0f2dSArmin Le Grand sal_Bool Bitmap::ImplScaleSuper(
135537ab0f2dSArmin Le Grand     const double& rScaleX,
135637ab0f2dSArmin Le Grand     const double& rScaleY )
135737ab0f2dSArmin Le Grand {
135837ab0f2dSArmin Le Grand 	const Size	aSizePix( GetSizePixel() );
135937ab0f2dSArmin Le Grand 	bool   bHMirr = ( rScaleX < 0 );
136037ab0f2dSArmin Le Grand     bool   bVMirr = ( rScaleY < 0 );
136137ab0f2dSArmin Le Grand     double scaleX = bHMirr ? -rScaleX : rScaleX;
136237ab0f2dSArmin Le Grand     double scaleY = bVMirr ? -rScaleY : rScaleY;
136337ab0f2dSArmin Le Grand 	const long	nDstW = FRound( aSizePix.Width() * scaleX );
136437ab0f2dSArmin Le Grand 	const long	nDstH = FRound( aSizePix.Height() * scaleY );
136537ab0f2dSArmin Le Grand 	const double fScaleThresh = 0.6;
136637ab0f2dSArmin Le Grand 	bool bRet = false;
136737ab0f2dSArmin Le Grand 
136837ab0f2dSArmin Le Grand 	if( ( nDstW > 1L ) && ( nDstH > 1L ) )
136937ab0f2dSArmin Le Grand 	{
137037ab0f2dSArmin Le Grand 		BitmapColor			aCol0, aCol1, aColRes;
137137ab0f2dSArmin Le Grand 		BitmapReadAccess*	pAcc = AcquireReadAccess();
137237ab0f2dSArmin Le Grand 		long				nW = pAcc->Width() ;
137337ab0f2dSArmin Le Grand 		long				nH = pAcc->Height() ;
137437ab0f2dSArmin Le Grand 		Bitmap				aOutBmp( Size( nDstW, nDstH ), 24 );
137537ab0f2dSArmin Le Grand 		BitmapWriteAccess*	pWAcc = aOutBmp.AcquireWriteAccess();
137637ab0f2dSArmin Le Grand 		long*			    pMapIX = new long[ nDstW ];
137737ab0f2dSArmin Le Grand 		long*			    pMapIY = new long[ nDstH ];
137837ab0f2dSArmin Le Grand 		long*			    pMapFX = new long[ nDstW ];
137937ab0f2dSArmin Le Grand 		long*			    pMapFY = new long[ nDstH ];
138037ab0f2dSArmin Le Grand 		long				nX, nY, nXDst, nYDst;;
138137ab0f2dSArmin Le Grand 		double				fTemp;
138237ab0f2dSArmin Le Grand 		long				nTemp , nTempX, nTempY, nTempFX, nTempFY;
138337ab0f2dSArmin Le Grand 		sal_uInt8           cR0, cG0, cB0, cR1, cG1, cB1;
138437ab0f2dSArmin Le Grand 		long                nStartX = 0 , nStartY = 0;
138537ab0f2dSArmin Le Grand 		long                nEndX = nDstW - 1L;
138637ab0f2dSArmin Le Grand 		long                nEndY = nDstH - 1L;
138737ab0f2dSArmin Le Grand 		long		        nMax = 1 << 7L;
138837ab0f2dSArmin Le Grand 
138937ab0f2dSArmin Le Grand 		if( pAcc && pWAcc )
139037ab0f2dSArmin Le Grand 		{
139137ab0f2dSArmin Le Grand             const double	fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0;
139237ab0f2dSArmin Le Grand             const double	fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0;
139337ab0f2dSArmin Le Grand 
139437ab0f2dSArmin Le Grand             // create horizontal mapping table
139537ab0f2dSArmin Le Grand             for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ )
139637ab0f2dSArmin Le Grand             {
139737ab0f2dSArmin Le Grand                 fTemp = nX * fRevScaleX;
139837ab0f2dSArmin Le Grand 
139937ab0f2dSArmin Le Grand                 if( bHMirr )
140037ab0f2dSArmin Le Grand                     fTemp = nTempX - fTemp;
140137ab0f2dSArmin Le Grand 
140237ab0f2dSArmin Le Grand                 pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
140337ab0f2dSArmin Le Grand             }
140437ab0f2dSArmin Le Grand 
140537ab0f2dSArmin Le Grand             // create vertical mapping table
140637ab0f2dSArmin Le Grand             for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ )
140737ab0f2dSArmin Le Grand             {
140837ab0f2dSArmin Le Grand                 fTemp = nY * fRevScaleY;
140937ab0f2dSArmin Le Grand 
141037ab0f2dSArmin Le Grand                 if( bVMirr )
141137ab0f2dSArmin Le Grand                     fTemp = nTempY - fTemp;
141237ab0f2dSArmin Le Grand 
141337ab0f2dSArmin Le Grand                 pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
141437ab0f2dSArmin Le Grand             }
141537ab0f2dSArmin Le Grand 
141637ab0f2dSArmin Le Grand 			if( pAcc->HasPalette() )
141737ab0f2dSArmin Le Grand 			{
141837ab0f2dSArmin Le Grand 				if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
141937ab0f2dSArmin Le Grand 				{
142037ab0f2dSArmin Le Grand 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
142137ab0f2dSArmin Le Grand 					{
142237ab0f2dSArmin Le Grand 						Scanline pLine0, pLine1;
142337ab0f2dSArmin Le Grand 
142437ab0f2dSArmin Le Grand 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
142537ab0f2dSArmin Le Grand 						{
142637ab0f2dSArmin Le Grand 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
142737ab0f2dSArmin Le Grand 							pLine0 = pAcc->GetScanline( nTempY );
142837ab0f2dSArmin Le Grand 							pLine1 = pAcc->GetScanline( ++nTempY );
142937ab0f2dSArmin Le Grand 
143037ab0f2dSArmin Le Grand 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
143137ab0f2dSArmin Le Grand 							{
143237ab0f2dSArmin Le Grand 								nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
143337ab0f2dSArmin Le Grand 
143437ab0f2dSArmin Le Grand 								const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] );
143537ab0f2dSArmin Le Grand 								const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
143637ab0f2dSArmin Le Grand 								const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] );
143737ab0f2dSArmin Le Grand 								const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
143837ab0f2dSArmin Le Grand 
143937ab0f2dSArmin Le Grand 								cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
144037ab0f2dSArmin Le Grand 								cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
144137ab0f2dSArmin Le Grand 								cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
144237ab0f2dSArmin Le Grand 
144337ab0f2dSArmin Le Grand 								cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
144437ab0f2dSArmin Le Grand 								cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
144537ab0f2dSArmin Le Grand 								cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
144637ab0f2dSArmin Le Grand 
144737ab0f2dSArmin Le Grand 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
144837ab0f2dSArmin Le Grand 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
144937ab0f2dSArmin Le Grand 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
145037ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
145137ab0f2dSArmin Le Grand 							}
145237ab0f2dSArmin Le Grand 						}
145337ab0f2dSArmin Le Grand 					}
145437ab0f2dSArmin Le Grand 					else
145537ab0f2dSArmin Le Grand 					{
145637ab0f2dSArmin Le Grand 						Scanline	pTmpY;
145737ab0f2dSArmin Le Grand 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
145837ab0f2dSArmin Le Grand 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
145937ab0f2dSArmin Le Grand 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
146037ab0f2dSArmin Le Grand 
146137ab0f2dSArmin Le Grand 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
146237ab0f2dSArmin Le Grand 						{
146337ab0f2dSArmin Le Grand 							nTop = bVMirr ? ( nY + 1 ) : nY;
146437ab0f2dSArmin Le Grand 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
146537ab0f2dSArmin Le Grand 
146637ab0f2dSArmin Le Grand 							if( nY ==nEndY )
146737ab0f2dSArmin Le Grand                             {
146837ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nY ];
146937ab0f2dSArmin Le Grand 								nLineRange = 0;
147037ab0f2dSArmin Le Grand 							}
147137ab0f2dSArmin Le Grand 							else
147237ab0f2dSArmin Le Grand 							{
147337ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nTop ] ;
147437ab0f2dSArmin Le Grand 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
147537ab0f2dSArmin Le Grand 							}
147637ab0f2dSArmin Le Grand 
147737ab0f2dSArmin Le Grand 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
147837ab0f2dSArmin Le Grand 							{
147937ab0f2dSArmin Le Grand 								nLeft = bHMirr ? ( nX + 1 ) : nX;
148037ab0f2dSArmin Le Grand 								nRight = bHMirr ? nX : ( nX + 1 ) ;
148137ab0f2dSArmin Le Grand 
148237ab0f2dSArmin Le Grand 								if( nX == nEndX )
148337ab0f2dSArmin Le Grand                                 {
148437ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nX ];
148537ab0f2dSArmin Le Grand 									nRowRange = 0;
148637ab0f2dSArmin Le Grand 								}
148737ab0f2dSArmin Le Grand 								else
148837ab0f2dSArmin Le Grand 								{
148937ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nLeft ];
149037ab0f2dSArmin Le Grand 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
149137ab0f2dSArmin Le Grand 								}
149237ab0f2dSArmin Le Grand 
149337ab0f2dSArmin Le Grand 								nSumR = nSumG = nSumB = 0;
149437ab0f2dSArmin Le Grand 								nTotalWeightY = 0;
149537ab0f2dSArmin Le Grand 
149637ab0f2dSArmin Le Grand 								for(int i = 0; i<= nLineRange; i++)
149737ab0f2dSArmin Le Grand 								{
149837ab0f2dSArmin Le Grand 									pTmpY = pAcc->GetScanline( nLineStart + i );
149937ab0f2dSArmin Le Grand 									nSumRowR = nSumRowG = nSumRowB = 0;
150037ab0f2dSArmin Le Grand 									nTotalWeightX = 0;
150137ab0f2dSArmin Le Grand 
150237ab0f2dSArmin Le Grand 									for(int j = 0; j <= nRowRange; j++)
150337ab0f2dSArmin Le Grand 									{
150437ab0f2dSArmin Le Grand 										const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] );
150537ab0f2dSArmin Le Grand 
150637ab0f2dSArmin Le Grand 										if(nX == nEndX )
150737ab0f2dSArmin Le Grand                                         {
150837ab0f2dSArmin Le Grand 											nSumRowB += rCol.GetBlue() << 7L;
150937ab0f2dSArmin Le Grand 											nSumRowG += rCol.GetGreen() << 7L;
151037ab0f2dSArmin Le Grand 											nSumRowR += rCol.GetRed() << 7L;
151137ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
151237ab0f2dSArmin Le Grand 										}
151337ab0f2dSArmin Le Grand 										else if( j == 0 )
151437ab0f2dSArmin Le Grand                                         {
151537ab0f2dSArmin Le Grand 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
151637ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *rCol.GetBlue()) ;
151737ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *rCol.GetGreen()) ;
151837ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *rCol.GetRed()) ;
151937ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
152037ab0f2dSArmin Le Grand 										}
152137ab0f2dSArmin Le Grand 										else if ( nRowRange == j )
152237ab0f2dSArmin Le Grand                                         {
152337ab0f2dSArmin Le Grand 											nWeightX = pMapFX[ nRight ] ;
152437ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *rCol.GetBlue() );
152537ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *rCol.GetGreen() );
152637ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *rCol.GetRed() );
152737ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
152837ab0f2dSArmin Le Grand 										}
152937ab0f2dSArmin Le Grand 										else
153037ab0f2dSArmin Le Grand                                         {
153137ab0f2dSArmin Le Grand 											nSumRowB += rCol.GetBlue() << 7L;
153237ab0f2dSArmin Le Grand 											nSumRowG += rCol.GetGreen() << 7L;
153337ab0f2dSArmin Le Grand 											nSumRowR += rCol.GetRed() << 7L;
153437ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
153537ab0f2dSArmin Le Grand 										}
153637ab0f2dSArmin Le Grand 									}
153737ab0f2dSArmin Le Grand 
153837ab0f2dSArmin Le Grand 									if( nY == nEndY )
153937ab0f2dSArmin Le Grand 										nWeightY = nMax;
154037ab0f2dSArmin Le Grand 									else if( i == 0 )
154137ab0f2dSArmin Le Grand 										nWeightY = nMax - pMapFY[ nTop ];
154237ab0f2dSArmin Le Grand 									else if( nLineRange == 1 )
154337ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nTop ];
154437ab0f2dSArmin Le Grand 									else if ( nLineRange == i )
154537ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nBottom ];
154637ab0f2dSArmin Le Grand 									else
154737ab0f2dSArmin Le Grand 										nWeightY = nMax;
154837ab0f2dSArmin Le Grand 
154937ab0f2dSArmin Le Grand 									nWeightY = nWeightY ;
155037ab0f2dSArmin Le Grand 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
155137ab0f2dSArmin Le Grand 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
155237ab0f2dSArmin Le Grand 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
155337ab0f2dSArmin Le Grand 									nTotalWeightY += nWeightY;
155437ab0f2dSArmin Le Grand 								}
155537ab0f2dSArmin Le Grand 
155637ab0f2dSArmin Le Grand 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
155737ab0f2dSArmin Le Grand 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
155837ab0f2dSArmin Le Grand 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
155937ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
156037ab0f2dSArmin Le Grand 
156137ab0f2dSArmin Le Grand 							}
156237ab0f2dSArmin Le Grand     					}
156337ab0f2dSArmin Le Grand 					}
156437ab0f2dSArmin Le Grand }
156537ab0f2dSArmin Le Grand 				else
156637ab0f2dSArmin Le Grand 				{
156737ab0f2dSArmin Le Grand 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
156837ab0f2dSArmin Le Grand 					{
156937ab0f2dSArmin Le Grand 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
157037ab0f2dSArmin Le Grand 						{
157137ab0f2dSArmin Le Grand 							nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ];
157237ab0f2dSArmin Le Grand 
157337ab0f2dSArmin Le Grand 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
157437ab0f2dSArmin Le Grand 							{
157537ab0f2dSArmin Le Grand 								nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
157637ab0f2dSArmin Le Grand 
157737ab0f2dSArmin Le Grand 								aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) );
157837ab0f2dSArmin Le Grand 								aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) );
157937ab0f2dSArmin Le Grand 								cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
158037ab0f2dSArmin Le Grand 								cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
158137ab0f2dSArmin Le Grand 								cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
158237ab0f2dSArmin Le Grand 
158337ab0f2dSArmin Le Grand 								aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) );
158437ab0f2dSArmin Le Grand 								aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) );
158537ab0f2dSArmin Le Grand 								cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
158637ab0f2dSArmin Le Grand 								cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
158737ab0f2dSArmin Le Grand 								cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
158837ab0f2dSArmin Le Grand 
158937ab0f2dSArmin Le Grand 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
159037ab0f2dSArmin Le Grand 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
159137ab0f2dSArmin Le Grand 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
159237ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
159337ab0f2dSArmin Le Grand 							}
159437ab0f2dSArmin Le Grand 						}
159537ab0f2dSArmin Le Grand 
159637ab0f2dSArmin Le Grand 					}
159737ab0f2dSArmin Le Grand 					else
159837ab0f2dSArmin Le Grand 					{
159937ab0f2dSArmin Le Grand 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
160037ab0f2dSArmin Le Grand 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
160137ab0f2dSArmin Le Grand 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
160237ab0f2dSArmin Le Grand 
160337ab0f2dSArmin Le Grand 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
160437ab0f2dSArmin Le Grand 						{
160537ab0f2dSArmin Le Grand 							nTop = bVMirr ? ( nY + 1 ) : nY;
160637ab0f2dSArmin Le Grand 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
160737ab0f2dSArmin Le Grand 
160837ab0f2dSArmin Le Grand 							if( nY ==nEndY )
160937ab0f2dSArmin Le Grand                             {
161037ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nY ];
161137ab0f2dSArmin Le Grand 								nLineRange = 0;
161237ab0f2dSArmin Le Grand 							}
161337ab0f2dSArmin Le Grand 							else
161437ab0f2dSArmin Le Grand 							{
161537ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nTop ] ;
161637ab0f2dSArmin Le Grand 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
161737ab0f2dSArmin Le Grand 							}
161837ab0f2dSArmin Le Grand 
161937ab0f2dSArmin Le Grand 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
162037ab0f2dSArmin Le Grand 							{
162137ab0f2dSArmin Le Grand 								nLeft = bHMirr ? ( nX + 1 ) : nX;
162237ab0f2dSArmin Le Grand 								nRight = bHMirr ? nX : ( nX + 1 ) ;
162337ab0f2dSArmin Le Grand 
162437ab0f2dSArmin Le Grand 								if( nX == nEndX )
162537ab0f2dSArmin Le Grand                                 {
162637ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nX ];
162737ab0f2dSArmin Le Grand 									nRowRange = 0;
162837ab0f2dSArmin Le Grand 								}
162937ab0f2dSArmin Le Grand 								else
163037ab0f2dSArmin Le Grand 								{
163137ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nLeft ];
163237ab0f2dSArmin Le Grand 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
163337ab0f2dSArmin Le Grand 								}
163437ab0f2dSArmin Le Grand 
163537ab0f2dSArmin Le Grand 								nSumR = nSumG = nSumB = 0;
163637ab0f2dSArmin Le Grand 								nTotalWeightY = 0;
163737ab0f2dSArmin Le Grand 
163837ab0f2dSArmin Le Grand 								for(int i = 0; i<= nLineRange; i++)
163937ab0f2dSArmin Le Grand 								{
164037ab0f2dSArmin Le Grand 									nSumRowR = nSumRowG = nSumRowB = 0;
164137ab0f2dSArmin Le Grand 									nTotalWeightX = 0;
164237ab0f2dSArmin Le Grand 
164337ab0f2dSArmin Le Grand 									for(int j = 0; j <= nRowRange; j++)
164437ab0f2dSArmin Le Grand 									{
164537ab0f2dSArmin Le Grand 										aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
164637ab0f2dSArmin Le Grand 
164737ab0f2dSArmin Le Grand                                         if(nX == nEndX )
164837ab0f2dSArmin Le Grand                                         {
164937ab0f2dSArmin Le Grand 
165037ab0f2dSArmin Le Grand 											nSumRowB += aCol0.GetBlue() << 7L;
165137ab0f2dSArmin Le Grand 											nSumRowG += aCol0.GetGreen() << 7L;
165237ab0f2dSArmin Le Grand 											nSumRowR += aCol0.GetRed() << 7L;
165337ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
165437ab0f2dSArmin Le Grand 										}
165537ab0f2dSArmin Le Grand 										else if( j == 0 )
165637ab0f2dSArmin Le Grand                                         {
165737ab0f2dSArmin Le Grand 
165837ab0f2dSArmin Le Grand 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
165937ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
166037ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
166137ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *aCol0.GetRed()) ;
166237ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
166337ab0f2dSArmin Le Grand 										}
166437ab0f2dSArmin Le Grand 										else if ( nRowRange == j )
166537ab0f2dSArmin Le Grand                                         {
166637ab0f2dSArmin Le Grand 
166737ab0f2dSArmin Le Grand 											nWeightX = pMapFX[ nRight ] ;
166837ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *aCol0.GetBlue() );
166937ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *aCol0.GetGreen() );
167037ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *aCol0.GetRed() );
167137ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
167237ab0f2dSArmin Le Grand 										}
167337ab0f2dSArmin Le Grand 										else
167437ab0f2dSArmin Le Grand                                         {
167537ab0f2dSArmin Le Grand 
167637ab0f2dSArmin Le Grand 											nSumRowB += aCol0.GetBlue() << 7L;
167737ab0f2dSArmin Le Grand 											nSumRowG += aCol0.GetGreen() << 7L;
167837ab0f2dSArmin Le Grand 											nSumRowR += aCol0.GetRed() << 7L;
167937ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
168037ab0f2dSArmin Le Grand 										}
168137ab0f2dSArmin Le Grand 									}
168237ab0f2dSArmin Le Grand 
168337ab0f2dSArmin Le Grand 									if( nY == nEndY )
168437ab0f2dSArmin Le Grand 										nWeightY = nMax;
168537ab0f2dSArmin Le Grand 									else if( i == 0 )
168637ab0f2dSArmin Le Grand 										nWeightY = nMax - pMapFY[ nTop ];
168737ab0f2dSArmin Le Grand 									else if( nLineRange == 1 )
168837ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nTop ];
168937ab0f2dSArmin Le Grand 									else if ( nLineRange == i )
169037ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nBottom ];
169137ab0f2dSArmin Le Grand 									else
169237ab0f2dSArmin Le Grand 										nWeightY = nMax;
169337ab0f2dSArmin Le Grand 
169437ab0f2dSArmin Le Grand 									nWeightY = nWeightY ;
169537ab0f2dSArmin Le Grand 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
169637ab0f2dSArmin Le Grand 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
169737ab0f2dSArmin Le Grand 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
169837ab0f2dSArmin Le Grand 									nTotalWeightY += nWeightY;
169937ab0f2dSArmin Le Grand 								}
170037ab0f2dSArmin Le Grand 
170137ab0f2dSArmin Le Grand 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
170237ab0f2dSArmin Le Grand 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
170337ab0f2dSArmin Le Grand 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
170437ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
170537ab0f2dSArmin Le Grand 							}
170637ab0f2dSArmin Le Grand                         }
170737ab0f2dSArmin Le Grand 					}
170837ab0f2dSArmin Le Grand 				}
170937ab0f2dSArmin Le Grand 			}
171037ab0f2dSArmin Le Grand 			else
171137ab0f2dSArmin Le Grand 			{
171237ab0f2dSArmin Le Grand 				if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
171337ab0f2dSArmin Le Grand 				{
171437ab0f2dSArmin Le Grand 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
171537ab0f2dSArmin Le Grand 					{
171637ab0f2dSArmin Le Grand 						Scanline	pLine0, pLine1, pTmp0, pTmp1;
171737ab0f2dSArmin Le Grand 						long		nOff;
171837ab0f2dSArmin Le Grand 
171937ab0f2dSArmin Le Grand 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
172037ab0f2dSArmin Le Grand 						{
172137ab0f2dSArmin Le Grand 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
172237ab0f2dSArmin Le Grand 							pLine0 = pAcc->GetScanline( nTempY );
172337ab0f2dSArmin Le Grand 							pLine1 = pAcc->GetScanline( ++nTempY );
172437ab0f2dSArmin Le Grand 
172537ab0f2dSArmin Le Grand                             for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
172637ab0f2dSArmin Le Grand 							{
172737ab0f2dSArmin Le Grand 								nOff = 3L * ( nTempX = pMapIX[ nX ] );
172837ab0f2dSArmin Le Grand 								nTempFX = pMapFX[ nX ];
172937ab0f2dSArmin Le Grand 
173037ab0f2dSArmin Le Grand 								pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
173137ab0f2dSArmin Le Grand 								cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
173237ab0f2dSArmin Le Grand 								cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
173337ab0f2dSArmin Le Grand 								cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
173437ab0f2dSArmin Le Grand 
173537ab0f2dSArmin Le Grand 								pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
173637ab0f2dSArmin Le Grand 								cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
173737ab0f2dSArmin Le Grand 								cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
173837ab0f2dSArmin Le Grand 								cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
173937ab0f2dSArmin Le Grand 
174037ab0f2dSArmin Le Grand 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
174137ab0f2dSArmin Le Grand 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
174237ab0f2dSArmin Le Grand 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
174337ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
174437ab0f2dSArmin Le Grand 							}
174537ab0f2dSArmin Le Grand 						}
174637ab0f2dSArmin Le Grand 					}
174737ab0f2dSArmin Le Grand 					else
174837ab0f2dSArmin Le Grand 					{
174937ab0f2dSArmin Le Grand 						Scanline	pTmpY, pTmpX;
175037ab0f2dSArmin Le Grand 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
175137ab0f2dSArmin Le Grand 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
175237ab0f2dSArmin Le Grand 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
175337ab0f2dSArmin Le Grand 
175437ab0f2dSArmin Le Grand 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
175537ab0f2dSArmin Le Grand 						{
175637ab0f2dSArmin Le Grand 							nTop = bVMirr ? ( nY + 1 ) : nY;
175737ab0f2dSArmin Le Grand 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
175837ab0f2dSArmin Le Grand 
175937ab0f2dSArmin Le Grand 							if( nY ==nEndY )
176037ab0f2dSArmin Le Grand                             {
176137ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nY ];
176237ab0f2dSArmin Le Grand 								nLineRange = 0;
176337ab0f2dSArmin Le Grand 							}
176437ab0f2dSArmin Le Grand 							else
176537ab0f2dSArmin Le Grand 							{
176637ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nTop ] ;
176737ab0f2dSArmin Le Grand 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
176837ab0f2dSArmin Le Grand 							}
176937ab0f2dSArmin Le Grand 
177037ab0f2dSArmin Le Grand 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
177137ab0f2dSArmin Le Grand 							{
177237ab0f2dSArmin Le Grand 								nLeft = bHMirr ? ( nX + 1 ) : nX;
177337ab0f2dSArmin Le Grand 								nRight = bHMirr ? nX : ( nX + 1 ) ;
177437ab0f2dSArmin Le Grand 
177537ab0f2dSArmin Le Grand 								if( nX == nEndX  )
177637ab0f2dSArmin Le Grand                                 {
177737ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nX ];
177837ab0f2dSArmin Le Grand 									nRowRange = 0;
177937ab0f2dSArmin Le Grand 								}
178037ab0f2dSArmin Le Grand 								else
178137ab0f2dSArmin Le Grand 								{
178237ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nLeft ];
178337ab0f2dSArmin Le Grand 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
178437ab0f2dSArmin Le Grand 								}
178537ab0f2dSArmin Le Grand 
178637ab0f2dSArmin Le Grand 								nSumR = nSumG = nSumB = 0;
178737ab0f2dSArmin Le Grand 								nTotalWeightY = 0;
178837ab0f2dSArmin Le Grand 
178937ab0f2dSArmin Le Grand 								for(int i = 0; i<= nLineRange; i++)
179037ab0f2dSArmin Le Grand 								{
179137ab0f2dSArmin Le Grand 									pTmpY = pAcc->GetScanline( nLineStart + i );
179237ab0f2dSArmin Le Grand 									pTmpX = pTmpY + 3L * nRowStart;
179337ab0f2dSArmin Le Grand 									nSumRowR = nSumRowG = nSumRowB = 0;
179437ab0f2dSArmin Le Grand 									nTotalWeightX = 0;
179537ab0f2dSArmin Le Grand 
179637ab0f2dSArmin Le Grand 									for(int j = 0; j <= nRowRange; j++)
179737ab0f2dSArmin Le Grand 									{
179837ab0f2dSArmin Le Grand 										if(nX == nEndX )
179937ab0f2dSArmin Le Grand                                         {
180037ab0f2dSArmin Le Grand 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
180137ab0f2dSArmin Le Grand 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
180237ab0f2dSArmin Le Grand 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
180337ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
180437ab0f2dSArmin Le Grand 										}
180537ab0f2dSArmin Le Grand 										else if( j == 0 )
180637ab0f2dSArmin Le Grand                                         {
180737ab0f2dSArmin Le Grand 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
180837ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
180937ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
181037ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
181137ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
181237ab0f2dSArmin Le Grand 										}
181337ab0f2dSArmin Le Grand 										else if ( nRowRange == j )
181437ab0f2dSArmin Le Grand                                         {
181537ab0f2dSArmin Le Grand 											nWeightX = pMapFX[ nRight ] ;
181637ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
181737ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
181837ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
181937ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
182037ab0f2dSArmin Le Grand 										}
182137ab0f2dSArmin Le Grand 										else
182237ab0f2dSArmin Le Grand 										{
182337ab0f2dSArmin Le Grand 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
182437ab0f2dSArmin Le Grand 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
182537ab0f2dSArmin Le Grand 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
182637ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
182737ab0f2dSArmin Le Grand 										}
182837ab0f2dSArmin Le Grand 									}
182937ab0f2dSArmin Le Grand 
183037ab0f2dSArmin Le Grand 									if( nY == nEndY )
183137ab0f2dSArmin Le Grand 										nWeightY = nMax;
183237ab0f2dSArmin Le Grand 									else if( i == 0 )
183337ab0f2dSArmin Le Grand 										nWeightY = nMax - pMapFY[ nTop ];
183437ab0f2dSArmin Le Grand 									else if( nLineRange == 1 )
183537ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nTop ];
183637ab0f2dSArmin Le Grand 									else if ( nLineRange == i )
183737ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nBottom ];
183837ab0f2dSArmin Le Grand 									else
183937ab0f2dSArmin Le Grand 										nWeightY = nMax;
184037ab0f2dSArmin Le Grand 
184137ab0f2dSArmin Le Grand 									nWeightY = nWeightY ;
184237ab0f2dSArmin Le Grand 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
184337ab0f2dSArmin Le Grand 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
184437ab0f2dSArmin Le Grand 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
184537ab0f2dSArmin Le Grand 									nTotalWeightY += nWeightY;
184637ab0f2dSArmin Le Grand 								}
184737ab0f2dSArmin Le Grand 
184837ab0f2dSArmin Le Grand 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
184937ab0f2dSArmin Le Grand 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
185037ab0f2dSArmin Le Grand 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
185137ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
185237ab0f2dSArmin Le Grand 
185337ab0f2dSArmin Le Grand 							}
185437ab0f2dSArmin Le Grand                         }
185537ab0f2dSArmin Le Grand 					}
185637ab0f2dSArmin Le Grand 				}
185737ab0f2dSArmin Le Grand 				else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
185837ab0f2dSArmin Le Grand 				{
185937ab0f2dSArmin Le Grand 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
186037ab0f2dSArmin Le Grand 					{
186137ab0f2dSArmin Le Grand 						Scanline	pLine0, pLine1, pTmp0, pTmp1;
186237ab0f2dSArmin Le Grand 						long		nOff;
186337ab0f2dSArmin Le Grand 
186437ab0f2dSArmin Le Grand 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
186537ab0f2dSArmin Le Grand 						{
186637ab0f2dSArmin Le Grand 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
186737ab0f2dSArmin Le Grand 							pLine0 = pAcc->GetScanline( nTempY );
186837ab0f2dSArmin Le Grand 							pLine1 = pAcc->GetScanline( ++nTempY );
186937ab0f2dSArmin Le Grand 
187037ab0f2dSArmin Le Grand 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
187137ab0f2dSArmin Le Grand 							{
187237ab0f2dSArmin Le Grand 								nOff = 3L * ( nTempX = pMapIX[ nX ] );
187337ab0f2dSArmin Le Grand 								nTempFX = pMapFX[ nX ];
187437ab0f2dSArmin Le Grand 
187537ab0f2dSArmin Le Grand 								pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
187637ab0f2dSArmin Le Grand 								cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
187737ab0f2dSArmin Le Grand 								cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
187837ab0f2dSArmin Le Grand 								cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
187937ab0f2dSArmin Le Grand 
188037ab0f2dSArmin Le Grand 								pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
188137ab0f2dSArmin Le Grand 								cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
188237ab0f2dSArmin Le Grand 								cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
188337ab0f2dSArmin Le Grand 								cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
188437ab0f2dSArmin Le Grand 
188537ab0f2dSArmin Le Grand 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
188637ab0f2dSArmin Le Grand 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
188737ab0f2dSArmin Le Grand 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
188837ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
188937ab0f2dSArmin Le Grand 							}
189037ab0f2dSArmin Le Grand 						}
189137ab0f2dSArmin Le Grand 					}
189237ab0f2dSArmin Le Grand 					else
189337ab0f2dSArmin Le Grand 					{
189437ab0f2dSArmin Le Grand 						Scanline	pTmpY, pTmpX;
189537ab0f2dSArmin Le Grand 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
189637ab0f2dSArmin Le Grand 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
189737ab0f2dSArmin Le Grand 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
189837ab0f2dSArmin Le Grand 
189937ab0f2dSArmin Le Grand 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
190037ab0f2dSArmin Le Grand 						{
190137ab0f2dSArmin Le Grand 							nTop = bVMirr ? ( nY + 1 ) : nY;
190237ab0f2dSArmin Le Grand 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
190337ab0f2dSArmin Le Grand 
190437ab0f2dSArmin Le Grand 							if( nY ==nEndY )
190537ab0f2dSArmin Le Grand                             {
190637ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nY ];
190737ab0f2dSArmin Le Grand 								nLineRange = 0;
190837ab0f2dSArmin Le Grand 							}
190937ab0f2dSArmin Le Grand 							else
191037ab0f2dSArmin Le Grand 							{
191137ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nTop ] ;
191237ab0f2dSArmin Le Grand 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
191337ab0f2dSArmin Le Grand 							}
191437ab0f2dSArmin Le Grand 
191537ab0f2dSArmin Le Grand 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
191637ab0f2dSArmin Le Grand 							{
191737ab0f2dSArmin Le Grand 								nLeft = bHMirr ? ( nX + 1 ) : nX;
191837ab0f2dSArmin Le Grand 								nRight = bHMirr ? nX : ( nX + 1 ) ;
191937ab0f2dSArmin Le Grand 
192037ab0f2dSArmin Le Grand 								if( nX == nEndX )
192137ab0f2dSArmin Le Grand                                 {
192237ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nX ];
192337ab0f2dSArmin Le Grand 									nRowRange = 0;
192437ab0f2dSArmin Le Grand 								}
192537ab0f2dSArmin Le Grand 								else
192637ab0f2dSArmin Le Grand 								{
192737ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nLeft ];
192837ab0f2dSArmin Le Grand 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
192937ab0f2dSArmin Le Grand 								}
193037ab0f2dSArmin Le Grand 
193137ab0f2dSArmin Le Grand 								nSumR = nSumG = nSumB = 0;
193237ab0f2dSArmin Le Grand 								nTotalWeightY = 0;
193337ab0f2dSArmin Le Grand 
193437ab0f2dSArmin Le Grand 								for(int i = 0; i<= nLineRange; i++)
193537ab0f2dSArmin Le Grand 								{
193637ab0f2dSArmin Le Grand 									pTmpY = pAcc->GetScanline( nLineStart + i );
193737ab0f2dSArmin Le Grand 									pTmpX = pTmpY + 3L * nRowStart;
193837ab0f2dSArmin Le Grand 									nSumRowR = nSumRowG = nSumRowB = 0;
193937ab0f2dSArmin Le Grand 									nTotalWeightX = 0;
194037ab0f2dSArmin Le Grand 
194137ab0f2dSArmin Le Grand 									for(int j = 0; j <= nRowRange; j++)
194237ab0f2dSArmin Le Grand 									{
194337ab0f2dSArmin Le Grand 										if(nX == nEndX )
194437ab0f2dSArmin Le Grand                                         {
194537ab0f2dSArmin Le Grand 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
194637ab0f2dSArmin Le Grand 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
194737ab0f2dSArmin Le Grand 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
194837ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
194937ab0f2dSArmin Le Grand 										}
195037ab0f2dSArmin Le Grand 										else if( j == 0 )
195137ab0f2dSArmin Le Grand                                         {
195237ab0f2dSArmin Le Grand 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
195337ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
195437ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
195537ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
195637ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
195737ab0f2dSArmin Le Grand 										}
195837ab0f2dSArmin Le Grand 										else if ( nRowRange == j )
195937ab0f2dSArmin Le Grand                                         {
196037ab0f2dSArmin Le Grand 											nWeightX = pMapFX[ nRight ] ;
196137ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
196237ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
196337ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
196437ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
196537ab0f2dSArmin Le Grand 										}
196637ab0f2dSArmin Le Grand 										else
196737ab0f2dSArmin Le Grand                                         {
196837ab0f2dSArmin Le Grand 											nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
196937ab0f2dSArmin Le Grand 											nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
197037ab0f2dSArmin Le Grand 											nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
197137ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
197237ab0f2dSArmin Le Grand 										}
197337ab0f2dSArmin Le Grand 									}
197437ab0f2dSArmin Le Grand 
197537ab0f2dSArmin Le Grand 									if( nY == nEndY )
197637ab0f2dSArmin Le Grand 										nWeightY = nMax;
197737ab0f2dSArmin Le Grand 									else if( i == 0 )
197837ab0f2dSArmin Le Grand 										nWeightY = nMax - pMapFY[ nTop ];
197937ab0f2dSArmin Le Grand 									else if( nLineRange == 1 )
198037ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nTop ];
198137ab0f2dSArmin Le Grand 									else if ( nLineRange == i )
198237ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nBottom ];
198337ab0f2dSArmin Le Grand 									else
198437ab0f2dSArmin Le Grand 										nWeightY = nMax;
198537ab0f2dSArmin Le Grand 
198637ab0f2dSArmin Le Grand 									nWeightY = nWeightY ;
198737ab0f2dSArmin Le Grand 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
198837ab0f2dSArmin Le Grand 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
198937ab0f2dSArmin Le Grand 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
199037ab0f2dSArmin Le Grand 									nTotalWeightY += nWeightY;
199137ab0f2dSArmin Le Grand 								}
199237ab0f2dSArmin Le Grand 
199337ab0f2dSArmin Le Grand 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
199437ab0f2dSArmin Le Grand 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
199537ab0f2dSArmin Le Grand 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
199637ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
199737ab0f2dSArmin Le Grand 
199837ab0f2dSArmin Le Grand 							}
199937ab0f2dSArmin Le Grand                         }
200037ab0f2dSArmin Le Grand 					}
200137ab0f2dSArmin Le Grand 				}
200237ab0f2dSArmin Le Grand 				else
200337ab0f2dSArmin Le Grand 				{
200437ab0f2dSArmin Le Grand 					if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
200537ab0f2dSArmin Le Grand 					{
200637ab0f2dSArmin Le Grand 						for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
200737ab0f2dSArmin Le Grand 						{
200837ab0f2dSArmin Le Grand 							nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
200937ab0f2dSArmin Le Grand 
201037ab0f2dSArmin Le Grand 							for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
201137ab0f2dSArmin Le Grand 							{
201237ab0f2dSArmin Le Grand 								nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
201337ab0f2dSArmin Le Grand 
201437ab0f2dSArmin Le Grand 								aCol0 = pAcc->GetPixel( nTempY, nTempX );
201537ab0f2dSArmin Le Grand 								aCol1 = pAcc->GetPixel( nTempY, ++nTempX );
201637ab0f2dSArmin Le Grand 								cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
201737ab0f2dSArmin Le Grand 								cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
201837ab0f2dSArmin Le Grand 								cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
201937ab0f2dSArmin Le Grand 
202037ab0f2dSArmin Le Grand 								aCol1 = pAcc->GetPixel( ++nTempY, nTempX );
202137ab0f2dSArmin Le Grand 								aCol0 = pAcc->GetPixel( nTempY--, --nTempX );
202237ab0f2dSArmin Le Grand 								cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
202337ab0f2dSArmin Le Grand 								cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
202437ab0f2dSArmin Le Grand 								cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
202537ab0f2dSArmin Le Grand 
202637ab0f2dSArmin Le Grand 								aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
202737ab0f2dSArmin Le Grand 								aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
202837ab0f2dSArmin Le Grand 								aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
202937ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
203037ab0f2dSArmin Le Grand 							}
203137ab0f2dSArmin Le Grand 						}
203237ab0f2dSArmin Le Grand 					}
203337ab0f2dSArmin Le Grand 					else
203437ab0f2dSArmin Le Grand 					{
203537ab0f2dSArmin Le Grand 						long		nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
203637ab0f2dSArmin Le Grand 						long		nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
203737ab0f2dSArmin Le Grand 						long		nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
203837ab0f2dSArmin Le Grand 
203937ab0f2dSArmin Le Grand 						for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
204037ab0f2dSArmin Le Grand 						{
204137ab0f2dSArmin Le Grand 							nTop = bVMirr ? ( nY + 1 ) : nY;
204237ab0f2dSArmin Le Grand 							nBottom = bVMirr ? nY : ( nY + 1 ) ;
204337ab0f2dSArmin Le Grand 
204437ab0f2dSArmin Le Grand 							if( nY ==nEndY )
204537ab0f2dSArmin Le Grand                             {
204637ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nY ];
204737ab0f2dSArmin Le Grand 								nLineRange = 0;
204837ab0f2dSArmin Le Grand 							}
204937ab0f2dSArmin Le Grand 							else
205037ab0f2dSArmin Le Grand 							{
205137ab0f2dSArmin Le Grand 								nLineStart = pMapIY[ nTop ] ;
205237ab0f2dSArmin Le Grand 								nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
205337ab0f2dSArmin Le Grand 							}
205437ab0f2dSArmin Le Grand 
205537ab0f2dSArmin Le Grand 							for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
205637ab0f2dSArmin Le Grand 							{
205737ab0f2dSArmin Le Grand 								nLeft = bHMirr ? ( nX + 1 ) : nX;
205837ab0f2dSArmin Le Grand 								nRight = bHMirr ? nX : ( nX + 1 ) ;
205937ab0f2dSArmin Le Grand 
206037ab0f2dSArmin Le Grand 								if( nX == nEndX )
206137ab0f2dSArmin Le Grand                                 {
206237ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nX ];
206337ab0f2dSArmin Le Grand 									nRowRange = 0;
206437ab0f2dSArmin Le Grand 								}
206537ab0f2dSArmin Le Grand 								else
206637ab0f2dSArmin Le Grand 								{
206737ab0f2dSArmin Le Grand 									nRowStart = pMapIX[ nLeft ];
206837ab0f2dSArmin Le Grand 									nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
206937ab0f2dSArmin Le Grand 								}
207037ab0f2dSArmin Le Grand 
207137ab0f2dSArmin Le Grand 								nSumR = nSumG = nSumB = 0;
207237ab0f2dSArmin Le Grand 								nTotalWeightY = 0;
207337ab0f2dSArmin Le Grand 
207437ab0f2dSArmin Le Grand 								for(int i = 0; i<= nLineRange; i++)
207537ab0f2dSArmin Le Grand 								{
207637ab0f2dSArmin Le Grand 									nSumRowR = nSumRowG = nSumRowB = 0;
207737ab0f2dSArmin Le Grand 									nTotalWeightX = 0;
207837ab0f2dSArmin Le Grand 
207937ab0f2dSArmin Le Grand 									for(int j = 0; j <= nRowRange; j++)
208037ab0f2dSArmin Le Grand 									{
208137ab0f2dSArmin Le Grand 										aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j );
208237ab0f2dSArmin Le Grand 
208337ab0f2dSArmin Le Grand                                         if(nX == nEndX )
208437ab0f2dSArmin Le Grand                                         {
208537ab0f2dSArmin Le Grand 
208637ab0f2dSArmin Le Grand 											nSumRowB += aCol0.GetBlue() << 7L;
208737ab0f2dSArmin Le Grand 											nSumRowG += aCol0.GetGreen() << 7L;
208837ab0f2dSArmin Le Grand 											nSumRowR += aCol0.GetRed() << 7L;
208937ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
209037ab0f2dSArmin Le Grand 										}
209137ab0f2dSArmin Le Grand 										else if( j == 0 )
209237ab0f2dSArmin Le Grand                                         {
209337ab0f2dSArmin Le Grand 
209437ab0f2dSArmin Le Grand 											nWeightX = (nMax- pMapFX[ nLeft ]) ;
209537ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
209637ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
209737ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *aCol0.GetRed()) ;
209837ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
209937ab0f2dSArmin Le Grand 										}
210037ab0f2dSArmin Le Grand 										else if ( nRowRange == j )
210137ab0f2dSArmin Le Grand                                         {
210237ab0f2dSArmin Le Grand 
210337ab0f2dSArmin Le Grand 											nWeightX = pMapFX[ nRight ] ;
210437ab0f2dSArmin Le Grand 											nSumRowB += ( nWeightX *aCol0.GetBlue() );
210537ab0f2dSArmin Le Grand 											nSumRowG += ( nWeightX *aCol0.GetGreen() );
210637ab0f2dSArmin Le Grand 											nSumRowR += ( nWeightX *aCol0.GetRed() );
210737ab0f2dSArmin Le Grand 											nTotalWeightX += nWeightX;
210837ab0f2dSArmin Le Grand 										}
210937ab0f2dSArmin Le Grand 										else
211037ab0f2dSArmin Le Grand                                         {
211137ab0f2dSArmin Le Grand 											nSumRowB += aCol0.GetBlue() << 7L;
211237ab0f2dSArmin Le Grand 											nSumRowG += aCol0.GetGreen() << 7L;
211337ab0f2dSArmin Le Grand 											nSumRowR += aCol0.GetRed() << 7L;
211437ab0f2dSArmin Le Grand 											nTotalWeightX += 1 << 7L;
211537ab0f2dSArmin Le Grand 										}
211637ab0f2dSArmin Le Grand 									}
211737ab0f2dSArmin Le Grand 
211837ab0f2dSArmin Le Grand 									if( nY == nEndY )
211937ab0f2dSArmin Le Grand 										nWeightY = nMax;
212037ab0f2dSArmin Le Grand 									else if( i == 0 )
212137ab0f2dSArmin Le Grand 										nWeightY = nMax - pMapFY[ nTop ];
212237ab0f2dSArmin Le Grand 									else if( nLineRange == 1 )
212337ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nTop ];
212437ab0f2dSArmin Le Grand 									else if ( nLineRange == i )
212537ab0f2dSArmin Le Grand 										nWeightY = pMapFY[ nBottom ];
212637ab0f2dSArmin Le Grand 									else
212737ab0f2dSArmin Le Grand 										nWeightY = nMax;
212837ab0f2dSArmin Le Grand 
212937ab0f2dSArmin Le Grand 									nWeightY = nWeightY ;
213037ab0f2dSArmin Le Grand 									nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
213137ab0f2dSArmin Le Grand 									nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
213237ab0f2dSArmin Le Grand 									nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
213337ab0f2dSArmin Le Grand 									nTotalWeightY += nWeightY;
213437ab0f2dSArmin Le Grand 								}
213537ab0f2dSArmin Le Grand 
213637ab0f2dSArmin Le Grand 								aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
213737ab0f2dSArmin Le Grand 								aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
213837ab0f2dSArmin Le Grand 								aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
213937ab0f2dSArmin Le Grand 								pWAcc->SetPixel( nYDst, nXDst++, aColRes );
214037ab0f2dSArmin Le Grand 
214137ab0f2dSArmin Le Grand 							}
214237ab0f2dSArmin Le Grand                         }
214337ab0f2dSArmin Le Grand 					}
214437ab0f2dSArmin Le Grand 				}
214537ab0f2dSArmin Le Grand             }
214637ab0f2dSArmin Le Grand 
214737ab0f2dSArmin Le Grand             bRet = true;
214837ab0f2dSArmin Le Grand 		}
214937ab0f2dSArmin Le Grand 
215037ab0f2dSArmin Le Grand 		delete[] pMapIX;
215137ab0f2dSArmin Le Grand 		delete[] pMapIY;
215237ab0f2dSArmin Le Grand 		delete[] pMapFX;
215337ab0f2dSArmin Le Grand 		delete[] pMapFY;
215437ab0f2dSArmin Le Grand 
215537ab0f2dSArmin Le Grand 		ReleaseAccess( pAcc );
215637ab0f2dSArmin Le Grand 		aOutBmp.ReleaseAccess( pWAcc );
215737ab0f2dSArmin Le Grand 
215837ab0f2dSArmin Le Grand 		if( bRet )
215937ab0f2dSArmin Le Grand         {
216037ab0f2dSArmin Le Grand             ImplAdaptBitCount(aOutBmp);
216137ab0f2dSArmin Le Grand 			ImplAssignWithSize(aOutBmp);
216237ab0f2dSArmin Le Grand         }
216337ab0f2dSArmin Le Grand 
216437ab0f2dSArmin Le Grand 		if( !bRet )
216537ab0f2dSArmin Le Grand 			bRet = ImplScaleFast( scaleX, scaleY );
216637ab0f2dSArmin Le Grand 	}
216737ab0f2dSArmin Le Grand 
216837ab0f2dSArmin Le Grand 	return bRet;
216937ab0f2dSArmin Le Grand }
217037ab0f2dSArmin Le Grand 
217137ab0f2dSArmin Le Grand //-----------------------------------------------------------------------------------
217237ab0f2dSArmin Le Grand 
217337ab0f2dSArmin Le Grand namespace
217437ab0f2dSArmin Le Grand {
217537ab0f2dSArmin Le Grand     void ImplCalculateContributions(
217637ab0f2dSArmin Le Grand         const sal_uInt32 aSourceSize,
217737ab0f2dSArmin Le Grand         const sal_uInt32 aDestinationSize,
217837ab0f2dSArmin Le Grand         sal_uInt32& aNumberOfContributions,
217937ab0f2dSArmin Le Grand         double*& pWeights,
218037ab0f2dSArmin Le Grand         sal_uInt32*& pPixels,
218137ab0f2dSArmin Le Grand         sal_uInt32*& pCount,
218237ab0f2dSArmin Le Grand         const Kernel& aKernel)
218337ab0f2dSArmin Le Grand     {
218437ab0f2dSArmin Le Grand         const double fSamplingRadius(aKernel.GetWidth());
218537ab0f2dSArmin Le Grand         const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
218637ab0f2dSArmin Le Grand         const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
218737ab0f2dSArmin Le Grand         const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
218837ab0f2dSArmin Le Grand 
218937ab0f2dSArmin Le Grand         aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
219037ab0f2dSArmin Le Grand         const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
219137ab0f2dSArmin Le Grand         pWeights = new double[nAllocSize];
219237ab0f2dSArmin Le Grand         pPixels = new sal_uInt32[nAllocSize];
219337ab0f2dSArmin Le Grand         pCount = new sal_uInt32[aDestinationSize];
219437ab0f2dSArmin Le Grand 
219537ab0f2dSArmin Le Grand         for(sal_uInt32 i(0); i < aDestinationSize; i++)
219637ab0f2dSArmin Le Grand         {
219737ab0f2dSArmin Le Grand             const sal_uInt32 aIndex(i * aNumberOfContributions);
219837ab0f2dSArmin Le Grand             const double aCenter(i / fScale);
219937ab0f2dSArmin Le Grand             const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
220037ab0f2dSArmin Le Grand             const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
220137ab0f2dSArmin Le Grand             sal_uInt32 aCurrentCount(0);
220237ab0f2dSArmin Le Grand 
220337ab0f2dSArmin Le Grand             for(sal_Int32 j(aLeft); j <= aRight; j++)
220437ab0f2dSArmin Le Grand             {
220537ab0f2dSArmin Le Grand                 const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
220637ab0f2dSArmin Le Grand 
220737ab0f2dSArmin Le Grand                 // Reduce calculations with ignoring weights of 0.0
220837ab0f2dSArmin Le Grand                 if(fabs(aWeight) < 0.0001)
220937ab0f2dSArmin Le Grand                 {
221037ab0f2dSArmin Le Grand                     continue;
221137ab0f2dSArmin Le Grand                 }
221237ab0f2dSArmin Le Grand 
221337ab0f2dSArmin Le Grand                 // Handling on edges
221437ab0f2dSArmin Le Grand                 const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
221537ab0f2dSArmin Le Grand                 const sal_uInt32 nIndex(aIndex + aCurrentCount);
221637ab0f2dSArmin Le Grand 
221737ab0f2dSArmin Le Grand                 pWeights[nIndex] = aWeight;
221837ab0f2dSArmin Le Grand                 pPixels[nIndex] = aPixelIndex;
221937ab0f2dSArmin Le Grand 
222037ab0f2dSArmin Le Grand                 aCurrentCount++;
222137ab0f2dSArmin Le Grand             }
222237ab0f2dSArmin Le Grand 
222337ab0f2dSArmin Le Grand             pCount[i] = aCurrentCount;
222437ab0f2dSArmin Le Grand         }
222537ab0f2dSArmin Le Grand     }
222637ab0f2dSArmin Le Grand 
222737ab0f2dSArmin Le Grand     sal_Bool ImplScaleConvolutionHor(
222837ab0f2dSArmin Le Grand         Bitmap& rSource,
222937ab0f2dSArmin Le Grand         Bitmap& rTarget,
223037ab0f2dSArmin Le Grand         const double& rScaleX,
223137ab0f2dSArmin Le Grand         const Kernel& aKernel)
223237ab0f2dSArmin Le Grand     {
223337ab0f2dSArmin Le Grand         // Do horizontal filtering
223437ab0f2dSArmin Le Grand         OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
223537ab0f2dSArmin Le Grand         const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
223637ab0f2dSArmin Le Grand         const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
223737ab0f2dSArmin Le Grand 
223837ab0f2dSArmin Le Grand         if(nWidth == nNewWidth)
223937ab0f2dSArmin Le Grand         {
224037ab0f2dSArmin Le Grand             return true;
224137ab0f2dSArmin Le Grand         }
224237ab0f2dSArmin Le Grand 
224337ab0f2dSArmin Le Grand         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
224437ab0f2dSArmin Le Grand 
224537ab0f2dSArmin Le Grand         if(pReadAcc)
224637ab0f2dSArmin Le Grand         {
224737ab0f2dSArmin Le Grand             double* pWeights = 0;
224837ab0f2dSArmin Le Grand             sal_uInt32* pPixels = 0;
224937ab0f2dSArmin Le Grand             sal_uInt32* pCount = 0;
225037ab0f2dSArmin Le Grand             sal_uInt32 aNumberOfContributions(0);
225137ab0f2dSArmin Le Grand 
225237ab0f2dSArmin Le Grand             const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
225337ab0f2dSArmin Le Grand             ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
225437ab0f2dSArmin Le Grand             rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
225537ab0f2dSArmin Le Grand             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
225637ab0f2dSArmin Le Grand             bool bResult(0 != pWriteAcc);
225737ab0f2dSArmin Le Grand 
225837ab0f2dSArmin Le Grand             if(bResult)
225937ab0f2dSArmin Le Grand             {
226037ab0f2dSArmin Le Grand                 for(sal_uInt32 y(0); y < nHeight; y++)
226137ab0f2dSArmin Le Grand                 {
226237ab0f2dSArmin Le Grand                     for(sal_uInt32 x(0); x < nNewWidth; x++)
226337ab0f2dSArmin Le Grand                     {
226437ab0f2dSArmin Le Grand                         const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
226537ab0f2dSArmin Le Grand                         double aSum(0.0);
226637ab0f2dSArmin Le Grand                         double aValueRed(0.0);
226737ab0f2dSArmin Le Grand                         double aValueGreen(0.0);
226837ab0f2dSArmin Le Grand                         double aValueBlue(0.0);
226937ab0f2dSArmin Le Grand 
227037ab0f2dSArmin Le Grand                         for(sal_uInt32 j(0); j < pCount[x]; j++)
227137ab0f2dSArmin Le Grand                         {
227237ab0f2dSArmin Le Grand                             const sal_uInt32 aIndex(aBaseIndex + j);
227337ab0f2dSArmin Le Grand                             const double aWeight(pWeights[aIndex]);
227437ab0f2dSArmin Le Grand                             BitmapColor aColor;
227537ab0f2dSArmin Le Grand 
227637ab0f2dSArmin Le Grand                             aSum += aWeight;
227737ab0f2dSArmin Le Grand 
227837ab0f2dSArmin Le Grand                             if(pReadAcc->HasPalette())
227937ab0f2dSArmin Le Grand                             {
228037ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
228137ab0f2dSArmin Le Grand                             }
228237ab0f2dSArmin Le Grand                             else
228337ab0f2dSArmin Le Grand                             {
228437ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
228537ab0f2dSArmin Le Grand                             }
228637ab0f2dSArmin Le Grand 
228737ab0f2dSArmin Le Grand                             aValueRed += aWeight * aColor.GetRed();
228837ab0f2dSArmin Le Grand                             aValueGreen += aWeight * aColor.GetGreen();
228937ab0f2dSArmin Le Grand                             aValueBlue += aWeight * aColor.GetBlue();
229037ab0f2dSArmin Le Grand                         }
229137ab0f2dSArmin Le Grand 
229237ab0f2dSArmin Le Grand                         const BitmapColor aResultColor(
229337ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
229437ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
229537ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
229637ab0f2dSArmin Le Grand 
229737ab0f2dSArmin Le Grand                         pWriteAcc->SetPixel(y, x, aResultColor);
229837ab0f2dSArmin Le Grand                     }
229937ab0f2dSArmin Le Grand                 }
230037ab0f2dSArmin Le Grand 
230137ab0f2dSArmin Le Grand                 rTarget.ReleaseAccess(pWriteAcc);
230237ab0f2dSArmin Le Grand             }
230337ab0f2dSArmin Le Grand 
230437ab0f2dSArmin Le Grand             rSource.ReleaseAccess(pReadAcc);
230537ab0f2dSArmin Le Grand             delete[] pWeights;
230637ab0f2dSArmin Le Grand             delete[] pCount;
230737ab0f2dSArmin Le Grand             delete[] pPixels;
230837ab0f2dSArmin Le Grand 
230937ab0f2dSArmin Le Grand             if(bResult)
231037ab0f2dSArmin Le Grand             {
231137ab0f2dSArmin Le Grand                 return true;
231237ab0f2dSArmin Le Grand             }
231337ab0f2dSArmin Le Grand         }
231437ab0f2dSArmin Le Grand 
231537ab0f2dSArmin Le Grand         return false;
231637ab0f2dSArmin Le Grand     }
231737ab0f2dSArmin Le Grand 
231837ab0f2dSArmin Le Grand     bool ImplScaleConvolutionVer(
231937ab0f2dSArmin Le Grand         Bitmap& rSource,
232037ab0f2dSArmin Le Grand         Bitmap& rTarget,
232137ab0f2dSArmin Le Grand         const double& rScaleY,
232237ab0f2dSArmin Le Grand         const Kernel& aKernel)
232337ab0f2dSArmin Le Grand     {
232437ab0f2dSArmin Le Grand         // Do vertical filtering
232537ab0f2dSArmin Le Grand         OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
232637ab0f2dSArmin Le Grand         const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
232737ab0f2dSArmin Le Grand         const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
232837ab0f2dSArmin Le Grand 
232937ab0f2dSArmin Le Grand         if(nHeight == nNewHeight)
233037ab0f2dSArmin Le Grand         {
233137ab0f2dSArmin Le Grand             return true;
233237ab0f2dSArmin Le Grand         }
233337ab0f2dSArmin Le Grand 
233437ab0f2dSArmin Le Grand         BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
233537ab0f2dSArmin Le Grand 
233637ab0f2dSArmin Le Grand         if(pReadAcc)
233737ab0f2dSArmin Le Grand         {
233837ab0f2dSArmin Le Grand             double* pWeights = 0;
233937ab0f2dSArmin Le Grand             sal_uInt32* pPixels = 0;
234037ab0f2dSArmin Le Grand             sal_uInt32* pCount = 0;
234137ab0f2dSArmin Le Grand             sal_uInt32 aNumberOfContributions(0);
234237ab0f2dSArmin Le Grand 
234337ab0f2dSArmin Le Grand             const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
234437ab0f2dSArmin Le Grand             ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
234537ab0f2dSArmin Le Grand             rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
234637ab0f2dSArmin Le Grand             BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
234737ab0f2dSArmin Le Grand             bool bResult(0 != pWriteAcc);
234837ab0f2dSArmin Le Grand 
234937ab0f2dSArmin Le Grand             if(pWriteAcc)
235037ab0f2dSArmin Le Grand             {
235137ab0f2dSArmin Le Grand                 for(sal_uInt32 x(0); x < nWidth; x++)
235237ab0f2dSArmin Le Grand                 {
235337ab0f2dSArmin Le Grand                     for(sal_uInt32 y(0); y < nNewHeight; y++)
235437ab0f2dSArmin Le Grand                     {
235537ab0f2dSArmin Le Grand                         const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
235637ab0f2dSArmin Le Grand                         double aSum(0.0);
235737ab0f2dSArmin Le Grand                         double aValueRed(0.0);
235837ab0f2dSArmin Le Grand                         double aValueGreen(0.0);
235937ab0f2dSArmin Le Grand                         double aValueBlue(0.0);
236037ab0f2dSArmin Le Grand 
236137ab0f2dSArmin Le Grand                         for(sal_uInt32 j(0); j < pCount[y]; j++)
236237ab0f2dSArmin Le Grand                         {
236337ab0f2dSArmin Le Grand                             const sal_uInt32 aIndex(aBaseIndex + j);
236437ab0f2dSArmin Le Grand                             const double aWeight(pWeights[aIndex]);
236537ab0f2dSArmin Le Grand                             BitmapColor aColor;
236637ab0f2dSArmin Le Grand 
236737ab0f2dSArmin Le Grand                             aSum += aWeight;
236837ab0f2dSArmin Le Grand 
236937ab0f2dSArmin Le Grand                             if(pReadAcc->HasPalette())
237037ab0f2dSArmin Le Grand                             {
237137ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
237237ab0f2dSArmin Le Grand                             }
237337ab0f2dSArmin Le Grand                             else
237437ab0f2dSArmin Le Grand                             {
237537ab0f2dSArmin Le Grand                                 aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
237637ab0f2dSArmin Le Grand                             }
237737ab0f2dSArmin Le Grand 
237837ab0f2dSArmin Le Grand                             aValueRed += aWeight * aColor.GetRed();
237937ab0f2dSArmin Le Grand                             aValueGreen += aWeight * aColor.GetGreen();
238037ab0f2dSArmin Le Grand                             aValueBlue += aWeight * aColor.GetBlue();
238137ab0f2dSArmin Le Grand                         }
238237ab0f2dSArmin Le Grand 
238337ab0f2dSArmin Le Grand                         const BitmapColor aResultColor(
238437ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
238537ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
238637ab0f2dSArmin Le Grand                             static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
238737ab0f2dSArmin Le Grand 
238837ab0f2dSArmin Le Grand                         if(pWriteAcc->HasPalette())
238937ab0f2dSArmin Le Grand                         {
239037ab0f2dSArmin Le Grand                             pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
239137ab0f2dSArmin Le Grand                         }
239237ab0f2dSArmin Le Grand                         else
239337ab0f2dSArmin Le Grand                         {
239437ab0f2dSArmin Le Grand                             pWriteAcc->SetPixel(y, x, aResultColor);
239537ab0f2dSArmin Le Grand                         }
239637ab0f2dSArmin Le Grand                     }
239737ab0f2dSArmin Le Grand                 }
239837ab0f2dSArmin Le Grand             }
239937ab0f2dSArmin Le Grand 
240037ab0f2dSArmin Le Grand             rTarget.ReleaseAccess(pWriteAcc);
240137ab0f2dSArmin Le Grand             rSource.ReleaseAccess(pReadAcc);
240237ab0f2dSArmin Le Grand 
240337ab0f2dSArmin Le Grand             delete[] pWeights;
240437ab0f2dSArmin Le Grand             delete[] pCount;
240537ab0f2dSArmin Le Grand             delete[] pPixels;
240637ab0f2dSArmin Le Grand 
240737ab0f2dSArmin Le Grand             if(bResult)
240837ab0f2dSArmin Le Grand             {
240937ab0f2dSArmin Le Grand                 return true;
241037ab0f2dSArmin Le Grand             }
241137ab0f2dSArmin Le Grand         }
241237ab0f2dSArmin Le Grand 
241337ab0f2dSArmin Le Grand         return false;
241437ab0f2dSArmin Le Grand     }
241537ab0f2dSArmin Le Grand }
241637ab0f2dSArmin Le Grand 
241737ab0f2dSArmin Le Grand // #121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and
241837ab0f2dSArmin Le Grand // BMP_SCALE_BOX derived from the original commit from Toma� Vajngerl (see
241937ab0f2dSArmin Le Grand // bugzilla task for deitails) Thanks!
242037ab0f2dSArmin Le Grand sal_Bool Bitmap::ImplScaleConvolution(
242137ab0f2dSArmin Le Grand     const double& rScaleX,
242237ab0f2dSArmin Le Grand     const double& rScaleY,
242337ab0f2dSArmin Le Grand     const Kernel& aKernel)
242437ab0f2dSArmin Le Grand {
242537ab0f2dSArmin Le Grand     const bool bMirrorHor(rScaleX < 0.0);
242637ab0f2dSArmin Le Grand     const bool bMirrorVer(rScaleY < 0.0);
242737ab0f2dSArmin Le Grand     const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
242837ab0f2dSArmin Le Grand     const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
242937ab0f2dSArmin Le Grand     const sal_uInt32 nWidth(GetSizePixel().Width());
243037ab0f2dSArmin Le Grand     const sal_uInt32 nHeight(GetSizePixel().Height());
243137ab0f2dSArmin Le Grand     const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
243237ab0f2dSArmin Le Grand     const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
243337ab0f2dSArmin Le Grand     const bool bScaleHor(nWidth != nNewWidth);
243437ab0f2dSArmin Le Grand     const bool bScaleVer(nHeight != nNewHeight);
243537ab0f2dSArmin Le Grand     const bool bMirror(bMirrorHor || bMirrorVer);
243637ab0f2dSArmin Le Grand 
243737ab0f2dSArmin Le Grand     if(!bMirror && !bScaleHor && !bScaleVer)
243837ab0f2dSArmin Le Grand     {
243937ab0f2dSArmin Le Grand         return true;
244037ab0f2dSArmin Le Grand     }
244137ab0f2dSArmin Le Grand 
244237ab0f2dSArmin Le Grand     bool bResult(true);
244337ab0f2dSArmin Le Grand     sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
244437ab0f2dSArmin Le Grand     bool bMirrorAfter(false);
244537ab0f2dSArmin Le Grand 
244637ab0f2dSArmin Le Grand     if(bMirror)
244737ab0f2dSArmin Le Grand     {
244837ab0f2dSArmin Le Grand         if(bMirrorHor)
244937ab0f2dSArmin Le Grand         {
245037ab0f2dSArmin Le Grand             nMirrorFlags |= BMP_MIRROR_HORZ;
245137ab0f2dSArmin Le Grand         }
245237ab0f2dSArmin Le Grand 
245337ab0f2dSArmin Le Grand         if(bMirrorVer)
245437ab0f2dSArmin Le Grand         {
245537ab0f2dSArmin Le Grand             nMirrorFlags |= BMP_MIRROR_VERT;
245637ab0f2dSArmin Le Grand         }
245737ab0f2dSArmin Le Grand 
245837ab0f2dSArmin Le Grand         const sal_uInt32 nStartSize(nWidth * nHeight);
245937ab0f2dSArmin Le Grand         const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
246037ab0f2dSArmin Le Grand 
246137ab0f2dSArmin Le Grand         bMirrorAfter = nStartSize > nEndSize;
246237ab0f2dSArmin Le Grand 
246337ab0f2dSArmin Le Grand         if(!bMirrorAfter)
246437ab0f2dSArmin Le Grand         {
246537ab0f2dSArmin Le Grand             bResult = Mirror(nMirrorFlags);
246637ab0f2dSArmin Le Grand         }
246737ab0f2dSArmin Le Grand     }
246837ab0f2dSArmin Le Grand 
246937ab0f2dSArmin Le Grand     Bitmap aResult;
247037ab0f2dSArmin Le Grand 
247137ab0f2dSArmin Le Grand     if(bResult)
247237ab0f2dSArmin Le Grand     {
247337ab0f2dSArmin Le Grand         const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
247437ab0f2dSArmin Le Grand         const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
247537ab0f2dSArmin Le Grand 
247637ab0f2dSArmin Le Grand         if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
247737ab0f2dSArmin Le Grand         {
247837ab0f2dSArmin Le Grand             if(bScaleHor)
247937ab0f2dSArmin Le Grand             {
248037ab0f2dSArmin Le Grand                 bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel);
248137ab0f2dSArmin Le Grand             }
248237ab0f2dSArmin Le Grand 
248337ab0f2dSArmin Le Grand             if(bResult && bScaleVer)
248437ab0f2dSArmin Le Grand             {
248537ab0f2dSArmin Le Grand                 bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel);
248637ab0f2dSArmin Le Grand             }
248737ab0f2dSArmin Le Grand         }
248837ab0f2dSArmin Le Grand         else
248937ab0f2dSArmin Le Grand         {
249037ab0f2dSArmin Le Grand             if(bScaleVer)
249137ab0f2dSArmin Le Grand             {
249237ab0f2dSArmin Le Grand                 bResult = ImplScaleConvolutionVer(*this, aResult, fScaleY, aKernel);
249337ab0f2dSArmin Le Grand             }
249437ab0f2dSArmin Le Grand 
249537ab0f2dSArmin Le Grand             if(bResult && bScaleHor)
249637ab0f2dSArmin Le Grand             {
249737ab0f2dSArmin Le Grand                 bResult = ImplScaleConvolutionHor(*this, aResult, fScaleX, aKernel);
249837ab0f2dSArmin Le Grand             }
249937ab0f2dSArmin Le Grand         }
250037ab0f2dSArmin Le Grand     }
250137ab0f2dSArmin Le Grand 
250237ab0f2dSArmin Le Grand     if(bResult && bMirrorAfter)
250337ab0f2dSArmin Le Grand     {
250437ab0f2dSArmin Le Grand         bResult = aResult.Mirror(nMirrorFlags);
250537ab0f2dSArmin Le Grand     }
250637ab0f2dSArmin Le Grand 
250737ab0f2dSArmin Le Grand     if(bResult)
250837ab0f2dSArmin Le Grand     {
250937ab0f2dSArmin Le Grand         ImplAdaptBitCount(aResult);
251037ab0f2dSArmin Le Grand         *this = aResult;
251137ab0f2dSArmin Le Grand     }
251237ab0f2dSArmin Le Grand 
251337ab0f2dSArmin Le Grand     return bResult;
251437ab0f2dSArmin Le Grand }
251537ab0f2dSArmin Le Grand 
2516cdf0e10cSrcweir // ------------------------------------------------------------------------
2517cdf0e10cSrcweir 
2518cdf0e10cSrcweir sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
2519cdf0e10cSrcweir {
2520cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
2521cdf0e10cSrcweir 
2522cdf0e10cSrcweir 	const Size aSizePix( GetSizePixel() );
2523cdf0e10cSrcweir 
2524cdf0e10cSrcweir 	if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
2525cdf0e10cSrcweir 		bRet = sal_True;
2526cdf0e10cSrcweir 	else if( nDitherFlags & BMP_DITHER_MATRIX )
2527cdf0e10cSrcweir 		bRet = ImplDitherMatrix();
2528cdf0e10cSrcweir 	else if( nDitherFlags & BMP_DITHER_FLOYD )
2529cdf0e10cSrcweir 		bRet = ImplDitherFloyd();
2530cdf0e10cSrcweir 	else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
2531cdf0e10cSrcweir 		bRet = ImplDitherFloyd16();
2532cdf0e10cSrcweir 
2533cdf0e10cSrcweir 	return bRet;
2534cdf0e10cSrcweir }
2535cdf0e10cSrcweir 
2536cdf0e10cSrcweir // ------------------------------------------------------------------------
2537cdf0e10cSrcweir 
2538cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherMatrix()
2539cdf0e10cSrcweir {
2540cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
2541cdf0e10cSrcweir 	Bitmap				aNewBmp( GetSizePixel(), 8 );
2542cdf0e10cSrcweir 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
2543cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
2544cdf0e10cSrcweir 
2545cdf0e10cSrcweir 	if( pReadAcc && pWriteAcc )
2546cdf0e10cSrcweir 	{
2547cdf0e10cSrcweir 		const sal_uLong	nWidth = pReadAcc->Width();
2548cdf0e10cSrcweir 		const sal_uLong	nHeight = pReadAcc->Height();
2549cdf0e10cSrcweir 		BitmapColor	aIndex( (sal_uInt8) 0 );
2550cdf0e10cSrcweir 
2551cdf0e10cSrcweir 		if( pReadAcc->HasPalette() )
2552cdf0e10cSrcweir 		{
2553cdf0e10cSrcweir 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2554cdf0e10cSrcweir 			{
2555cdf0e10cSrcweir 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2556cdf0e10cSrcweir 				{
255787bc88d3SHerbert Dürr 					const BitmapColor	aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
2558cdf0e10cSrcweir 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2559cdf0e10cSrcweir 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2560cdf0e10cSrcweir 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2561cdf0e10cSrcweir 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2562cdf0e10cSrcweir 
2563cdf0e10cSrcweir 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2564cdf0e10cSrcweir 					pWriteAcc->SetPixel( nY, nX, aIndex );
2565cdf0e10cSrcweir 				}
2566cdf0e10cSrcweir 			}
2567cdf0e10cSrcweir 		}
2568cdf0e10cSrcweir 		else
2569cdf0e10cSrcweir 		{
2570cdf0e10cSrcweir 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2571cdf0e10cSrcweir 			{
2572cdf0e10cSrcweir 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2573cdf0e10cSrcweir 				{
2574cdf0e10cSrcweir 					const BitmapColor	aCol( pReadAcc->GetPixel( nY, nX ) );
2575cdf0e10cSrcweir 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2576cdf0e10cSrcweir 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2577cdf0e10cSrcweir 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2578cdf0e10cSrcweir 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2579cdf0e10cSrcweir 
2580cdf0e10cSrcweir 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2581cdf0e10cSrcweir 					pWriteAcc->SetPixel( nY, nX, aIndex );
2582cdf0e10cSrcweir 				}
2583cdf0e10cSrcweir 			}
2584cdf0e10cSrcweir 		}
2585cdf0e10cSrcweir 
2586cdf0e10cSrcweir 		bRet = sal_True;
2587cdf0e10cSrcweir 	}
2588cdf0e10cSrcweir 
2589cdf0e10cSrcweir 	ReleaseAccess( pReadAcc );
2590cdf0e10cSrcweir 	aNewBmp.ReleaseAccess( pWriteAcc );
2591cdf0e10cSrcweir 
2592cdf0e10cSrcweir 	if( bRet )
2593cdf0e10cSrcweir 	{
2594cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
2595cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
2596cdf0e10cSrcweir 
2597cdf0e10cSrcweir 		*this = aNewBmp;
2598cdf0e10cSrcweir 
2599cdf0e10cSrcweir 		maPrefMapMode = aMap;
2600cdf0e10cSrcweir 		maPrefSize = aSize;
2601cdf0e10cSrcweir 	}
2602cdf0e10cSrcweir 
2603cdf0e10cSrcweir 	return bRet;
2604cdf0e10cSrcweir }
2605cdf0e10cSrcweir 
2606cdf0e10cSrcweir // ------------------------------------------------------------------------
2607cdf0e10cSrcweir 
2608cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherFloyd()
2609cdf0e10cSrcweir {
2610cdf0e10cSrcweir 	const Size	aSize( GetSizePixel() );
2611cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
2612cdf0e10cSrcweir 
2613cdf0e10cSrcweir 	if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
2614cdf0e10cSrcweir 	{
2615cdf0e10cSrcweir 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
2616cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), 8 );
2617cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
2618cdf0e10cSrcweir 
2619cdf0e10cSrcweir 		if( pReadAcc && pWriteAcc )
2620cdf0e10cSrcweir 		{
2621cdf0e10cSrcweir 			BitmapColor	aColor;
2622cdf0e10cSrcweir 			long		nWidth = pReadAcc->Width();
2623cdf0e10cSrcweir 			long		nWidth1 = nWidth - 1L;
2624cdf0e10cSrcweir 			long		nHeight = pReadAcc->Height();
2625cdf0e10cSrcweir 			long		nX;
2626cdf0e10cSrcweir 			long		nW = nWidth * 3L;
2627cdf0e10cSrcweir 			long		nW2 = nW - 3L;
2628cdf0e10cSrcweir 			long		nRErr, nGErr, nBErr;
2629cdf0e10cSrcweir 			long		nRC, nGC, nBC;
2630cdf0e10cSrcweir 			long		nTemp;
2631cdf0e10cSrcweir 			long		nZ;
2632cdf0e10cSrcweir 			long*		p1 = new long[ nW ];
2633cdf0e10cSrcweir 			long*		p2 = new long[ nW ];
2634cdf0e10cSrcweir 			long*		p1T = p1;
2635cdf0e10cSrcweir 			long*		p2T = p2;
2636cdf0e10cSrcweir 			long*		pTmp;
2637cdf0e10cSrcweir 			sal_Bool		bPal = pReadAcc->HasPalette();
2638cdf0e10cSrcweir 
2639cdf0e10cSrcweir 			pTmp = p2T;
2640cdf0e10cSrcweir 
2641cdf0e10cSrcweir 			if( bPal )
2642cdf0e10cSrcweir 			{
2643cdf0e10cSrcweir 				for( nZ = 0; nZ < nWidth; nZ++ )
2644cdf0e10cSrcweir 				{
264587bc88d3SHerbert Dürr 					aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) );
2646cdf0e10cSrcweir 
2647cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetBlue() << 12;
2648cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetGreen() << 12;
2649cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetRed() << 12;
2650cdf0e10cSrcweir 				}
2651cdf0e10cSrcweir 			}
2652cdf0e10cSrcweir 			else
2653cdf0e10cSrcweir 			{
2654cdf0e10cSrcweir 				for( nZ = 0; nZ < nWidth; nZ++ )
2655cdf0e10cSrcweir 				{
2656cdf0e10cSrcweir 					aColor = pReadAcc->GetPixel( 0, nZ );
2657cdf0e10cSrcweir 
2658cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetBlue() << 12;
2659cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetGreen() << 12;
2660cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetRed() << 12;
2661cdf0e10cSrcweir 				}
2662cdf0e10cSrcweir 			}
2663cdf0e10cSrcweir 
2664cdf0e10cSrcweir 			for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
2665cdf0e10cSrcweir 			{
2666cdf0e10cSrcweir 				pTmp = p1T;
2667cdf0e10cSrcweir 				p1T = p2T;
2668cdf0e10cSrcweir 				p2T = pTmp;
2669cdf0e10cSrcweir 
2670cdf0e10cSrcweir 				if( nY < nHeight )
2671cdf0e10cSrcweir 				{
2672cdf0e10cSrcweir 					if( bPal )
2673cdf0e10cSrcweir 					{
2674cdf0e10cSrcweir 						for( nZ = 0; nZ < nWidth; nZ++ )
2675cdf0e10cSrcweir 						{
267687bc88d3SHerbert Dürr 							aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) );
2677cdf0e10cSrcweir 
2678cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetBlue() << 12;
2679cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetGreen() << 12;
2680cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetRed() << 12;
2681cdf0e10cSrcweir 						}
2682cdf0e10cSrcweir 					}
2683cdf0e10cSrcweir 					else
2684cdf0e10cSrcweir 					{
2685cdf0e10cSrcweir 						for( nZ = 0; nZ < nWidth; nZ++ )
2686cdf0e10cSrcweir 						{
2687cdf0e10cSrcweir 							aColor = pReadAcc->GetPixel( nY, nZ );
2688cdf0e10cSrcweir 
2689cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetBlue() << 12;
2690cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetGreen() << 12;
2691cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetRed() << 12;
2692cdf0e10cSrcweir 						}
2693cdf0e10cSrcweir 					}
2694cdf0e10cSrcweir 				}
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir 				// erstes Pixel gesondert betrachten
2697cdf0e10cSrcweir 				nX = 0;
2698cdf0e10cSrcweir 				CALC_ERRORS;
2699cdf0e10cSrcweir 				CALC_TABLES7;
2700cdf0e10cSrcweir 				nX -= 5;
2701cdf0e10cSrcweir 				CALC_TABLES5;
270287bc88d3SHerbert Dürr 				pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2703cdf0e10cSrcweir 
2704cdf0e10cSrcweir 				// mittlere Pixel ueber Schleife
2705cdf0e10cSrcweir 				long nXAcc;
2706cdf0e10cSrcweir 				for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
2707cdf0e10cSrcweir 				{
2708cdf0e10cSrcweir 					CALC_ERRORS;
2709cdf0e10cSrcweir 					CALC_TABLES7;
2710cdf0e10cSrcweir 					nX -= 8;
2711cdf0e10cSrcweir 					CALC_TABLES3;
2712cdf0e10cSrcweir 					CALC_TABLES5;
271387bc88d3SHerbert Dürr 					pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2714cdf0e10cSrcweir 				}
2715cdf0e10cSrcweir 
2716cdf0e10cSrcweir 				// letztes Pixel gesondert betrachten
2717cdf0e10cSrcweir 				CALC_ERRORS;
2718cdf0e10cSrcweir 				nX -= 5;
2719cdf0e10cSrcweir 				CALC_TABLES3;
2720cdf0e10cSrcweir 				CALC_TABLES5;
272187bc88d3SHerbert Dürr 				pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2722cdf0e10cSrcweir 			}
2723cdf0e10cSrcweir 
2724cdf0e10cSrcweir 			delete[] p1;
2725cdf0e10cSrcweir 			delete[] p2;
2726cdf0e10cSrcweir 			bRet = sal_True;
2727cdf0e10cSrcweir 		}
2728cdf0e10cSrcweir 
2729cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
2730cdf0e10cSrcweir 		aNewBmp.ReleaseAccess( pWriteAcc );
2731cdf0e10cSrcweir 
2732cdf0e10cSrcweir 		if( bRet )
2733cdf0e10cSrcweir 		{
2734cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
2735cdf0e10cSrcweir 			const Size		aPrefSize( maPrefSize );
2736cdf0e10cSrcweir 
2737cdf0e10cSrcweir 			*this = aNewBmp;
2738cdf0e10cSrcweir 
2739cdf0e10cSrcweir 			maPrefMapMode = aMap;
2740cdf0e10cSrcweir 			maPrefSize = aPrefSize;
2741cdf0e10cSrcweir 		}
2742cdf0e10cSrcweir 	}
2743cdf0e10cSrcweir 
2744cdf0e10cSrcweir 	return bRet;
2745cdf0e10cSrcweir }
2746cdf0e10cSrcweir 
2747cdf0e10cSrcweir // ------------------------------------------------------------------------
2748cdf0e10cSrcweir 
2749cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherFloyd16()
2750cdf0e10cSrcweir {
2751cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
2752cdf0e10cSrcweir 	Bitmap				aNewBmp( GetSizePixel(), 24 );
2753cdf0e10cSrcweir 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
2754cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
2755cdf0e10cSrcweir 
2756cdf0e10cSrcweir 	if( pReadAcc && pWriteAcc )
2757cdf0e10cSrcweir 	{
2758cdf0e10cSrcweir 		const long		nWidth = pWriteAcc->Width();
2759cdf0e10cSrcweir 		const long		nWidth1 = nWidth - 1L;
2760cdf0e10cSrcweir 		const long		nHeight = pWriteAcc->Height();
2761cdf0e10cSrcweir 		BitmapColor 	aColor;
2762cdf0e10cSrcweir 		BitmapColor		aBestCol;
2763cdf0e10cSrcweir 		ImpErrorQuad	aErrQuad;
2764cdf0e10cSrcweir 		ImpErrorQuad*	pErrQuad1 = new ImpErrorQuad[ nWidth ];
2765cdf0e10cSrcweir 		ImpErrorQuad*	pErrQuad2 = new ImpErrorQuad[ nWidth ];
2766cdf0e10cSrcweir 		ImpErrorQuad*	pQLine1 = pErrQuad1;
2767cdf0e10cSrcweir 		ImpErrorQuad*	pQLine2 = 0;
2768cdf0e10cSrcweir 		long			nX, nY;
2769cdf0e10cSrcweir 		long			nYTmp = 0L;
2770cdf0e10cSrcweir 		sal_Bool			bQ1 = sal_True;
2771cdf0e10cSrcweir 
2772cdf0e10cSrcweir 		for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
2773cdf0e10cSrcweir 			for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
2774cdf0e10cSrcweir 				pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2775cdf0e10cSrcweir 
2776cdf0e10cSrcweir 		for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
2777cdf0e10cSrcweir 		{
2778cdf0e10cSrcweir 			// erstes ZeilenPixel
2779cdf0e10cSrcweir 			aBestCol = pQLine1[ 0 ].ImplGetColor();
2780cdf0e10cSrcweir 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2781cdf0e10cSrcweir 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2782cdf0e10cSrcweir 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2783cdf0e10cSrcweir 			pWriteAcc->SetPixel( nY, 0, aBestCol );
2784cdf0e10cSrcweir 
2785cdf0e10cSrcweir 			for( nX = 1L; nX < nWidth1; nX++ )
2786cdf0e10cSrcweir 			{
2787cdf0e10cSrcweir 				aColor = pQLine1[ nX ].ImplGetColor();
2788cdf0e10cSrcweir 				aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
2789cdf0e10cSrcweir 				aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
2790cdf0e10cSrcweir 				aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
2791cdf0e10cSrcweir 				aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
2792cdf0e10cSrcweir 				pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
2793cdf0e10cSrcweir 				pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
2794cdf0e10cSrcweir 				pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
2795cdf0e10cSrcweir 				pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
2796cdf0e10cSrcweir 				pWriteAcc->SetPixel( nY, nX, aBestCol );
2797cdf0e10cSrcweir 			}
2798cdf0e10cSrcweir 
2799cdf0e10cSrcweir 			// letztes ZeilenPixel
2800cdf0e10cSrcweir 			aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
2801cdf0e10cSrcweir 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2802cdf0e10cSrcweir 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2803cdf0e10cSrcweir 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2804cdf0e10cSrcweir 			pWriteAcc->SetPixel( nY, nX, aBestCol );
2805cdf0e10cSrcweir 
2806cdf0e10cSrcweir 			// Zeilenpuffer neu fuellen/kopieren
2807cdf0e10cSrcweir 			pQLine1 = pQLine2;
2808cdf0e10cSrcweir 			pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
2809cdf0e10cSrcweir 
2810cdf0e10cSrcweir 			if( nYTmp < nHeight )
2811cdf0e10cSrcweir 				for( nX = 0L; nX < nWidth; nX++ )
2812cdf0e10cSrcweir 					pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2813cdf0e10cSrcweir 		}
2814cdf0e10cSrcweir 
2815cdf0e10cSrcweir 		// Zeilenpuffer zerstoeren
2816cdf0e10cSrcweir 		delete[] pErrQuad1;
2817cdf0e10cSrcweir 		delete[] pErrQuad2;
2818cdf0e10cSrcweir 		bRet = sal_True;
2819cdf0e10cSrcweir 	}
2820cdf0e10cSrcweir 
2821cdf0e10cSrcweir 	ReleaseAccess( pReadAcc );
2822cdf0e10cSrcweir 	aNewBmp.ReleaseAccess( pWriteAcc );
2823cdf0e10cSrcweir 
2824cdf0e10cSrcweir 	if( bRet )
2825cdf0e10cSrcweir 	{
2826cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
2827cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
2828cdf0e10cSrcweir 
2829cdf0e10cSrcweir 		*this = aNewBmp;
2830cdf0e10cSrcweir 
2831cdf0e10cSrcweir 		maPrefMapMode = aMap;
2832cdf0e10cSrcweir 		maPrefSize = aSize;
2833cdf0e10cSrcweir 	}
2834cdf0e10cSrcweir 
2835cdf0e10cSrcweir 	return bRet;
2836cdf0e10cSrcweir }
2837cdf0e10cSrcweir 
2838cdf0e10cSrcweir // ------------------------------------------------------------------------
2839cdf0e10cSrcweir 
2840cdf0e10cSrcweir sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
2841cdf0e10cSrcweir {
2842cdf0e10cSrcweir 	sal_Bool bRet;
2843cdf0e10cSrcweir 
2844cdf0e10cSrcweir 	if( GetColorCount() <= (sal_uLong) nColorCount )
2845cdf0e10cSrcweir 		bRet = sal_True;
2846cdf0e10cSrcweir 	else if( nColorCount )
2847cdf0e10cSrcweir 	{
2848cdf0e10cSrcweir 		if( BMP_REDUCE_SIMPLE == eReduce )
2849cdf0e10cSrcweir 			bRet = ImplReduceSimple( nColorCount );
2850cdf0e10cSrcweir 		else if( BMP_REDUCE_POPULAR == eReduce )
2851cdf0e10cSrcweir 			bRet = ImplReducePopular( nColorCount );
2852cdf0e10cSrcweir 		else
2853cdf0e10cSrcweir 			bRet = ImplReduceMedian( nColorCount );
2854cdf0e10cSrcweir 	}
2855cdf0e10cSrcweir 	else
2856cdf0e10cSrcweir 		bRet = sal_False;
2857cdf0e10cSrcweir 
2858cdf0e10cSrcweir 	return bRet;
2859cdf0e10cSrcweir }
2860cdf0e10cSrcweir 
2861cdf0e10cSrcweir // ------------------------------------------------------------------------
2862cdf0e10cSrcweir 
2863cdf0e10cSrcweir sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
2864cdf0e10cSrcweir {
2865cdf0e10cSrcweir 	Bitmap				aNewBmp;
2866cdf0e10cSrcweir 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
2867cdf0e10cSrcweir 	const sal_uInt16		nColCount = Min( nColorCount, (sal_uInt16) 256 );
2868cdf0e10cSrcweir 	sal_uInt16				nBitCount;
2869cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
2870cdf0e10cSrcweir 
2871cdf0e10cSrcweir 	if( nColCount <= 2 )
2872cdf0e10cSrcweir 		nBitCount = 1;
2873cdf0e10cSrcweir 	else if( nColCount <= 16 )
2874cdf0e10cSrcweir 		nBitCount = 4;
2875cdf0e10cSrcweir 	else
2876cdf0e10cSrcweir 		nBitCount = 8;
2877cdf0e10cSrcweir 
2878cdf0e10cSrcweir 	if( pRAcc )
2879cdf0e10cSrcweir 	{
2880cdf0e10cSrcweir 		Octree					aOct( *pRAcc, nColCount );
2881cdf0e10cSrcweir 		const BitmapPalette&	rPal = aOct.GetPalette();
2882cdf0e10cSrcweir 		BitmapWriteAccess*		pWAcc;
2883cdf0e10cSrcweir 
2884cdf0e10cSrcweir 		aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
2885cdf0e10cSrcweir 		pWAcc = aNewBmp.AcquireWriteAccess();
2886cdf0e10cSrcweir 
2887cdf0e10cSrcweir 		if( pWAcc )
2888cdf0e10cSrcweir 		{
2889cdf0e10cSrcweir 			const long nWidth = pRAcc->Width();
2890cdf0e10cSrcweir 			const long nHeight = pRAcc->Height();
2891cdf0e10cSrcweir 
2892cdf0e10cSrcweir 			if( pRAcc->HasPalette() )
2893cdf0e10cSrcweir 			{
2894cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
2895cdf0e10cSrcweir 					for( long nX =0L; nX < nWidth; nX++ )
289687bc88d3SHerbert Dürr 						pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) );
2897cdf0e10cSrcweir 			}
2898cdf0e10cSrcweir 			else
2899cdf0e10cSrcweir 			{
2900cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
2901cdf0e10cSrcweir 					for( long nX =0L; nX < nWidth; nX++ )
290287bc88d3SHerbert Dürr 						pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) );
2903cdf0e10cSrcweir 			}
2904cdf0e10cSrcweir 
2905cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWAcc );
2906cdf0e10cSrcweir 			bRet = sal_True;
2907cdf0e10cSrcweir 		}
2908cdf0e10cSrcweir 
2909cdf0e10cSrcweir 		ReleaseAccess( pRAcc );
2910cdf0e10cSrcweir 	}
2911cdf0e10cSrcweir 
2912cdf0e10cSrcweir 	if( bRet )
2913cdf0e10cSrcweir 	{
2914cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
2915cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
2916cdf0e10cSrcweir 
2917cdf0e10cSrcweir 		*this = aNewBmp;
2918cdf0e10cSrcweir 		maPrefMapMode = aMap;
2919cdf0e10cSrcweir 		maPrefSize = aSize;
2920cdf0e10cSrcweir 	}
2921cdf0e10cSrcweir 
2922cdf0e10cSrcweir 	return bRet;
2923cdf0e10cSrcweir }
2924cdf0e10cSrcweir 
2925cdf0e10cSrcweir // ------------------------------------------------------------------------
2926cdf0e10cSrcweir 
2927cdf0e10cSrcweir struct PopularColorCount
2928cdf0e10cSrcweir {
2929cdf0e10cSrcweir 	sal_uInt32	mnIndex;
2930cdf0e10cSrcweir 	sal_uInt32	mnCount;
2931cdf0e10cSrcweir };
2932cdf0e10cSrcweir 
2933cdf0e10cSrcweir // ------------------------------------------------------------------------
2934cdf0e10cSrcweir 
2935cdf0e10cSrcweir extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
2936cdf0e10cSrcweir {
2937cdf0e10cSrcweir 	int nRet;
2938cdf0e10cSrcweir 
2939cdf0e10cSrcweir 	if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
2940cdf0e10cSrcweir 		nRet = 1;
2941cdf0e10cSrcweir 	else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
2942cdf0e10cSrcweir 		nRet = 0;
2943cdf0e10cSrcweir 	else
2944cdf0e10cSrcweir 		nRet = -1;
2945cdf0e10cSrcweir 
2946cdf0e10cSrcweir 	return nRet;
2947cdf0e10cSrcweir }
2948cdf0e10cSrcweir 
2949cdf0e10cSrcweir // ------------------------------------------------------------------------
2950cdf0e10cSrcweir 
2951cdf0e10cSrcweir sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
2952cdf0e10cSrcweir {
2953cdf0e10cSrcweir 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
2954cdf0e10cSrcweir 	sal_uInt16				nBitCount;
2955cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
2956cdf0e10cSrcweir 
2957cdf0e10cSrcweir 	if( nColCount > 256 )
2958cdf0e10cSrcweir 		nColCount = 256;
2959cdf0e10cSrcweir 
2960cdf0e10cSrcweir 	if( nColCount < 17 )
2961cdf0e10cSrcweir 		nBitCount = 4;
2962cdf0e10cSrcweir 	else
2963cdf0e10cSrcweir 		nBitCount = 8;
2964cdf0e10cSrcweir 
2965cdf0e10cSrcweir 	if( pRAcc )
2966cdf0e10cSrcweir 	{
2967cdf0e10cSrcweir 		const sal_uInt32	nValidBits = 4;
2968cdf0e10cSrcweir 		const sal_uInt32	nRightShiftBits = 8 - nValidBits;
2969cdf0e10cSrcweir 		const sal_uInt32	nLeftShiftBits1 = nValidBits;
2970cdf0e10cSrcweir 		const sal_uInt32	nLeftShiftBits2 = nValidBits << 1;
2971cdf0e10cSrcweir 		const sal_uInt32	nColorsPerComponent = 1 << nValidBits;
2972cdf0e10cSrcweir 		const sal_uInt32	nColorOffset = 256 / nColorsPerComponent;
2973cdf0e10cSrcweir 		const sal_uInt32	nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
2974cdf0e10cSrcweir 		const long			nWidth = pRAcc->Width();
2975cdf0e10cSrcweir 		const long			nHeight = pRAcc->Height();
2976cdf0e10cSrcweir 		PopularColorCount*	pCountTable = new PopularColorCount[ nTotalColors ];
2977cdf0e10cSrcweir 		long				nX, nY, nR, nG, nB, nIndex;
2978cdf0e10cSrcweir 
2979cdf0e10cSrcweir 		rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
2980cdf0e10cSrcweir 
2981cdf0e10cSrcweir 		for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
2982cdf0e10cSrcweir         {
2983cdf0e10cSrcweir 			for( nG = 0; nG < 256; nG += nColorOffset )
2984cdf0e10cSrcweir             {
2985cdf0e10cSrcweir 				for( nB = 0; nB < 256; nB += nColorOffset )
2986cdf0e10cSrcweir                 {
2987cdf0e10cSrcweir 					pCountTable[ nIndex ].mnIndex = nIndex;
2988cdf0e10cSrcweir                     nIndex++;
2989cdf0e10cSrcweir                 }
2990cdf0e10cSrcweir             }
2991cdf0e10cSrcweir         }
2992cdf0e10cSrcweir 
2993cdf0e10cSrcweir 		if( pRAcc->HasPalette() )
2994cdf0e10cSrcweir 		{
2995cdf0e10cSrcweir 			for( nY = 0L; nY < nHeight; nY++ )
2996cdf0e10cSrcweir 			{
2997cdf0e10cSrcweir 				for( nX = 0L; nX < nWidth; nX++ )
2998cdf0e10cSrcweir 				{
299987bc88d3SHerbert Dürr 					const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3000cdf0e10cSrcweir 					pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3001cdf0e10cSrcweir 								 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3002cdf0e10cSrcweir 								 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3003cdf0e10cSrcweir 				}
3004cdf0e10cSrcweir 			}
3005cdf0e10cSrcweir 		}
3006cdf0e10cSrcweir 		else
3007cdf0e10cSrcweir 		{
3008cdf0e10cSrcweir 			for( nY = 0L; nY < nHeight; nY++ )
3009cdf0e10cSrcweir 			{
3010cdf0e10cSrcweir 				for( nX = 0L; nX < nWidth; nX++ )
3011cdf0e10cSrcweir 				{
3012cdf0e10cSrcweir 					const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3013cdf0e10cSrcweir 					pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3014cdf0e10cSrcweir 								 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3015cdf0e10cSrcweir 								 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
3016cdf0e10cSrcweir 				}
3017cdf0e10cSrcweir 			}
3018cdf0e10cSrcweir 		}
3019cdf0e10cSrcweir 
3020cdf0e10cSrcweir 		BitmapPalette aNewPal( nColCount );
3021cdf0e10cSrcweir 
3022cdf0e10cSrcweir 		qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
3023cdf0e10cSrcweir 
3024cdf0e10cSrcweir 		for( sal_uInt16 n = 0; n < nColCount; n++ )
3025cdf0e10cSrcweir 		{
3026cdf0e10cSrcweir 			const PopularColorCount& rPop = pCountTable[ n ];
3027cdf0e10cSrcweir 			aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
3028cdf0e10cSrcweir 										(sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
3029cdf0e10cSrcweir 										(sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
3030cdf0e10cSrcweir 		}
3031cdf0e10cSrcweir 
3032cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
3033cdf0e10cSrcweir 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
3034cdf0e10cSrcweir 
3035cdf0e10cSrcweir 		if( pWAcc )
3036cdf0e10cSrcweir 		{
3037cdf0e10cSrcweir 			BitmapColor	aDstCol( (sal_uInt8) 0 );
3038cdf0e10cSrcweir 			sal_uInt8*		pIndexMap = new sal_uInt8[ nTotalColors ];
3039cdf0e10cSrcweir 
3040cdf0e10cSrcweir 			for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
3041cdf0e10cSrcweir 				for( nG = 0; nG < 256; nG += nColorOffset )
3042cdf0e10cSrcweir 					for( nB = 0; nB < 256; nB += nColorOffset )
3043cdf0e10cSrcweir 						pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
3044cdf0e10cSrcweir 
3045cdf0e10cSrcweir 			if( pRAcc->HasPalette() )
3046cdf0e10cSrcweir 			{
3047cdf0e10cSrcweir 				for( nY = 0L; nY < nHeight; nY++ )
3048cdf0e10cSrcweir 				{
3049cdf0e10cSrcweir 					for( nX = 0L; nX < nWidth; nX++ )
3050cdf0e10cSrcweir 					{
305187bc88d3SHerbert Dürr 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3052cdf0e10cSrcweir 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3053cdf0e10cSrcweir 													 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3054cdf0e10cSrcweir 													 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
3055cdf0e10cSrcweir 						pWAcc->SetPixel( nY, nX, aDstCol );
3056cdf0e10cSrcweir 					}
3057cdf0e10cSrcweir 				}
3058cdf0e10cSrcweir 			}
3059cdf0e10cSrcweir 			else
3060cdf0e10cSrcweir 			{
3061cdf0e10cSrcweir 				for( nY = 0L; nY < nHeight; nY++ )
3062cdf0e10cSrcweir 				{
3063cdf0e10cSrcweir 					for( nX = 0L; nX < nWidth; nX++ )
3064cdf0e10cSrcweir 					{
3065cdf0e10cSrcweir 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3066cdf0e10cSrcweir 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
3067cdf0e10cSrcweir 													 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
3068cdf0e10cSrcweir 													 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
3069cdf0e10cSrcweir 						pWAcc->SetPixel( nY, nX, aDstCol );
3070cdf0e10cSrcweir 					}
3071cdf0e10cSrcweir 				}
3072cdf0e10cSrcweir 			}
3073cdf0e10cSrcweir 
3074cdf0e10cSrcweir 			delete[] pIndexMap;
3075cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWAcc );
3076cdf0e10cSrcweir 			bRet = sal_True;
3077cdf0e10cSrcweir 		}
3078cdf0e10cSrcweir 
3079cdf0e10cSrcweir 		delete[] pCountTable;
3080cdf0e10cSrcweir 		ReleaseAccess( pRAcc );
3081cdf0e10cSrcweir 
3082cdf0e10cSrcweir 		if( bRet )
3083cdf0e10cSrcweir 		{
3084cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
3085cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
3086cdf0e10cSrcweir 
3087cdf0e10cSrcweir 			*this = aNewBmp;
3088cdf0e10cSrcweir 			maPrefMapMode = aMap;
3089cdf0e10cSrcweir 			maPrefSize = aSize;
3090cdf0e10cSrcweir 		}
3091cdf0e10cSrcweir 	}
3092cdf0e10cSrcweir 
3093cdf0e10cSrcweir 	return bRet;
3094cdf0e10cSrcweir }
3095cdf0e10cSrcweir 
3096cdf0e10cSrcweir // ------------------------------------------------------------------------
3097cdf0e10cSrcweir 
3098cdf0e10cSrcweir sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
3099cdf0e10cSrcweir {
3100cdf0e10cSrcweir 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
3101cdf0e10cSrcweir 	sal_uInt16				nBitCount;
3102cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
3103cdf0e10cSrcweir 
3104cdf0e10cSrcweir 	if( nColCount < 17 )
3105cdf0e10cSrcweir 		nBitCount = 4;
3106cdf0e10cSrcweir 	else if( nColCount < 257 )
3107cdf0e10cSrcweir 		nBitCount = 8;
3108cdf0e10cSrcweir 	else
3109cdf0e10cSrcweir 	{
3110cdf0e10cSrcweir 		DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
3111cdf0e10cSrcweir 		nBitCount = 8;
3112cdf0e10cSrcweir 		nColCount = 256;
3113cdf0e10cSrcweir 	}
3114cdf0e10cSrcweir 
3115cdf0e10cSrcweir 	if( pRAcc )
3116cdf0e10cSrcweir 	{
3117cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), nBitCount );
3118cdf0e10cSrcweir 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
3119cdf0e10cSrcweir 
3120cdf0e10cSrcweir 		if( pWAcc )
3121cdf0e10cSrcweir 		{
3122cdf0e10cSrcweir 			const sal_uLong	nSize = 32768UL * sizeof( sal_uLong );
3123cdf0e10cSrcweir 			sal_uLong*		pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
3124cdf0e10cSrcweir 			const long	nWidth = pWAcc->Width();
3125cdf0e10cSrcweir 			const long	nHeight = pWAcc->Height();
3126cdf0e10cSrcweir 			long		nIndex = 0L;
3127cdf0e10cSrcweir 
3128cdf0e10cSrcweir 			memset( (HPBYTE) pColBuf, 0, nSize );
3129cdf0e10cSrcweir 
3130cdf0e10cSrcweir 			// create Buffer
3131cdf0e10cSrcweir 			if( pRAcc->HasPalette() )
3132cdf0e10cSrcweir 			{
3133cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
3134cdf0e10cSrcweir 				{
3135cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
3136cdf0e10cSrcweir 					{
313787bc88d3SHerbert Dürr 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3138cdf0e10cSrcweir 						pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
3139cdf0e10cSrcweir 					}
3140cdf0e10cSrcweir 				}
3141cdf0e10cSrcweir 			}
3142cdf0e10cSrcweir 			else
3143cdf0e10cSrcweir 			{
3144cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
3145cdf0e10cSrcweir 				{
3146cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
3147cdf0e10cSrcweir 					{
3148cdf0e10cSrcweir 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3149cdf0e10cSrcweir 						pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
3150cdf0e10cSrcweir 					}
3151cdf0e10cSrcweir 				}
3152cdf0e10cSrcweir 			}
3153cdf0e10cSrcweir 
3154cdf0e10cSrcweir 			// create palette via median cut
3155cdf0e10cSrcweir 			BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
3156cdf0e10cSrcweir 			ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
3157cdf0e10cSrcweir 						   nColCount, nWidth * nHeight, nIndex );
3158cdf0e10cSrcweir 
3159cdf0e10cSrcweir 			// do mapping of colors to palette
3160cdf0e10cSrcweir 			InverseColorMap aMap( aPal );
3161cdf0e10cSrcweir 			pWAcc->SetPalette( aPal );
3162cdf0e10cSrcweir 			for( long nY = 0L; nY < nHeight; nY++ )
3163cdf0e10cSrcweir 				for( long nX = 0L; nX < nWidth; nX++ )
316487bc88d3SHerbert Dürr 					pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) );
3165cdf0e10cSrcweir 
3166cdf0e10cSrcweir 			rtl_freeMemory( pColBuf );
3167cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWAcc );
3168cdf0e10cSrcweir 			bRet = sal_True;
3169cdf0e10cSrcweir 		}
3170cdf0e10cSrcweir 
3171cdf0e10cSrcweir 		ReleaseAccess( pRAcc );
3172cdf0e10cSrcweir 
3173cdf0e10cSrcweir 		if( bRet )
3174cdf0e10cSrcweir 		{
3175cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
3176cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
3177cdf0e10cSrcweir 
3178cdf0e10cSrcweir 			*this = aNewBmp;
3179cdf0e10cSrcweir 			maPrefMapMode = aMap;
3180cdf0e10cSrcweir 			maPrefSize = aSize;
3181cdf0e10cSrcweir 		}
3182cdf0e10cSrcweir 	}
3183cdf0e10cSrcweir 
3184cdf0e10cSrcweir 	return bRet;
3185cdf0e10cSrcweir }
3186cdf0e10cSrcweir 
3187cdf0e10cSrcweir // ------------------------------------------------------------------------
3188cdf0e10cSrcweir 
3189cdf0e10cSrcweir void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
3190cdf0e10cSrcweir 							long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
3191cdf0e10cSrcweir 							long nColors, long nPixels, long& rIndex )
3192cdf0e10cSrcweir {
3193cdf0e10cSrcweir 	if( !nPixels )
3194cdf0e10cSrcweir 		return;
3195cdf0e10cSrcweir 
3196cdf0e10cSrcweir 	BitmapColor	aCol;
3197cdf0e10cSrcweir 	const long	nRLen = nR2 - nR1;
3198cdf0e10cSrcweir 	const long	nGLen = nG2 - nG1;
3199cdf0e10cSrcweir 	const long	nBLen = nB2 - nB1;
3200cdf0e10cSrcweir 	long 		nR, nG, nB;
3201cdf0e10cSrcweir 	sal_uLong*		pBuf = pColBuf;
3202cdf0e10cSrcweir 
3203cdf0e10cSrcweir 	if( !nRLen && !nGLen && !nBLen )
3204cdf0e10cSrcweir 	{
3205cdf0e10cSrcweir 		if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
3206cdf0e10cSrcweir 		{
3207cdf0e10cSrcweir 			aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
3208cdf0e10cSrcweir 			aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
3209cdf0e10cSrcweir 			aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
3210cdf0e10cSrcweir 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
3211cdf0e10cSrcweir 		}
3212cdf0e10cSrcweir 	}
3213cdf0e10cSrcweir 	else
3214cdf0e10cSrcweir 	{
3215cdf0e10cSrcweir 		if( 1 == nColors || 1 == nPixels )
3216cdf0e10cSrcweir 		{
3217cdf0e10cSrcweir 			long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
3218cdf0e10cSrcweir 
3219cdf0e10cSrcweir 			for( nR = nR1; nR <= nR2; nR++ )
3220cdf0e10cSrcweir 			{
3221cdf0e10cSrcweir 				for( nG = nG1; nG <= nG2; nG++ )
3222cdf0e10cSrcweir 				{
3223cdf0e10cSrcweir 					for( nB = nB1; nB <= nB2; nB++ )
3224cdf0e10cSrcweir 					{
3225cdf0e10cSrcweir 						nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
3226cdf0e10cSrcweir 
3227cdf0e10cSrcweir 						if( nPixSum )
3228cdf0e10cSrcweir 						{
3229cdf0e10cSrcweir 							nRSum += nR * nPixSum;
3230cdf0e10cSrcweir 							nGSum += nG * nPixSum;
3231cdf0e10cSrcweir 							nBSum += nB * nPixSum;
3232cdf0e10cSrcweir 						}
3233cdf0e10cSrcweir 					}
3234cdf0e10cSrcweir 				}
3235cdf0e10cSrcweir 			}
3236cdf0e10cSrcweir 
3237cdf0e10cSrcweir 			aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
3238cdf0e10cSrcweir 			aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
3239cdf0e10cSrcweir 			aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
3240cdf0e10cSrcweir 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
3241cdf0e10cSrcweir 		}
3242cdf0e10cSrcweir 		else
3243cdf0e10cSrcweir 		{
3244cdf0e10cSrcweir 			const long	nTest = ( nPixels >> 1 );
3245cdf0e10cSrcweir 			long		nPixOld = 0;
3246cdf0e10cSrcweir 			long		nPixNew = 0;
3247cdf0e10cSrcweir 
3248cdf0e10cSrcweir 			if( nBLen > nGLen && nBLen > nRLen )
3249cdf0e10cSrcweir 			{
3250cdf0e10cSrcweir 				nB = nB1 - 1;
3251cdf0e10cSrcweir 
3252cdf0e10cSrcweir 				while( nPixNew < nTest )
3253cdf0e10cSrcweir 				{
3254cdf0e10cSrcweir 					nB++, nPixOld = nPixNew;
3255cdf0e10cSrcweir 					for( nR = nR1; nR <= nR2; nR++ )
3256cdf0e10cSrcweir 						for( nG = nG1; nG <= nG2; nG++ )
3257cdf0e10cSrcweir 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3258cdf0e10cSrcweir 				}
3259cdf0e10cSrcweir 
3260cdf0e10cSrcweir 				if( nB < nB2 )
3261cdf0e10cSrcweir 				{
3262cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
3263cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3264cdf0e10cSrcweir 				}
3265cdf0e10cSrcweir 				else
3266cdf0e10cSrcweir 				{
3267cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
3268cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3269cdf0e10cSrcweir 				}
3270cdf0e10cSrcweir 			}
3271cdf0e10cSrcweir 			else if( nGLen > nRLen )
3272cdf0e10cSrcweir 			{
3273cdf0e10cSrcweir 				nG = nG1 - 1;
3274cdf0e10cSrcweir 
3275cdf0e10cSrcweir 				while( nPixNew < nTest )
3276cdf0e10cSrcweir 				{
3277cdf0e10cSrcweir 					nG++, nPixOld = nPixNew;
3278cdf0e10cSrcweir 					for( nR = nR1; nR <= nR2; nR++ )
3279cdf0e10cSrcweir 						for( nB = nB1; nB <= nB2; nB++ )
3280cdf0e10cSrcweir 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3281cdf0e10cSrcweir 				}
3282cdf0e10cSrcweir 
3283cdf0e10cSrcweir 				if( nG < nG2 )
3284cdf0e10cSrcweir 				{
3285cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3286cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3287cdf0e10cSrcweir 				}
3288cdf0e10cSrcweir 				else
3289cdf0e10cSrcweir 				{
3290cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3291cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3292cdf0e10cSrcweir 				}
3293cdf0e10cSrcweir 			}
3294cdf0e10cSrcweir 			else
3295cdf0e10cSrcweir 			{
3296cdf0e10cSrcweir 				nR = nR1 - 1;
3297cdf0e10cSrcweir 
3298cdf0e10cSrcweir 				while( nPixNew < nTest )
3299cdf0e10cSrcweir 				{
3300cdf0e10cSrcweir 					nR++, nPixOld = nPixNew;
3301cdf0e10cSrcweir 					for( nG = nG1; nG <= nG2; nG++ )
3302cdf0e10cSrcweir 						for( nB = nB1; nB <= nB2; nB++ )
3303cdf0e10cSrcweir 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3304cdf0e10cSrcweir 				}
3305cdf0e10cSrcweir 
3306cdf0e10cSrcweir 				if( nR < nR2 )
3307cdf0e10cSrcweir 				{
3308cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3309cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3310cdf0e10cSrcweir 				}
3311cdf0e10cSrcweir 				else
3312cdf0e10cSrcweir 				{
3313cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3314cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3315cdf0e10cSrcweir 				}
3316cdf0e10cSrcweir 			}
3317cdf0e10cSrcweir 		}
3318cdf0e10cSrcweir 	}
3319cdf0e10cSrcweir }
3320cdf0e10cSrcweir 
3321cdf0e10cSrcweir // ------------------------------------------------------------------------
3322cdf0e10cSrcweir 
3323cdf0e10cSrcweir sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
3324cdf0e10cSrcweir {
3325cdf0e10cSrcweir 	return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
3326cdf0e10cSrcweir }
3327cdf0e10cSrcweir 
3328cdf0e10cSrcweir // ------------------------------------------------------------------------
3329cdf0e10cSrcweir 
3330cdf0e10cSrcweir sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
3331cdf0e10cSrcweir {
3332cdf0e10cSrcweir 	return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
3333cdf0e10cSrcweir }
3334cdf0e10cSrcweir 
3335cdf0e10cSrcweir // ------------------------------------------------------------------------
3336cdf0e10cSrcweir 
3337cdf0e10cSrcweir sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
3338cdf0e10cSrcweir 					 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
3339cdf0e10cSrcweir 					 double fGamma, sal_Bool bInvert )
3340cdf0e10cSrcweir {
3341cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
3342cdf0e10cSrcweir 
3343cdf0e10cSrcweir 	// nothing to do => return quickly
3344cdf0e10cSrcweir 	if( !nLuminancePercent && !nContrastPercent &&
3345cdf0e10cSrcweir 		!nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
3346cdf0e10cSrcweir 		( fGamma == 1.0 ) && !bInvert )
3347cdf0e10cSrcweir 	{
3348cdf0e10cSrcweir 		bRet = sal_True;
3349cdf0e10cSrcweir 	}
3350cdf0e10cSrcweir 	else
3351cdf0e10cSrcweir 	{
3352cdf0e10cSrcweir 		BitmapWriteAccess* pAcc = AcquireWriteAccess();
3353cdf0e10cSrcweir 
3354cdf0e10cSrcweir 		if( pAcc )
3355cdf0e10cSrcweir 		{
3356cdf0e10cSrcweir 			BitmapColor		aCol;
3357cdf0e10cSrcweir 			const long		nW = pAcc->Width();
3358cdf0e10cSrcweir 			const long		nH = pAcc->Height();
3359cdf0e10cSrcweir 			sal_uInt8*			cMapR = new sal_uInt8[ 256 ];
3360cdf0e10cSrcweir 			sal_uInt8*			cMapG = new sal_uInt8[ 256 ];
3361cdf0e10cSrcweir 			sal_uInt8*			cMapB = new sal_uInt8[ 256 ];
3362cdf0e10cSrcweir 			long			nX, nY;
3363cdf0e10cSrcweir 			double			fM, fROff, fGOff, fBOff, fOff;
3364cdf0e10cSrcweir 
3365cdf0e10cSrcweir 			// calculate slope
3366cdf0e10cSrcweir 			if( nContrastPercent >= 0 )
3367cdf0e10cSrcweir 				fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
3368cdf0e10cSrcweir 			else
3369cdf0e10cSrcweir 				fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
3370cdf0e10cSrcweir 
3371cdf0e10cSrcweir 			// total offset = luminance offset + contrast offset
3372cdf0e10cSrcweir 			fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
3373cdf0e10cSrcweir 
3374cdf0e10cSrcweir 			// channel offset = channel offset  + total offset
3375cdf0e10cSrcweir 			fROff = nChannelRPercent * 2.55 + fOff;
3376cdf0e10cSrcweir 			fGOff = nChannelGPercent * 2.55 + fOff;
3377cdf0e10cSrcweir 			fBOff = nChannelBPercent * 2.55 + fOff;
3378cdf0e10cSrcweir 
3379cdf0e10cSrcweir 			// calculate gamma value
3380cdf0e10cSrcweir 			fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
3381cdf0e10cSrcweir 			const sal_Bool bGamma = ( fGamma != 1.0 );
3382cdf0e10cSrcweir 
3383cdf0e10cSrcweir 			// create mapping table
3384cdf0e10cSrcweir 			for( nX = 0L; nX < 256L; nX++ )
3385cdf0e10cSrcweir 			{
3386cdf0e10cSrcweir 				cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
3387cdf0e10cSrcweir 				cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
3388cdf0e10cSrcweir 				cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
3389cdf0e10cSrcweir 
3390cdf0e10cSrcweir 				if( bGamma )
3391cdf0e10cSrcweir 				{
3392cdf0e10cSrcweir 					cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
3393cdf0e10cSrcweir 					cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
3394cdf0e10cSrcweir 					cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
3395cdf0e10cSrcweir 				}
3396cdf0e10cSrcweir 
3397cdf0e10cSrcweir 				if( bInvert )
3398cdf0e10cSrcweir 				{
3399cdf0e10cSrcweir 					cMapR[ nX ] = ~cMapR[ nX ];
3400cdf0e10cSrcweir 					cMapG[ nX ] = ~cMapG[ nX ];
3401cdf0e10cSrcweir 					cMapB[ nX ] = ~cMapB[ nX ];
3402cdf0e10cSrcweir 				}
3403cdf0e10cSrcweir 			}
3404cdf0e10cSrcweir 
3405cdf0e10cSrcweir 			// do modifying
3406cdf0e10cSrcweir 			if( pAcc->HasPalette() )
3407cdf0e10cSrcweir 			{
3408cdf0e10cSrcweir 				BitmapColor aNewCol;
3409cdf0e10cSrcweir 
3410cdf0e10cSrcweir 				for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
3411cdf0e10cSrcweir 				{
3412cdf0e10cSrcweir 					const BitmapColor& rCol = pAcc->GetPaletteColor( i );
3413cdf0e10cSrcweir 					aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
3414cdf0e10cSrcweir 					aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
3415cdf0e10cSrcweir 					aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
3416cdf0e10cSrcweir 					pAcc->SetPaletteColor( i, aNewCol );
3417cdf0e10cSrcweir 				}
3418cdf0e10cSrcweir 			}
3419cdf0e10cSrcweir 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
3420cdf0e10cSrcweir 			{
3421cdf0e10cSrcweir 				for( nY = 0L; nY < nH; nY++ )
3422cdf0e10cSrcweir 				{
3423cdf0e10cSrcweir 					Scanline pScan = pAcc->GetScanline( nY );
3424cdf0e10cSrcweir 
3425cdf0e10cSrcweir 					for( nX = 0L; nX < nW; nX++ )
3426cdf0e10cSrcweir 					{
3427cdf0e10cSrcweir 						*pScan = cMapB[ *pScan ]; pScan++;
3428cdf0e10cSrcweir 						*pScan = cMapG[ *pScan ]; pScan++;
3429cdf0e10cSrcweir 						*pScan = cMapR[ *pScan ]; pScan++;
3430cdf0e10cSrcweir 					}
3431cdf0e10cSrcweir 				}
3432cdf0e10cSrcweir 			}
3433cdf0e10cSrcweir 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
3434cdf0e10cSrcweir 			{
3435cdf0e10cSrcweir 				for( nY = 0L; nY < nH; nY++ )
3436cdf0e10cSrcweir 				{
3437cdf0e10cSrcweir 					Scanline pScan = pAcc->GetScanline( nY );
3438cdf0e10cSrcweir 
3439cdf0e10cSrcweir 					for( nX = 0L; nX < nW; nX++ )
3440cdf0e10cSrcweir 					{
3441cdf0e10cSrcweir 						*pScan = cMapR[ *pScan ]; pScan++;
3442cdf0e10cSrcweir 						*pScan = cMapG[ *pScan ]; pScan++;
3443cdf0e10cSrcweir 						*pScan = cMapB[ *pScan ]; pScan++;
3444cdf0e10cSrcweir 					}
3445cdf0e10cSrcweir 				}
3446cdf0e10cSrcweir 			}
3447cdf0e10cSrcweir 			else
3448cdf0e10cSrcweir 			{
3449cdf0e10cSrcweir 				for( nY = 0L; nY < nH; nY++ )
3450cdf0e10cSrcweir 				{
3451cdf0e10cSrcweir 					for( nX = 0L; nX < nW; nX++ )
3452cdf0e10cSrcweir 					{
3453cdf0e10cSrcweir 						aCol = pAcc->GetPixel( nY, nX );
3454cdf0e10cSrcweir 						aCol.SetRed( cMapR[ aCol.GetRed() ] );
3455cdf0e10cSrcweir 						aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
3456cdf0e10cSrcweir 						aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
3457cdf0e10cSrcweir 						pAcc->SetPixel( nY, nX, aCol );
3458cdf0e10cSrcweir 					}
3459cdf0e10cSrcweir 				}
3460cdf0e10cSrcweir 			}
3461cdf0e10cSrcweir 
3462cdf0e10cSrcweir 			delete[] cMapR;
3463cdf0e10cSrcweir 			delete[] cMapG;
3464cdf0e10cSrcweir 			delete[] cMapB;
3465cdf0e10cSrcweir 			ReleaseAccess( pAcc );
3466cdf0e10cSrcweir 			bRet = sal_True;
3467cdf0e10cSrcweir 		}
3468cdf0e10cSrcweir 	}
3469cdf0e10cSrcweir 
3470cdf0e10cSrcweir 	return bRet;
3471cdf0e10cSrcweir }
3472