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