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