xref: /aoo41x/main/vcl/source/gdi/bitmap3.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <stdlib.h>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
34*cdf0e10cSrcweir #include <vcl/octree.hxx>
35*cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
36*cdf0e10cSrcweir #include <vcl/bitmap.hxx>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <impoct.hxx>
39*cdf0e10cSrcweir #include <impvect.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir // -----------
42*cdf0e10cSrcweir // - Defines -
43*cdf0e10cSrcweir // -----------
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #define RGB15( _def_cR, _def_cG, _def_cB )	(((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
46*cdf0e10cSrcweir #define GAMMA( _def_cVal, _def_InvGamma )	((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir #define CALC_ERRORS																\
49*cdf0e10cSrcweir 						nTemp   = p1T[nX++] >> 12;								\
50*cdf0e10cSrcweir 						nBErr = MinMax( nTemp, 0, 255 );						\
51*cdf0e10cSrcweir 						nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ];	\
52*cdf0e10cSrcweir 						nTemp   = p1T[nX++] >> 12;								\
53*cdf0e10cSrcweir 						nGErr = MinMax( nTemp, 0, 255 );						\
54*cdf0e10cSrcweir 						nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ];	\
55*cdf0e10cSrcweir 						nTemp   = p1T[nX] >> 12;								\
56*cdf0e10cSrcweir 						nRErr = MinMax( nTemp, 0, 255 );						\
57*cdf0e10cSrcweir 						nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir #define CALC_TABLES3										\
60*cdf0e10cSrcweir 						p2T[nX++] += FloydError3[nBErr];	\
61*cdf0e10cSrcweir 						p2T[nX++] += FloydError3[nGErr];	\
62*cdf0e10cSrcweir 						p2T[nX++] += FloydError3[nRErr];
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir #define CALC_TABLES5										\
65*cdf0e10cSrcweir 						p2T[nX++] += FloydError5[nBErr];	\
66*cdf0e10cSrcweir 						p2T[nX++] += FloydError5[nGErr];	\
67*cdf0e10cSrcweir 						p2T[nX++] += FloydError5[nRErr];
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir #define CALC_TABLES7										\
70*cdf0e10cSrcweir 						p1T[++nX] += FloydError7[nBErr];	\
71*cdf0e10cSrcweir 						p2T[nX++] += FloydError1[nBErr];	\
72*cdf0e10cSrcweir 						p1T[nX] += FloydError7[nGErr];		\
73*cdf0e10cSrcweir 						p2T[nX++] += FloydError1[nGErr];	\
74*cdf0e10cSrcweir 						p1T[nX] += FloydError7[nRErr];		\
75*cdf0e10cSrcweir 						p2T[nX] += FloydError1[nRErr];
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir // -----------
78*cdf0e10cSrcweir // - Statics -
79*cdf0e10cSrcweir // -----------
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
82*cdf0e10cSrcweir sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
83*cdf0e10cSrcweir sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir // ------------------------------------------------------------------------
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir sal_uLong nVCLDitherLut[ 256 ] =
88*cdf0e10cSrcweir {
89*cdf0e10cSrcweir        0, 49152, 12288, 61440,  3072, 52224, 15360, 64512,   768, 49920, 13056,
90*cdf0e10cSrcweir    62208,  3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
91*cdf0e10cSrcweir    48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
92*cdf0e10cSrcweir    57344,  4096, 53248, 11264, 60416,  7168, 56320,  8960, 58112,  4864, 54016,
93*cdf0e10cSrcweir    12032, 61184,  7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
94*cdf0e10cSrcweir    23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
95*cdf0e10cSrcweir    14336, 63488,  1024, 50176, 13312, 62464,  2816, 51968, 15104, 64256,  1792,
96*cdf0e10cSrcweir    50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
97*cdf0e10cSrcweir    35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392,  6144,
98*cdf0e10cSrcweir    55296,  9216, 58368,  5120, 54272, 11008, 60160,  6912, 56064,  9984, 59136,
99*cdf0e10cSrcweir     5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
100*cdf0e10cSrcweir    27392, 39680, 23296, 42752, 26368, 38656, 22272,   512, 49664, 12800, 61952,
101*cdf0e10cSrcweir     3584, 52736, 15872, 65024,   256, 49408, 12544, 61696,  3328, 52480, 15616,
102*cdf0e10cSrcweir    64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
103*cdf0e10cSrcweir    45312, 28928, 36096, 19712, 48384, 32000,  8704, 57856,  4608, 53760, 11776,
104*cdf0e10cSrcweir    60928,  7680, 56832,  8448, 57600,  4352, 53504, 11520, 60672,  7424, 56576,
105*cdf0e10cSrcweir    41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
106*cdf0e10cSrcweir    20736, 44288, 27904, 40192, 23808,  2560, 51712, 14848, 64000,  1536, 50688,
107*cdf0e10cSrcweir    13824, 62976,  2304, 51456, 14592, 63744,  1280, 50432, 13568, 62720, 35328,
108*cdf0e10cSrcweir    18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
109*cdf0e10cSrcweir    34048, 17664, 46336, 29952, 10752, 59904,  6656, 55808,  9728, 58880,  5632,
110*cdf0e10cSrcweir    54784, 10496, 59648,  6400, 55552,  9472, 58624,  5376, 54528, 43520, 27136,
111*cdf0e10cSrcweir    39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
112*cdf0e10cSrcweir    25856, 38144, 21760
113*cdf0e10cSrcweir };
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir // ------------------------------------------------------------------------
116*cdf0e10cSrcweir 
117*cdf0e10cSrcweir sal_uLong nVCLLut[ 256 ] =
118*cdf0e10cSrcweir {
119*cdf0e10cSrcweir          0,  1286,  2572,  3858,  5144,  6430,  7716,  9002,
120*cdf0e10cSrcweir      10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
121*cdf0e10cSrcweir      20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
122*cdf0e10cSrcweir      30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
123*cdf0e10cSrcweir      41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
124*cdf0e10cSrcweir      51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
125*cdf0e10cSrcweir      61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
126*cdf0e10cSrcweir      72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
127*cdf0e10cSrcweir      82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
128*cdf0e10cSrcweir      92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
129*cdf0e10cSrcweir     102880,104166,105452,106738,108024,109310,110596,111882,
130*cdf0e10cSrcweir     113168,114454,115740,117026,118312,119598,120884,122170,
131*cdf0e10cSrcweir     123456,124742,126028,127314,128600,129886,131172,132458,
132*cdf0e10cSrcweir     133744,135030,136316,137602,138888,140174,141460,142746,
133*cdf0e10cSrcweir     144032,145318,146604,147890,149176,150462,151748,153034,
134*cdf0e10cSrcweir     154320,155606,156892,158178,159464,160750,162036,163322,
135*cdf0e10cSrcweir     164608,165894,167180,168466,169752,171038,172324,173610,
136*cdf0e10cSrcweir     174896,176182,177468,178754,180040,181326,182612,183898,
137*cdf0e10cSrcweir     185184,186470,187756,189042,190328,191614,192900,194186,
138*cdf0e10cSrcweir     195472,196758,198044,199330,200616,201902,203188,204474,
139*cdf0e10cSrcweir     205760,207046,208332,209618,210904,212190,213476,214762,
140*cdf0e10cSrcweir     216048,217334,218620,219906,221192,222478,223764,225050,
141*cdf0e10cSrcweir     226336,227622,228908,230194,231480,232766,234052,235338,
142*cdf0e10cSrcweir     236624,237910,239196,240482,241768,243054,244340,245626,
143*cdf0e10cSrcweir     246912,248198,249484,250770,252056,253342,254628,255914,
144*cdf0e10cSrcweir     257200,258486,259772,261058,262344,263630,264916,266202,
145*cdf0e10cSrcweir     267488,268774,270060,271346,272632,273918,275204,276490,
146*cdf0e10cSrcweir     277776,279062,280348,281634,282920,284206,285492,286778,
147*cdf0e10cSrcweir     288064,289350,290636,291922,293208,294494,295780,297066,
148*cdf0e10cSrcweir     298352,299638,300924,302210,303496,304782,306068,307354,
149*cdf0e10cSrcweir     308640,309926,311212,312498,313784,315070,316356,317642,
150*cdf0e10cSrcweir     318928,320214,321500,322786,324072,325358,326644,327930
151*cdf0e10cSrcweir };
152*cdf0e10cSrcweir 
153*cdf0e10cSrcweir // ------------------------------------------------------------------------
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir long FloydMap[256] =
156*cdf0e10cSrcweir {
157*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
158*cdf0e10cSrcweir     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
159*cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
160*cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
161*cdf0e10cSrcweir     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
162*cdf0e10cSrcweir     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
163*cdf0e10cSrcweir     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
164*cdf0e10cSrcweir     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
165*cdf0e10cSrcweir     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
166*cdf0e10cSrcweir     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
167*cdf0e10cSrcweir     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
168*cdf0e10cSrcweir     3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
169*cdf0e10cSrcweir     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
170*cdf0e10cSrcweir     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
171*cdf0e10cSrcweir     4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
172*cdf0e10cSrcweir     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
173*cdf0e10cSrcweir };
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir // ------------------------------------------------------------------------
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir long FloydError1[61] =
178*cdf0e10cSrcweir {
179*cdf0e10cSrcweir     -7680, -7424, -7168, -6912, -6656, -6400, -6144,
180*cdf0e10cSrcweir     -5888, -5632, -5376, -5120, -4864, -4608, -4352,
181*cdf0e10cSrcweir     -4096, -3840, -3584, -3328, -3072, -2816, -2560,
182*cdf0e10cSrcweir     -2304, -2048, -1792, -1536, -1280, -1024, -768,
183*cdf0e10cSrcweir     -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
184*cdf0e10cSrcweir     1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
185*cdf0e10cSrcweir     3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
186*cdf0e10cSrcweir     5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
187*cdf0e10cSrcweir };
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir // ------------------------------------------------------------------------
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir long FloydError3[61] =
192*cdf0e10cSrcweir {
193*cdf0e10cSrcweir     -23040, -22272, -21504, -20736, -19968, -19200,
194*cdf0e10cSrcweir     -18432, -17664, -16896, -16128, -15360, -14592,
195*cdf0e10cSrcweir     -13824, -13056, -12288, -11520, -10752, -9984,
196*cdf0e10cSrcweir     -9216, -8448, -7680, -6912, -6144, -5376, -4608,
197*cdf0e10cSrcweir     -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
198*cdf0e10cSrcweir     2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
199*cdf0e10cSrcweir     8448, 9216, 9984, 10752, 11520, 12288, 13056,
200*cdf0e10cSrcweir     13824, 14592, 15360, 16128, 16896, 17664, 18432,
201*cdf0e10cSrcweir     19200, 19968, 20736, 21504, 22272, 23040
202*cdf0e10cSrcweir };
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir // ------------------------------------------------------------------------
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir long FloydError5[61] =
207*cdf0e10cSrcweir {
208*cdf0e10cSrcweir     -38400, -37120, -35840, -34560, -33280, -32000,
209*cdf0e10cSrcweir     -30720, -29440, -28160, -26880, -25600, -24320,
210*cdf0e10cSrcweir     -23040, -21760, -20480, -19200, -17920, -16640,
211*cdf0e10cSrcweir     -15360, -14080, -12800, -11520, -10240, -8960,
212*cdf0e10cSrcweir     -7680, -6400, -5120, -3840, -2560, -1280,   0,
213*cdf0e10cSrcweir     1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
214*cdf0e10cSrcweir     11520, 12800, 14080, 15360, 16640, 17920, 19200,
215*cdf0e10cSrcweir     20480, 21760, 23040, 24320, 25600, 26880, 28160,
216*cdf0e10cSrcweir     29440, 30720, 32000, 33280, 34560, 35840, 37120,
217*cdf0e10cSrcweir     38400
218*cdf0e10cSrcweir };
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir // ------------------------------------------------------------------------
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir long FloydError7[61] =
223*cdf0e10cSrcweir {
224*cdf0e10cSrcweir     -53760, -51968, -50176, -48384, -46592, -44800,
225*cdf0e10cSrcweir     -43008, -41216, -39424, -37632, -35840, -34048,
226*cdf0e10cSrcweir     -32256, -30464, -28672, -26880, -25088, -23296,
227*cdf0e10cSrcweir     -21504, -19712, -17920, -16128, -14336, -12544,
228*cdf0e10cSrcweir     -10752, -8960, -7168, -5376, -3584, -1792,  0,
229*cdf0e10cSrcweir     1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
230*cdf0e10cSrcweir     16128, 17920, 19712, 21504, 23296, 25088, 26880,
231*cdf0e10cSrcweir     28672, 30464, 32256, 34048, 35840, 37632, 39424,
232*cdf0e10cSrcweir     41216, 43008, 44800, 46592, 48384, 50176, 51968,
233*cdf0e10cSrcweir     53760
234*cdf0e10cSrcweir };
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir // ------------------------------------------------------------------------
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir long FloydIndexMap[6] =
239*cdf0e10cSrcweir {
240*cdf0e10cSrcweir     -30,  21, 72, 123, 174, 225
241*cdf0e10cSrcweir };
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir // --------------------------
244*cdf0e10cSrcweir // - ImplCreateDitherMatrix -
245*cdf0e10cSrcweir // --------------------------
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] )
248*cdf0e10cSrcweir {
249*cdf0e10cSrcweir 	double			fVal = 3.125;
250*cdf0e10cSrcweir 	const double	fVal16 = fVal / 16.;
251*cdf0e10cSrcweir 	long			i, j, k, l;
252*cdf0e10cSrcweir 	sal_uInt16			pMtx[ 16 ][ 16 ];
253*cdf0e10cSrcweir 	sal_uInt16			nMax = 0;
254*cdf0e10cSrcweir 	static sal_uInt8 	pMagic[4][4] = { { 0, 14,  3, 13, },
255*cdf0e10cSrcweir                                      {11,  5,  8,  6, },
256*cdf0e10cSrcweir                                      {12,  2, 15,  1, },
257*cdf0e10cSrcweir                                      {7,   9,  4, 10 } };
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir 	// MagicSquare aufbauen
260*cdf0e10cSrcweir 	for ( i = 0; i < 4; i++ )
261*cdf0e10cSrcweir 	   for ( j = 0; j < 4; j++ )
262*cdf0e10cSrcweir 		   for ( k = 0; k < 4; k++ )
263*cdf0e10cSrcweir 				for ( l = 0; l < 4; l++ )
264*cdf0e10cSrcweir 					nMax = Max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
265*cdf0e10cSrcweir 					(sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir 	// auf Intervall [0;254] skalieren
268*cdf0e10cSrcweir 	for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
269*cdf0e10cSrcweir 		for( j = 0; j < 16; j++ )
270*cdf0e10cSrcweir 			(*pDitherMatrix)[i][j] = (sal_uInt8) ( fVal * pMtx[i][j] );
271*cdf0e10cSrcweir }
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir // ----------
274*cdf0e10cSrcweir // - Bitmap -
275*cdf0e10cSrcweir // ----------
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir sal_Bool Bitmap::Convert( BmpConversion eConversion )
278*cdf0e10cSrcweir {
279*cdf0e10cSrcweir 	const sal_uInt16	nBitCount = GetBitCount();
280*cdf0e10cSrcweir 	sal_Bool			bRet = sal_False;
281*cdf0e10cSrcweir 
282*cdf0e10cSrcweir 	switch( eConversion )
283*cdf0e10cSrcweir 	{
284*cdf0e10cSrcweir 		case( BMP_CONVERSION_1BIT_THRESHOLD ):
285*cdf0e10cSrcweir 			bRet = ImplMakeMono( 128 );
286*cdf0e10cSrcweir 		break;
287*cdf0e10cSrcweir 
288*cdf0e10cSrcweir 		case( BMP_CONVERSION_1BIT_MATRIX ):
289*cdf0e10cSrcweir 			bRet = ImplMakeMonoDither();
290*cdf0e10cSrcweir 		break;
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir 		case( BMP_CONVERSION_4BIT_GREYS ):
293*cdf0e10cSrcweir 			bRet = ImplMakeGreyscales( 16 );
294*cdf0e10cSrcweir 		break;
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir 		case( BMP_CONVERSION_4BIT_COLORS ):
297*cdf0e10cSrcweir 		{
298*cdf0e10cSrcweir 			if( nBitCount < 4 )
299*cdf0e10cSrcweir 				bRet = ImplConvertUp( 4, NULL );
300*cdf0e10cSrcweir 			else if( nBitCount > 4 )
301*cdf0e10cSrcweir 				bRet = ImplConvertDown( 4, NULL );
302*cdf0e10cSrcweir 			else
303*cdf0e10cSrcweir 				bRet = sal_True;
304*cdf0e10cSrcweir 		}
305*cdf0e10cSrcweir 		break;
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir 		case( BMP_CONVERSION_4BIT_TRANS ):
308*cdf0e10cSrcweir 		{
309*cdf0e10cSrcweir 			Color aTrans( BMP_COL_TRANS );
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir 			if( nBitCount < 4 )
312*cdf0e10cSrcweir 				bRet = ImplConvertUp( 4, &aTrans );
313*cdf0e10cSrcweir 			else
314*cdf0e10cSrcweir 				bRet = ImplConvertDown( 4, &aTrans );
315*cdf0e10cSrcweir 		}
316*cdf0e10cSrcweir 		break;
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir 		case( BMP_CONVERSION_8BIT_GREYS ):
319*cdf0e10cSrcweir 			bRet = ImplMakeGreyscales( 256 );
320*cdf0e10cSrcweir 		break;
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir 		case( BMP_CONVERSION_8BIT_COLORS ):
323*cdf0e10cSrcweir 		{
324*cdf0e10cSrcweir 			if( nBitCount < 8 )
325*cdf0e10cSrcweir 				bRet = ImplConvertUp( 8 );
326*cdf0e10cSrcweir 			else if( nBitCount > 8 )
327*cdf0e10cSrcweir 				bRet = ImplConvertDown( 8 );
328*cdf0e10cSrcweir 			else
329*cdf0e10cSrcweir 				bRet = sal_True;
330*cdf0e10cSrcweir 		}
331*cdf0e10cSrcweir 		break;
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir 		case( BMP_CONVERSION_8BIT_TRANS ):
334*cdf0e10cSrcweir 		{
335*cdf0e10cSrcweir 			Color aTrans( BMP_COL_TRANS );
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir 			if( nBitCount < 8 )
338*cdf0e10cSrcweir 				bRet = ImplConvertUp( 8, &aTrans );
339*cdf0e10cSrcweir 			else
340*cdf0e10cSrcweir 				bRet = ImplConvertDown( 8, &aTrans );
341*cdf0e10cSrcweir 		}
342*cdf0e10cSrcweir 		break;
343*cdf0e10cSrcweir 
344*cdf0e10cSrcweir 		case( BMP_CONVERSION_24BIT ):
345*cdf0e10cSrcweir 		{
346*cdf0e10cSrcweir 			if( nBitCount < 24 )
347*cdf0e10cSrcweir 				bRet = ImplConvertUp( 24, sal_False );
348*cdf0e10cSrcweir 			else
349*cdf0e10cSrcweir 				bRet = sal_True;
350*cdf0e10cSrcweir 		}
351*cdf0e10cSrcweir 		break;
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir 		case( BMP_CONVERSION_GHOSTED ):
354*cdf0e10cSrcweir 			bRet = ImplConvertGhosted();
355*cdf0e10cSrcweir 		break;
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir 		default:
358*cdf0e10cSrcweir 			DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
359*cdf0e10cSrcweir 		break;
360*cdf0e10cSrcweir 	}
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir 	return bRet;
363*cdf0e10cSrcweir }
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir // ------------------------------------------------------------------------
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir sal_Bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold )
368*cdf0e10cSrcweir {
369*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
370*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir 	if( pReadAcc )
373*cdf0e10cSrcweir 	{
374*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), 1 );
375*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir 		if( pWriteAcc )
378*cdf0e10cSrcweir 		{
379*cdf0e10cSrcweir 			const BitmapColor	aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
380*cdf0e10cSrcweir 			const BitmapColor	aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
381*cdf0e10cSrcweir 			const long			nWidth = pWriteAcc->Width();
382*cdf0e10cSrcweir 			const long			nHeight = pWriteAcc->Height();
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir 			if( pReadAcc->HasPalette() )
385*cdf0e10cSrcweir 			{
386*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
387*cdf0e10cSrcweir 				{
388*cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
389*cdf0e10cSrcweir 					{
390*cdf0e10cSrcweir 						if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >=
391*cdf0e10cSrcweir 							cThreshold )
392*cdf0e10cSrcweir 						{
393*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aWhite );
394*cdf0e10cSrcweir 						}
395*cdf0e10cSrcweir 						else
396*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aBlack );
397*cdf0e10cSrcweir 					}
398*cdf0e10cSrcweir 				}
399*cdf0e10cSrcweir 			}
400*cdf0e10cSrcweir 			else
401*cdf0e10cSrcweir 			{
402*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
403*cdf0e10cSrcweir 				{
404*cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
405*cdf0e10cSrcweir 					{
406*cdf0e10cSrcweir 						if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
407*cdf0e10cSrcweir 							cThreshold )
408*cdf0e10cSrcweir 						{
409*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aWhite );
410*cdf0e10cSrcweir 						}
411*cdf0e10cSrcweir 						else
412*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aBlack );
413*cdf0e10cSrcweir 					}
414*cdf0e10cSrcweir 				}
415*cdf0e10cSrcweir 			}
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWriteAcc );
418*cdf0e10cSrcweir 			bRet = sal_True;
419*cdf0e10cSrcweir 		}
420*cdf0e10cSrcweir 
421*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir 		if( bRet )
424*cdf0e10cSrcweir 		{
425*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
426*cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
427*cdf0e10cSrcweir 
428*cdf0e10cSrcweir 			*this = aNewBmp;
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir 			maPrefMapMode = aMap;
431*cdf0e10cSrcweir 			maPrefSize = aSize;
432*cdf0e10cSrcweir 		}
433*cdf0e10cSrcweir 	}
434*cdf0e10cSrcweir 
435*cdf0e10cSrcweir 	return bRet;
436*cdf0e10cSrcweir }
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir // ------------------------------------------------------------------------
439*cdf0e10cSrcweir 
440*cdf0e10cSrcweir sal_Bool Bitmap::ImplMakeMonoDither()
441*cdf0e10cSrcweir {
442*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
443*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
444*cdf0e10cSrcweir 
445*cdf0e10cSrcweir 	if( pReadAcc )
446*cdf0e10cSrcweir 	{
447*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), 1 );
448*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir 		if( pWriteAcc )
451*cdf0e10cSrcweir 		{
452*cdf0e10cSrcweir 			const BitmapColor	aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
453*cdf0e10cSrcweir 			const BitmapColor	aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
454*cdf0e10cSrcweir 			const long			nWidth = pWriteAcc->Width();
455*cdf0e10cSrcweir 			const long			nHeight = pWriteAcc->Height();
456*cdf0e10cSrcweir 			sal_uInt8				pDitherMatrix[ 16 ][ 16 ];
457*cdf0e10cSrcweir 
458*cdf0e10cSrcweir 			ImplCreateDitherMatrix( &pDitherMatrix );
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir 			if( pReadAcc->HasPalette() )
461*cdf0e10cSrcweir 			{
462*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
463*cdf0e10cSrcweir 				{
464*cdf0e10cSrcweir 					for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
465*cdf0e10cSrcweir 					{
466*cdf0e10cSrcweir 						if( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >
467*cdf0e10cSrcweir 							pDitherMatrix[ nModY ][ nX % 16 ] )
468*cdf0e10cSrcweir 						{
469*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aWhite );
470*cdf0e10cSrcweir 						}
471*cdf0e10cSrcweir 						else
472*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aBlack );
473*cdf0e10cSrcweir 					}
474*cdf0e10cSrcweir 				}
475*cdf0e10cSrcweir 			}
476*cdf0e10cSrcweir 			else
477*cdf0e10cSrcweir 			{
478*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
479*cdf0e10cSrcweir 				{
480*cdf0e10cSrcweir 					for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
481*cdf0e10cSrcweir 					{
482*cdf0e10cSrcweir 						if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
483*cdf0e10cSrcweir 							pDitherMatrix[ nModY ][ nX % 16 ]  )
484*cdf0e10cSrcweir 						{
485*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aWhite );
486*cdf0e10cSrcweir 						}
487*cdf0e10cSrcweir 						else
488*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aBlack );
489*cdf0e10cSrcweir 					}
490*cdf0e10cSrcweir 				}
491*cdf0e10cSrcweir 			}
492*cdf0e10cSrcweir 
493*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWriteAcc );
494*cdf0e10cSrcweir 			bRet = sal_True;
495*cdf0e10cSrcweir 		}
496*cdf0e10cSrcweir 
497*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
498*cdf0e10cSrcweir 
499*cdf0e10cSrcweir 		if( bRet )
500*cdf0e10cSrcweir 		{
501*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
502*cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
503*cdf0e10cSrcweir 
504*cdf0e10cSrcweir 			*this = aNewBmp;
505*cdf0e10cSrcweir 
506*cdf0e10cSrcweir 			maPrefMapMode = aMap;
507*cdf0e10cSrcweir 			maPrefSize = aSize;
508*cdf0e10cSrcweir 		}
509*cdf0e10cSrcweir 	}
510*cdf0e10cSrcweir 
511*cdf0e10cSrcweir 	return bRet;
512*cdf0e10cSrcweir }
513*cdf0e10cSrcweir 
514*cdf0e10cSrcweir // ------------------------------------------------------------------------
515*cdf0e10cSrcweir 
516*cdf0e10cSrcweir sal_Bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
517*cdf0e10cSrcweir {
518*cdf0e10cSrcweir 	DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" );
519*cdf0e10cSrcweir 
520*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
521*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
522*cdf0e10cSrcweir 
523*cdf0e10cSrcweir 	if( pReadAcc )
524*cdf0e10cSrcweir 	{
525*cdf0e10cSrcweir 		const BitmapPalette&	rPal = GetGreyPalette( nGreys );
526*cdf0e10cSrcweir 		sal_uLong 					nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
527*cdf0e10cSrcweir 		sal_Bool					bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
528*cdf0e10cSrcweir 
529*cdf0e10cSrcweir 		if( !bPalDiffers )
530*cdf0e10cSrcweir 			bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
531*cdf0e10cSrcweir 
532*cdf0e10cSrcweir 		if( bPalDiffers )
533*cdf0e10cSrcweir 		{
534*cdf0e10cSrcweir 			Bitmap				aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
535*cdf0e10cSrcweir 			BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir 			if( pWriteAcc )
538*cdf0e10cSrcweir 			{
539*cdf0e10cSrcweir 				const long	nWidth = pWriteAcc->Width();
540*cdf0e10cSrcweir 				const long	nHeight = pWriteAcc->Height();
541*cdf0e10cSrcweir 
542*cdf0e10cSrcweir 				if( pReadAcc->HasPalette() )
543*cdf0e10cSrcweir 				{
544*cdf0e10cSrcweir 					for( long nY = 0L; nY < nHeight; nY++ )
545*cdf0e10cSrcweir 					{
546*cdf0e10cSrcweir 						for( long nX = 0L; nX < nWidth; nX++ )
547*cdf0e10cSrcweir 						{
548*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX,
549*cdf0e10cSrcweir 								(sal_uInt8) ( pReadAcc->GetPaletteColor(
550*cdf0e10cSrcweir 									pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift ) );
551*cdf0e10cSrcweir 						}
552*cdf0e10cSrcweir 					}
553*cdf0e10cSrcweir 				}
554*cdf0e10cSrcweir 				else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
555*cdf0e10cSrcweir 						 pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
556*cdf0e10cSrcweir 				{
557*cdf0e10cSrcweir 					nShift += 8;
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir 					for( long nY = 0L; nY < nHeight; nY++ )
560*cdf0e10cSrcweir 					{
561*cdf0e10cSrcweir 						Scanline pReadScan = pReadAcc->GetScanline( nY );
562*cdf0e10cSrcweir 						Scanline pWriteScan = pWriteAcc->GetScanline( nY );
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir 						for( long nX = 0L; nX < nWidth; nX++ )
565*cdf0e10cSrcweir 						{
566*cdf0e10cSrcweir 							const sal_uLong nB = *pReadScan++;
567*cdf0e10cSrcweir 							const sal_uLong nG = *pReadScan++;
568*cdf0e10cSrcweir 							const sal_uLong nR = *pReadScan++;
569*cdf0e10cSrcweir 
570*cdf0e10cSrcweir 							*pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
571*cdf0e10cSrcweir 						}
572*cdf0e10cSrcweir 					}
573*cdf0e10cSrcweir 				}
574*cdf0e10cSrcweir 				else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
575*cdf0e10cSrcweir 						 pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
576*cdf0e10cSrcweir 				{
577*cdf0e10cSrcweir 					nShift += 8;
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir 					for( long nY = 0L; nY < nHeight; nY++ )
580*cdf0e10cSrcweir 					{
581*cdf0e10cSrcweir 						Scanline pReadScan = pReadAcc->GetScanline( nY );
582*cdf0e10cSrcweir 						Scanline pWriteScan = pWriteAcc->GetScanline( nY );
583*cdf0e10cSrcweir 
584*cdf0e10cSrcweir 						for( long nX = 0L; nX < nWidth; nX++ )
585*cdf0e10cSrcweir 						{
586*cdf0e10cSrcweir 							const sal_uLong nR = *pReadScan++;
587*cdf0e10cSrcweir 							const sal_uLong nG = *pReadScan++;
588*cdf0e10cSrcweir 							const sal_uLong nB = *pReadScan++;
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir 							*pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
591*cdf0e10cSrcweir 						}
592*cdf0e10cSrcweir 					}
593*cdf0e10cSrcweir 				}
594*cdf0e10cSrcweir 				else
595*cdf0e10cSrcweir 				{
596*cdf0e10cSrcweir 					for( long nY = 0L; nY < nHeight; nY++ )
597*cdf0e10cSrcweir 						for( long nX = 0L; nX < nWidth; nX++ )
598*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, sal::static_int_cast<sal_uInt8>(( pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift) );
599*cdf0e10cSrcweir 				}
600*cdf0e10cSrcweir 
601*cdf0e10cSrcweir 				aNewBmp.ReleaseAccess( pWriteAcc );
602*cdf0e10cSrcweir 				bRet = sal_True;
603*cdf0e10cSrcweir 			}
604*cdf0e10cSrcweir 
605*cdf0e10cSrcweir 			ReleaseAccess( pReadAcc );
606*cdf0e10cSrcweir 
607*cdf0e10cSrcweir 			if( bRet )
608*cdf0e10cSrcweir 			{
609*cdf0e10cSrcweir 				const MapMode	aMap( maPrefMapMode );
610*cdf0e10cSrcweir 				const Size		aSize( maPrefSize );
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir 				*this = aNewBmp;
613*cdf0e10cSrcweir 
614*cdf0e10cSrcweir 				maPrefMapMode = aMap;
615*cdf0e10cSrcweir 				maPrefSize = aSize;
616*cdf0e10cSrcweir 			}
617*cdf0e10cSrcweir 		}
618*cdf0e10cSrcweir 		else
619*cdf0e10cSrcweir 		{
620*cdf0e10cSrcweir 			ReleaseAccess( pReadAcc );
621*cdf0e10cSrcweir 			bRet = sal_True;
622*cdf0e10cSrcweir 		}
623*cdf0e10cSrcweir 	}
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir 	return bRet;
626*cdf0e10cSrcweir }
627*cdf0e10cSrcweir 
628*cdf0e10cSrcweir // ------------------------------------------------------------------------
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir sal_Bool Bitmap::ImplConvertUp( sal_uInt16 nBitCount, Color* pExtColor )
631*cdf0e10cSrcweir {
632*cdf0e10cSrcweir 	DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
635*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir 	if( pReadAcc )
638*cdf0e10cSrcweir 	{
639*cdf0e10cSrcweir 		BitmapPalette		aPal;
640*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPal );
641*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
642*cdf0e10cSrcweir 
643*cdf0e10cSrcweir 		if( pWriteAcc )
644*cdf0e10cSrcweir 		{
645*cdf0e10cSrcweir 			const long	nWidth = pWriteAcc->Width();
646*cdf0e10cSrcweir 			const long	nHeight = pWriteAcc->Height();
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir 			if( pWriteAcc->HasPalette() )
649*cdf0e10cSrcweir 			{
650*cdf0e10cSrcweir 				const sal_uInt16			nOldCount = 1 << GetBitCount();
651*cdf0e10cSrcweir 				const BitmapPalette&	rOldPal = pReadAcc->GetPalette();
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir 				aPal.SetEntryCount( 1 << nBitCount );
654*cdf0e10cSrcweir 
655*cdf0e10cSrcweir 				for( sal_uInt16 i = 0; i < nOldCount; i++ )
656*cdf0e10cSrcweir 					aPal[ i ] = rOldPal[ i ];
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir 				if( pExtColor )
659*cdf0e10cSrcweir 					aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
660*cdf0e10cSrcweir 
661*cdf0e10cSrcweir 				pWriteAcc->SetPalette( aPal );
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
664*cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
665*cdf0e10cSrcweir 						pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
666*cdf0e10cSrcweir 			}
667*cdf0e10cSrcweir 			else
668*cdf0e10cSrcweir 			{
669*cdf0e10cSrcweir 				if( pReadAcc->HasPalette() )
670*cdf0e10cSrcweir 				{
671*cdf0e10cSrcweir 					for( long nY = 0L; nY < nHeight; nY++ )
672*cdf0e10cSrcweir 						for( long nX = 0L; nX < nWidth; nX++ )
673*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
674*cdf0e10cSrcweir 				}
675*cdf0e10cSrcweir 				else
676*cdf0e10cSrcweir 				{
677*cdf0e10cSrcweir 					for( long nY = 0L; nY < nHeight; nY++ )
678*cdf0e10cSrcweir 						for( long nX = 0L; nX < nWidth; nX++ )
679*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
680*cdf0e10cSrcweir 				}
681*cdf0e10cSrcweir 			}
682*cdf0e10cSrcweir 
683*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWriteAcc );
684*cdf0e10cSrcweir 			bRet = sal_True;
685*cdf0e10cSrcweir 		}
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
688*cdf0e10cSrcweir 
689*cdf0e10cSrcweir 		if( bRet )
690*cdf0e10cSrcweir 		{
691*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
692*cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir 			*this = aNewBmp;
695*cdf0e10cSrcweir 
696*cdf0e10cSrcweir 			maPrefMapMode = aMap;
697*cdf0e10cSrcweir 			maPrefSize = aSize;
698*cdf0e10cSrcweir 		}
699*cdf0e10cSrcweir 	}
700*cdf0e10cSrcweir 
701*cdf0e10cSrcweir 	return bRet;
702*cdf0e10cSrcweir }
703*cdf0e10cSrcweir 
704*cdf0e10cSrcweir // ------------------------------------------------------------------------
705*cdf0e10cSrcweir 
706*cdf0e10cSrcweir sal_Bool Bitmap::ImplConvertDown( sal_uInt16 nBitCount, Color* pExtColor )
707*cdf0e10cSrcweir {
708*cdf0e10cSrcweir 	DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
711*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
712*cdf0e10cSrcweir 
713*cdf0e10cSrcweir 	if( pReadAcc )
714*cdf0e10cSrcweir 	{
715*cdf0e10cSrcweir 		BitmapPalette		aPal;
716*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, &aPal );
717*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
718*cdf0e10cSrcweir 
719*cdf0e10cSrcweir 		if( pWriteAcc )
720*cdf0e10cSrcweir 		{
721*cdf0e10cSrcweir 			const sal_uInt16	nCount = 1 << nBitCount;
722*cdf0e10cSrcweir 			const long		nWidth = pWriteAcc->Width();
723*cdf0e10cSrcweir 			const long		nWidth1 = nWidth - 1L;
724*cdf0e10cSrcweir 			const long		nHeight = pWriteAcc->Height();
725*cdf0e10cSrcweir 			Octree			aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
726*cdf0e10cSrcweir 			InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
727*cdf0e10cSrcweir 			BitmapColor 	aColor;
728*cdf0e10cSrcweir 			ImpErrorQuad	aErrQuad;
729*cdf0e10cSrcweir 			ImpErrorQuad*	pErrQuad1 = new ImpErrorQuad[ nWidth ];
730*cdf0e10cSrcweir 			ImpErrorQuad*	pErrQuad2 = new ImpErrorQuad[ nWidth ];
731*cdf0e10cSrcweir 			ImpErrorQuad*	pQLine1 = pErrQuad1;
732*cdf0e10cSrcweir 			ImpErrorQuad*	pQLine2 = 0;
733*cdf0e10cSrcweir 			long			nX, nY;
734*cdf0e10cSrcweir 			long			nYTmp = 0L;
735*cdf0e10cSrcweir 			sal_uInt8			cIndex;
736*cdf0e10cSrcweir 			sal_Bool			bQ1 = sal_True;
737*cdf0e10cSrcweir 
738*cdf0e10cSrcweir 			if( pExtColor )
739*cdf0e10cSrcweir 			{
740*cdf0e10cSrcweir 				aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
741*cdf0e10cSrcweir 				aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
742*cdf0e10cSrcweir 			}
743*cdf0e10cSrcweir 
744*cdf0e10cSrcweir 			// set Black/White always, if we have enough space
745*cdf0e10cSrcweir 			if( aPal.GetEntryCount() < ( nCount - 1 ) )
746*cdf0e10cSrcweir 			{
747*cdf0e10cSrcweir 				aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
748*cdf0e10cSrcweir 				aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
749*cdf0e10cSrcweir 				aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
750*cdf0e10cSrcweir 			}
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir 			pWriteAcc->SetPalette( aPal );
753*cdf0e10cSrcweir 
754*cdf0e10cSrcweir 			for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
755*cdf0e10cSrcweir 			{
756*cdf0e10cSrcweir 				for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
757*cdf0e10cSrcweir 				{
758*cdf0e10cSrcweir 					if( pReadAcc->HasPalette() )
759*cdf0e10cSrcweir 						pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
760*cdf0e10cSrcweir 					else
761*cdf0e10cSrcweir 						pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
762*cdf0e10cSrcweir 				}
763*cdf0e10cSrcweir 			}
764*cdf0e10cSrcweir 
765*cdf0e10cSrcweir 			for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
766*cdf0e10cSrcweir 			{
767*cdf0e10cSrcweir 				// erstes ZeilenPixel
768*cdf0e10cSrcweir 				cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
769*cdf0e10cSrcweir 				pWriteAcc->SetPixel( nY, 0, cIndex );
770*cdf0e10cSrcweir 
771*cdf0e10cSrcweir 				for( nX = 1L; nX < nWidth1; nX++ )
772*cdf0e10cSrcweir 				{
773*cdf0e10cSrcweir 					cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
774*cdf0e10cSrcweir 					aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
775*cdf0e10cSrcweir 					pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
776*cdf0e10cSrcweir 					pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
777*cdf0e10cSrcweir 					pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
778*cdf0e10cSrcweir 					pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
779*cdf0e10cSrcweir 					pWriteAcc->SetPixel( nY, nX, cIndex );
780*cdf0e10cSrcweir 				}
781*cdf0e10cSrcweir 
782*cdf0e10cSrcweir 				// letztes ZeilenPixel
783*cdf0e10cSrcweir                 if( nX < nWidth )
784*cdf0e10cSrcweir                 {
785*cdf0e10cSrcweir 				    cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
786*cdf0e10cSrcweir 				    pWriteAcc->SetPixel( nY, nX, cIndex );
787*cdf0e10cSrcweir                 }
788*cdf0e10cSrcweir 
789*cdf0e10cSrcweir 				// Zeilenpuffer neu fuellen/kopieren
790*cdf0e10cSrcweir 				pQLine1 = pQLine2;
791*cdf0e10cSrcweir 				pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
792*cdf0e10cSrcweir 
793*cdf0e10cSrcweir 				if( nYTmp < nHeight )
794*cdf0e10cSrcweir 				{
795*cdf0e10cSrcweir 					for( nX = 0L; nX < nWidth; nX++ )
796*cdf0e10cSrcweir 					{
797*cdf0e10cSrcweir 						if( pReadAcc->HasPalette() )
798*cdf0e10cSrcweir 								pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nYTmp, nX ) );
799*cdf0e10cSrcweir 						else
800*cdf0e10cSrcweir 							pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
801*cdf0e10cSrcweir 					}
802*cdf0e10cSrcweir 				}
803*cdf0e10cSrcweir 			}
804*cdf0e10cSrcweir 
805*cdf0e10cSrcweir 			// Zeilenpuffer zerstoeren
806*cdf0e10cSrcweir 			delete[] pErrQuad1;
807*cdf0e10cSrcweir 			delete[] pErrQuad2;
808*cdf0e10cSrcweir 
809*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWriteAcc );
810*cdf0e10cSrcweir 			bRet = sal_True;
811*cdf0e10cSrcweir 		}
812*cdf0e10cSrcweir 
813*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
814*cdf0e10cSrcweir 
815*cdf0e10cSrcweir 		if( bRet )
816*cdf0e10cSrcweir 		{
817*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
818*cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir 			*this = aNewBmp;
821*cdf0e10cSrcweir 
822*cdf0e10cSrcweir 			maPrefMapMode = aMap;
823*cdf0e10cSrcweir 			maPrefSize = aSize;
824*cdf0e10cSrcweir 		}
825*cdf0e10cSrcweir 	}
826*cdf0e10cSrcweir 
827*cdf0e10cSrcweir 	return bRet;
828*cdf0e10cSrcweir }
829*cdf0e10cSrcweir 
830*cdf0e10cSrcweir // ------------------------------------------------------------------------
831*cdf0e10cSrcweir 
832*cdf0e10cSrcweir sal_Bool Bitmap::ImplConvertGhosted()
833*cdf0e10cSrcweir {
834*cdf0e10cSrcweir 	Bitmap				aNewBmp;
835*cdf0e10cSrcweir 	BitmapReadAccess*	pR = AcquireReadAccess();
836*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
837*cdf0e10cSrcweir 
838*cdf0e10cSrcweir 	if( pR )
839*cdf0e10cSrcweir 	{
840*cdf0e10cSrcweir 		if( pR->HasPalette() )
841*cdf0e10cSrcweir 		{
842*cdf0e10cSrcweir 			BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
843*cdf0e10cSrcweir 
844*cdf0e10cSrcweir 			for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
845*cdf0e10cSrcweir 			{
846*cdf0e10cSrcweir 				const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i );
847*cdf0e10cSrcweir 				aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
848*cdf0e10cSrcweir 													 ( rOld.GetGreen() >> 1 ) | 0x80,
849*cdf0e10cSrcweir 													 ( rOld.GetBlue() >> 1 ) | 0x80 );
850*cdf0e10cSrcweir 			}
851*cdf0e10cSrcweir 
852*cdf0e10cSrcweir 			aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
853*cdf0e10cSrcweir 			BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
854*cdf0e10cSrcweir 
855*cdf0e10cSrcweir 			if( pW )
856*cdf0e10cSrcweir 			{
857*cdf0e10cSrcweir 				pW->CopyBuffer( *pR );
858*cdf0e10cSrcweir 				aNewBmp.ReleaseAccess( pW );
859*cdf0e10cSrcweir 				bRet = sal_True;
860*cdf0e10cSrcweir 			}
861*cdf0e10cSrcweir 		}
862*cdf0e10cSrcweir 		else
863*cdf0e10cSrcweir 		{
864*cdf0e10cSrcweir 			aNewBmp = Bitmap( GetSizePixel(), 24 );
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir 			BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
867*cdf0e10cSrcweir 
868*cdf0e10cSrcweir 			if( pW )
869*cdf0e10cSrcweir 			{
870*cdf0e10cSrcweir 				const long nWidth = pR->Width(), nHeight = pR->Height();
871*cdf0e10cSrcweir 
872*cdf0e10cSrcweir 				for( long nY = 0; nY < nHeight; nY++ )
873*cdf0e10cSrcweir 				{
874*cdf0e10cSrcweir 					for( long nX = 0; nX < nWidth; nX++ )
875*cdf0e10cSrcweir 					{
876*cdf0e10cSrcweir 						const BitmapColor aOld( pR->GetPixel( nY, nX ) );
877*cdf0e10cSrcweir 						pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
878*cdf0e10cSrcweir 														   ( aOld.GetGreen() >> 1 ) | 0x80,
879*cdf0e10cSrcweir 														   ( aOld.GetBlue() >> 1 ) | 0x80 ) );
880*cdf0e10cSrcweir 
881*cdf0e10cSrcweir 					}
882*cdf0e10cSrcweir 				}
883*cdf0e10cSrcweir 
884*cdf0e10cSrcweir 				aNewBmp.ReleaseAccess( pW );
885*cdf0e10cSrcweir 				bRet = sal_True;
886*cdf0e10cSrcweir 			}
887*cdf0e10cSrcweir 		}
888*cdf0e10cSrcweir 
889*cdf0e10cSrcweir 		ReleaseAccess( pR );
890*cdf0e10cSrcweir 	}
891*cdf0e10cSrcweir 
892*cdf0e10cSrcweir 	if( bRet )
893*cdf0e10cSrcweir 	{
894*cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
895*cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
896*cdf0e10cSrcweir 
897*cdf0e10cSrcweir 		*this = aNewBmp;
898*cdf0e10cSrcweir 
899*cdf0e10cSrcweir 		maPrefMapMode = aMap;
900*cdf0e10cSrcweir 		maPrefSize = aSize;
901*cdf0e10cSrcweir 	}
902*cdf0e10cSrcweir 
903*cdf0e10cSrcweir 	return bRet;
904*cdf0e10cSrcweir }
905*cdf0e10cSrcweir 
906*cdf0e10cSrcweir // ------------------------------------------------------------------------
907*cdf0e10cSrcweir 
908*cdf0e10cSrcweir sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
909*cdf0e10cSrcweir {
910*cdf0e10cSrcweir 	sal_Bool bRet;
911*cdf0e10cSrcweir 
912*cdf0e10cSrcweir 	if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) )
913*cdf0e10cSrcweir 	{
914*cdf0e10cSrcweir 		if( BMP_SCALE_FAST == nScaleFlag )
915*cdf0e10cSrcweir 			bRet = ImplScaleFast( rScaleX, rScaleY );
916*cdf0e10cSrcweir 		else if( BMP_SCALE_INTERPOLATE == nScaleFlag )
917*cdf0e10cSrcweir 			bRet = ImplScaleInterpolate( rScaleX, rScaleY );
918*cdf0e10cSrcweir 		else
919*cdf0e10cSrcweir 			bRet = sal_False;
920*cdf0e10cSrcweir 	}
921*cdf0e10cSrcweir 	else
922*cdf0e10cSrcweir 		bRet = sal_True;
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir 	return bRet;
925*cdf0e10cSrcweir }
926*cdf0e10cSrcweir 
927*cdf0e10cSrcweir // ------------------------------------------------------------------------
928*cdf0e10cSrcweir 
929*cdf0e10cSrcweir sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
930*cdf0e10cSrcweir {
931*cdf0e10cSrcweir 	const Size	aSize( GetSizePixel() );
932*cdf0e10cSrcweir 	sal_Bool		bRet;
933*cdf0e10cSrcweir 
934*cdf0e10cSrcweir 	if( aSize.Width() && aSize.Height() )
935*cdf0e10cSrcweir 	{
936*cdf0e10cSrcweir 		bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
937*cdf0e10cSrcweir 					  (double) rNewSize.Height() / aSize.Height(),
938*cdf0e10cSrcweir 					  nScaleFlag );
939*cdf0e10cSrcweir 	}
940*cdf0e10cSrcweir 	else
941*cdf0e10cSrcweir 		bRet = sal_True;
942*cdf0e10cSrcweir 
943*cdf0e10cSrcweir 	return bRet;
944*cdf0e10cSrcweir }
945*cdf0e10cSrcweir 
946*cdf0e10cSrcweir // ------------------------------------------------------------------------
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
949*cdf0e10cSrcweir {
950*cdf0e10cSrcweir 	const Size	aSizePix( GetSizePixel() );
951*cdf0e10cSrcweir 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
952*cdf0e10cSrcweir 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
953*cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
954*cdf0e10cSrcweir 
955*cdf0e10cSrcweir 	if( nNewWidth && nNewHeight )
956*cdf0e10cSrcweir 	{
957*cdf0e10cSrcweir 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
958*cdf0e10cSrcweir 		Bitmap				aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
959*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
960*cdf0e10cSrcweir 
961*cdf0e10cSrcweir 		if( pReadAcc && pWriteAcc )
962*cdf0e10cSrcweir 		{
963*cdf0e10cSrcweir 			const long	nScanlineSize = pWriteAcc->GetScanlineSize();
964*cdf0e10cSrcweir 			const long	nNewWidth1 = nNewWidth - 1L;
965*cdf0e10cSrcweir 			const long	nNewHeight1 = nNewHeight - 1L;
966*cdf0e10cSrcweir 			const long	nWidth = pReadAcc->Width();
967*cdf0e10cSrcweir 			const long	nHeight = pReadAcc->Height();
968*cdf0e10cSrcweir 			long*		pLutX = new long[ nNewWidth ];
969*cdf0e10cSrcweir 			long*		pLutY = new long[ nNewHeight ];
970*cdf0e10cSrcweir 			long		nX, nY, nMapY, nActY = 0L;
971*cdf0e10cSrcweir 
972*cdf0e10cSrcweir 			if( nNewWidth1 && nNewHeight1 )
973*cdf0e10cSrcweir 			{
974*cdf0e10cSrcweir 				for( nX = 0L; nX < nNewWidth; nX++ )
975*cdf0e10cSrcweir 					pLutX[ nX ] = nX * nWidth / nNewWidth;
976*cdf0e10cSrcweir 
977*cdf0e10cSrcweir 				for( nY = 0L; nY < nNewHeight; nY++ )
978*cdf0e10cSrcweir 					pLutY[ nY ] = nY * nHeight / nNewHeight;
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir 				while( nActY < nNewHeight )
981*cdf0e10cSrcweir 				{
982*cdf0e10cSrcweir 					nMapY = pLutY[ nActY ];
983*cdf0e10cSrcweir 
984*cdf0e10cSrcweir 					for( nX = 0L; nX < nNewWidth; nX++ )
985*cdf0e10cSrcweir 						pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
986*cdf0e10cSrcweir 
987*cdf0e10cSrcweir 					while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
988*cdf0e10cSrcweir 					{
989*cdf0e10cSrcweir 						memcpy( pWriteAcc->GetScanline( nActY + 1L ),
990*cdf0e10cSrcweir 								 pWriteAcc->GetScanline( nActY ), nScanlineSize );
991*cdf0e10cSrcweir 						nActY++;
992*cdf0e10cSrcweir 					}
993*cdf0e10cSrcweir 
994*cdf0e10cSrcweir 					nActY++;
995*cdf0e10cSrcweir 				}
996*cdf0e10cSrcweir 
997*cdf0e10cSrcweir 				bRet = sal_True;
998*cdf0e10cSrcweir 			}
999*cdf0e10cSrcweir 
1000*cdf0e10cSrcweir 			delete[] pLutX;
1001*cdf0e10cSrcweir 			delete[] pLutY;
1002*cdf0e10cSrcweir 		}
1003*cdf0e10cSrcweir 
1004*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
1005*cdf0e10cSrcweir 		aNewBmp.ReleaseAccess( pWriteAcc );
1006*cdf0e10cSrcweir 
1007*cdf0e10cSrcweir 		if( bRet )
1008*cdf0e10cSrcweir 			ImplAssignWithSize( aNewBmp );
1009*cdf0e10cSrcweir 	}
1010*cdf0e10cSrcweir 
1011*cdf0e10cSrcweir 	return bRet;
1012*cdf0e10cSrcweir }
1013*cdf0e10cSrcweir 
1014*cdf0e10cSrcweir // ------------------------------------------------------------------------
1015*cdf0e10cSrcweir 
1016*cdf0e10cSrcweir sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1017*cdf0e10cSrcweir {
1018*cdf0e10cSrcweir 	const Size	aSizePix( GetSizePixel() );
1019*cdf0e10cSrcweir 	const long	nNewWidth = FRound( aSizePix.Width() * rScaleX );
1020*cdf0e10cSrcweir 	const long	nNewHeight = FRound( aSizePix.Height() * rScaleY );
1021*cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir 	if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1024*cdf0e10cSrcweir 	{
1025*cdf0e10cSrcweir 		BitmapColor 		aCol0;
1026*cdf0e10cSrcweir 		BitmapColor 		aCol1;
1027*cdf0e10cSrcweir 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1028*cdf0e10cSrcweir 		long				nWidth = pReadAcc->Width();
1029*cdf0e10cSrcweir 		long				nHeight = pReadAcc->Height();
1030*cdf0e10cSrcweir 		Bitmap				aNewBmp( Size( nNewWidth, nHeight ), 24 );
1031*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1032*cdf0e10cSrcweir 		long*				pLutInt;
1033*cdf0e10cSrcweir 		long*				pLutFrac;
1034*cdf0e10cSrcweir 		long				nX, nY;
1035*cdf0e10cSrcweir 		long				lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1036*cdf0e10cSrcweir 		double				fTemp;
1037*cdf0e10cSrcweir 		long				nTemp;
1038*cdf0e10cSrcweir 
1039*cdf0e10cSrcweir 		if( pReadAcc && pWriteAcc )
1040*cdf0e10cSrcweir 		{
1041*cdf0e10cSrcweir 			const long		nNewWidth1 = nNewWidth - 1L;
1042*cdf0e10cSrcweir 			const long		nWidth1 = pReadAcc->Width() - 1L;
1043*cdf0e10cSrcweir 			const double	fRevScaleX = (double) nWidth1 / nNewWidth1;
1044*cdf0e10cSrcweir 
1045*cdf0e10cSrcweir 			pLutInt = new long[ nNewWidth ];
1046*cdf0e10cSrcweir 			pLutFrac = new long[ nNewWidth ];
1047*cdf0e10cSrcweir 
1048*cdf0e10cSrcweir 			for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1049*cdf0e10cSrcweir 			{
1050*cdf0e10cSrcweir 				fTemp = nX * fRevScaleX;
1051*cdf0e10cSrcweir 				pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1052*cdf0e10cSrcweir 				fTemp -= pLutInt[ nX ];
1053*cdf0e10cSrcweir 				pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1054*cdf0e10cSrcweir 			}
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir 			if( pReadAcc->HasPalette() )
1057*cdf0e10cSrcweir 			{
1058*cdf0e10cSrcweir 				for( nY = 0L; nY < nHeight; nY++ )
1059*cdf0e10cSrcweir 				{
1060*cdf0e10cSrcweir 					if( 1 == nWidth )
1061*cdf0e10cSrcweir 					{
1062*cdf0e10cSrcweir 						aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, 0 ) );
1063*cdf0e10cSrcweir 
1064*cdf0e10cSrcweir 						for( nX = 0L; nX < nNewWidth; nX++ )
1065*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1066*cdf0e10cSrcweir 					}
1067*cdf0e10cSrcweir 					else
1068*cdf0e10cSrcweir 					{
1069*cdf0e10cSrcweir 						for( nX = 0L; nX < nNewWidth; nX++ )
1070*cdf0e10cSrcweir 						{
1071*cdf0e10cSrcweir 							nTemp = pLutInt[ nX ];
1072*cdf0e10cSrcweir 
1073*cdf0e10cSrcweir 							aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp++ ) );
1074*cdf0e10cSrcweir 							aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nTemp ) );
1075*cdf0e10cSrcweir 
1076*cdf0e10cSrcweir 							nTemp = pLutFrac[ nX ];
1077*cdf0e10cSrcweir 
1078*cdf0e10cSrcweir 							lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1079*cdf0e10cSrcweir 							lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1080*cdf0e10cSrcweir 							lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1081*cdf0e10cSrcweir 
1082*cdf0e10cSrcweir 							aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1083*cdf0e10cSrcweir 							aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1084*cdf0e10cSrcweir 							aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1085*cdf0e10cSrcweir 
1086*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1087*cdf0e10cSrcweir 						}
1088*cdf0e10cSrcweir 					}
1089*cdf0e10cSrcweir 				}
1090*cdf0e10cSrcweir 			}
1091*cdf0e10cSrcweir 			else
1092*cdf0e10cSrcweir 			{
1093*cdf0e10cSrcweir 				for( nY = 0L; nY < nHeight; nY++ )
1094*cdf0e10cSrcweir 				{
1095*cdf0e10cSrcweir 					if( 1 == nWidth )
1096*cdf0e10cSrcweir 					{
1097*cdf0e10cSrcweir 						aCol0 = pReadAcc->GetPixel( nY, 0 );
1098*cdf0e10cSrcweir 
1099*cdf0e10cSrcweir 						for( nX = 0L; nX < nNewWidth; nX++ )
1100*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1101*cdf0e10cSrcweir 					}
1102*cdf0e10cSrcweir 					else
1103*cdf0e10cSrcweir 					{
1104*cdf0e10cSrcweir 						for( nX = 0L; nX < nNewWidth; nX++ )
1105*cdf0e10cSrcweir 						{
1106*cdf0e10cSrcweir 							nTemp = pLutInt[ nX ];
1107*cdf0e10cSrcweir 
1108*cdf0e10cSrcweir 							aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1109*cdf0e10cSrcweir 							aCol1 = pReadAcc->GetPixel( nY, nTemp );
1110*cdf0e10cSrcweir 
1111*cdf0e10cSrcweir 							nTemp = pLutFrac[ nX ];
1112*cdf0e10cSrcweir 
1113*cdf0e10cSrcweir 							lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1114*cdf0e10cSrcweir 							lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1115*cdf0e10cSrcweir 							lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1116*cdf0e10cSrcweir 
1117*cdf0e10cSrcweir 							aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1118*cdf0e10cSrcweir 							aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1119*cdf0e10cSrcweir 							aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1120*cdf0e10cSrcweir 
1121*cdf0e10cSrcweir 							pWriteAcc->SetPixel( nY, nX, aCol0 );
1122*cdf0e10cSrcweir 						}
1123*cdf0e10cSrcweir 					}
1124*cdf0e10cSrcweir 				}
1125*cdf0e10cSrcweir 			}
1126*cdf0e10cSrcweir 
1127*cdf0e10cSrcweir 			delete[] pLutInt;
1128*cdf0e10cSrcweir 			delete[] pLutFrac;
1129*cdf0e10cSrcweir 			bRet = sal_True;
1130*cdf0e10cSrcweir 		}
1131*cdf0e10cSrcweir 
1132*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
1133*cdf0e10cSrcweir 		aNewBmp.ReleaseAccess( pWriteAcc );
1134*cdf0e10cSrcweir 
1135*cdf0e10cSrcweir 		if( bRet )
1136*cdf0e10cSrcweir 		{
1137*cdf0e10cSrcweir 			bRet = sal_False;
1138*cdf0e10cSrcweir 			ImplAssignWithSize( aNewBmp );
1139*cdf0e10cSrcweir 			pReadAcc = AcquireReadAccess();
1140*cdf0e10cSrcweir 			aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1141*cdf0e10cSrcweir 			pWriteAcc = aNewBmp.AcquireWriteAccess();
1142*cdf0e10cSrcweir 
1143*cdf0e10cSrcweir 			if( pReadAcc && pWriteAcc )
1144*cdf0e10cSrcweir 			{
1145*cdf0e10cSrcweir 				const long		nNewHeight1 = nNewHeight - 1L;
1146*cdf0e10cSrcweir 				const long		nHeight1 = pReadAcc->Height() - 1L;
1147*cdf0e10cSrcweir 				const double	fRevScaleY = (double) nHeight1 / nNewHeight1;
1148*cdf0e10cSrcweir 
1149*cdf0e10cSrcweir 				pLutInt = new long[ nNewHeight ];
1150*cdf0e10cSrcweir 				pLutFrac = new long[ nNewHeight ];
1151*cdf0e10cSrcweir 
1152*cdf0e10cSrcweir 				for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1153*cdf0e10cSrcweir 				{
1154*cdf0e10cSrcweir 					fTemp = nY * fRevScaleY;
1155*cdf0e10cSrcweir 					pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1156*cdf0e10cSrcweir 					fTemp -= pLutInt[ nY ];
1157*cdf0e10cSrcweir 					pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1158*cdf0e10cSrcweir 				}
1159*cdf0e10cSrcweir 
1160*cdf0e10cSrcweir 				if( pReadAcc->HasPalette() )
1161*cdf0e10cSrcweir 				{
1162*cdf0e10cSrcweir 					for( nX = 0L; nX < nNewWidth; nX++ )
1163*cdf0e10cSrcweir 					{
1164*cdf0e10cSrcweir 						if( 1 == nHeight )
1165*cdf0e10cSrcweir 						{
1166*cdf0e10cSrcweir 							aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nX ) );
1167*cdf0e10cSrcweir 
1168*cdf0e10cSrcweir 							for( nY = 0L; nY < nNewHeight; nY++ )
1169*cdf0e10cSrcweir 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1170*cdf0e10cSrcweir 						}
1171*cdf0e10cSrcweir 						else
1172*cdf0e10cSrcweir 						{
1173*cdf0e10cSrcweir 							for( nY = 0L; nY < nNewHeight; nY++ )
1174*cdf0e10cSrcweir 							{
1175*cdf0e10cSrcweir 								nTemp = pLutInt[ nY ];
1176*cdf0e10cSrcweir 
1177*cdf0e10cSrcweir 								aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp++, nX ) );
1178*cdf0e10cSrcweir 								aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nTemp, nX ) );
1179*cdf0e10cSrcweir 
1180*cdf0e10cSrcweir 								nTemp = pLutFrac[ nY ];
1181*cdf0e10cSrcweir 
1182*cdf0e10cSrcweir 								lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1183*cdf0e10cSrcweir 								lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1184*cdf0e10cSrcweir 								lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1185*cdf0e10cSrcweir 
1186*cdf0e10cSrcweir 								aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1187*cdf0e10cSrcweir 								aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1188*cdf0e10cSrcweir 								aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1189*cdf0e10cSrcweir 
1190*cdf0e10cSrcweir 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1191*cdf0e10cSrcweir 							}
1192*cdf0e10cSrcweir 						}
1193*cdf0e10cSrcweir 					}
1194*cdf0e10cSrcweir 				}
1195*cdf0e10cSrcweir 				else
1196*cdf0e10cSrcweir 				{
1197*cdf0e10cSrcweir 					for( nX = 0L; nX < nNewWidth; nX++ )
1198*cdf0e10cSrcweir 					{
1199*cdf0e10cSrcweir 						if( 1 == nHeight )
1200*cdf0e10cSrcweir 						{
1201*cdf0e10cSrcweir 							aCol0 = pReadAcc->GetPixel( 0, nX );
1202*cdf0e10cSrcweir 
1203*cdf0e10cSrcweir 							for( nY = 0L; nY < nNewHeight; nY++ )
1204*cdf0e10cSrcweir 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1205*cdf0e10cSrcweir 						}
1206*cdf0e10cSrcweir 						else
1207*cdf0e10cSrcweir 						{
1208*cdf0e10cSrcweir 							for( nY = 0L; nY < nNewHeight; nY++ )
1209*cdf0e10cSrcweir 							{
1210*cdf0e10cSrcweir 								nTemp = pLutInt[ nY ];
1211*cdf0e10cSrcweir 
1212*cdf0e10cSrcweir 								aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1213*cdf0e10cSrcweir 								aCol1 = pReadAcc->GetPixel( nTemp, nX );
1214*cdf0e10cSrcweir 
1215*cdf0e10cSrcweir 								nTemp = pLutFrac[ nY ];
1216*cdf0e10cSrcweir 
1217*cdf0e10cSrcweir 								lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1218*cdf0e10cSrcweir 								lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1219*cdf0e10cSrcweir 								lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1220*cdf0e10cSrcweir 
1221*cdf0e10cSrcweir 								aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1222*cdf0e10cSrcweir 								aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1223*cdf0e10cSrcweir 								aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1224*cdf0e10cSrcweir 
1225*cdf0e10cSrcweir 								pWriteAcc->SetPixel( nY, nX, aCol0 );
1226*cdf0e10cSrcweir 							}
1227*cdf0e10cSrcweir 						}
1228*cdf0e10cSrcweir 					}
1229*cdf0e10cSrcweir 				}
1230*cdf0e10cSrcweir 
1231*cdf0e10cSrcweir 				delete[] pLutInt;
1232*cdf0e10cSrcweir 				delete[] pLutFrac;
1233*cdf0e10cSrcweir 				bRet = sal_True;
1234*cdf0e10cSrcweir 			}
1235*cdf0e10cSrcweir 
1236*cdf0e10cSrcweir 			ReleaseAccess( pReadAcc );
1237*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWriteAcc );
1238*cdf0e10cSrcweir 
1239*cdf0e10cSrcweir 			if( bRet )
1240*cdf0e10cSrcweir 				ImplAssignWithSize( aNewBmp );
1241*cdf0e10cSrcweir 		}
1242*cdf0e10cSrcweir 	}
1243*cdf0e10cSrcweir 
1244*cdf0e10cSrcweir 	if( !bRet )
1245*cdf0e10cSrcweir 		bRet = ImplScaleFast( rScaleX, rScaleY );
1246*cdf0e10cSrcweir 
1247*cdf0e10cSrcweir 	return bRet;
1248*cdf0e10cSrcweir }
1249*cdf0e10cSrcweir 
1250*cdf0e10cSrcweir // ------------------------------------------------------------------------
1251*cdf0e10cSrcweir 
1252*cdf0e10cSrcweir sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
1253*cdf0e10cSrcweir {
1254*cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
1255*cdf0e10cSrcweir 
1256*cdf0e10cSrcweir 	const Size aSizePix( GetSizePixel() );
1257*cdf0e10cSrcweir 
1258*cdf0e10cSrcweir 	if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
1259*cdf0e10cSrcweir 		bRet = sal_True;
1260*cdf0e10cSrcweir 	else if( nDitherFlags & BMP_DITHER_MATRIX )
1261*cdf0e10cSrcweir 		bRet = ImplDitherMatrix();
1262*cdf0e10cSrcweir 	else if( nDitherFlags & BMP_DITHER_FLOYD )
1263*cdf0e10cSrcweir 		bRet = ImplDitherFloyd();
1264*cdf0e10cSrcweir 	else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
1265*cdf0e10cSrcweir 		bRet = ImplDitherFloyd16();
1266*cdf0e10cSrcweir 
1267*cdf0e10cSrcweir 	return bRet;
1268*cdf0e10cSrcweir }
1269*cdf0e10cSrcweir 
1270*cdf0e10cSrcweir // ------------------------------------------------------------------------
1271*cdf0e10cSrcweir 
1272*cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherMatrix()
1273*cdf0e10cSrcweir {
1274*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1275*cdf0e10cSrcweir 	Bitmap				aNewBmp( GetSizePixel(), 8 );
1276*cdf0e10cSrcweir 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1277*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
1278*cdf0e10cSrcweir 
1279*cdf0e10cSrcweir 	if( pReadAcc && pWriteAcc )
1280*cdf0e10cSrcweir 	{
1281*cdf0e10cSrcweir 		const sal_uLong	nWidth = pReadAcc->Width();
1282*cdf0e10cSrcweir 		const sal_uLong	nHeight = pReadAcc->Height();
1283*cdf0e10cSrcweir 		BitmapColor	aIndex( (sal_uInt8) 0 );
1284*cdf0e10cSrcweir 
1285*cdf0e10cSrcweir 		if( pReadAcc->HasPalette() )
1286*cdf0e10cSrcweir 		{
1287*cdf0e10cSrcweir 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
1288*cdf0e10cSrcweir 			{
1289*cdf0e10cSrcweir 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
1290*cdf0e10cSrcweir 				{
1291*cdf0e10cSrcweir 					const BitmapColor	aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nX ) ) );
1292*cdf0e10cSrcweir 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
1293*cdf0e10cSrcweir 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
1294*cdf0e10cSrcweir 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
1295*cdf0e10cSrcweir 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
1296*cdf0e10cSrcweir 
1297*cdf0e10cSrcweir 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
1298*cdf0e10cSrcweir 					pWriteAcc->SetPixel( nY, nX, aIndex );
1299*cdf0e10cSrcweir 				}
1300*cdf0e10cSrcweir 			}
1301*cdf0e10cSrcweir 		}
1302*cdf0e10cSrcweir 		else
1303*cdf0e10cSrcweir 		{
1304*cdf0e10cSrcweir 			for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
1305*cdf0e10cSrcweir 			{
1306*cdf0e10cSrcweir 				for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
1307*cdf0e10cSrcweir 				{
1308*cdf0e10cSrcweir 					const BitmapColor	aCol( pReadAcc->GetPixel( nY, nX ) );
1309*cdf0e10cSrcweir 					const sal_uLong			nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
1310*cdf0e10cSrcweir 					const sal_uLong			nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
1311*cdf0e10cSrcweir 					const sal_uLong			nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
1312*cdf0e10cSrcweir 					const sal_uLong			nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
1313*cdf0e10cSrcweir 
1314*cdf0e10cSrcweir 					aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
1315*cdf0e10cSrcweir 					pWriteAcc->SetPixel( nY, nX, aIndex );
1316*cdf0e10cSrcweir 				}
1317*cdf0e10cSrcweir 			}
1318*cdf0e10cSrcweir 		}
1319*cdf0e10cSrcweir 
1320*cdf0e10cSrcweir 		bRet = sal_True;
1321*cdf0e10cSrcweir 	}
1322*cdf0e10cSrcweir 
1323*cdf0e10cSrcweir 	ReleaseAccess( pReadAcc );
1324*cdf0e10cSrcweir 	aNewBmp.ReleaseAccess( pWriteAcc );
1325*cdf0e10cSrcweir 
1326*cdf0e10cSrcweir 	if( bRet )
1327*cdf0e10cSrcweir 	{
1328*cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
1329*cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
1330*cdf0e10cSrcweir 
1331*cdf0e10cSrcweir 		*this = aNewBmp;
1332*cdf0e10cSrcweir 
1333*cdf0e10cSrcweir 		maPrefMapMode = aMap;
1334*cdf0e10cSrcweir 		maPrefSize = aSize;
1335*cdf0e10cSrcweir 	}
1336*cdf0e10cSrcweir 
1337*cdf0e10cSrcweir 	return bRet;
1338*cdf0e10cSrcweir }
1339*cdf0e10cSrcweir 
1340*cdf0e10cSrcweir // ------------------------------------------------------------------------
1341*cdf0e10cSrcweir 
1342*cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherFloyd()
1343*cdf0e10cSrcweir {
1344*cdf0e10cSrcweir 	const Size	aSize( GetSizePixel() );
1345*cdf0e10cSrcweir 	sal_Bool		bRet = sal_False;
1346*cdf0e10cSrcweir 
1347*cdf0e10cSrcweir 	if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
1348*cdf0e10cSrcweir 	{
1349*cdf0e10cSrcweir 		BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1350*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), 8 );
1351*cdf0e10cSrcweir 		BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1352*cdf0e10cSrcweir 
1353*cdf0e10cSrcweir 		if( pReadAcc && pWriteAcc )
1354*cdf0e10cSrcweir 		{
1355*cdf0e10cSrcweir 			BitmapColor	aColor;
1356*cdf0e10cSrcweir 			long		nWidth = pReadAcc->Width();
1357*cdf0e10cSrcweir 			long		nWidth1 = nWidth - 1L;
1358*cdf0e10cSrcweir 			long		nHeight = pReadAcc->Height();
1359*cdf0e10cSrcweir 			long		nX;
1360*cdf0e10cSrcweir 			long		nW = nWidth * 3L;
1361*cdf0e10cSrcweir 			long		nW2 = nW - 3L;
1362*cdf0e10cSrcweir 			long		nRErr, nGErr, nBErr;
1363*cdf0e10cSrcweir 			long		nRC, nGC, nBC;
1364*cdf0e10cSrcweir 			long		nTemp;
1365*cdf0e10cSrcweir 			long		nZ;
1366*cdf0e10cSrcweir 			long*		p1 = new long[ nW ];
1367*cdf0e10cSrcweir 			long*		p2 = new long[ nW ];
1368*cdf0e10cSrcweir 			long*		p1T = p1;
1369*cdf0e10cSrcweir 			long*		p2T = p2;
1370*cdf0e10cSrcweir 			long*		pTmp;
1371*cdf0e10cSrcweir 			sal_Bool		bPal = pReadAcc->HasPalette();
1372*cdf0e10cSrcweir 
1373*cdf0e10cSrcweir 			pTmp = p2T;
1374*cdf0e10cSrcweir 
1375*cdf0e10cSrcweir 			if( bPal )
1376*cdf0e10cSrcweir 			{
1377*cdf0e10cSrcweir 				for( nZ = 0; nZ < nWidth; nZ++ )
1378*cdf0e10cSrcweir 				{
1379*cdf0e10cSrcweir 					aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( 0, nZ ) );
1380*cdf0e10cSrcweir 
1381*cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetBlue() << 12;
1382*cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetGreen() << 12;
1383*cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetRed() << 12;
1384*cdf0e10cSrcweir 				}
1385*cdf0e10cSrcweir 			}
1386*cdf0e10cSrcweir 			else
1387*cdf0e10cSrcweir 			{
1388*cdf0e10cSrcweir 				for( nZ = 0; nZ < nWidth; nZ++ )
1389*cdf0e10cSrcweir 				{
1390*cdf0e10cSrcweir 					aColor = pReadAcc->GetPixel( 0, nZ );
1391*cdf0e10cSrcweir 
1392*cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetBlue() << 12;
1393*cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetGreen() << 12;
1394*cdf0e10cSrcweir 					*pTmp++ = (long) aColor.GetRed() << 12;
1395*cdf0e10cSrcweir 				}
1396*cdf0e10cSrcweir 			}
1397*cdf0e10cSrcweir 
1398*cdf0e10cSrcweir 			for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
1399*cdf0e10cSrcweir 			{
1400*cdf0e10cSrcweir 				pTmp = p1T;
1401*cdf0e10cSrcweir 				p1T = p2T;
1402*cdf0e10cSrcweir 				p2T = pTmp;
1403*cdf0e10cSrcweir 
1404*cdf0e10cSrcweir 				if( nY < nHeight )
1405*cdf0e10cSrcweir 				{
1406*cdf0e10cSrcweir 					if( bPal )
1407*cdf0e10cSrcweir 					{
1408*cdf0e10cSrcweir 						for( nZ = 0; nZ < nWidth; nZ++ )
1409*cdf0e10cSrcweir 						{
1410*cdf0e10cSrcweir 							aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( nY, nZ ) );
1411*cdf0e10cSrcweir 
1412*cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetBlue() << 12;
1413*cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetGreen() << 12;
1414*cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetRed() << 12;
1415*cdf0e10cSrcweir 						}
1416*cdf0e10cSrcweir 					}
1417*cdf0e10cSrcweir 					else
1418*cdf0e10cSrcweir 					{
1419*cdf0e10cSrcweir 						for( nZ = 0; nZ < nWidth; nZ++ )
1420*cdf0e10cSrcweir 						{
1421*cdf0e10cSrcweir 							aColor = pReadAcc->GetPixel( nY, nZ );
1422*cdf0e10cSrcweir 
1423*cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetBlue() << 12;
1424*cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetGreen() << 12;
1425*cdf0e10cSrcweir 							*pTmp++ = (long) aColor.GetRed() << 12;
1426*cdf0e10cSrcweir 						}
1427*cdf0e10cSrcweir 					}
1428*cdf0e10cSrcweir 				}
1429*cdf0e10cSrcweir 
1430*cdf0e10cSrcweir 				// erstes Pixel gesondert betrachten
1431*cdf0e10cSrcweir 				nX = 0;
1432*cdf0e10cSrcweir 				CALC_ERRORS;
1433*cdf0e10cSrcweir 				CALC_TABLES7;
1434*cdf0e10cSrcweir 				nX -= 5;
1435*cdf0e10cSrcweir 				CALC_TABLES5;
1436*cdf0e10cSrcweir 				pWriteAcc->SetPixel( nYAcc, 0, BitmapColor( (sal_uInt8) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
1437*cdf0e10cSrcweir 
1438*cdf0e10cSrcweir 				// mittlere Pixel ueber Schleife
1439*cdf0e10cSrcweir 				long nXAcc;
1440*cdf0e10cSrcweir 				for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
1441*cdf0e10cSrcweir 				{
1442*cdf0e10cSrcweir 					CALC_ERRORS;
1443*cdf0e10cSrcweir 					CALC_TABLES7;
1444*cdf0e10cSrcweir 					nX -= 8;
1445*cdf0e10cSrcweir 					CALC_TABLES3;
1446*cdf0e10cSrcweir 					CALC_TABLES5;
1447*cdf0e10cSrcweir 					pWriteAcc->SetPixel( nYAcc, nXAcc, BitmapColor( (sal_uInt8) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
1448*cdf0e10cSrcweir 				}
1449*cdf0e10cSrcweir 
1450*cdf0e10cSrcweir 				// letztes Pixel gesondert betrachten
1451*cdf0e10cSrcweir 				CALC_ERRORS;
1452*cdf0e10cSrcweir 				nX -= 5;
1453*cdf0e10cSrcweir 				CALC_TABLES3;
1454*cdf0e10cSrcweir 				CALC_TABLES5;
1455*cdf0e10cSrcweir 				pWriteAcc->SetPixel( nYAcc, nWidth1, BitmapColor( (sal_uInt8) ( nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ] ) ) );
1456*cdf0e10cSrcweir 			}
1457*cdf0e10cSrcweir 
1458*cdf0e10cSrcweir 			delete[] p1;
1459*cdf0e10cSrcweir 			delete[] p2;
1460*cdf0e10cSrcweir 			bRet = sal_True;
1461*cdf0e10cSrcweir 		}
1462*cdf0e10cSrcweir 
1463*cdf0e10cSrcweir 		ReleaseAccess( pReadAcc );
1464*cdf0e10cSrcweir 		aNewBmp.ReleaseAccess( pWriteAcc );
1465*cdf0e10cSrcweir 
1466*cdf0e10cSrcweir 		if( bRet )
1467*cdf0e10cSrcweir 		{
1468*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
1469*cdf0e10cSrcweir 			const Size		aPrefSize( maPrefSize );
1470*cdf0e10cSrcweir 
1471*cdf0e10cSrcweir 			*this = aNewBmp;
1472*cdf0e10cSrcweir 
1473*cdf0e10cSrcweir 			maPrefMapMode = aMap;
1474*cdf0e10cSrcweir 			maPrefSize = aPrefSize;
1475*cdf0e10cSrcweir 		}
1476*cdf0e10cSrcweir 	}
1477*cdf0e10cSrcweir 
1478*cdf0e10cSrcweir 	return bRet;
1479*cdf0e10cSrcweir }
1480*cdf0e10cSrcweir 
1481*cdf0e10cSrcweir // ------------------------------------------------------------------------
1482*cdf0e10cSrcweir 
1483*cdf0e10cSrcweir sal_Bool Bitmap::ImplDitherFloyd16()
1484*cdf0e10cSrcweir {
1485*cdf0e10cSrcweir 	BitmapReadAccess*	pReadAcc = AcquireReadAccess();
1486*cdf0e10cSrcweir 	Bitmap				aNewBmp( GetSizePixel(), 24 );
1487*cdf0e10cSrcweir 	BitmapWriteAccess*	pWriteAcc = aNewBmp.AcquireWriteAccess();
1488*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
1489*cdf0e10cSrcweir 
1490*cdf0e10cSrcweir 	if( pReadAcc && pWriteAcc )
1491*cdf0e10cSrcweir 	{
1492*cdf0e10cSrcweir 		const long		nWidth = pWriteAcc->Width();
1493*cdf0e10cSrcweir 		const long		nWidth1 = nWidth - 1L;
1494*cdf0e10cSrcweir 		const long		nHeight = pWriteAcc->Height();
1495*cdf0e10cSrcweir 		BitmapColor 	aColor;
1496*cdf0e10cSrcweir 		BitmapColor		aBestCol;
1497*cdf0e10cSrcweir 		ImpErrorQuad	aErrQuad;
1498*cdf0e10cSrcweir 		ImpErrorQuad*	pErrQuad1 = new ImpErrorQuad[ nWidth ];
1499*cdf0e10cSrcweir 		ImpErrorQuad*	pErrQuad2 = new ImpErrorQuad[ nWidth ];
1500*cdf0e10cSrcweir 		ImpErrorQuad*	pQLine1 = pErrQuad1;
1501*cdf0e10cSrcweir 		ImpErrorQuad*	pQLine2 = 0;
1502*cdf0e10cSrcweir 		long			nX, nY;
1503*cdf0e10cSrcweir 		long			nYTmp = 0L;
1504*cdf0e10cSrcweir 		sal_Bool			bQ1 = sal_True;
1505*cdf0e10cSrcweir 
1506*cdf0e10cSrcweir 		for( nY = 0L; nY < Min( nHeight, 2L ); nY++, nYTmp++ )
1507*cdf0e10cSrcweir 			for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
1508*cdf0e10cSrcweir 				pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
1509*cdf0e10cSrcweir 
1510*cdf0e10cSrcweir 		for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
1511*cdf0e10cSrcweir 		{
1512*cdf0e10cSrcweir 			// erstes ZeilenPixel
1513*cdf0e10cSrcweir 			aBestCol = pQLine1[ 0 ].ImplGetColor();
1514*cdf0e10cSrcweir 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
1515*cdf0e10cSrcweir 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
1516*cdf0e10cSrcweir 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
1517*cdf0e10cSrcweir 			pWriteAcc->SetPixel( nY, 0, aBestCol );
1518*cdf0e10cSrcweir 
1519*cdf0e10cSrcweir 			for( nX = 1L; nX < nWidth1; nX++ )
1520*cdf0e10cSrcweir 			{
1521*cdf0e10cSrcweir 				aColor = pQLine1[ nX ].ImplGetColor();
1522*cdf0e10cSrcweir 				aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
1523*cdf0e10cSrcweir 				aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
1524*cdf0e10cSrcweir 				aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
1525*cdf0e10cSrcweir 				aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
1526*cdf0e10cSrcweir 				pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
1527*cdf0e10cSrcweir 				pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
1528*cdf0e10cSrcweir 				pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
1529*cdf0e10cSrcweir 				pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
1530*cdf0e10cSrcweir 				pWriteAcc->SetPixel( nY, nX, aBestCol );
1531*cdf0e10cSrcweir 			}
1532*cdf0e10cSrcweir 
1533*cdf0e10cSrcweir 			// letztes ZeilenPixel
1534*cdf0e10cSrcweir 			aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
1535*cdf0e10cSrcweir 			aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
1536*cdf0e10cSrcweir 			aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
1537*cdf0e10cSrcweir 			aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
1538*cdf0e10cSrcweir 			pWriteAcc->SetPixel( nY, nX, aBestCol );
1539*cdf0e10cSrcweir 
1540*cdf0e10cSrcweir 			// Zeilenpuffer neu fuellen/kopieren
1541*cdf0e10cSrcweir 			pQLine1 = pQLine2;
1542*cdf0e10cSrcweir 			pQLine2 = ( bQ1 = !bQ1 ) != sal_False ? pErrQuad2 : pErrQuad1;
1543*cdf0e10cSrcweir 
1544*cdf0e10cSrcweir 			if( nYTmp < nHeight )
1545*cdf0e10cSrcweir 				for( nX = 0L; nX < nWidth; nX++ )
1546*cdf0e10cSrcweir 					pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
1547*cdf0e10cSrcweir 		}
1548*cdf0e10cSrcweir 
1549*cdf0e10cSrcweir 		// Zeilenpuffer zerstoeren
1550*cdf0e10cSrcweir 		delete[] pErrQuad1;
1551*cdf0e10cSrcweir 		delete[] pErrQuad2;
1552*cdf0e10cSrcweir 		bRet = sal_True;
1553*cdf0e10cSrcweir 	}
1554*cdf0e10cSrcweir 
1555*cdf0e10cSrcweir 	ReleaseAccess( pReadAcc );
1556*cdf0e10cSrcweir 	aNewBmp.ReleaseAccess( pWriteAcc );
1557*cdf0e10cSrcweir 
1558*cdf0e10cSrcweir 	if( bRet )
1559*cdf0e10cSrcweir 	{
1560*cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
1561*cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
1562*cdf0e10cSrcweir 
1563*cdf0e10cSrcweir 		*this = aNewBmp;
1564*cdf0e10cSrcweir 
1565*cdf0e10cSrcweir 		maPrefMapMode = aMap;
1566*cdf0e10cSrcweir 		maPrefSize = aSize;
1567*cdf0e10cSrcweir 	}
1568*cdf0e10cSrcweir 
1569*cdf0e10cSrcweir 	return bRet;
1570*cdf0e10cSrcweir }
1571*cdf0e10cSrcweir 
1572*cdf0e10cSrcweir // ------------------------------------------------------------------------
1573*cdf0e10cSrcweir 
1574*cdf0e10cSrcweir sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
1575*cdf0e10cSrcweir {
1576*cdf0e10cSrcweir 	sal_Bool bRet;
1577*cdf0e10cSrcweir 
1578*cdf0e10cSrcweir 	if( GetColorCount() <= (sal_uLong) nColorCount )
1579*cdf0e10cSrcweir 		bRet = sal_True;
1580*cdf0e10cSrcweir 	else if( nColorCount )
1581*cdf0e10cSrcweir 	{
1582*cdf0e10cSrcweir 		if( BMP_REDUCE_SIMPLE == eReduce )
1583*cdf0e10cSrcweir 			bRet = ImplReduceSimple( nColorCount );
1584*cdf0e10cSrcweir 		else if( BMP_REDUCE_POPULAR == eReduce )
1585*cdf0e10cSrcweir 			bRet = ImplReducePopular( nColorCount );
1586*cdf0e10cSrcweir 		else
1587*cdf0e10cSrcweir 			bRet = ImplReduceMedian( nColorCount );
1588*cdf0e10cSrcweir 	}
1589*cdf0e10cSrcweir 	else
1590*cdf0e10cSrcweir 		bRet = sal_False;
1591*cdf0e10cSrcweir 
1592*cdf0e10cSrcweir 	return bRet;
1593*cdf0e10cSrcweir }
1594*cdf0e10cSrcweir 
1595*cdf0e10cSrcweir // ------------------------------------------------------------------------
1596*cdf0e10cSrcweir 
1597*cdf0e10cSrcweir sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
1598*cdf0e10cSrcweir {
1599*cdf0e10cSrcweir 	Bitmap				aNewBmp;
1600*cdf0e10cSrcweir 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
1601*cdf0e10cSrcweir 	const sal_uInt16		nColCount = Min( nColorCount, (sal_uInt16) 256 );
1602*cdf0e10cSrcweir 	sal_uInt16				nBitCount;
1603*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
1604*cdf0e10cSrcweir 
1605*cdf0e10cSrcweir 	if( nColCount <= 2 )
1606*cdf0e10cSrcweir 		nBitCount = 1;
1607*cdf0e10cSrcweir 	else if( nColCount <= 16 )
1608*cdf0e10cSrcweir 		nBitCount = 4;
1609*cdf0e10cSrcweir 	else
1610*cdf0e10cSrcweir 		nBitCount = 8;
1611*cdf0e10cSrcweir 
1612*cdf0e10cSrcweir 	if( pRAcc )
1613*cdf0e10cSrcweir 	{
1614*cdf0e10cSrcweir 		Octree					aOct( *pRAcc, nColCount );
1615*cdf0e10cSrcweir 		const BitmapPalette&	rPal = aOct.GetPalette();
1616*cdf0e10cSrcweir 		BitmapWriteAccess*		pWAcc;
1617*cdf0e10cSrcweir 
1618*cdf0e10cSrcweir 		aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
1619*cdf0e10cSrcweir 		pWAcc = aNewBmp.AcquireWriteAccess();
1620*cdf0e10cSrcweir 
1621*cdf0e10cSrcweir 		if( pWAcc )
1622*cdf0e10cSrcweir 		{
1623*cdf0e10cSrcweir 			const long nWidth = pRAcc->Width();
1624*cdf0e10cSrcweir 			const long nHeight = pRAcc->Height();
1625*cdf0e10cSrcweir 
1626*cdf0e10cSrcweir 			if( pRAcc->HasPalette() )
1627*cdf0e10cSrcweir 			{
1628*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
1629*cdf0e10cSrcweir 					for( long nX =0L; nX < nWidth; nX++ )
1630*cdf0e10cSrcweir 						pWAcc->SetPixel( nY, nX, (sal_uInt8) aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) ) ) );
1631*cdf0e10cSrcweir 			}
1632*cdf0e10cSrcweir 			else
1633*cdf0e10cSrcweir 			{
1634*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
1635*cdf0e10cSrcweir 					for( long nX =0L; nX < nWidth; nX++ )
1636*cdf0e10cSrcweir 						pWAcc->SetPixel( nY, nX, (sal_uInt8) aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) ) );
1637*cdf0e10cSrcweir 			}
1638*cdf0e10cSrcweir 
1639*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWAcc );
1640*cdf0e10cSrcweir 			bRet = sal_True;
1641*cdf0e10cSrcweir 		}
1642*cdf0e10cSrcweir 
1643*cdf0e10cSrcweir 		ReleaseAccess( pRAcc );
1644*cdf0e10cSrcweir 	}
1645*cdf0e10cSrcweir 
1646*cdf0e10cSrcweir 	if( bRet )
1647*cdf0e10cSrcweir 	{
1648*cdf0e10cSrcweir 		const MapMode	aMap( maPrefMapMode );
1649*cdf0e10cSrcweir 		const Size		aSize( maPrefSize );
1650*cdf0e10cSrcweir 
1651*cdf0e10cSrcweir 		*this = aNewBmp;
1652*cdf0e10cSrcweir 		maPrefMapMode = aMap;
1653*cdf0e10cSrcweir 		maPrefSize = aSize;
1654*cdf0e10cSrcweir 	}
1655*cdf0e10cSrcweir 
1656*cdf0e10cSrcweir 	return bRet;
1657*cdf0e10cSrcweir }
1658*cdf0e10cSrcweir 
1659*cdf0e10cSrcweir // ------------------------------------------------------------------------
1660*cdf0e10cSrcweir 
1661*cdf0e10cSrcweir struct PopularColorCount
1662*cdf0e10cSrcweir {
1663*cdf0e10cSrcweir 	sal_uInt32	mnIndex;
1664*cdf0e10cSrcweir 	sal_uInt32	mnCount;
1665*cdf0e10cSrcweir };
1666*cdf0e10cSrcweir 
1667*cdf0e10cSrcweir // ------------------------------------------------------------------------
1668*cdf0e10cSrcweir 
1669*cdf0e10cSrcweir extern "C" int __LOADONCALLAPI ImplPopularCmpFnc( const void* p1, const void* p2 )
1670*cdf0e10cSrcweir {
1671*cdf0e10cSrcweir 	int nRet;
1672*cdf0e10cSrcweir 
1673*cdf0e10cSrcweir 	if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
1674*cdf0e10cSrcweir 		nRet = 1;
1675*cdf0e10cSrcweir 	else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
1676*cdf0e10cSrcweir 		nRet = 0;
1677*cdf0e10cSrcweir 	else
1678*cdf0e10cSrcweir 		nRet = -1;
1679*cdf0e10cSrcweir 
1680*cdf0e10cSrcweir 	return nRet;
1681*cdf0e10cSrcweir }
1682*cdf0e10cSrcweir 
1683*cdf0e10cSrcweir // ------------------------------------------------------------------------
1684*cdf0e10cSrcweir 
1685*cdf0e10cSrcweir sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
1686*cdf0e10cSrcweir {
1687*cdf0e10cSrcweir 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
1688*cdf0e10cSrcweir 	sal_uInt16				nBitCount;
1689*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
1690*cdf0e10cSrcweir 
1691*cdf0e10cSrcweir 	if( nColCount > 256 )
1692*cdf0e10cSrcweir 		nColCount = 256;
1693*cdf0e10cSrcweir 
1694*cdf0e10cSrcweir 	if( nColCount < 17 )
1695*cdf0e10cSrcweir 		nBitCount = 4;
1696*cdf0e10cSrcweir 	else
1697*cdf0e10cSrcweir 		nBitCount = 8;
1698*cdf0e10cSrcweir 
1699*cdf0e10cSrcweir 	if( pRAcc )
1700*cdf0e10cSrcweir 	{
1701*cdf0e10cSrcweir 		const sal_uInt32	nValidBits = 4;
1702*cdf0e10cSrcweir 		const sal_uInt32	nRightShiftBits = 8 - nValidBits;
1703*cdf0e10cSrcweir 		const sal_uInt32	nLeftShiftBits1 = nValidBits;
1704*cdf0e10cSrcweir 		const sal_uInt32	nLeftShiftBits2 = nValidBits << 1;
1705*cdf0e10cSrcweir 		const sal_uInt32	nColorsPerComponent = 1 << nValidBits;
1706*cdf0e10cSrcweir 		const sal_uInt32	nColorOffset = 256 / nColorsPerComponent;
1707*cdf0e10cSrcweir 		const sal_uInt32	nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
1708*cdf0e10cSrcweir 		const long			nWidth = pRAcc->Width();
1709*cdf0e10cSrcweir 		const long			nHeight = pRAcc->Height();
1710*cdf0e10cSrcweir 		PopularColorCount*	pCountTable = new PopularColorCount[ nTotalColors ];
1711*cdf0e10cSrcweir 		long				nX, nY, nR, nG, nB, nIndex;
1712*cdf0e10cSrcweir 
1713*cdf0e10cSrcweir 		rtl_zeroMemory( pCountTable, nTotalColors * sizeof( PopularColorCount ) );
1714*cdf0e10cSrcweir 
1715*cdf0e10cSrcweir 		for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
1716*cdf0e10cSrcweir         {
1717*cdf0e10cSrcweir 			for( nG = 0; nG < 256; nG += nColorOffset )
1718*cdf0e10cSrcweir             {
1719*cdf0e10cSrcweir 				for( nB = 0; nB < 256; nB += nColorOffset )
1720*cdf0e10cSrcweir                 {
1721*cdf0e10cSrcweir 					pCountTable[ nIndex ].mnIndex = nIndex;
1722*cdf0e10cSrcweir                     nIndex++;
1723*cdf0e10cSrcweir                 }
1724*cdf0e10cSrcweir             }
1725*cdf0e10cSrcweir         }
1726*cdf0e10cSrcweir 
1727*cdf0e10cSrcweir 		if( pRAcc->HasPalette() )
1728*cdf0e10cSrcweir 		{
1729*cdf0e10cSrcweir 			for( nY = 0L; nY < nHeight; nY++ )
1730*cdf0e10cSrcweir 			{
1731*cdf0e10cSrcweir 				for( nX = 0L; nX < nWidth; nX++ )
1732*cdf0e10cSrcweir 				{
1733*cdf0e10cSrcweir 					const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
1734*cdf0e10cSrcweir 					pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1735*cdf0e10cSrcweir 								 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1736*cdf0e10cSrcweir 								 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
1737*cdf0e10cSrcweir 				}
1738*cdf0e10cSrcweir 			}
1739*cdf0e10cSrcweir 		}
1740*cdf0e10cSrcweir 		else
1741*cdf0e10cSrcweir 		{
1742*cdf0e10cSrcweir 			for( nY = 0L; nY < nHeight; nY++ )
1743*cdf0e10cSrcweir 			{
1744*cdf0e10cSrcweir 				for( nX = 0L; nX < nWidth; nX++ )
1745*cdf0e10cSrcweir 				{
1746*cdf0e10cSrcweir 					const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
1747*cdf0e10cSrcweir 					pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1748*cdf0e10cSrcweir 								 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1749*cdf0e10cSrcweir 								 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
1750*cdf0e10cSrcweir 				}
1751*cdf0e10cSrcweir 			}
1752*cdf0e10cSrcweir 		}
1753*cdf0e10cSrcweir 
1754*cdf0e10cSrcweir 		BitmapPalette aNewPal( nColCount );
1755*cdf0e10cSrcweir 
1756*cdf0e10cSrcweir 		qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
1757*cdf0e10cSrcweir 
1758*cdf0e10cSrcweir 		for( sal_uInt16 n = 0; n < nColCount; n++ )
1759*cdf0e10cSrcweir 		{
1760*cdf0e10cSrcweir 			const PopularColorCount& rPop = pCountTable[ n ];
1761*cdf0e10cSrcweir 			aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
1762*cdf0e10cSrcweir 										(sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
1763*cdf0e10cSrcweir 										(sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
1764*cdf0e10cSrcweir 		}
1765*cdf0e10cSrcweir 
1766*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
1767*cdf0e10cSrcweir 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
1768*cdf0e10cSrcweir 
1769*cdf0e10cSrcweir 		if( pWAcc )
1770*cdf0e10cSrcweir 		{
1771*cdf0e10cSrcweir 			BitmapColor	aDstCol( (sal_uInt8) 0 );
1772*cdf0e10cSrcweir 			sal_uInt8*		pIndexMap = new sal_uInt8[ nTotalColors ];
1773*cdf0e10cSrcweir 
1774*cdf0e10cSrcweir 			for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
1775*cdf0e10cSrcweir 				for( nG = 0; nG < 256; nG += nColorOffset )
1776*cdf0e10cSrcweir 					for( nB = 0; nB < 256; nB += nColorOffset )
1777*cdf0e10cSrcweir 						pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
1778*cdf0e10cSrcweir 
1779*cdf0e10cSrcweir 			if( pRAcc->HasPalette() )
1780*cdf0e10cSrcweir 			{
1781*cdf0e10cSrcweir 				for( nY = 0L; nY < nHeight; nY++ )
1782*cdf0e10cSrcweir 				{
1783*cdf0e10cSrcweir 					for( nX = 0L; nX < nWidth; nX++ )
1784*cdf0e10cSrcweir 					{
1785*cdf0e10cSrcweir 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
1786*cdf0e10cSrcweir 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1787*cdf0e10cSrcweir 													 ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1788*cdf0e10cSrcweir 													 ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
1789*cdf0e10cSrcweir 						pWAcc->SetPixel( nY, nX, aDstCol );
1790*cdf0e10cSrcweir 					}
1791*cdf0e10cSrcweir 				}
1792*cdf0e10cSrcweir 			}
1793*cdf0e10cSrcweir 			else
1794*cdf0e10cSrcweir 			{
1795*cdf0e10cSrcweir 				for( nY = 0L; nY < nHeight; nY++ )
1796*cdf0e10cSrcweir 				{
1797*cdf0e10cSrcweir 					for( nX = 0L; nX < nWidth; nX++ )
1798*cdf0e10cSrcweir 					{
1799*cdf0e10cSrcweir 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
1800*cdf0e10cSrcweir 						aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
1801*cdf0e10cSrcweir 													 ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
1802*cdf0e10cSrcweir 													 ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
1803*cdf0e10cSrcweir 						pWAcc->SetPixel( nY, nX, aDstCol );
1804*cdf0e10cSrcweir 					}
1805*cdf0e10cSrcweir 				}
1806*cdf0e10cSrcweir 			}
1807*cdf0e10cSrcweir 
1808*cdf0e10cSrcweir 			delete[] pIndexMap;
1809*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWAcc );
1810*cdf0e10cSrcweir 			bRet = sal_True;
1811*cdf0e10cSrcweir 		}
1812*cdf0e10cSrcweir 
1813*cdf0e10cSrcweir 		delete[] pCountTable;
1814*cdf0e10cSrcweir 		ReleaseAccess( pRAcc );
1815*cdf0e10cSrcweir 
1816*cdf0e10cSrcweir 		if( bRet )
1817*cdf0e10cSrcweir 		{
1818*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
1819*cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
1820*cdf0e10cSrcweir 
1821*cdf0e10cSrcweir 			*this = aNewBmp;
1822*cdf0e10cSrcweir 			maPrefMapMode = aMap;
1823*cdf0e10cSrcweir 			maPrefSize = aSize;
1824*cdf0e10cSrcweir 		}
1825*cdf0e10cSrcweir 	}
1826*cdf0e10cSrcweir 
1827*cdf0e10cSrcweir 	return bRet;
1828*cdf0e10cSrcweir }
1829*cdf0e10cSrcweir 
1830*cdf0e10cSrcweir // ------------------------------------------------------------------------
1831*cdf0e10cSrcweir 
1832*cdf0e10cSrcweir sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
1833*cdf0e10cSrcweir {
1834*cdf0e10cSrcweir 	BitmapReadAccess*	pRAcc = AcquireReadAccess();
1835*cdf0e10cSrcweir 	sal_uInt16				nBitCount;
1836*cdf0e10cSrcweir 	sal_Bool				bRet = sal_False;
1837*cdf0e10cSrcweir 
1838*cdf0e10cSrcweir 	if( nColCount < 17 )
1839*cdf0e10cSrcweir 		nBitCount = 4;
1840*cdf0e10cSrcweir 	else if( nColCount < 257 )
1841*cdf0e10cSrcweir 		nBitCount = 8;
1842*cdf0e10cSrcweir 	else
1843*cdf0e10cSrcweir 	{
1844*cdf0e10cSrcweir 		DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
1845*cdf0e10cSrcweir 		nBitCount = 8;
1846*cdf0e10cSrcweir 		nColCount = 256;
1847*cdf0e10cSrcweir 	}
1848*cdf0e10cSrcweir 
1849*cdf0e10cSrcweir 	if( pRAcc )
1850*cdf0e10cSrcweir 	{
1851*cdf0e10cSrcweir 		Bitmap				aNewBmp( GetSizePixel(), nBitCount );
1852*cdf0e10cSrcweir 		BitmapWriteAccess*	pWAcc = aNewBmp.AcquireWriteAccess();
1853*cdf0e10cSrcweir 
1854*cdf0e10cSrcweir 		if( pWAcc )
1855*cdf0e10cSrcweir 		{
1856*cdf0e10cSrcweir 			const sal_uLong	nSize = 32768UL * sizeof( sal_uLong );
1857*cdf0e10cSrcweir 			sal_uLong*		pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
1858*cdf0e10cSrcweir 			const long	nWidth = pWAcc->Width();
1859*cdf0e10cSrcweir 			const long	nHeight = pWAcc->Height();
1860*cdf0e10cSrcweir 			long		nIndex = 0L;
1861*cdf0e10cSrcweir 
1862*cdf0e10cSrcweir 			memset( (HPBYTE) pColBuf, 0, nSize );
1863*cdf0e10cSrcweir 
1864*cdf0e10cSrcweir 			// create Buffer
1865*cdf0e10cSrcweir 			if( pRAcc->HasPalette() )
1866*cdf0e10cSrcweir 			{
1867*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
1868*cdf0e10cSrcweir 				{
1869*cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
1870*cdf0e10cSrcweir 					{
1871*cdf0e10cSrcweir 						const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixel( nY, nX ) );
1872*cdf0e10cSrcweir 						pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
1873*cdf0e10cSrcweir 					}
1874*cdf0e10cSrcweir 				}
1875*cdf0e10cSrcweir 			}
1876*cdf0e10cSrcweir 			else
1877*cdf0e10cSrcweir 			{
1878*cdf0e10cSrcweir 				for( long nY = 0L; nY < nHeight; nY++ )
1879*cdf0e10cSrcweir 				{
1880*cdf0e10cSrcweir 					for( long nX = 0L; nX < nWidth; nX++ )
1881*cdf0e10cSrcweir 					{
1882*cdf0e10cSrcweir 						const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
1883*cdf0e10cSrcweir 						pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
1884*cdf0e10cSrcweir 					}
1885*cdf0e10cSrcweir 				}
1886*cdf0e10cSrcweir 			}
1887*cdf0e10cSrcweir 
1888*cdf0e10cSrcweir 			// create palette via median cut
1889*cdf0e10cSrcweir 			BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
1890*cdf0e10cSrcweir 			ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
1891*cdf0e10cSrcweir 						   nColCount, nWidth * nHeight, nIndex );
1892*cdf0e10cSrcweir 
1893*cdf0e10cSrcweir 			// do mapping of colors to palette
1894*cdf0e10cSrcweir 			InverseColorMap aMap( aPal );
1895*cdf0e10cSrcweir 			pWAcc->SetPalette( aPal );
1896*cdf0e10cSrcweir 			for( long nY = 0L; nY < nHeight; nY++ )
1897*cdf0e10cSrcweir 				for( long nX = 0L; nX < nWidth; nX++ )
1898*cdf0e10cSrcweir 					pWAcc->SetPixel( nY, nX, (sal_uInt8) aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) ) );
1899*cdf0e10cSrcweir 
1900*cdf0e10cSrcweir 			rtl_freeMemory( pColBuf );
1901*cdf0e10cSrcweir 			aNewBmp.ReleaseAccess( pWAcc );
1902*cdf0e10cSrcweir 			bRet = sal_True;
1903*cdf0e10cSrcweir 		}
1904*cdf0e10cSrcweir 
1905*cdf0e10cSrcweir 		ReleaseAccess( pRAcc );
1906*cdf0e10cSrcweir 
1907*cdf0e10cSrcweir 		if( bRet )
1908*cdf0e10cSrcweir 		{
1909*cdf0e10cSrcweir 			const MapMode	aMap( maPrefMapMode );
1910*cdf0e10cSrcweir 			const Size		aSize( maPrefSize );
1911*cdf0e10cSrcweir 
1912*cdf0e10cSrcweir 			*this = aNewBmp;
1913*cdf0e10cSrcweir 			maPrefMapMode = aMap;
1914*cdf0e10cSrcweir 			maPrefSize = aSize;
1915*cdf0e10cSrcweir 		}
1916*cdf0e10cSrcweir 	}
1917*cdf0e10cSrcweir 
1918*cdf0e10cSrcweir 	return bRet;
1919*cdf0e10cSrcweir }
1920*cdf0e10cSrcweir 
1921*cdf0e10cSrcweir // ------------------------------------------------------------------------
1922*cdf0e10cSrcweir 
1923*cdf0e10cSrcweir void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
1924*cdf0e10cSrcweir 							long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
1925*cdf0e10cSrcweir 							long nColors, long nPixels, long& rIndex )
1926*cdf0e10cSrcweir {
1927*cdf0e10cSrcweir 	if( !nPixels )
1928*cdf0e10cSrcweir 		return;
1929*cdf0e10cSrcweir 
1930*cdf0e10cSrcweir 	BitmapColor	aCol;
1931*cdf0e10cSrcweir 	const long	nRLen = nR2 - nR1;
1932*cdf0e10cSrcweir 	const long	nGLen = nG2 - nG1;
1933*cdf0e10cSrcweir 	const long	nBLen = nB2 - nB1;
1934*cdf0e10cSrcweir 	long 		nR, nG, nB;
1935*cdf0e10cSrcweir 	sal_uLong*		pBuf = pColBuf;
1936*cdf0e10cSrcweir 
1937*cdf0e10cSrcweir 	if( !nRLen && !nGLen && !nBLen )
1938*cdf0e10cSrcweir 	{
1939*cdf0e10cSrcweir 		if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
1940*cdf0e10cSrcweir 		{
1941*cdf0e10cSrcweir 			aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
1942*cdf0e10cSrcweir 			aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
1943*cdf0e10cSrcweir 			aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
1944*cdf0e10cSrcweir 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
1945*cdf0e10cSrcweir 		}
1946*cdf0e10cSrcweir 	}
1947*cdf0e10cSrcweir 	else
1948*cdf0e10cSrcweir 	{
1949*cdf0e10cSrcweir 		if( 1 == nColors || 1 == nPixels )
1950*cdf0e10cSrcweir 		{
1951*cdf0e10cSrcweir 			long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
1952*cdf0e10cSrcweir 
1953*cdf0e10cSrcweir 			for( nR = nR1; nR <= nR2; nR++ )
1954*cdf0e10cSrcweir 			{
1955*cdf0e10cSrcweir 				for( nG = nG1; nG <= nG2; nG++ )
1956*cdf0e10cSrcweir 				{
1957*cdf0e10cSrcweir 					for( nB = nB1; nB <= nB2; nB++ )
1958*cdf0e10cSrcweir 					{
1959*cdf0e10cSrcweir 						nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
1960*cdf0e10cSrcweir 
1961*cdf0e10cSrcweir 						if( nPixSum )
1962*cdf0e10cSrcweir 						{
1963*cdf0e10cSrcweir 							nRSum += nR * nPixSum;
1964*cdf0e10cSrcweir 							nGSum += nG * nPixSum;
1965*cdf0e10cSrcweir 							nBSum += nB * nPixSum;
1966*cdf0e10cSrcweir 						}
1967*cdf0e10cSrcweir 					}
1968*cdf0e10cSrcweir 				}
1969*cdf0e10cSrcweir 			}
1970*cdf0e10cSrcweir 
1971*cdf0e10cSrcweir 			aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
1972*cdf0e10cSrcweir 			aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
1973*cdf0e10cSrcweir 			aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
1974*cdf0e10cSrcweir 			rPal[ (sal_uInt16) rIndex++ ] = aCol;
1975*cdf0e10cSrcweir 		}
1976*cdf0e10cSrcweir 		else
1977*cdf0e10cSrcweir 		{
1978*cdf0e10cSrcweir 			const long	nTest = ( nPixels >> 1 );
1979*cdf0e10cSrcweir 			long		nPixOld = 0;
1980*cdf0e10cSrcweir 			long		nPixNew = 0;
1981*cdf0e10cSrcweir 
1982*cdf0e10cSrcweir 			if( nBLen > nGLen && nBLen > nRLen )
1983*cdf0e10cSrcweir 			{
1984*cdf0e10cSrcweir 				nB = nB1 - 1;
1985*cdf0e10cSrcweir 
1986*cdf0e10cSrcweir 				while( nPixNew < nTest )
1987*cdf0e10cSrcweir 				{
1988*cdf0e10cSrcweir 					nB++, nPixOld = nPixNew;
1989*cdf0e10cSrcweir 					for( nR = nR1; nR <= nR2; nR++ )
1990*cdf0e10cSrcweir 						for( nG = nG1; nG <= nG2; nG++ )
1991*cdf0e10cSrcweir 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
1992*cdf0e10cSrcweir 				}
1993*cdf0e10cSrcweir 
1994*cdf0e10cSrcweir 				if( nB < nB2 )
1995*cdf0e10cSrcweir 				{
1996*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
1997*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
1998*cdf0e10cSrcweir 				}
1999*cdf0e10cSrcweir 				else
2000*cdf0e10cSrcweir 				{
2001*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
2002*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
2003*cdf0e10cSrcweir 				}
2004*cdf0e10cSrcweir 			}
2005*cdf0e10cSrcweir 			else if( nGLen > nRLen )
2006*cdf0e10cSrcweir 			{
2007*cdf0e10cSrcweir 				nG = nG1 - 1;
2008*cdf0e10cSrcweir 
2009*cdf0e10cSrcweir 				while( nPixNew < nTest )
2010*cdf0e10cSrcweir 				{
2011*cdf0e10cSrcweir 					nG++, nPixOld = nPixNew;
2012*cdf0e10cSrcweir 					for( nR = nR1; nR <= nR2; nR++ )
2013*cdf0e10cSrcweir 						for( nB = nB1; nB <= nB2; nB++ )
2014*cdf0e10cSrcweir 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
2015*cdf0e10cSrcweir 				}
2016*cdf0e10cSrcweir 
2017*cdf0e10cSrcweir 				if( nG < nG2 )
2018*cdf0e10cSrcweir 				{
2019*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
2020*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
2021*cdf0e10cSrcweir 				}
2022*cdf0e10cSrcweir 				else
2023*cdf0e10cSrcweir 				{
2024*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
2025*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
2026*cdf0e10cSrcweir 				}
2027*cdf0e10cSrcweir 			}
2028*cdf0e10cSrcweir 			else
2029*cdf0e10cSrcweir 			{
2030*cdf0e10cSrcweir 				nR = nR1 - 1;
2031*cdf0e10cSrcweir 
2032*cdf0e10cSrcweir 				while( nPixNew < nTest )
2033*cdf0e10cSrcweir 				{
2034*cdf0e10cSrcweir 					nR++, nPixOld = nPixNew;
2035*cdf0e10cSrcweir 					for( nG = nG1; nG <= nG2; nG++ )
2036*cdf0e10cSrcweir 						for( nB = nB1; nB <= nB2; nB++ )
2037*cdf0e10cSrcweir 							nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
2038*cdf0e10cSrcweir 				}
2039*cdf0e10cSrcweir 
2040*cdf0e10cSrcweir 				if( nR < nR2 )
2041*cdf0e10cSrcweir 				{
2042*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
2043*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
2044*cdf0e10cSrcweir 				}
2045*cdf0e10cSrcweir 				else
2046*cdf0e10cSrcweir 				{
2047*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
2048*cdf0e10cSrcweir 					ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
2049*cdf0e10cSrcweir 				}
2050*cdf0e10cSrcweir 			}
2051*cdf0e10cSrcweir 		}
2052*cdf0e10cSrcweir 	}
2053*cdf0e10cSrcweir }
2054*cdf0e10cSrcweir 
2055*cdf0e10cSrcweir // ------------------------------------------------------------------------
2056*cdf0e10cSrcweir 
2057*cdf0e10cSrcweir sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
2058*cdf0e10cSrcweir {
2059*cdf0e10cSrcweir 	return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
2060*cdf0e10cSrcweir }
2061*cdf0e10cSrcweir 
2062*cdf0e10cSrcweir // ------------------------------------------------------------------------
2063*cdf0e10cSrcweir 
2064*cdf0e10cSrcweir sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
2065*cdf0e10cSrcweir {
2066*cdf0e10cSrcweir 	return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
2067*cdf0e10cSrcweir }
2068*cdf0e10cSrcweir 
2069*cdf0e10cSrcweir // ------------------------------------------------------------------------
2070*cdf0e10cSrcweir 
2071*cdf0e10cSrcweir sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
2072*cdf0e10cSrcweir 					 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
2073*cdf0e10cSrcweir 					 double fGamma, sal_Bool bInvert )
2074*cdf0e10cSrcweir {
2075*cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
2076*cdf0e10cSrcweir 
2077*cdf0e10cSrcweir 	// nothing to do => return quickly
2078*cdf0e10cSrcweir 	if( !nLuminancePercent && !nContrastPercent &&
2079*cdf0e10cSrcweir 		!nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
2080*cdf0e10cSrcweir 		( fGamma == 1.0 ) && !bInvert )
2081*cdf0e10cSrcweir 	{
2082*cdf0e10cSrcweir 		bRet = sal_True;
2083*cdf0e10cSrcweir 	}
2084*cdf0e10cSrcweir 	else
2085*cdf0e10cSrcweir 	{
2086*cdf0e10cSrcweir 		BitmapWriteAccess* pAcc = AcquireWriteAccess();
2087*cdf0e10cSrcweir 
2088*cdf0e10cSrcweir 		if( pAcc )
2089*cdf0e10cSrcweir 		{
2090*cdf0e10cSrcweir 			BitmapColor		aCol;
2091*cdf0e10cSrcweir 			const long		nW = pAcc->Width();
2092*cdf0e10cSrcweir 			const long		nH = pAcc->Height();
2093*cdf0e10cSrcweir 			sal_uInt8*			cMapR = new sal_uInt8[ 256 ];
2094*cdf0e10cSrcweir 			sal_uInt8*			cMapG = new sal_uInt8[ 256 ];
2095*cdf0e10cSrcweir 			sal_uInt8*			cMapB = new sal_uInt8[ 256 ];
2096*cdf0e10cSrcweir 			long			nX, nY;
2097*cdf0e10cSrcweir 			double			fM, fROff, fGOff, fBOff, fOff;
2098*cdf0e10cSrcweir 
2099*cdf0e10cSrcweir 			// calculate slope
2100*cdf0e10cSrcweir 			if( nContrastPercent >= 0 )
2101*cdf0e10cSrcweir 				fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
2102*cdf0e10cSrcweir 			else
2103*cdf0e10cSrcweir 				fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
2104*cdf0e10cSrcweir 
2105*cdf0e10cSrcweir 			// total offset = luminance offset + contrast offset
2106*cdf0e10cSrcweir 			fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
2107*cdf0e10cSrcweir 
2108*cdf0e10cSrcweir 			// channel offset = channel offset  + total offset
2109*cdf0e10cSrcweir 			fROff = nChannelRPercent * 2.55 + fOff;
2110*cdf0e10cSrcweir 			fGOff = nChannelGPercent * 2.55 + fOff;
2111*cdf0e10cSrcweir 			fBOff = nChannelBPercent * 2.55 + fOff;
2112*cdf0e10cSrcweir 
2113*cdf0e10cSrcweir 			// calculate gamma value
2114*cdf0e10cSrcweir 			fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2115*cdf0e10cSrcweir 			const sal_Bool bGamma = ( fGamma != 1.0 );
2116*cdf0e10cSrcweir 
2117*cdf0e10cSrcweir 			// create mapping table
2118*cdf0e10cSrcweir 			for( nX = 0L; nX < 256L; nX++ )
2119*cdf0e10cSrcweir 			{
2120*cdf0e10cSrcweir 				cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
2121*cdf0e10cSrcweir 				cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
2122*cdf0e10cSrcweir 				cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
2123*cdf0e10cSrcweir 
2124*cdf0e10cSrcweir 				if( bGamma )
2125*cdf0e10cSrcweir 				{
2126*cdf0e10cSrcweir 					cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
2127*cdf0e10cSrcweir 					cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
2128*cdf0e10cSrcweir 					cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
2129*cdf0e10cSrcweir 				}
2130*cdf0e10cSrcweir 
2131*cdf0e10cSrcweir 				if( bInvert )
2132*cdf0e10cSrcweir 				{
2133*cdf0e10cSrcweir 					cMapR[ nX ] = ~cMapR[ nX ];
2134*cdf0e10cSrcweir 					cMapG[ nX ] = ~cMapG[ nX ];
2135*cdf0e10cSrcweir 					cMapB[ nX ] = ~cMapB[ nX ];
2136*cdf0e10cSrcweir 				}
2137*cdf0e10cSrcweir 			}
2138*cdf0e10cSrcweir 
2139*cdf0e10cSrcweir 			// do modifying
2140*cdf0e10cSrcweir 			if( pAcc->HasPalette() )
2141*cdf0e10cSrcweir 			{
2142*cdf0e10cSrcweir 				BitmapColor aNewCol;
2143*cdf0e10cSrcweir 
2144*cdf0e10cSrcweir 				for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
2145*cdf0e10cSrcweir 				{
2146*cdf0e10cSrcweir 					const BitmapColor& rCol = pAcc->GetPaletteColor( i );
2147*cdf0e10cSrcweir 					aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
2148*cdf0e10cSrcweir 					aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
2149*cdf0e10cSrcweir 					aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
2150*cdf0e10cSrcweir 					pAcc->SetPaletteColor( i, aNewCol );
2151*cdf0e10cSrcweir 				}
2152*cdf0e10cSrcweir 			}
2153*cdf0e10cSrcweir 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
2154*cdf0e10cSrcweir 			{
2155*cdf0e10cSrcweir 				for( nY = 0L; nY < nH; nY++ )
2156*cdf0e10cSrcweir 				{
2157*cdf0e10cSrcweir 					Scanline pScan = pAcc->GetScanline( nY );
2158*cdf0e10cSrcweir 
2159*cdf0e10cSrcweir 					for( nX = 0L; nX < nW; nX++ )
2160*cdf0e10cSrcweir 					{
2161*cdf0e10cSrcweir 						*pScan = cMapB[ *pScan ]; pScan++;
2162*cdf0e10cSrcweir 						*pScan = cMapG[ *pScan ]; pScan++;
2163*cdf0e10cSrcweir 						*pScan = cMapR[ *pScan ]; pScan++;
2164*cdf0e10cSrcweir 					}
2165*cdf0e10cSrcweir 				}
2166*cdf0e10cSrcweir 			}
2167*cdf0e10cSrcweir 			else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
2168*cdf0e10cSrcweir 			{
2169*cdf0e10cSrcweir 				for( nY = 0L; nY < nH; nY++ )
2170*cdf0e10cSrcweir 				{
2171*cdf0e10cSrcweir 					Scanline pScan = pAcc->GetScanline( nY );
2172*cdf0e10cSrcweir 
2173*cdf0e10cSrcweir 					for( nX = 0L; nX < nW; nX++ )
2174*cdf0e10cSrcweir 					{
2175*cdf0e10cSrcweir 						*pScan = cMapR[ *pScan ]; pScan++;
2176*cdf0e10cSrcweir 						*pScan = cMapG[ *pScan ]; pScan++;
2177*cdf0e10cSrcweir 						*pScan = cMapB[ *pScan ]; pScan++;
2178*cdf0e10cSrcweir 					}
2179*cdf0e10cSrcweir 				}
2180*cdf0e10cSrcweir 			}
2181*cdf0e10cSrcweir 			else
2182*cdf0e10cSrcweir 			{
2183*cdf0e10cSrcweir 				for( nY = 0L; nY < nH; nY++ )
2184*cdf0e10cSrcweir 				{
2185*cdf0e10cSrcweir 					for( nX = 0L; nX < nW; nX++ )
2186*cdf0e10cSrcweir 					{
2187*cdf0e10cSrcweir 						aCol = pAcc->GetPixel( nY, nX );
2188*cdf0e10cSrcweir 						aCol.SetRed( cMapR[ aCol.GetRed() ] );
2189*cdf0e10cSrcweir 						aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
2190*cdf0e10cSrcweir 						aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
2191*cdf0e10cSrcweir 						pAcc->SetPixel( nY, nX, aCol );
2192*cdf0e10cSrcweir 					}
2193*cdf0e10cSrcweir 				}
2194*cdf0e10cSrcweir 			}
2195*cdf0e10cSrcweir 
2196*cdf0e10cSrcweir 			delete[] cMapR;
2197*cdf0e10cSrcweir 			delete[] cMapG;
2198*cdf0e10cSrcweir 			delete[] cMapB;
2199*cdf0e10cSrcweir 			ReleaseAccess( pAcc );
2200*cdf0e10cSrcweir 			bRet = sal_True;
2201*cdf0e10cSrcweir 		}
2202*cdf0e10cSrcweir 	}
2203*cdf0e10cSrcweir 
2204*cdf0e10cSrcweir 	return bRet;
2205*cdf0e10cSrcweir }
2206