Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <stdlib.h>
22 :
23 : #include <vcl/bmpacc.hxx>
24 : #include <vcl/octree.hxx>
25 : #include <vcl/bitmapex.hxx>
26 : #include <vcl/bitmap.hxx>
27 :
28 : #include <impoct.hxx>
29 : #include <impvect.hxx>
30 : #include <math.h>
31 :
32 : #define RGB15( _def_cR, _def_cG, _def_cB ) (((sal_uLong)(_def_cR)<<10UL)|((sal_uLong)(_def_cG)<<5UL)|(sal_uLong)(_def_cB))
33 : #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
34 : #define MAP( cVal0, cVal1, nFrac ) ((sal_uInt8)((((long)(cVal0)<<7L)+nFrac*((long)(cVal1)-(cVal0)))>>7L))
35 :
36 : #define CALC_ERRORS \
37 : nTemp = p1T[nX++] >> 12; \
38 : nBErr = MinMax( nTemp, 0, 255 ); \
39 : nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
40 : nTemp = p1T[nX++] >> 12; \
41 : nGErr = MinMax( nTemp, 0, 255 ); \
42 : nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
43 : nTemp = p1T[nX] >> 12; \
44 : nRErr = MinMax( nTemp, 0, 255 ); \
45 : nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
46 :
47 : #define CALC_TABLES3 \
48 : p2T[nX++] += FloydError3[nBErr]; \
49 : p2T[nX++] += FloydError3[nGErr]; \
50 : p2T[nX++] += FloydError3[nRErr];
51 :
52 : #define CALC_TABLES5 \
53 : p2T[nX++] += FloydError5[nBErr]; \
54 : p2T[nX++] += FloydError5[nGErr]; \
55 : p2T[nX++] += FloydError5[nRErr];
56 :
57 : #define CALC_TABLES7 \
58 : p1T[++nX] += FloydError7[nBErr]; \
59 : p2T[nX++] += FloydError1[nBErr]; \
60 : p1T[nX] += FloydError7[nGErr]; \
61 : p2T[nX++] += FloydError1[nGErr]; \
62 : p1T[nX] += FloydError7[nRErr]; \
63 : p2T[nX] += FloydError1[nRErr];
64 :
65 : const extern sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
66 : const extern sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
67 : const extern sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
68 :
69 : const extern sal_uLong nVCLDitherLut[ 256 ] =
70 : {
71 : 0, 49152, 12288, 61440, 3072, 52224, 15360, 64512, 768, 49920, 13056,
72 : 62208, 3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
73 : 48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
74 : 57344, 4096, 53248, 11264, 60416, 7168, 56320, 8960, 58112, 4864, 54016,
75 : 12032, 61184, 7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
76 : 23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
77 : 14336, 63488, 1024, 50176, 13312, 62464, 2816, 51968, 15104, 64256, 1792,
78 : 50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
79 : 35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392, 6144,
80 : 55296, 9216, 58368, 5120, 54272, 11008, 60160, 6912, 56064, 9984, 59136,
81 : 5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
82 : 27392, 39680, 23296, 42752, 26368, 38656, 22272, 512, 49664, 12800, 61952,
83 : 3584, 52736, 15872, 65024, 256, 49408, 12544, 61696, 3328, 52480, 15616,
84 : 64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
85 : 45312, 28928, 36096, 19712, 48384, 32000, 8704, 57856, 4608, 53760, 11776,
86 : 60928, 7680, 56832, 8448, 57600, 4352, 53504, 11520, 60672, 7424, 56576,
87 : 41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
88 : 20736, 44288, 27904, 40192, 23808, 2560, 51712, 14848, 64000, 1536, 50688,
89 : 13824, 62976, 2304, 51456, 14592, 63744, 1280, 50432, 13568, 62720, 35328,
90 : 18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
91 : 34048, 17664, 46336, 29952, 10752, 59904, 6656, 55808, 9728, 58880, 5632,
92 : 54784, 10496, 59648, 6400, 55552, 9472, 58624, 5376, 54528, 43520, 27136,
93 : 39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
94 : 25856, 38144, 21760
95 : };
96 :
97 : const extern sal_uLong nVCLLut[ 256 ] =
98 : {
99 : 0, 1286, 2572, 3858, 5144, 6430, 7716, 9002,
100 : 10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
101 : 20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
102 : 30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
103 : 41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
104 : 51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
105 : 61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
106 : 72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
107 : 82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
108 : 92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
109 : 102880,104166,105452,106738,108024,109310,110596,111882,
110 : 113168,114454,115740,117026,118312,119598,120884,122170,
111 : 123456,124742,126028,127314,128600,129886,131172,132458,
112 : 133744,135030,136316,137602,138888,140174,141460,142746,
113 : 144032,145318,146604,147890,149176,150462,151748,153034,
114 : 154320,155606,156892,158178,159464,160750,162036,163322,
115 : 164608,165894,167180,168466,169752,171038,172324,173610,
116 : 174896,176182,177468,178754,180040,181326,182612,183898,
117 : 185184,186470,187756,189042,190328,191614,192900,194186,
118 : 195472,196758,198044,199330,200616,201902,203188,204474,
119 : 205760,207046,208332,209618,210904,212190,213476,214762,
120 : 216048,217334,218620,219906,221192,222478,223764,225050,
121 : 226336,227622,228908,230194,231480,232766,234052,235338,
122 : 236624,237910,239196,240482,241768,243054,244340,245626,
123 : 246912,248198,249484,250770,252056,253342,254628,255914,
124 : 257200,258486,259772,261058,262344,263630,264916,266202,
125 : 267488,268774,270060,271346,272632,273918,275204,276490,
126 : 277776,279062,280348,281634,282920,284206,285492,286778,
127 : 288064,289350,290636,291922,293208,294494,295780,297066,
128 : 298352,299638,300924,302210,303496,304782,306068,307354,
129 : 308640,309926,311212,312498,313784,315070,316356,317642,
130 : 318928,320214,321500,322786,324072,325358,326644,327930
131 : };
132 :
133 : const long FloydMap[256] =
134 : {
135 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
137 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
138 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
139 : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
140 : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
141 : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
142 : 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
143 : 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
144 : 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
145 : 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
146 : 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
147 : 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
148 : 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
149 : 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
150 : 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
151 : };
152 :
153 : const long FloydError1[61] =
154 : {
155 : -7680, -7424, -7168, -6912, -6656, -6400, -6144,
156 : -5888, -5632, -5376, -5120, -4864, -4608, -4352,
157 : -4096, -3840, -3584, -3328, -3072, -2816, -2560,
158 : -2304, -2048, -1792, -1536, -1280, -1024, -768,
159 : -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
160 : 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
161 : 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
162 : 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
163 : };
164 :
165 : const long FloydError3[61] =
166 : {
167 : -23040, -22272, -21504, -20736, -19968, -19200,
168 : -18432, -17664, -16896, -16128, -15360, -14592,
169 : -13824, -13056, -12288, -11520, -10752, -9984,
170 : -9216, -8448, -7680, -6912, -6144, -5376, -4608,
171 : -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
172 : 2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
173 : 8448, 9216, 9984, 10752, 11520, 12288, 13056,
174 : 13824, 14592, 15360, 16128, 16896, 17664, 18432,
175 : 19200, 19968, 20736, 21504, 22272, 23040
176 : };
177 :
178 : const long FloydError5[61] =
179 : {
180 : -38400, -37120, -35840, -34560, -33280, -32000,
181 : -30720, -29440, -28160, -26880, -25600, -24320,
182 : -23040, -21760, -20480, -19200, -17920, -16640,
183 : -15360, -14080, -12800, -11520, -10240, -8960,
184 : -7680, -6400, -5120, -3840, -2560, -1280, 0,
185 : 1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
186 : 11520, 12800, 14080, 15360, 16640, 17920, 19200,
187 : 20480, 21760, 23040, 24320, 25600, 26880, 28160,
188 : 29440, 30720, 32000, 33280, 34560, 35840, 37120,
189 : 38400
190 : };
191 :
192 : const long FloydError7[61] =
193 : {
194 : -53760, -51968, -50176, -48384, -46592, -44800,
195 : -43008, -41216, -39424, -37632, -35840, -34048,
196 : -32256, -30464, -28672, -26880, -25088, -23296,
197 : -21504, -19712, -17920, -16128, -14336, -12544,
198 : -10752, -8960, -7168, -5376, -3584, -1792, 0,
199 : 1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
200 : 16128, 17920, 19712, 21504, 23296, 25088, 26880,
201 : 28672, 30464, 32256, 34048, 35840, 37632, 39424,
202 : 41216, 43008, 44800, 46592, 48384, 50176, 51968,
203 : 53760
204 : };
205 :
206 : const long FloydIndexMap[6] =
207 : {
208 : -30, 21, 72, 123, 174, 225
209 : };
210 :
211 0 : void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] )
212 : {
213 0 : double fVal = 3.125;
214 0 : const double fVal16 = fVal / 16.;
215 : long i, j, k, l;
216 : sal_uInt16 pMtx[ 16 ][ 16 ];
217 0 : sal_uInt16 nMax = 0;
218 : static const sal_uInt8 pMagic[4][4] = { { 0, 14, 3, 13, },
219 : {11, 5, 8, 6, },
220 : {12, 2, 15, 1, },
221 : {7, 9, 4, 10 } };
222 :
223 : // Build MagicSquare
224 0 : for ( i = 0; i < 4; i++ )
225 0 : for ( j = 0; j < 4; j++ )
226 0 : for ( k = 0; k < 4; k++ )
227 0 : for ( l = 0; l < 4; l++ )
228 0 : nMax = std::max ( pMtx[ (k<<2) + i][(l<<2 ) + j] =
229 0 : (sal_uInt16) ( 0.5 + pMagic[i][j]*fVal + pMagic[k][l]*fVal16 ), nMax );
230 :
231 : // Scale to interval [0;254]
232 0 : for ( i = 0, fVal = 254. / nMax; i < 16; i++ )
233 0 : for( j = 0; j < 16; j++ )
234 0 : (*pDitherMatrix)[i][j] = (sal_uInt8) ( fVal * pMtx[i][j] );
235 0 : }
236 :
237 124017 : sal_Bool Bitmap::Convert( BmpConversion eConversion )
238 : {
239 124017 : const sal_uInt16 nBitCount = GetBitCount();
240 124017 : sal_Bool bRet = sal_False;
241 :
242 124017 : switch( eConversion )
243 : {
244 : case( BMP_CONVERSION_1BIT_THRESHOLD ):
245 0 : bRet = ImplMakeMono( 128 );
246 0 : break;
247 :
248 : case( BMP_CONVERSION_1BIT_MATRIX ):
249 0 : bRet = ImplMakeMonoDither();
250 0 : break;
251 :
252 : case( BMP_CONVERSION_4BIT_GREYS ):
253 0 : bRet = ImplMakeGreyscales( 16 );
254 0 : break;
255 :
256 : case( BMP_CONVERSION_4BIT_COLORS ):
257 : {
258 0 : if( nBitCount < 4 )
259 0 : bRet = ImplConvertUp( 4, NULL );
260 0 : else if( nBitCount > 4 )
261 0 : bRet = ImplConvertDown( 4, NULL );
262 : else
263 0 : bRet = sal_True;
264 : }
265 0 : break;
266 :
267 : case( BMP_CONVERSION_4BIT_TRANS ):
268 : {
269 0 : Color aTrans( BMP_COL_TRANS );
270 :
271 0 : if( nBitCount < 4 )
272 0 : bRet = ImplConvertUp( 4, &aTrans );
273 : else
274 0 : bRet = ImplConvertDown( 4, &aTrans );
275 : }
276 0 : break;
277 :
278 : case( BMP_CONVERSION_8BIT_GREYS ):
279 123516 : bRet = ImplMakeGreyscales( 256 );
280 123516 : break;
281 :
282 : case( BMP_CONVERSION_8BIT_COLORS ):
283 : {
284 469 : if( nBitCount < 8 )
285 0 : bRet = ImplConvertUp( 8 );
286 469 : else if( nBitCount > 8 )
287 469 : bRet = ImplConvertDown( 8 );
288 : else
289 0 : bRet = sal_True;
290 : }
291 469 : break;
292 :
293 : case( BMP_CONVERSION_8BIT_TRANS ):
294 : {
295 0 : Color aTrans( BMP_COL_TRANS );
296 :
297 0 : if( nBitCount < 8 )
298 0 : bRet = ImplConvertUp( 8, &aTrans );
299 : else
300 0 : bRet = ImplConvertDown( 8, &aTrans );
301 : }
302 0 : break;
303 :
304 : case( BMP_CONVERSION_24BIT ):
305 : {
306 32 : if( nBitCount < 24 )
307 32 : bRet = ImplConvertUp( 24, NULL );
308 : else
309 0 : bRet = sal_True;
310 : }
311 32 : break;
312 :
313 : case( BMP_CONVERSION_GHOSTED ):
314 0 : bRet = ImplConvertGhosted();
315 0 : break;
316 :
317 : default:
318 : OSL_FAIL( "Bitmap::Convert(): Unsupported conversion" );
319 0 : break;
320 : }
321 :
322 124017 : return bRet;
323 : }
324 :
325 9 : sal_Bool Bitmap::ImplMakeMono( sal_uInt8 cThreshold )
326 : {
327 9 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
328 9 : sal_Bool bRet = sal_False;
329 :
330 9 : if( pReadAcc )
331 : {
332 9 : Bitmap aNewBmp( GetSizePixel(), 1 );
333 9 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
334 :
335 9 : if( pWriteAcc )
336 : {
337 9 : const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
338 18 : const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
339 9 : const long nWidth = pWriteAcc->Width();
340 9 : const long nHeight = pWriteAcc->Height();
341 :
342 9 : if( pReadAcc->HasPalette() )
343 : {
344 58 : for( long nY = 0L; nY < nHeight; nY++ )
345 : {
346 12496 : for( long nX = 0L; nX < nWidth; nX++ )
347 : {
348 12440 : const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
349 12440 : if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >=
350 : cThreshold )
351 : {
352 6218 : pWriteAcc->SetPixel( nY, nX, aWhite );
353 : }
354 : else
355 6222 : pWriteAcc->SetPixel( nY, nX, aBlack );
356 : }
357 : }
358 : }
359 : else
360 : {
361 102 : for( long nY = 0L; nY < nHeight; nY++ )
362 : {
363 4133 : for( long nX = 0L; nX < nWidth; nX++ )
364 : {
365 4038 : if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >=
366 : cThreshold )
367 : {
368 524 : pWriteAcc->SetPixel( nY, nX, aWhite );
369 : }
370 : else
371 3514 : pWriteAcc->SetPixel( nY, nX, aBlack );
372 : }
373 : }
374 : }
375 :
376 9 : aNewBmp.ReleaseAccess( pWriteAcc );
377 18 : bRet = sal_True;
378 : }
379 :
380 9 : ReleaseAccess( pReadAcc );
381 :
382 9 : if( bRet )
383 : {
384 9 : const MapMode aMap( maPrefMapMode );
385 9 : const Size aSize( maPrefSize );
386 :
387 9 : *this = aNewBmp;
388 :
389 9 : maPrefMapMode = aMap;
390 9 : maPrefSize = aSize;
391 9 : }
392 : }
393 :
394 9 : return bRet;
395 : }
396 :
397 0 : sal_Bool Bitmap::ImplMakeMonoDither()
398 : {
399 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
400 0 : sal_Bool bRet = sal_False;
401 :
402 0 : if( pReadAcc )
403 : {
404 0 : Bitmap aNewBmp( GetSizePixel(), 1 );
405 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
406 :
407 0 : if( pWriteAcc )
408 : {
409 0 : const BitmapColor aBlack( pWriteAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
410 0 : const BitmapColor aWhite( pWriteAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
411 0 : const long nWidth = pWriteAcc->Width();
412 0 : const long nHeight = pWriteAcc->Height();
413 : sal_uInt8 pDitherMatrix[ 16 ][ 16 ];
414 :
415 0 : ImplCreateDitherMatrix( &pDitherMatrix );
416 :
417 0 : if( pReadAcc->HasPalette() )
418 : {
419 0 : for( long nY = 0L; nY < nHeight; nY++ )
420 : {
421 0 : for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
422 : {
423 0 : const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
424 0 : if( pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >
425 0 : pDitherMatrix[ nModY ][ nX % 16 ] )
426 : {
427 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
428 : }
429 : else
430 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
431 : }
432 : }
433 : }
434 : else
435 : {
436 0 : for( long nY = 0L; nY < nHeight; nY++ )
437 : {
438 0 : for( long nX = 0L, nModY = nY % 16; nX < nWidth; nX++ )
439 : {
440 0 : if( pReadAcc->GetPixel( nY, nX ).GetLuminance() >
441 0 : pDitherMatrix[ nModY ][ nX % 16 ] )
442 : {
443 0 : pWriteAcc->SetPixel( nY, nX, aWhite );
444 : }
445 : else
446 0 : pWriteAcc->SetPixel( nY, nX, aBlack );
447 : }
448 : }
449 : }
450 :
451 0 : aNewBmp.ReleaseAccess( pWriteAcc );
452 0 : bRet = sal_True;
453 : }
454 :
455 0 : ReleaseAccess( pReadAcc );
456 :
457 0 : if( bRet )
458 : {
459 0 : const MapMode aMap( maPrefMapMode );
460 0 : const Size aSize( maPrefSize );
461 :
462 0 : *this = aNewBmp;
463 :
464 0 : maPrefMapMode = aMap;
465 0 : maPrefSize = aSize;
466 0 : }
467 : }
468 :
469 0 : return bRet;
470 : }
471 :
472 123516 : sal_Bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
473 : {
474 : DBG_ASSERT( nGreys == 16 || nGreys == 256, "Only 16 or 256 greyscales are supported!" );
475 :
476 123516 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
477 123516 : sal_Bool bRet = sal_False;
478 :
479 123516 : if( pReadAcc )
480 : {
481 123516 : const BitmapPalette& rPal = GetGreyPalette( nGreys );
482 123516 : sal_uLong nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
483 123516 : bool bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
484 :
485 123516 : if( !bPalDiffers )
486 116483 : bPalDiffers = ( (BitmapPalette&) rPal != pReadAcc->GetPalette() );
487 :
488 123516 : if( bPalDiffers )
489 : {
490 7033 : Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
491 7033 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
492 :
493 7033 : if( pWriteAcc )
494 : {
495 7033 : const long nWidth = pWriteAcc->Width();
496 7033 : const long nHeight = pWriteAcc->Height();
497 :
498 7033 : if( pReadAcc->HasPalette() )
499 : {
500 0 : for( long nY = 0L; nY < nHeight; nY++ )
501 : {
502 0 : for( long nX = 0L; nX < nWidth; nX++ )
503 : {
504 0 : const sal_uInt8 cIndex = pReadAcc->GetPixelIndex( nY, nX );
505 : pWriteAcc->SetPixelIndex( nY, nX,
506 0 : (pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
507 : }
508 : }
509 : }
510 14066 : else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR &&
511 7033 : pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
512 : {
513 7033 : nShift += 8;
514 :
515 733102 : for( long nY = 0L; nY < nHeight; nY++ )
516 : {
517 726069 : Scanline pReadScan = pReadAcc->GetScanline( nY );
518 726069 : Scanline pWriteScan = pWriteAcc->GetScanline( nY );
519 :
520 109801854 : for( long nX = 0L; nX < nWidth; nX++ )
521 : {
522 109075785 : const sal_uLong nB = *pReadScan++;
523 109075785 : const sal_uLong nG = *pReadScan++;
524 109075785 : const sal_uLong nR = *pReadScan++;
525 :
526 109075785 : *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
527 : }
528 : }
529 : }
530 0 : else if( pReadAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB &&
531 0 : pWriteAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
532 : {
533 0 : nShift += 8;
534 :
535 0 : for( long nY = 0L; nY < nHeight; nY++ )
536 : {
537 0 : Scanline pReadScan = pReadAcc->GetScanline( nY );
538 0 : Scanline pWriteScan = pWriteAcc->GetScanline( nY );
539 :
540 0 : for( long nX = 0L; nX < nWidth; nX++ )
541 : {
542 0 : const sal_uLong nR = *pReadScan++;
543 0 : const sal_uLong nG = *pReadScan++;
544 0 : const sal_uLong nB = *pReadScan++;
545 :
546 0 : *pWriteScan++ = (sal_uInt8) ( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
547 : }
548 : }
549 : }
550 : else
551 : {
552 0 : for( long nY = 0L; nY < nHeight; nY++ )
553 0 : for( long nX = 0L; nX < nWidth; nX++ )
554 0 : pWriteAcc->SetPixelIndex( nY, nX, (pReadAcc->GetPixel( nY, nX ) ).GetLuminance() >> nShift );
555 : }
556 :
557 7033 : aNewBmp.ReleaseAccess( pWriteAcc );
558 7033 : bRet = sal_True;
559 : }
560 :
561 7033 : ReleaseAccess( pReadAcc );
562 :
563 7033 : if( bRet )
564 : {
565 7033 : const MapMode aMap( maPrefMapMode );
566 7033 : const Size aSize( maPrefSize );
567 :
568 7033 : *this = aNewBmp;
569 :
570 7033 : maPrefMapMode = aMap;
571 7033 : maPrefSize = aSize;
572 7033 : }
573 : }
574 : else
575 : {
576 116483 : ReleaseAccess( pReadAcc );
577 116483 : bRet = sal_True;
578 : }
579 : }
580 :
581 123516 : return bRet;
582 : }
583 :
584 32 : sal_Bool Bitmap::ImplConvertUp( sal_uInt16 nBitCount, Color* pExtColor )
585 : {
586 : DBG_ASSERT( nBitCount > GetBitCount(), "New BitCount must be greater!" );
587 :
588 32 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
589 32 : sal_Bool bRet = sal_False;
590 :
591 32 : if( pReadAcc )
592 : {
593 32 : BitmapPalette aPal;
594 64 : Bitmap aNewBmp( GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPal );
595 32 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
596 :
597 32 : if( pWriteAcc )
598 : {
599 32 : const long nWidth = pWriteAcc->Width();
600 32 : const long nHeight = pWriteAcc->Height();
601 :
602 32 : if( pWriteAcc->HasPalette() )
603 : {
604 0 : const sal_uInt16 nOldCount = 1 << GetBitCount();
605 0 : const BitmapPalette& rOldPal = pReadAcc->GetPalette();
606 :
607 0 : aPal.SetEntryCount( 1 << nBitCount );
608 :
609 0 : for( sal_uInt16 i = 0; i < nOldCount; i++ )
610 0 : aPal[ i ] = rOldPal[ i ];
611 :
612 0 : if( pExtColor )
613 0 : aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
614 :
615 0 : pWriteAcc->SetPalette( aPal );
616 :
617 0 : for( long nY = 0L; nY < nHeight; nY++ )
618 0 : for( long nX = 0L; nX < nWidth; nX++ )
619 0 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
620 : }
621 : else
622 : {
623 32 : if( pReadAcc->HasPalette() )
624 : {
625 373 : for( long nY = 0L; nY < nHeight; nY++ )
626 5046 : for( long nX = 0L; nX < nWidth; nX++ )
627 4705 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
628 : }
629 : else
630 : {
631 0 : for( long nY = 0L; nY < nHeight; nY++ )
632 0 : for( long nX = 0L; nX < nWidth; nX++ )
633 0 : pWriteAcc->SetPixel( nY, nX, pReadAcc->GetPixel( nY, nX ) );
634 : }
635 : }
636 :
637 32 : aNewBmp.ReleaseAccess( pWriteAcc );
638 32 : bRet = sal_True;
639 : }
640 :
641 32 : ReleaseAccess( pReadAcc );
642 :
643 32 : if( bRet )
644 : {
645 32 : const MapMode aMap( maPrefMapMode );
646 32 : const Size aSize( maPrefSize );
647 :
648 32 : *this = aNewBmp;
649 :
650 32 : maPrefMapMode = aMap;
651 32 : maPrefSize = aSize;
652 32 : }
653 : }
654 :
655 32 : return bRet;
656 : }
657 :
658 469 : sal_Bool Bitmap::ImplConvertDown( sal_uInt16 nBitCount, Color* pExtColor )
659 : {
660 : DBG_ASSERT( nBitCount <= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
661 :
662 469 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
663 469 : sal_Bool bRet = sal_False;
664 :
665 469 : if( pReadAcc )
666 : {
667 469 : BitmapPalette aPal;
668 938 : Bitmap aNewBmp( GetSizePixel(), nBitCount, &aPal );
669 469 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
670 :
671 469 : if( pWriteAcc )
672 : {
673 469 : const sal_uInt16 nCount = 1 << nBitCount;
674 469 : const long nWidth = pWriteAcc->Width();
675 469 : const long nWidth1 = nWidth - 1L;
676 469 : const long nHeight = pWriteAcc->Height();
677 469 : Octree aOctree( *pReadAcc, pExtColor ? ( nCount - 1 ) : nCount );
678 938 : InverseColorMap aColorMap( aPal = aOctree.GetPalette() );
679 938 : BitmapColor aColor;
680 469 : ImpErrorQuad aErrQuad;
681 469 : ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ];
682 469 : ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ];
683 469 : ImpErrorQuad* pQLine1 = pErrQuad1;
684 469 : ImpErrorQuad* pQLine2 = 0;
685 : long nX, nY;
686 469 : long nYTmp = 0L;
687 : sal_uInt8 cIndex;
688 469 : bool bQ1 = true;
689 :
690 469 : if( pExtColor )
691 : {
692 0 : aPal.SetEntryCount( aPal.GetEntryCount() + 1 );
693 0 : aPal[ aPal.GetEntryCount() - 1 ] = *pExtColor;
694 : }
695 :
696 : // set Black/White always, if we have enough space
697 469 : if( aPal.GetEntryCount() < ( nCount - 1 ) )
698 : {
699 334 : aPal.SetEntryCount( aPal.GetEntryCount() + 2 );
700 334 : aPal[ aPal.GetEntryCount() - 2 ] = Color( COL_BLACK );
701 334 : aPal[ aPal.GetEntryCount() - 1 ] = Color( COL_WHITE );
702 : }
703 :
704 469 : pWriteAcc->SetPalette( aPal );
705 :
706 1407 : for( nY = 0L; nY < std::min( nHeight, 2L ); nY++, nYTmp++ )
707 : {
708 71734 : for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
709 : {
710 70796 : if( pReadAcc->HasPalette() )
711 0 : pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) );
712 : else
713 70796 : pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
714 : }
715 : }
716 :
717 32879 : for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
718 : {
719 : // first pixel in the line
720 32410 : cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ 0 ].ImplGetColor() );
721 32410 : pWriteAcc->SetPixelIndex( nY, 0, cIndex );
722 :
723 2497179 : for( nX = 1L; nX < nWidth1; nX++ )
724 : {
725 2464769 : cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( aColor = pQLine1[ nX ].ImplGetColor() );
726 2464769 : aErrQuad = ( ImpErrorQuad( aColor ) -= pWriteAcc->GetPaletteColor( cIndex ) );
727 2464769 : pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
728 2464769 : pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
729 2464769 : pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
730 2464769 : pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
731 2464769 : pWriteAcc->SetPixelIndex( nY, nX, cIndex );
732 : }
733 :
734 : // Last RowPixel
735 32410 : if( nX < nWidth )
736 : {
737 32410 : cIndex = (sal_uInt8) aColorMap.GetBestPaletteIndex( pQLine1[ nWidth1 ].ImplGetColor() );
738 32410 : pWriteAcc->SetPixelIndex( nY, nX, cIndex );
739 : }
740 :
741 : // Refill/copy row buffer
742 32410 : pQLine1 = pQLine2;
743 32410 : pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2 : pErrQuad1;
744 :
745 32410 : if( nYTmp < nHeight )
746 : {
747 2490265 : for( nX = 0L; nX < nWidth; nX++ )
748 : {
749 2458793 : if( pReadAcc->HasPalette() )
750 0 : pQLine2[ nX ] = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nYTmp, nX ) );
751 : else
752 2458793 : pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
753 : }
754 : }
755 : }
756 :
757 : // Delete row buffer
758 469 : delete[] pErrQuad1;
759 469 : delete[] pErrQuad2;
760 :
761 469 : aNewBmp.ReleaseAccess( pWriteAcc );
762 938 : bRet = sal_True;
763 : }
764 :
765 469 : ReleaseAccess( pReadAcc );
766 :
767 469 : if( bRet )
768 : {
769 469 : const MapMode aMap( maPrefMapMode );
770 469 : const Size aSize( maPrefSize );
771 :
772 469 : *this = aNewBmp;
773 :
774 469 : maPrefMapMode = aMap;
775 469 : maPrefSize = aSize;
776 469 : }
777 : }
778 :
779 469 : return bRet;
780 : }
781 :
782 0 : sal_Bool Bitmap::ImplConvertGhosted()
783 : {
784 0 : Bitmap aNewBmp;
785 0 : BitmapReadAccess* pR = AcquireReadAccess();
786 0 : sal_Bool bRet = sal_False;
787 :
788 0 : if( pR )
789 : {
790 0 : if( pR->HasPalette() )
791 : {
792 0 : BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
793 :
794 0 : for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
795 : {
796 0 : const BitmapColor& rOld = pR->GetPaletteColor( (sal_uInt16) i );
797 0 : aNewPal[ (sal_uInt16) i ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
798 0 : ( rOld.GetGreen() >> 1 ) | 0x80,
799 0 : ( rOld.GetBlue() >> 1 ) | 0x80 );
800 : }
801 :
802 0 : aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
803 0 : BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
804 :
805 0 : if( pW )
806 : {
807 0 : pW->CopyBuffer( *pR );
808 0 : aNewBmp.ReleaseAccess( pW );
809 0 : bRet = sal_True;
810 0 : }
811 : }
812 : else
813 : {
814 0 : aNewBmp = Bitmap( GetSizePixel(), 24 );
815 :
816 0 : BitmapWriteAccess* pW = aNewBmp.AcquireWriteAccess();
817 :
818 0 : if( pW )
819 : {
820 0 : const long nWidth = pR->Width(), nHeight = pR->Height();
821 :
822 0 : for( long nY = 0; nY < nHeight; nY++ )
823 : {
824 0 : for( long nX = 0; nX < nWidth; nX++ )
825 : {
826 0 : const BitmapColor aOld( pR->GetPixel( nY, nX ) );
827 0 : pW->SetPixel( nY, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
828 0 : ( aOld.GetGreen() >> 1 ) | 0x80,
829 0 : ( aOld.GetBlue() >> 1 ) | 0x80 ) );
830 :
831 0 : }
832 : }
833 :
834 0 : aNewBmp.ReleaseAccess( pW );
835 0 : bRet = sal_True;
836 : }
837 : }
838 :
839 0 : ReleaseAccess( pR );
840 : }
841 :
842 0 : if( bRet )
843 : {
844 0 : const MapMode aMap( maPrefMapMode );
845 0 : const Size aSize( maPrefSize );
846 :
847 0 : *this = aNewBmp;
848 :
849 0 : maPrefMapMode = aMap;
850 0 : maPrefSize = aSize;
851 : }
852 :
853 0 : return bRet;
854 : }
855 :
856 49393 : sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
857 : {
858 49393 : bool bRetval(false);
859 :
860 : #ifdef DBG_UTIL
861 : const sal_uInt16 nStartCount(GetBitCount());
862 : #endif
863 :
864 49393 : if(basegfx::fTools::equalZero(rScaleX) || basegfx::fTools::equalZero(rScaleY))
865 : {
866 : // no scale
867 0 : bRetval = true;
868 : }
869 :
870 49393 : if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
871 : {
872 : // no scale
873 0 : bRetval = true;
874 : }
875 :
876 49393 : switch(nScaleFlag)
877 : {
878 : case BMP_SCALE_NONE :
879 : {
880 0 : bRetval = false;
881 0 : break;
882 : }
883 : case BMP_SCALE_FAST :
884 : {
885 1 : bRetval = ImplScaleFast( rScaleX, rScaleY );
886 1 : break;
887 : }
888 : case BMP_SCALE_INTERPOLATE :
889 : {
890 124 : bRetval = ImplScaleInterpolate( rScaleX, rScaleY );
891 124 : break;
892 : }
893 : case BMP_SCALE_SUPER :
894 : {
895 48113 : if(GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
896 : {
897 : // fallback to ImplScaleFast
898 47374 : bRetval = ImplScaleFast( rScaleX, rScaleY );
899 : }
900 : else
901 : {
902 : // #i121233# use method from symphony
903 739 : bRetval = ImplScaleSuper( rScaleX, rScaleY );
904 : }
905 48113 : break;
906 : }
907 : case BMP_SCALE_LANCZOS :
908 : {
909 1152 : const Lanczos3Kernel kernel;
910 :
911 1152 : bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
912 1152 : break;
913 : }
914 : case BMP_SCALE_BICUBIC :
915 : {
916 1 : const BicubicKernel kernel;
917 :
918 1 : bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
919 1 : break;
920 : }
921 : case BMP_SCALE_BILINEAR :
922 : {
923 1 : const BilinearKernel kernel;
924 :
925 1 : bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
926 1 : break;
927 : }
928 : case BMP_SCALE_BOX :
929 : {
930 1 : const BoxKernel kernel;
931 :
932 1 : bRetval = ImplScaleConvolution( rScaleX, rScaleY, kernel );
933 1 : break;
934 : }
935 : }
936 :
937 : #ifdef DBG_UTIL
938 : if(bRetval && nStartCount != GetBitCount())
939 : {
940 : OSL_ENSURE(false, "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
941 : }
942 : #endif
943 :
944 49393 : return bRetval;
945 : }
946 :
947 : // ------------------------------------------------------------------------
948 :
949 869 : sal_Bool Bitmap::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
950 : {
951 869 : const Size aSize( GetSizePixel() );
952 : bool bRet;
953 :
954 869 : if( aSize.Width() && aSize.Height() )
955 : {
956 869 : bRet = Scale( (double) rNewSize.Width() / aSize.Width(),
957 869 : (double) rNewSize.Height() / aSize.Height(),
958 1738 : nScaleFlag );
959 : }
960 : else
961 0 : bRet = sal_True;
962 :
963 869 : return bRet;
964 : }
965 :
966 : // ------------------------------------------------------------------------
967 :
968 68 : void Bitmap::AdaptBitCount(Bitmap& rNew) const
969 : {
970 68 : ImplAdaptBitCount(rNew);
971 68 : }
972 :
973 : // ------------------------------------------------------------------------
974 :
975 2086 : void Bitmap::ImplAdaptBitCount(Bitmap& rNew) const
976 : {
977 : // aNew is the result of some operation; adapt it's BitCount to the original (this)
978 2086 : if(GetBitCount() != rNew.GetBitCount())
979 : {
980 543 : switch(GetBitCount())
981 : {
982 : case 1:
983 : {
984 0 : rNew.Convert(BMP_CONVERSION_1BIT_THRESHOLD);
985 0 : break;
986 : }
987 : case 4:
988 : {
989 0 : if(HasGreyPalette())
990 : {
991 0 : rNew.Convert(BMP_CONVERSION_4BIT_GREYS);
992 : }
993 : else
994 : {
995 0 : rNew.Convert(BMP_CONVERSION_4BIT_COLORS);
996 : }
997 0 : break;
998 : }
999 : case 8:
1000 : {
1001 543 : if(HasGreyPalette())
1002 : {
1003 542 : rNew.Convert(BMP_CONVERSION_8BIT_GREYS);
1004 : }
1005 : else
1006 : {
1007 1 : rNew.Convert(BMP_CONVERSION_8BIT_COLORS);
1008 : }
1009 543 : break;
1010 : }
1011 : case 24:
1012 : {
1013 0 : rNew.Convert(BMP_CONVERSION_24BIT);
1014 0 : break;
1015 : }
1016 : default:
1017 : {
1018 : OSL_ENSURE(false, "BitDepth adaption failed (!)");
1019 0 : break;
1020 : }
1021 : }
1022 : }
1023 2086 : }
1024 :
1025 47375 : sal_Bool Bitmap::ImplScaleFast( const double& rScaleX, const double& rScaleY )
1026 : {
1027 47375 : const Size aSizePix( GetSizePixel() );
1028 47375 : const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
1029 47375 : const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
1030 47375 : sal_Bool bRet = sal_False;
1031 :
1032 47375 : if( nNewWidth && nNewHeight )
1033 : {
1034 47375 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
1035 :
1036 47375 : if(pReadAcc)
1037 : {
1038 47375 : Bitmap aNewBmp( Size( nNewWidth, nNewHeight ), GetBitCount(), &pReadAcc->GetPalette() );
1039 47375 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
1040 :
1041 47375 : if( pWriteAcc )
1042 : {
1043 47375 : const long nScanlineSize = pWriteAcc->GetScanlineSize();
1044 47375 : const long nNewWidth1 = nNewWidth - 1L;
1045 47375 : const long nNewHeight1 = nNewHeight - 1L;
1046 47375 : const long nWidth = pReadAcc->Width();
1047 47375 : const long nHeight = pReadAcc->Height();
1048 47375 : long* pLutX = new long[ nNewWidth ];
1049 47375 : long* pLutY = new long[ nNewHeight ];
1050 :
1051 47375 : if( nNewWidth1 && nNewHeight1 )
1052 : {
1053 47375 : long nX, nY, nMapY, nActY = 0L;
1054 :
1055 17948499 : for( nX = 0L; nX < nNewWidth; nX++ )
1056 17901124 : pLutX[ nX ] = nX * nWidth / nNewWidth;
1057 :
1058 25307162 : for( nY = 0L; nY < nNewHeight; nY++ )
1059 25259787 : pLutY[ nY ] = nY * nHeight / nNewHeight;
1060 :
1061 306387 : while( nActY < nNewHeight )
1062 : {
1063 211637 : nMapY = pLutY[ nActY ];
1064 :
1065 141921217 : for( nX = 0L; nX < nNewWidth; nX++ )
1066 141709580 : pWriteAcc->SetPixel( nActY, nX, pReadAcc->GetPixel( nMapY , pLutX[ nX ] ) );
1067 :
1068 25471424 : while( ( nActY < nNewHeight1 ) && ( pLutY[ nActY + 1 ] == nMapY ) )
1069 : {
1070 25048150 : memcpy( pWriteAcc->GetScanline( nActY + 1L ),
1071 50096300 : pWriteAcc->GetScanline( nActY ), nScanlineSize );
1072 25048150 : nActY++;
1073 : }
1074 211637 : nActY++;
1075 : }
1076 :
1077 47375 : bRet = sal_True;
1078 47375 : aNewBmp.ReleaseAccess( pWriteAcc );
1079 : }
1080 :
1081 47375 : delete[] pLutX;
1082 47375 : delete[] pLutY;
1083 : }
1084 47375 : ReleaseAccess( pReadAcc );
1085 :
1086 47375 : if( bRet )
1087 47375 : ImplAssignWithSize( aNewBmp );
1088 : }
1089 : }
1090 :
1091 47375 : return bRet;
1092 : }
1093 :
1094 124 : sal_Bool Bitmap::ImplScaleInterpolate( const double& rScaleX, const double& rScaleY )
1095 : {
1096 124 : const Size aSizePix( GetSizePixel() );
1097 124 : const long nNewWidth = FRound( aSizePix.Width() * rScaleX );
1098 124 : const long nNewHeight = FRound( aSizePix.Height() * rScaleY );
1099 124 : sal_Bool bRet = sal_False;
1100 :
1101 124 : if( ( nNewWidth > 1L ) && ( nNewHeight > 1L ) )
1102 : {
1103 124 : BitmapColor aCol0;
1104 248 : BitmapColor aCol1;
1105 124 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
1106 124 : long nWidth = pReadAcc->Width();
1107 124 : long nHeight = pReadAcc->Height();
1108 248 : Bitmap aNewBmp( Size( nNewWidth, nHeight ), 24 );
1109 124 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
1110 : long* pLutInt;
1111 : long* pLutFrac;
1112 : long nX, nY;
1113 : long lXB0, lXB1, lXG0, lXG1, lXR0, lXR1;
1114 : double fTemp;
1115 : long nTemp;
1116 :
1117 124 : if( pReadAcc && pWriteAcc )
1118 : {
1119 124 : const long nNewWidth1 = nNewWidth - 1L;
1120 124 : const long nWidth1 = pReadAcc->Width() - 1L;
1121 124 : const double fRevScaleX = (double) nWidth1 / nNewWidth1;
1122 :
1123 124 : pLutInt = new long[ nNewWidth ];
1124 124 : pLutFrac = new long[ nNewWidth ];
1125 :
1126 1557 : for( nX = 0L, nTemp = nWidth - 2L; nX < nNewWidth; nX++ )
1127 : {
1128 1433 : fTemp = nX * fRevScaleX;
1129 1433 : pLutInt[ nX ] = MinMax( (long) fTemp, 0, nTemp );
1130 1433 : fTemp -= pLutInt[ nX ];
1131 1433 : pLutFrac[ nX ] = (long) ( fTemp * 1024. );
1132 : }
1133 :
1134 1517 : for( nY = 0L; nY < nHeight; nY++ )
1135 : {
1136 1393 : if( 1 == nWidth )
1137 : {
1138 0 : if( pReadAcc->HasPalette() )
1139 : {
1140 0 : aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, 0 ) );
1141 : }
1142 : else
1143 : {
1144 0 : aCol0 = pReadAcc->GetPixel( nY, 0 );
1145 : }
1146 :
1147 0 : for( nX = 0L; nX < nNewWidth; nX++ )
1148 : {
1149 0 : pWriteAcc->SetPixel( nY, nX, aCol0 );
1150 : }
1151 : }
1152 : else
1153 : {
1154 44937 : for( nX = 0L; nX < nNewWidth; nX++ )
1155 : {
1156 43544 : nTemp = pLutInt[ nX ];
1157 :
1158 43544 : if( pReadAcc->HasPalette() )
1159 : {
1160 0 : aCol0 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp++ ) );
1161 0 : aCol1 = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nTemp ) );
1162 : }
1163 : else
1164 : {
1165 43544 : aCol0 = pReadAcc->GetPixel( nY, nTemp++ );
1166 43544 : aCol1 = pReadAcc->GetPixel( nY, nTemp );
1167 : }
1168 :
1169 43544 : nTemp = pLutFrac[ nX ];
1170 :
1171 43544 : lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1172 43544 : lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1173 43544 : lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1174 :
1175 43544 : aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1176 43544 : aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1177 43544 : aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1178 :
1179 43544 : pWriteAcc->SetPixel( nY, nX, aCol0 );
1180 : }
1181 : }
1182 : }
1183 :
1184 124 : delete[] pLutInt;
1185 124 : delete[] pLutFrac;
1186 124 : bRet = sal_True;
1187 : }
1188 :
1189 124 : ReleaseAccess( pReadAcc );
1190 124 : aNewBmp.ReleaseAccess( pWriteAcc );
1191 :
1192 124 : if( bRet )
1193 : {
1194 124 : bRet = sal_False;
1195 124 : const Bitmap aOriginal(*this);
1196 124 : *this = aNewBmp;
1197 124 : aNewBmp = Bitmap( Size( nNewWidth, nNewHeight ), 24 );
1198 124 : pReadAcc = AcquireReadAccess();
1199 124 : pWriteAcc = aNewBmp.AcquireWriteAccess();
1200 :
1201 124 : if( pReadAcc && pWriteAcc )
1202 : {
1203 124 : const long nNewHeight1 = nNewHeight - 1L;
1204 124 : const long nHeight1 = pReadAcc->Height() - 1L;
1205 124 : const double fRevScaleY = (double) nHeight1 / nNewHeight1;
1206 :
1207 124 : pLutInt = new long[ nNewHeight ];
1208 124 : pLutFrac = new long[ nNewHeight ];
1209 :
1210 1679 : for( nY = 0L, nTemp = nHeight - 2L; nY < nNewHeight; nY++ )
1211 : {
1212 1555 : fTemp = nY * fRevScaleY;
1213 1555 : pLutInt[ nY ] = MinMax( (long) fTemp, 0, nTemp );
1214 1555 : fTemp -= pLutInt[ nY ];
1215 1555 : pLutFrac[ nY ] = (long) ( fTemp * 1024. );
1216 : }
1217 :
1218 : // after 1st step, bitmap *is* 24bit format (see above)
1219 : OSL_ENSURE(!pReadAcc->HasPalette(), "OOps, somehow ImplScaleInterpolate in-between format has palette, should not happen (!)");
1220 :
1221 1557 : for( nX = 0L; nX < nNewWidth; nX++ )
1222 : {
1223 1433 : if( 1 == nHeight )
1224 : {
1225 0 : aCol0 = pReadAcc->GetPixel( 0, nX );
1226 :
1227 0 : for( nY = 0L; nY < nNewHeight; nY++ )
1228 : {
1229 0 : pWriteAcc->SetPixel( nY, nX, aCol0 );
1230 : }
1231 : }
1232 : else
1233 : {
1234 23989 : for( nY = 0L; nY < nNewHeight; nY++ )
1235 : {
1236 22556 : nTemp = pLutInt[ nY ];
1237 :
1238 22556 : aCol0 = pReadAcc->GetPixel( nTemp++, nX );
1239 22556 : aCol1 = pReadAcc->GetPixel( nTemp, nX );
1240 :
1241 22556 : nTemp = pLutFrac[ nY ];
1242 :
1243 22556 : lXR1 = aCol1.GetRed() - ( lXR0 = aCol0.GetRed() );
1244 22556 : lXG1 = aCol1.GetGreen() - ( lXG0 = aCol0.GetGreen() );
1245 22556 : lXB1 = aCol1.GetBlue() - ( lXB0 = aCol0.GetBlue() );
1246 :
1247 22556 : aCol0.SetRed( (sal_uInt8) ( ( lXR1 * nTemp + ( lXR0 << 10 ) ) >> 10 ) );
1248 22556 : aCol0.SetGreen( (sal_uInt8) ( ( lXG1 * nTemp + ( lXG0 << 10 ) ) >> 10 ) );
1249 22556 : aCol0.SetBlue( (sal_uInt8) ( ( lXB1 * nTemp + ( lXB0 << 10 ) ) >> 10 ) );
1250 :
1251 22556 : pWriteAcc->SetPixel( nY, nX, aCol0 );
1252 : }
1253 : }
1254 : }
1255 :
1256 124 : delete[] pLutInt;
1257 124 : delete[] pLutFrac;
1258 124 : bRet = sal_True;
1259 : }
1260 :
1261 124 : ReleaseAccess( pReadAcc );
1262 124 : aNewBmp.ReleaseAccess( pWriteAcc );
1263 :
1264 124 : if( bRet )
1265 : {
1266 124 : aOriginal.ImplAdaptBitCount(aNewBmp);
1267 124 : *this = aNewBmp;
1268 124 : }
1269 124 : }
1270 : }
1271 :
1272 124 : if( !bRet )
1273 : {
1274 0 : bRet = ImplScaleFast( rScaleX, rScaleY );
1275 : }
1276 :
1277 124 : return bRet;
1278 : }
1279 :
1280 : // #i121233# Added BMP_SCALE_SUPER from symphony code
1281 :
1282 739 : sal_Bool Bitmap::ImplScaleSuper(
1283 : const double& rScaleX,
1284 : const double& rScaleY )
1285 : {
1286 739 : const Size aSizePix( GetSizePixel() );
1287 739 : bool bHMirr = ( rScaleX < 0 );
1288 739 : bool bVMirr = ( rScaleY < 0 );
1289 739 : double scaleX = bHMirr ? -rScaleX : rScaleX;
1290 739 : double scaleY = bVMirr ? -rScaleY : rScaleY;
1291 739 : const long nDstW = FRound( aSizePix.Width() * scaleX );
1292 739 : const long nDstH = FRound( aSizePix.Height() * scaleY );
1293 739 : const double fScaleThresh = 0.6;
1294 739 : bool bRet = false;
1295 :
1296 739 : if( ( nDstW > 1L ) && ( nDstH > 1L ) )
1297 : {
1298 1478 : BitmapColor aCol0, aCol1, aColRes;
1299 739 : BitmapReadAccess* pAcc = AcquireReadAccess();
1300 1478 : Bitmap aOutBmp( Size( nDstW, nDstH ), 24 );
1301 739 : BitmapWriteAccess* pWAcc = aOutBmp.AcquireWriteAccess();
1302 739 : long* pMapIX = new long[ nDstW ];
1303 739 : long* pMapIY = new long[ nDstH ];
1304 739 : long* pMapFX = new long[ nDstW ];
1305 739 : long* pMapFY = new long[ nDstH ];
1306 : long nX, nY, nXDst, nYDst;;
1307 : double fTemp;
1308 : long nTemp , nTempX, nTempY, nTempFX, nTempFY;
1309 : sal_uInt8 cR0, cG0, cB0, cR1, cG1, cB1;
1310 739 : long nStartX = 0 , nStartY = 0;
1311 739 : long nEndX = nDstW - 1L;
1312 739 : long nEndY = nDstH - 1L;
1313 739 : long nMax = 1 << 7L;
1314 :
1315 739 : if( pAcc && pWAcc )
1316 : {
1317 739 : long nW = pAcc->Width() ;
1318 739 : long nH = pAcc->Height() ;
1319 739 : const double fRevScaleX = ( nDstW > 1L ) ? ( (double) ( nW - 1 ) / ( nDstW - 1 ) ) : 0.0;
1320 739 : const double fRevScaleY = ( nDstH > 1L ) ? ( (double) ( nH - 1 ) / ( nDstH - 1 ) ) : 0.0;
1321 :
1322 : // create horizontal mapping table
1323 58313 : for( nX = 0L, nTempX = nW - 1L, nTemp = nW - 2L; nX < nDstW; nX++ )
1324 : {
1325 57574 : fTemp = nX * fRevScaleX;
1326 :
1327 57574 : if( bHMirr )
1328 0 : fTemp = nTempX - fTemp;
1329 :
1330 57574 : pMapFX[ nX ] = (long) ( ( fTemp - ( pMapIX[ nX ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
1331 : }
1332 :
1333 : // create vertical mapping table
1334 10796 : for( nY = 0L, nTempY = nH - 1L, nTemp = nH - 2L; nY < nDstH; nY++ )
1335 : {
1336 10057 : fTemp = nY * fRevScaleY;
1337 :
1338 10057 : if( bVMirr )
1339 0 : fTemp = nTempY - fTemp;
1340 :
1341 10057 : pMapFY[ nY ] = (long) ( ( fTemp - ( pMapIY[ nY ] = MinMax( (long) fTemp, 0, nTemp ) ) ) * 128. );
1342 : }
1343 :
1344 739 : if( pAcc->HasPalette() )
1345 : {
1346 2 : if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
1347 : {
1348 2 : if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1349 : {
1350 : Scanline pLine0, pLine1;
1351 :
1352 1144 : for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1353 : {
1354 1142 : nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1355 1142 : pLine0 = pAcc->GetScanline( nTempY );
1356 1142 : pLine1 = pAcc->GetScanline( ++nTempY );
1357 :
1358 328896 : for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1359 : {
1360 327754 : nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1361 :
1362 327754 : const BitmapColor& rCol0 = pAcc->GetPaletteColor( pLine0[ nTempX ] );
1363 327754 : const BitmapColor& rCol2 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
1364 327754 : const BitmapColor& rCol1 = pAcc->GetPaletteColor( pLine0[ ++nTempX ] );
1365 327754 : const BitmapColor& rCol3 = pAcc->GetPaletteColor( pLine1[ nTempX ] );
1366 :
1367 327754 : cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTempFX );
1368 327754 : cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTempFX );
1369 327754 : cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTempFX );
1370 :
1371 327754 : cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTempFX );
1372 327754 : cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTempFX );
1373 327754 : cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTempFX );
1374 :
1375 327754 : aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1376 327754 : aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1377 327754 : aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1378 327754 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1379 : }
1380 2 : }
1381 : }
1382 : else
1383 : {
1384 : Scanline pTmpY;
1385 : long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1386 : long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1387 : long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1388 :
1389 0 : for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1390 : {
1391 0 : nTop = bVMirr ? ( nY + 1 ) : nY;
1392 0 : nBottom = bVMirr ? nY : ( nY + 1 ) ;
1393 :
1394 0 : if( nY ==nEndY )
1395 : {
1396 0 : nLineStart = pMapIY[ nY ];
1397 0 : nLineRange = 0;
1398 : }
1399 : else
1400 : {
1401 0 : nLineStart = pMapIY[ nTop ] ;
1402 0 : nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1403 : }
1404 :
1405 0 : for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1406 : {
1407 0 : nLeft = bHMirr ? ( nX + 1 ) : nX;
1408 0 : nRight = bHMirr ? nX : ( nX + 1 ) ;
1409 :
1410 0 : if( nX == nEndX )
1411 : {
1412 0 : nRowStart = pMapIX[ nX ];
1413 0 : nRowRange = 0;
1414 : }
1415 : else
1416 : {
1417 0 : nRowStart = pMapIX[ nLeft ];
1418 0 : nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1419 : }
1420 :
1421 0 : nSumR = nSumG = nSumB = 0;
1422 0 : nTotalWeightY = 0;
1423 :
1424 0 : for(int i = 0; i<= nLineRange; i++)
1425 : {
1426 0 : pTmpY = pAcc->GetScanline( nLineStart + i );
1427 0 : nSumRowR = nSumRowG = nSumRowB = 0;
1428 0 : nTotalWeightX = 0;
1429 :
1430 0 : for(int j = 0; j <= nRowRange; j++)
1431 : {
1432 0 : const BitmapColor& rCol = pAcc->GetPaletteColor( pTmpY[ nRowStart + j ] );
1433 :
1434 0 : if(nX == nEndX )
1435 : {
1436 0 : nSumRowB += rCol.GetBlue() << 7L;
1437 0 : nSumRowG += rCol.GetGreen() << 7L;
1438 0 : nSumRowR += rCol.GetRed() << 7L;
1439 0 : nTotalWeightX += 1 << 7L;
1440 : }
1441 0 : else if( j == 0 )
1442 : {
1443 0 : nWeightX = (nMax- pMapFX[ nLeft ]) ;
1444 0 : nSumRowB += ( nWeightX *rCol.GetBlue()) ;
1445 0 : nSumRowG += ( nWeightX *rCol.GetGreen()) ;
1446 0 : nSumRowR += ( nWeightX *rCol.GetRed()) ;
1447 0 : nTotalWeightX += nWeightX;
1448 : }
1449 0 : else if ( nRowRange == j )
1450 : {
1451 0 : nWeightX = pMapFX[ nRight ] ;
1452 0 : nSumRowB += ( nWeightX *rCol.GetBlue() );
1453 0 : nSumRowG += ( nWeightX *rCol.GetGreen() );
1454 0 : nSumRowR += ( nWeightX *rCol.GetRed() );
1455 0 : nTotalWeightX += nWeightX;
1456 : }
1457 : else
1458 : {
1459 0 : nSumRowB += rCol.GetBlue() << 7L;
1460 0 : nSumRowG += rCol.GetGreen() << 7L;
1461 0 : nSumRowR += rCol.GetRed() << 7L;
1462 0 : nTotalWeightX += 1 << 7L;
1463 : }
1464 : }
1465 :
1466 0 : if( nY == nEndY )
1467 0 : nWeightY = nMax;
1468 0 : else if( i == 0 )
1469 0 : nWeightY = nMax - pMapFY[ nTop ];
1470 0 : else if( nLineRange == 1 )
1471 0 : nWeightY = pMapFY[ nTop ];
1472 0 : else if ( nLineRange == i )
1473 0 : nWeightY = pMapFY[ nBottom ];
1474 : else
1475 0 : nWeightY = nMax;
1476 :
1477 0 : nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1478 0 : nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1479 0 : nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1480 0 : nTotalWeightY += nWeightY;
1481 : }
1482 :
1483 0 : aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1484 0 : aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1485 0 : aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1486 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1487 :
1488 : }
1489 : }
1490 : }
1491 : }
1492 : else
1493 : {
1494 0 : if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1495 : {
1496 0 : for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1497 : {
1498 0 : nTempY = pMapIY[ nY ], nTempFY = pMapFY[ nY ];
1499 :
1500 0 : for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1501 : {
1502 0 : nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1503 :
1504 0 : aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, nTempX ) );
1505 0 : aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY, ++nTempX ) );
1506 0 : cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1507 0 : cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1508 0 : cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1509 :
1510 0 : aCol1 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( ++nTempY, nTempX ) );
1511 0 : aCol0 = pAcc->GetPaletteColor( pAcc->GetPixelIndex( nTempY--, --nTempX ) );
1512 0 : cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1513 0 : cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1514 0 : cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1515 :
1516 0 : aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1517 0 : aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1518 0 : aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1519 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1520 : }
1521 : }
1522 :
1523 : }
1524 : else
1525 : {
1526 : long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1527 : long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1528 : long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1529 :
1530 0 : for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1531 : {
1532 0 : nTop = bVMirr ? ( nY + 1 ) : nY;
1533 0 : nBottom = bVMirr ? nY : ( nY + 1 ) ;
1534 :
1535 0 : if( nY ==nEndY )
1536 : {
1537 0 : nLineStart = pMapIY[ nY ];
1538 0 : nLineRange = 0;
1539 : }
1540 : else
1541 : {
1542 0 : nLineStart = pMapIY[ nTop ] ;
1543 0 : nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1544 : }
1545 :
1546 0 : for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1547 : {
1548 0 : nLeft = bHMirr ? ( nX + 1 ) : nX;
1549 0 : nRight = bHMirr ? nX : ( nX + 1 ) ;
1550 :
1551 0 : if( nX == nEndX )
1552 : {
1553 0 : nRowStart = pMapIX[ nX ];
1554 0 : nRowRange = 0;
1555 : }
1556 : else
1557 : {
1558 0 : nRowStart = pMapIX[ nLeft ];
1559 0 : nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1560 : }
1561 :
1562 0 : nSumR = nSumG = nSumB = 0;
1563 0 : nTotalWeightY = 0;
1564 :
1565 0 : for(int i = 0; i<= nLineRange; i++)
1566 : {
1567 0 : nSumRowR = nSumRowG = nSumRowB = 0;
1568 0 : nTotalWeightX = 0;
1569 :
1570 0 : for(int j = 0; j <= nRowRange; j++)
1571 : {
1572 0 : aCol0 = pAcc->GetPaletteColor ( pAcc->GetPixelIndex( nLineStart + i, nRowStart + j ) );
1573 :
1574 0 : if(nX == nEndX )
1575 : {
1576 :
1577 0 : nSumRowB += aCol0.GetBlue() << 7L;
1578 0 : nSumRowG += aCol0.GetGreen() << 7L;
1579 0 : nSumRowR += aCol0.GetRed() << 7L;
1580 0 : nTotalWeightX += 1 << 7L;
1581 : }
1582 0 : else if( j == 0 )
1583 : {
1584 :
1585 0 : nWeightX = (nMax- pMapFX[ nLeft ]) ;
1586 0 : nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
1587 0 : nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
1588 0 : nSumRowR += ( nWeightX *aCol0.GetRed()) ;
1589 0 : nTotalWeightX += nWeightX;
1590 : }
1591 0 : else if ( nRowRange == j )
1592 : {
1593 :
1594 0 : nWeightX = pMapFX[ nRight ] ;
1595 0 : nSumRowB += ( nWeightX *aCol0.GetBlue() );
1596 0 : nSumRowG += ( nWeightX *aCol0.GetGreen() );
1597 0 : nSumRowR += ( nWeightX *aCol0.GetRed() );
1598 0 : nTotalWeightX += nWeightX;
1599 : }
1600 : else
1601 : {
1602 :
1603 0 : nSumRowB += aCol0.GetBlue() << 7L;
1604 0 : nSumRowG += aCol0.GetGreen() << 7L;
1605 0 : nSumRowR += aCol0.GetRed() << 7L;
1606 0 : nTotalWeightX += 1 << 7L;
1607 : }
1608 : }
1609 :
1610 0 : if( nY == nEndY )
1611 0 : nWeightY = nMax;
1612 0 : else if( i == 0 )
1613 0 : nWeightY = nMax - pMapFY[ nTop ];
1614 0 : else if( nLineRange == 1 )
1615 0 : nWeightY = pMapFY[ nTop ];
1616 0 : else if ( nLineRange == i )
1617 0 : nWeightY = pMapFY[ nBottom ];
1618 : else
1619 0 : nWeightY = nMax;
1620 :
1621 0 : nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1622 0 : nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1623 0 : nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1624 0 : nTotalWeightY += nWeightY;
1625 : }
1626 :
1627 0 : aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1628 0 : aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1629 0 : aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1630 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1631 : }
1632 : }
1633 : }
1634 : }
1635 : }
1636 : else
1637 : {
1638 737 : if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
1639 : {
1640 737 : if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1641 : {
1642 : Scanline pLine0, pLine1, pTmp0, pTmp1;
1643 : long nOff;
1644 :
1645 788 : for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1646 : {
1647 784 : nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1648 784 : pLine0 = pAcc->GetScanline( nTempY );
1649 784 : pLine1 = pAcc->GetScanline( ++nTempY );
1650 :
1651 109760 : for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1652 : {
1653 108976 : nOff = 3L * ( nTempX = pMapIX[ nX ] );
1654 108976 : nTempFX = pMapFX[ nX ];
1655 :
1656 108976 : pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1657 108976 : cB0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1658 108976 : cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1659 108976 : cR0 = MAP( *pTmp0, *pTmp1, nTempFX );
1660 :
1661 108976 : pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1662 108976 : cB1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1663 108976 : cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1664 108976 : cR1 = MAP( *pTmp0, *pTmp1, nTempFX );
1665 :
1666 108976 : aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1667 108976 : aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1668 108976 : aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1669 108976 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1670 : }
1671 4 : }
1672 : }
1673 : else
1674 : {
1675 : Scanline pTmpY, pTmpX;
1676 : long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1677 : long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1678 : long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1679 :
1680 8864 : for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1681 : {
1682 8131 : nTop = bVMirr ? ( nY + 1 ) : nY;
1683 8131 : nBottom = bVMirr ? nY : ( nY + 1 ) ;
1684 :
1685 8131 : if( nY ==nEndY )
1686 : {
1687 733 : nLineStart = pMapIY[ nY ];
1688 733 : nLineRange = 0;
1689 : }
1690 : else
1691 : {
1692 7398 : nLineStart = pMapIY[ nTop ] ;
1693 7398 : nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1694 : }
1695 :
1696 634455 : for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1697 : {
1698 626324 : nLeft = bHMirr ? ( nX + 1 ) : nX;
1699 626324 : nRight = bHMirr ? nX : ( nX + 1 ) ;
1700 :
1701 626324 : if( nX == nEndX )
1702 : {
1703 8131 : nRowStart = pMapIX[ nX ];
1704 8131 : nRowRange = 0;
1705 : }
1706 : else
1707 : {
1708 618193 : nRowStart = pMapIX[ nLeft ];
1709 618193 : nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1710 : }
1711 :
1712 626324 : nSumR = nSumG = nSumB = 0;
1713 626324 : nTotalWeightY = 0;
1714 :
1715 2412488 : for(int i = 0; i<= nLineRange; i++)
1716 : {
1717 1786164 : pTmpY = pAcc->GetScanline( nLineStart + i );
1718 1786164 : pTmpX = pTmpY + 3L * nRowStart;
1719 1786164 : nSumRowR = nSumRowG = nSumRowB = 0;
1720 1786164 : nTotalWeightX = 0;
1721 :
1722 7243950 : for(int j = 0; j <= nRowRange; j++)
1723 : {
1724 5457786 : if(nX == nEndX )
1725 : {
1726 23178 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1727 23178 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1728 23178 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1729 23178 : nTotalWeightX += 1 << 7L;
1730 : }
1731 5434608 : else if( j == 0 )
1732 : {
1733 1762986 : nWeightX = (nMax- pMapFX[ nLeft ]) ;
1734 1762986 : nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
1735 1762986 : nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
1736 1762986 : nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
1737 1762986 : nTotalWeightX += nWeightX;
1738 : }
1739 3671622 : else if ( nRowRange == j )
1740 : {
1741 1762986 : nWeightX = pMapFX[ nRight ] ;
1742 1762986 : nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
1743 1762986 : nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
1744 1762986 : nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
1745 1762986 : nTotalWeightX += nWeightX;
1746 : }
1747 : else
1748 : {
1749 1908636 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1750 1908636 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1751 1908636 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1752 1908636 : nTotalWeightX += 1 << 7L;
1753 : }
1754 : }
1755 :
1756 1786164 : if( nY == nEndY )
1757 56444 : nWeightY = nMax;
1758 1729720 : else if( i == 0 )
1759 569880 : nWeightY = nMax - pMapFY[ nTop ];
1760 1159840 : else if( nLineRange == 1 )
1761 0 : nWeightY = pMapFY[ nTop ];
1762 1159840 : else if ( nLineRange == i )
1763 569880 : nWeightY = pMapFY[ nBottom ];
1764 : else
1765 589960 : nWeightY = nMax;
1766 :
1767 1786164 : nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1768 1786164 : nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1769 1786164 : nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1770 1786164 : nTotalWeightY += nWeightY;
1771 : }
1772 :
1773 626324 : aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1774 626324 : aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1775 626324 : aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1776 626324 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1777 :
1778 : }
1779 : }
1780 : }
1781 : }
1782 0 : else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
1783 : {
1784 0 : if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1785 : {
1786 : Scanline pLine0, pLine1, pTmp0, pTmp1;
1787 : long nOff;
1788 :
1789 0 : for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1790 : {
1791 0 : nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1792 0 : pLine0 = pAcc->GetScanline( nTempY );
1793 0 : pLine1 = pAcc->GetScanline( ++nTempY );
1794 :
1795 0 : for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1796 : {
1797 0 : nOff = 3L * ( nTempX = pMapIX[ nX ] );
1798 0 : nTempFX = pMapFX[ nX ];
1799 :
1800 0 : pTmp1 = ( pTmp0 = pLine0 + nOff ) + 3L;
1801 0 : cR0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1802 0 : cG0 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1803 0 : cB0 = MAP( *pTmp0, *pTmp1, nTempFX );
1804 :
1805 0 : pTmp1 = ( pTmp0 = pLine1 + nOff ) + 3L;
1806 0 : cR1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1807 0 : cG1 = MAP( *pTmp0, *pTmp1, nTempFX ); pTmp0++; pTmp1++;
1808 0 : cB1 = MAP( *pTmp0, *pTmp1, nTempFX );
1809 :
1810 0 : aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1811 0 : aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1812 0 : aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1813 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1814 : }
1815 0 : }
1816 : }
1817 : else
1818 : {
1819 : Scanline pTmpY, pTmpX;
1820 : long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1821 : long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1822 : long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1823 :
1824 0 : for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1825 : {
1826 0 : nTop = bVMirr ? ( nY + 1 ) : nY;
1827 0 : nBottom = bVMirr ? nY : ( nY + 1 ) ;
1828 :
1829 0 : if( nY ==nEndY )
1830 : {
1831 0 : nLineStart = pMapIY[ nY ];
1832 0 : nLineRange = 0;
1833 : }
1834 : else
1835 : {
1836 0 : nLineStart = pMapIY[ nTop ] ;
1837 0 : nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1838 : }
1839 :
1840 0 : for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1841 : {
1842 0 : nLeft = bHMirr ? ( nX + 1 ) : nX;
1843 0 : nRight = bHMirr ? nX : ( nX + 1 ) ;
1844 :
1845 0 : if( nX == nEndX )
1846 : {
1847 0 : nRowStart = pMapIX[ nX ];
1848 0 : nRowRange = 0;
1849 : }
1850 : else
1851 : {
1852 0 : nRowStart = pMapIX[ nLeft ];
1853 0 : nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1854 : }
1855 :
1856 0 : nSumR = nSumG = nSumB = 0;
1857 0 : nTotalWeightY = 0;
1858 :
1859 0 : for(int i = 0; i<= nLineRange; i++)
1860 : {
1861 0 : pTmpY = pAcc->GetScanline( nLineStart + i );
1862 0 : pTmpX = pTmpY + 3L * nRowStart;
1863 0 : nSumRowR = nSumRowG = nSumRowB = 0;
1864 0 : nTotalWeightX = 0;
1865 :
1866 0 : for(int j = 0; j <= nRowRange; j++)
1867 : {
1868 0 : if(nX == nEndX )
1869 : {
1870 0 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1871 0 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1872 0 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1873 0 : nTotalWeightX += 1 << 7L;
1874 : }
1875 0 : else if( j == 0 )
1876 : {
1877 0 : nWeightX = (nMax- pMapFX[ nLeft ]) ;
1878 0 : nSumRowR += ( nWeightX *( *pTmpX )) ;pTmpX++;
1879 0 : nSumRowG += ( nWeightX *( *pTmpX )) ;pTmpX++;
1880 0 : nSumRowB += ( nWeightX *( *pTmpX )) ;pTmpX++;
1881 0 : nTotalWeightX += nWeightX;
1882 : }
1883 0 : else if ( nRowRange == j )
1884 : {
1885 0 : nWeightX = pMapFX[ nRight ] ;
1886 0 : nSumRowR += ( nWeightX *( *pTmpX ) );pTmpX++;
1887 0 : nSumRowG += ( nWeightX *( *pTmpX ) );pTmpX++;
1888 0 : nSumRowB += ( nWeightX *( *pTmpX ) );pTmpX++;
1889 0 : nTotalWeightX += nWeightX;
1890 : }
1891 : else
1892 : {
1893 0 : nSumRowR += ( *pTmpX ) << 7L;pTmpX++;
1894 0 : nSumRowG += ( *pTmpX ) << 7L;pTmpX++;
1895 0 : nSumRowB += ( *pTmpX ) << 7L;pTmpX++;
1896 0 : nTotalWeightX += 1 << 7L;
1897 : }
1898 : }
1899 :
1900 0 : if( nY == nEndY )
1901 0 : nWeightY = nMax;
1902 0 : else if( i == 0 )
1903 0 : nWeightY = nMax - pMapFY[ nTop ];
1904 0 : else if( nLineRange == 1 )
1905 0 : nWeightY = pMapFY[ nTop ];
1906 0 : else if ( nLineRange == i )
1907 0 : nWeightY = pMapFY[ nBottom ];
1908 : else
1909 0 : nWeightY = nMax;
1910 :
1911 0 : nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
1912 0 : nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
1913 0 : nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
1914 0 : nTotalWeightY += nWeightY;
1915 : }
1916 :
1917 0 : aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
1918 0 : aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
1919 0 : aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
1920 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1921 :
1922 : }
1923 : }
1924 : }
1925 : }
1926 : else
1927 : {
1928 0 : if( scaleX >= fScaleThresh && scaleY >= fScaleThresh )
1929 : {
1930 0 : for( nY = nStartY, nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1931 : {
1932 0 : nTempY = pMapIY[ nY ]; nTempFY = pMapFY[ nY ];
1933 :
1934 0 : for( nX = nStartX, nXDst = 0L; nX <= nEndX; nX++ )
1935 : {
1936 0 : nTempX = pMapIX[ nX ]; nTempFX = pMapFX[ nX ];
1937 :
1938 0 : aCol0 = pAcc->GetPixel( nTempY, nTempX );
1939 0 : aCol1 = pAcc->GetPixel( nTempY, ++nTempX );
1940 0 : cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1941 0 : cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1942 0 : cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1943 :
1944 0 : aCol1 = pAcc->GetPixel( ++nTempY, nTempX );
1945 0 : aCol0 = pAcc->GetPixel( nTempY--, --nTempX );
1946 0 : cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTempFX );
1947 0 : cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTempFX );
1948 0 : cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTempFX );
1949 :
1950 0 : aColRes.SetRed( MAP( cR0, cR1, nTempFY ) );
1951 0 : aColRes.SetGreen( MAP( cG0, cG1, nTempFY ) );
1952 0 : aColRes.SetBlue( MAP( cB0, cB1, nTempFY ) );
1953 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
1954 : }
1955 : }
1956 : }
1957 : else
1958 : {
1959 : long nSumR, nSumG, nSumB,nLineStart , nLineRange, nRowStart , nRowRange ;
1960 : long nLeft, nRight, nTop, nBottom, nWeightX, nWeightY ;
1961 : long nSumRowR ,nSumRowG,nSumRowB, nTotalWeightX, nTotalWeightY;
1962 :
1963 0 : for( nY = nStartY , nYDst = 0L; nY <= nEndY; nY++, nYDst++ )
1964 : {
1965 0 : nTop = bVMirr ? ( nY + 1 ) : nY;
1966 0 : nBottom = bVMirr ? nY : ( nY + 1 ) ;
1967 :
1968 0 : if( nY ==nEndY )
1969 : {
1970 0 : nLineStart = pMapIY[ nY ];
1971 0 : nLineRange = 0;
1972 : }
1973 : else
1974 : {
1975 0 : nLineStart = pMapIY[ nTop ] ;
1976 0 : nLineRange = ( pMapIY[ nBottom ] == pMapIY[ nTop ] ) ? 1 :( pMapIY[ nBottom ] - pMapIY[ nTop ] );
1977 : }
1978 :
1979 0 : for( nX = nStartX , nXDst = 0L; nX <= nEndX; nX++ )
1980 : {
1981 0 : nLeft = bHMirr ? ( nX + 1 ) : nX;
1982 0 : nRight = bHMirr ? nX : ( nX + 1 ) ;
1983 :
1984 0 : if( nX == nEndX )
1985 : {
1986 0 : nRowStart = pMapIX[ nX ];
1987 0 : nRowRange = 0;
1988 : }
1989 : else
1990 : {
1991 0 : nRowStart = pMapIX[ nLeft ];
1992 0 : nRowRange = ( pMapIX[ nRight ] == pMapIX[ nLeft ] )? 1 : ( pMapIX[ nRight ] - pMapIX[ nLeft ] );
1993 : }
1994 :
1995 0 : nSumR = nSumG = nSumB = 0;
1996 0 : nTotalWeightY = 0;
1997 :
1998 0 : for(int i = 0; i<= nLineRange; i++)
1999 : {
2000 0 : nSumRowR = nSumRowG = nSumRowB = 0;
2001 0 : nTotalWeightX = 0;
2002 :
2003 0 : for(int j = 0; j <= nRowRange; j++)
2004 : {
2005 0 : aCol0 = pAcc->GetPixel( nLineStart + i, nRowStart + j );
2006 :
2007 0 : if(nX == nEndX )
2008 : {
2009 :
2010 0 : nSumRowB += aCol0.GetBlue() << 7L;
2011 0 : nSumRowG += aCol0.GetGreen() << 7L;
2012 0 : nSumRowR += aCol0.GetRed() << 7L;
2013 0 : nTotalWeightX += 1 << 7L;
2014 : }
2015 0 : else if( j == 0 )
2016 : {
2017 :
2018 0 : nWeightX = (nMax- pMapFX[ nLeft ]) ;
2019 0 : nSumRowB += ( nWeightX *aCol0.GetBlue()) ;
2020 0 : nSumRowG += ( nWeightX *aCol0.GetGreen()) ;
2021 0 : nSumRowR += ( nWeightX *aCol0.GetRed()) ;
2022 0 : nTotalWeightX += nWeightX;
2023 : }
2024 0 : else if ( nRowRange == j )
2025 : {
2026 :
2027 0 : nWeightX = pMapFX[ nRight ] ;
2028 0 : nSumRowB += ( nWeightX *aCol0.GetBlue() );
2029 0 : nSumRowG += ( nWeightX *aCol0.GetGreen() );
2030 0 : nSumRowR += ( nWeightX *aCol0.GetRed() );
2031 0 : nTotalWeightX += nWeightX;
2032 : }
2033 : else
2034 : {
2035 0 : nSumRowB += aCol0.GetBlue() << 7L;
2036 0 : nSumRowG += aCol0.GetGreen() << 7L;
2037 0 : nSumRowR += aCol0.GetRed() << 7L;
2038 0 : nTotalWeightX += 1 << 7L;
2039 : }
2040 : }
2041 :
2042 0 : if( nY == nEndY )
2043 0 : nWeightY = nMax;
2044 0 : else if( i == 0 )
2045 0 : nWeightY = nMax - pMapFY[ nTop ];
2046 0 : else if( nLineRange == 1 )
2047 0 : nWeightY = pMapFY[ nTop ];
2048 0 : else if ( nLineRange == i )
2049 0 : nWeightY = pMapFY[ nBottom ];
2050 : else
2051 0 : nWeightY = nMax;
2052 :
2053 0 : nSumB += nWeightY * ( nSumRowB / nTotalWeightX );
2054 0 : nSumG += nWeightY * ( nSumRowG / nTotalWeightX );
2055 0 : nSumR += nWeightY * ( nSumRowR / nTotalWeightX );
2056 0 : nTotalWeightY += nWeightY;
2057 : }
2058 :
2059 0 : aColRes.SetRed( ( sal_uInt8 ) (( nSumR / nTotalWeightY ) ));
2060 0 : aColRes.SetGreen( ( sal_uInt8 ) (( nSumG / nTotalWeightY) ));
2061 0 : aColRes.SetBlue( ( sal_uInt8 ) (( nSumB / nTotalWeightY ) ));
2062 0 : pWAcc->SetPixel( nYDst, nXDst++, aColRes );
2063 :
2064 : }
2065 : }
2066 : }
2067 : }
2068 : }
2069 :
2070 739 : bRet = true;
2071 : }
2072 :
2073 739 : delete[] pMapIX;
2074 739 : delete[] pMapIY;
2075 739 : delete[] pMapFX;
2076 739 : delete[] pMapFY;
2077 :
2078 739 : if(pAcc)
2079 : {
2080 739 : ReleaseAccess( pAcc );
2081 : }
2082 739 : if(pWAcc)
2083 : {
2084 739 : aOutBmp.ReleaseAccess( pWAcc );
2085 : }
2086 739 : if( bRet )
2087 : {
2088 739 : ImplAdaptBitCount(aOutBmp);
2089 739 : ImplAssignWithSize(aOutBmp);
2090 : }
2091 :
2092 739 : if( !bRet )
2093 739 : bRet = ImplScaleFast( scaleX, scaleY );
2094 : }
2095 :
2096 739 : return bRet;
2097 : }
2098 :
2099 : //-----------------------------------------------------------------------------------
2100 :
2101 : namespace
2102 : {
2103 2204 : void ImplCalculateContributions(
2104 : const sal_uInt32 aSourceSize,
2105 : const sal_uInt32 aDestinationSize,
2106 : sal_uInt32& aNumberOfContributions,
2107 : double*& pWeights,
2108 : sal_uInt32*& pPixels,
2109 : sal_uInt32*& pCount,
2110 : const Kernel& aKernel)
2111 : {
2112 2204 : const double fSamplingRadius(aKernel.GetWidth());
2113 2204 : const double fScale(aDestinationSize / static_cast< double >(aSourceSize));
2114 2204 : const double fScaledRadius((fScale < 1.0) ? fSamplingRadius / fScale : fSamplingRadius);
2115 2204 : const double fFilterFactor((fScale < 1.0) ? fScale : 1.0);
2116 :
2117 2204 : aNumberOfContributions = (static_cast< sal_uInt32 >(fabs(ceil(fScaledRadius))) * 2) + 1;
2118 2204 : const sal_uInt32 nAllocSize(aDestinationSize * aNumberOfContributions);
2119 2204 : pWeights = new double[nAllocSize];
2120 2204 : pPixels = new sal_uInt32[nAllocSize];
2121 2204 : pCount = new sal_uInt32[aDestinationSize];
2122 :
2123 207401 : for(sal_uInt32 i(0); i < aDestinationSize; i++)
2124 : {
2125 205197 : const sal_uInt32 aIndex(i * aNumberOfContributions);
2126 205197 : const double aCenter(i / fScale);
2127 205197 : const sal_Int32 aLeft(static_cast< sal_Int32 >(floor(aCenter - fScaledRadius)));
2128 205197 : const sal_Int32 aRight(static_cast< sal_Int32 >(ceil(aCenter + fScaledRadius)));
2129 205197 : sal_uInt32 aCurrentCount(0);
2130 :
2131 4470681 : for(sal_Int32 j(aLeft); j <= aRight; j++)
2132 : {
2133 4265484 : const double aWeight(aKernel.Calculate(fFilterFactor * (aCenter - static_cast< double>(j))));
2134 :
2135 : // Reduce calculations with ignoring weights of 0.0
2136 4265484 : if(fabs(aWeight) < 0.0001)
2137 : {
2138 662083 : continue;
2139 : }
2140 :
2141 : // Handling on edges
2142 3603401 : const sal_uInt32 aPixelIndex(MinMax(j, 0, aSourceSize - 1));
2143 3603401 : const sal_uInt32 nIndex(aIndex + aCurrentCount);
2144 :
2145 3603401 : pWeights[nIndex] = aWeight;
2146 3603401 : pPixels[nIndex] = aPixelIndex;
2147 :
2148 3603401 : aCurrentCount++;
2149 : }
2150 :
2151 205197 : pCount[i] = aCurrentCount;
2152 : }
2153 2204 : }
2154 :
2155 1123 : sal_Bool ImplScaleConvolutionHor(
2156 : Bitmap& rSource,
2157 : Bitmap& rTarget,
2158 : const double& rScaleX,
2159 : const Kernel& aKernel)
2160 : {
2161 : // Do horizontal filtering
2162 : OSL_ENSURE(rScaleX > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
2163 1123 : const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
2164 1123 : const sal_uInt32 nNewWidth(FRound(nWidth * rScaleX));
2165 :
2166 1123 : if(nWidth == nNewWidth)
2167 : {
2168 0 : return true;
2169 : }
2170 :
2171 1123 : BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
2172 :
2173 1123 : if(pReadAcc)
2174 : {
2175 1123 : double* pWeights = 0;
2176 1123 : sal_uInt32* pPixels = 0;
2177 1123 : sal_uInt32* pCount = 0;
2178 1123 : sal_uInt32 aNumberOfContributions(0);
2179 :
2180 1123 : const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
2181 1123 : ImplCalculateContributions(nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
2182 1123 : rTarget = Bitmap(Size(nNewWidth, nHeight), 24);
2183 1123 : BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
2184 1123 : bool bResult(0 != pWriteAcc);
2185 :
2186 1123 : if(bResult)
2187 : {
2188 180427 : for(sal_uInt32 y(0); y < nHeight; y++)
2189 : {
2190 17475570 : for(sal_uInt32 x(0); x < nNewWidth; x++)
2191 : {
2192 17296266 : const sal_uInt32 aBaseIndex(x * aNumberOfContributions);
2193 17296266 : double aSum(0.0);
2194 17296266 : double aValueRed(0.0);
2195 17296266 : double aValueGreen(0.0);
2196 17296266 : double aValueBlue(0.0);
2197 :
2198 343521168 : for(sal_uInt32 j(0); j < pCount[x]; j++)
2199 : {
2200 326224902 : const sal_uInt32 aIndex(aBaseIndex + j);
2201 326224902 : const double aWeight(pWeights[aIndex]);
2202 326224902 : BitmapColor aColor;
2203 :
2204 326224902 : aSum += aWeight;
2205 :
2206 326224902 : if(pReadAcc->HasPalette())
2207 : {
2208 113838885 : aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(y, pPixels[aIndex]));
2209 : }
2210 : else
2211 : {
2212 212386017 : aColor = pReadAcc->GetPixel(y, pPixels[aIndex]);
2213 : }
2214 :
2215 326224902 : aValueRed += aWeight * aColor.GetRed();
2216 326224902 : aValueGreen += aWeight * aColor.GetGreen();
2217 326224902 : aValueBlue += aWeight * aColor.GetBlue();
2218 326224902 : }
2219 :
2220 : const BitmapColor aResultColor(
2221 17296266 : static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
2222 17296266 : static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
2223 51888798 : static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
2224 :
2225 17296266 : pWriteAcc->SetPixel(y, x, aResultColor);
2226 17296266 : }
2227 : }
2228 :
2229 1123 : rTarget.ReleaseAccess(pWriteAcc);
2230 : }
2231 :
2232 1123 : rSource.ReleaseAccess(pReadAcc);
2233 1123 : delete[] pWeights;
2234 1123 : delete[] pCount;
2235 1123 : delete[] pPixels;
2236 :
2237 1123 : if(bResult)
2238 : {
2239 1123 : return true;
2240 : }
2241 : }
2242 :
2243 0 : return false;
2244 : }
2245 :
2246 1081 : bool ImplScaleConvolutionVer(
2247 : Bitmap& rSource,
2248 : Bitmap& rTarget,
2249 : const double& rScaleY,
2250 : const Kernel& aKernel)
2251 : {
2252 : // Do vertical filtering
2253 : OSL_ENSURE(rScaleY > 0.0, "Error in scaling: Mirror given in non-mirror-capable method (!)");
2254 1081 : const sal_uInt32 nHeight(rSource.GetSizePixel().Height());
2255 1081 : const sal_uInt32 nNewHeight(FRound(nHeight * rScaleY));
2256 :
2257 1081 : if(nHeight == nNewHeight)
2258 : {
2259 0 : return true;
2260 : }
2261 :
2262 1081 : BitmapReadAccess* pReadAcc = rSource.AcquireReadAccess();
2263 :
2264 1081 : if(pReadAcc)
2265 : {
2266 1081 : double* pWeights = 0;
2267 1081 : sal_uInt32* pPixels = 0;
2268 1081 : sal_uInt32* pCount = 0;
2269 1081 : sal_uInt32 aNumberOfContributions(0);
2270 :
2271 1081 : const sal_uInt32 nWidth(rSource.GetSizePixel().Width());
2272 1081 : ImplCalculateContributions(nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel);
2273 1081 : rTarget = Bitmap(Size(nWidth, nNewHeight), 24);
2274 1081 : BitmapWriteAccess* pWriteAcc = rTarget.AcquireWriteAccess();
2275 1081 : bool bResult(0 != pWriteAcc);
2276 :
2277 1081 : if(pWriteAcc)
2278 : {
2279 273425 : for(sal_uInt32 x(0); x < nWidth; x++)
2280 : {
2281 23241832 : for(sal_uInt32 y(0); y < nNewHeight; y++)
2282 : {
2283 22969488 : const sal_uInt32 aBaseIndex(y * aNumberOfContributions);
2284 22969488 : double aSum(0.0);
2285 22969488 : double aValueRed(0.0);
2286 22969488 : double aValueGreen(0.0);
2287 22969488 : double aValueBlue(0.0);
2288 :
2289 549222304 : for(sal_uInt32 j(0); j < pCount[y]; j++)
2290 : {
2291 526252816 : const sal_uInt32 aIndex(aBaseIndex + j);
2292 526252816 : const double aWeight(pWeights[aIndex]);
2293 526252816 : BitmapColor aColor;
2294 :
2295 526252816 : aSum += aWeight;
2296 :
2297 526252816 : if(pReadAcc->HasPalette())
2298 : {
2299 215449326 : aColor = pReadAcc->GetPaletteColor(pReadAcc->GetPixelIndex(pPixels[aIndex], x));
2300 : }
2301 : else
2302 : {
2303 310803490 : aColor = pReadAcc->GetPixel(pPixels[aIndex], x);
2304 : }
2305 :
2306 526252816 : aValueRed += aWeight * aColor.GetRed();
2307 526252816 : aValueGreen += aWeight * aColor.GetGreen();
2308 526252816 : aValueBlue += aWeight * aColor.GetBlue();
2309 526252816 : }
2310 :
2311 : const BitmapColor aResultColor(
2312 22969488 : static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueRed / aSum), 0, 255)),
2313 22969488 : static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueGreen / aSum), 0, 255)),
2314 68908464 : static_cast< sal_uInt8 >(MinMax(static_cast< sal_Int32 >(aValueBlue / aSum), 0, 255)));
2315 :
2316 22969488 : if(pWriteAcc->HasPalette())
2317 : {
2318 0 : pWriteAcc->SetPixelIndex(y, x, static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(aResultColor)));
2319 : }
2320 : else
2321 : {
2322 22969488 : pWriteAcc->SetPixel(y, x, aResultColor);
2323 : }
2324 22969488 : }
2325 : }
2326 : }
2327 :
2328 1081 : rTarget.ReleaseAccess(pWriteAcc);
2329 1081 : rSource.ReleaseAccess(pReadAcc);
2330 :
2331 1081 : delete[] pWeights;
2332 1081 : delete[] pCount;
2333 1081 : delete[] pPixels;
2334 :
2335 1081 : if(bResult)
2336 : {
2337 1081 : return true;
2338 : }
2339 : }
2340 :
2341 0 : return false;
2342 : }
2343 : }
2344 :
2345 : // #i121233# Added BMP_SCALE_LANCZOS, BMP_SCALE_BICUBIC, BMP_SCALE_BILINEAR and
2346 : // BMP_SCALE_BOX derived from the original commit from Tomas Vajngerl (see
2347 : // bugzilla task for deitails) Thanks!
2348 1155 : sal_Bool Bitmap::ImplScaleConvolution(
2349 : const double& rScaleX,
2350 : const double& rScaleY,
2351 : const Kernel& aKernel)
2352 : {
2353 1155 : const bool bMirrorHor(rScaleX < 0.0);
2354 1155 : const bool bMirrorVer(rScaleY < 0.0);
2355 1155 : const double fScaleX(bMirrorHor ? -rScaleX : rScaleX);
2356 1155 : const double fScaleY(bMirrorVer ? -rScaleY : rScaleY);
2357 1155 : const sal_uInt32 nWidth(GetSizePixel().Width());
2358 1155 : const sal_uInt32 nHeight(GetSizePixel().Height());
2359 1155 : const sal_uInt32 nNewWidth(FRound(nWidth * fScaleX));
2360 1155 : const sal_uInt32 nNewHeight(FRound(nHeight * fScaleY));
2361 1155 : const bool bScaleHor(nWidth != nNewWidth);
2362 1155 : const bool bScaleVer(nHeight != nNewHeight);
2363 1155 : const bool bMirror(bMirrorHor || bMirrorVer);
2364 :
2365 1155 : if(!bMirror && !bScaleHor && !bScaleVer)
2366 : {
2367 0 : return true;
2368 : }
2369 :
2370 1155 : bool bResult(true);
2371 1155 : sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
2372 1155 : bool bMirrorAfter(false);
2373 :
2374 1155 : if(bMirror)
2375 : {
2376 0 : if(bMirrorHor)
2377 : {
2378 0 : nMirrorFlags |= BMP_MIRROR_HORZ;
2379 : }
2380 :
2381 0 : if(bMirrorVer)
2382 : {
2383 0 : nMirrorFlags |= BMP_MIRROR_VERT;
2384 : }
2385 :
2386 0 : const sal_uInt32 nStartSize(nWidth * nHeight);
2387 0 : const sal_uInt32 nEndSize(nNewWidth * nNewHeight);
2388 :
2389 0 : bMirrorAfter = nStartSize > nEndSize;
2390 :
2391 0 : if(!bMirrorAfter)
2392 : {
2393 0 : bResult = Mirror(nMirrorFlags);
2394 : }
2395 : }
2396 :
2397 1155 : Bitmap aResult;
2398 :
2399 1155 : if(bResult)
2400 : {
2401 1155 : const sal_uInt32 nInBetweenSizeHorFirst(nHeight * nNewWidth);
2402 1155 : const sal_uInt32 nInBetweenSizeVerFirst(nNewHeight * nWidth);
2403 1155 : Bitmap aSource(*this);
2404 :
2405 1155 : if(nInBetweenSizeHorFirst < nInBetweenSizeVerFirst)
2406 : {
2407 322 : if(bScaleHor)
2408 : {
2409 322 : bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
2410 : }
2411 :
2412 322 : if(bResult && bScaleVer)
2413 : {
2414 248 : if(bScaleHor)
2415 : {
2416 : // copy partial result, independent of color depth
2417 248 : aSource = aResult;
2418 : }
2419 :
2420 248 : bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
2421 : }
2422 : }
2423 : else
2424 : {
2425 833 : if(bScaleVer)
2426 : {
2427 833 : bResult = ImplScaleConvolutionVer(aSource, aResult, fScaleY, aKernel);
2428 : }
2429 :
2430 833 : if(bResult && bScaleHor)
2431 : {
2432 801 : if(bScaleVer)
2433 : {
2434 : // copy partial result, independent of color depth
2435 801 : aSource = aResult;
2436 : }
2437 :
2438 801 : bResult = ImplScaleConvolutionHor(aSource, aResult, fScaleX, aKernel);
2439 : }
2440 1155 : }
2441 : }
2442 :
2443 1155 : if(bResult && bMirrorAfter)
2444 : {
2445 0 : bResult = aResult.Mirror(nMirrorFlags);
2446 : }
2447 :
2448 1155 : if(bResult)
2449 : {
2450 1155 : ImplAdaptBitCount(aResult);
2451 1155 : *this = aResult;
2452 : }
2453 :
2454 1155 : return bResult;
2455 : }
2456 :
2457 : // ------------------------------------------------------------------------
2458 :
2459 0 : sal_Bool Bitmap::Dither( sal_uLong nDitherFlags )
2460 : {
2461 0 : sal_Bool bRet = sal_False;
2462 :
2463 0 : const Size aSizePix( GetSizePixel() );
2464 :
2465 0 : if( aSizePix.Width() == 1 || aSizePix.Height() == 1 )
2466 0 : bRet = sal_True;
2467 0 : else if( nDitherFlags & BMP_DITHER_MATRIX )
2468 0 : bRet = ImplDitherMatrix();
2469 0 : else if( nDitherFlags & BMP_DITHER_FLOYD )
2470 0 : bRet = ImplDitherFloyd();
2471 0 : else if( ( nDitherFlags & BMP_DITHER_FLOYD_16 ) && ( GetBitCount() == 24 ) )
2472 0 : bRet = ImplDitherFloyd16();
2473 :
2474 0 : return bRet;
2475 : }
2476 :
2477 0 : sal_Bool Bitmap::ImplDitherMatrix()
2478 : {
2479 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
2480 0 : Bitmap aNewBmp( GetSizePixel(), 8 );
2481 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
2482 0 : sal_Bool bRet = sal_False;
2483 :
2484 0 : if( pReadAcc && pWriteAcc )
2485 : {
2486 0 : const sal_uLong nWidth = pReadAcc->Width();
2487 0 : const sal_uLong nHeight = pReadAcc->Height();
2488 0 : BitmapColor aIndex( (sal_uInt8) 0 );
2489 :
2490 0 : if( pReadAcc->HasPalette() )
2491 : {
2492 0 : for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2493 : {
2494 0 : for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2495 : {
2496 0 : const BitmapColor aCol( pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) ) );
2497 0 : const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2498 0 : const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2499 0 : const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2500 0 : const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2501 :
2502 0 : aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2503 0 : pWriteAcc->SetPixel( nY, nX, aIndex );
2504 0 : }
2505 : }
2506 : }
2507 : else
2508 : {
2509 0 : for( sal_uLong nY = 0UL; nY < nHeight; nY++ )
2510 : {
2511 0 : for( sal_uLong nX = 0UL, nModY = ( nY & 0x0FUL ) << 4UL; nX < nWidth; nX++ )
2512 : {
2513 0 : const BitmapColor aCol( pReadAcc->GetPixel( nY, nX ) );
2514 0 : const sal_uLong nD = nVCLDitherLut[ nModY + ( nX & 0x0FUL ) ];
2515 0 : const sal_uLong nR = ( nVCLLut[ aCol.GetRed() ] + nD ) >> 16UL;
2516 0 : const sal_uLong nG = ( nVCLLut[ aCol.GetGreen() ] + nD ) >> 16UL;
2517 0 : const sal_uLong nB = ( nVCLLut[ aCol.GetBlue() ] + nD ) >> 16UL;
2518 :
2519 0 : aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ nR ] + nVCLGLut[ nG ] + nVCLBLut[ nB ] ) );
2520 0 : pWriteAcc->SetPixel( nY, nX, aIndex );
2521 0 : }
2522 : }
2523 : }
2524 :
2525 0 : bRet = sal_True;
2526 : }
2527 :
2528 0 : ReleaseAccess( pReadAcc );
2529 0 : aNewBmp.ReleaseAccess( pWriteAcc );
2530 :
2531 0 : if( bRet )
2532 : {
2533 0 : const MapMode aMap( maPrefMapMode );
2534 0 : const Size aSize( maPrefSize );
2535 :
2536 0 : *this = aNewBmp;
2537 :
2538 0 : maPrefMapMode = aMap;
2539 0 : maPrefSize = aSize;
2540 : }
2541 :
2542 0 : return bRet;
2543 : }
2544 :
2545 0 : sal_Bool Bitmap::ImplDitherFloyd()
2546 : {
2547 0 : const Size aSize( GetSizePixel() );
2548 0 : sal_Bool bRet = sal_False;
2549 :
2550 0 : if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
2551 : {
2552 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
2553 0 : Bitmap aNewBmp( GetSizePixel(), 8 );
2554 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
2555 :
2556 0 : if( pReadAcc && pWriteAcc )
2557 : {
2558 0 : BitmapColor aColor;
2559 0 : long nWidth = pReadAcc->Width();
2560 0 : long nWidth1 = nWidth - 1L;
2561 0 : long nHeight = pReadAcc->Height();
2562 : long nX;
2563 0 : long nW = nWidth * 3L;
2564 0 : long nW2 = nW - 3L;
2565 : long nRErr, nGErr, nBErr;
2566 : long nRC, nGC, nBC;
2567 : long nTemp;
2568 : long nZ;
2569 0 : long* p1 = new long[ nW ];
2570 0 : long* p2 = new long[ nW ];
2571 0 : long* p1T = p1;
2572 0 : long* p2T = p2;
2573 : long* pTmp;
2574 0 : sal_Bool bPal = pReadAcc->HasPalette();
2575 :
2576 0 : pTmp = p2T;
2577 :
2578 0 : if( bPal )
2579 : {
2580 0 : for( nZ = 0; nZ < nWidth; nZ++ )
2581 : {
2582 0 : aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( 0, nZ ) );
2583 :
2584 0 : *pTmp++ = (long) aColor.GetBlue() << 12;
2585 0 : *pTmp++ = (long) aColor.GetGreen() << 12;
2586 0 : *pTmp++ = (long) aColor.GetRed() << 12;
2587 : }
2588 : }
2589 : else
2590 : {
2591 0 : for( nZ = 0; nZ < nWidth; nZ++ )
2592 : {
2593 0 : aColor = pReadAcc->GetPixel( 0, nZ );
2594 :
2595 0 : *pTmp++ = (long) aColor.GetBlue() << 12;
2596 0 : *pTmp++ = (long) aColor.GetGreen() << 12;
2597 0 : *pTmp++ = (long) aColor.GetRed() << 12;
2598 : }
2599 : }
2600 :
2601 0 : for( long nY = 1, nYAcc = 0L; nY <= nHeight; nY++, nYAcc++ )
2602 : {
2603 0 : pTmp = p1T;
2604 0 : p1T = p2T;
2605 0 : p2T = pTmp;
2606 :
2607 0 : if( nY < nHeight )
2608 : {
2609 0 : if( bPal )
2610 : {
2611 0 : for( nZ = 0; nZ < nWidth; nZ++ )
2612 : {
2613 0 : aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nZ ) );
2614 :
2615 0 : *pTmp++ = (long) aColor.GetBlue() << 12;
2616 0 : *pTmp++ = (long) aColor.GetGreen() << 12;
2617 0 : *pTmp++ = (long) aColor.GetRed() << 12;
2618 : }
2619 : }
2620 : else
2621 : {
2622 0 : for( nZ = 0; nZ < nWidth; nZ++ )
2623 : {
2624 0 : aColor = pReadAcc->GetPixel( nY, nZ );
2625 :
2626 0 : *pTmp++ = (long) aColor.GetBlue() << 12;
2627 0 : *pTmp++ = (long) aColor.GetGreen() << 12;
2628 0 : *pTmp++ = (long) aColor.GetRed() << 12;
2629 : }
2630 : }
2631 : }
2632 :
2633 : // Examine first Pixel separately
2634 0 : nX = 0;
2635 0 : CALC_ERRORS;
2636 0 : CALC_TABLES7;
2637 0 : nX -= 5;
2638 0 : CALC_TABLES5;
2639 0 : pWriteAcc->SetPixelIndex( nYAcc, 0, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2640 :
2641 : // Get middle Pixels using a loop
2642 : long nXAcc;
2643 0 : for ( nX = 3L, nXAcc = 1L; nX < nW2; nXAcc++ )
2644 : {
2645 0 : CALC_ERRORS;
2646 0 : CALC_TABLES7;
2647 0 : nX -= 8;
2648 0 : CALC_TABLES3;
2649 0 : CALC_TABLES5;
2650 0 : pWriteAcc->SetPixelIndex( nYAcc, nXAcc, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2651 : }
2652 :
2653 : // Treat last Pixel separately
2654 0 : CALC_ERRORS;
2655 0 : nX -= 5;
2656 0 : CALC_TABLES3;
2657 0 : CALC_TABLES5;
2658 0 : pWriteAcc->SetPixelIndex( nYAcc, nWidth1, static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ]) );
2659 : }
2660 :
2661 0 : delete[] p1;
2662 0 : delete[] p2;
2663 0 : bRet = sal_True;
2664 : }
2665 :
2666 0 : ReleaseAccess( pReadAcc );
2667 0 : aNewBmp.ReleaseAccess( pWriteAcc );
2668 :
2669 0 : if( bRet )
2670 : {
2671 0 : const MapMode aMap( maPrefMapMode );
2672 0 : const Size aPrefSize( maPrefSize );
2673 :
2674 0 : *this = aNewBmp;
2675 :
2676 0 : maPrefMapMode = aMap;
2677 0 : maPrefSize = aPrefSize;
2678 0 : }
2679 : }
2680 :
2681 0 : return bRet;
2682 : }
2683 :
2684 0 : sal_Bool Bitmap::ImplDitherFloyd16()
2685 : {
2686 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
2687 0 : Bitmap aNewBmp( GetSizePixel(), 24 );
2688 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
2689 0 : sal_Bool bRet = sal_False;
2690 :
2691 0 : if( pReadAcc && pWriteAcc )
2692 : {
2693 0 : const long nWidth = pWriteAcc->Width();
2694 0 : const long nWidth1 = nWidth - 1L;
2695 0 : const long nHeight = pWriteAcc->Height();
2696 0 : BitmapColor aColor;
2697 0 : BitmapColor aBestCol;
2698 0 : ImpErrorQuad aErrQuad;
2699 0 : ImpErrorQuad* pErrQuad1 = new ImpErrorQuad[ nWidth ];
2700 0 : ImpErrorQuad* pErrQuad2 = new ImpErrorQuad[ nWidth ];
2701 0 : ImpErrorQuad* pQLine1 = pErrQuad1;
2702 0 : ImpErrorQuad* pQLine2 = 0;
2703 : long nX, nY;
2704 0 : long nYTmp = 0L;
2705 0 : bool bQ1 = true;
2706 :
2707 0 : for( nY = 0L; nY < std::min( nHeight, 2L ); nY++, nYTmp++ )
2708 0 : for( nX = 0L, pQLine2 = !nY ? pErrQuad1 : pErrQuad2; nX < nWidth; nX++ )
2709 0 : pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2710 :
2711 0 : for( nY = 0L; nY < nHeight; nY++, nYTmp++ )
2712 : {
2713 : // First RowPixel
2714 0 : aBestCol = pQLine1[ 0 ].ImplGetColor();
2715 0 : aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2716 0 : aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2717 0 : aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2718 0 : pWriteAcc->SetPixel( nY, 0, aBestCol );
2719 :
2720 0 : for( nX = 1L; nX < nWidth1; nX++ )
2721 : {
2722 0 : aColor = pQLine1[ nX ].ImplGetColor();
2723 0 : aBestCol.SetRed( ( aColor.GetRed() & 248 ) | 7 );
2724 0 : aBestCol.SetGreen( ( aColor.GetGreen() & 248 ) | 7 );
2725 0 : aBestCol.SetBlue( ( aColor.GetBlue() & 248 ) | 7 );
2726 0 : aErrQuad = ( ImpErrorQuad( aColor ) -= aBestCol );
2727 0 : pQLine1[ ++nX ].ImplAddColorError7( aErrQuad );
2728 0 : pQLine2[ nX-- ].ImplAddColorError1( aErrQuad );
2729 0 : pQLine2[ nX-- ].ImplAddColorError5( aErrQuad );
2730 0 : pQLine2[ nX++ ].ImplAddColorError3( aErrQuad );
2731 0 : pWriteAcc->SetPixel( nY, nX, aBestCol );
2732 : }
2733 :
2734 : // Last RowPixel
2735 0 : aBestCol = pQLine1[ nWidth1 ].ImplGetColor();
2736 0 : aBestCol.SetRed( ( aBestCol.GetRed() & 248 ) | 7 );
2737 0 : aBestCol.SetGreen( ( aBestCol.GetGreen() & 248 ) | 7 );
2738 0 : aBestCol.SetBlue( ( aBestCol.GetBlue() & 248 ) | 7 );
2739 0 : pWriteAcc->SetPixel( nY, nX, aBestCol );
2740 :
2741 : // Refill/copy row buffer
2742 0 : pQLine1 = pQLine2;
2743 0 : pQLine2 = ( bQ1 = !bQ1 ) ? pErrQuad2 : pErrQuad1;
2744 :
2745 0 : if( nYTmp < nHeight )
2746 0 : for( nX = 0L; nX < nWidth; nX++ )
2747 0 : pQLine2[ nX ] = pReadAcc->GetPixel( nYTmp, nX );
2748 : }
2749 :
2750 : // Destroy row buffer
2751 0 : delete[] pErrQuad1;
2752 0 : delete[] pErrQuad2;
2753 0 : bRet = sal_True;
2754 : }
2755 :
2756 0 : ReleaseAccess( pReadAcc );
2757 0 : aNewBmp.ReleaseAccess( pWriteAcc );
2758 :
2759 0 : if( bRet )
2760 : {
2761 0 : const MapMode aMap( maPrefMapMode );
2762 0 : const Size aSize( maPrefSize );
2763 :
2764 0 : *this = aNewBmp;
2765 :
2766 0 : maPrefMapMode = aMap;
2767 0 : maPrefSize = aSize;
2768 : }
2769 :
2770 0 : return bRet;
2771 : }
2772 :
2773 0 : sal_Bool Bitmap::ReduceColors( sal_uInt16 nColorCount, BmpReduce eReduce )
2774 : {
2775 : sal_Bool bRet;
2776 :
2777 0 : if( GetColorCount() <= (sal_uLong) nColorCount )
2778 0 : bRet = sal_True;
2779 0 : else if( nColorCount )
2780 : {
2781 0 : if( BMP_REDUCE_SIMPLE == eReduce )
2782 0 : bRet = ImplReduceSimple( nColorCount );
2783 0 : else if( BMP_REDUCE_POPULAR == eReduce )
2784 0 : bRet = ImplReducePopular( nColorCount );
2785 : else
2786 0 : bRet = ImplReduceMedian( nColorCount );
2787 : }
2788 : else
2789 0 : bRet = sal_False;
2790 :
2791 0 : return bRet;
2792 : }
2793 :
2794 0 : sal_Bool Bitmap::ImplReduceSimple( sal_uInt16 nColorCount )
2795 : {
2796 0 : Bitmap aNewBmp;
2797 0 : BitmapReadAccess* pRAcc = AcquireReadAccess();
2798 0 : const sal_uInt16 nColCount = std::min( nColorCount, (sal_uInt16) 256 );
2799 : sal_uInt16 nBitCount;
2800 0 : sal_Bool bRet = sal_False;
2801 :
2802 0 : if( nColCount <= 2 )
2803 0 : nBitCount = 1;
2804 0 : else if( nColCount <= 16 )
2805 0 : nBitCount = 4;
2806 : else
2807 0 : nBitCount = 8;
2808 :
2809 0 : if( pRAcc )
2810 : {
2811 0 : Octree aOct( *pRAcc, nColCount );
2812 0 : const BitmapPalette& rPal = aOct.GetPalette();
2813 : BitmapWriteAccess* pWAcc;
2814 :
2815 0 : aNewBmp = Bitmap( GetSizePixel(), nBitCount, &rPal );
2816 0 : pWAcc = aNewBmp.AcquireWriteAccess();
2817 :
2818 0 : if( pWAcc )
2819 : {
2820 0 : const long nWidth = pRAcc->Width();
2821 0 : const long nHeight = pRAcc->Height();
2822 :
2823 0 : if( pRAcc->HasPalette() )
2824 : {
2825 0 : for( long nY = 0L; nY < nHeight; nY++ )
2826 0 : for( long nX =0L; nX < nWidth; nX++ )
2827 0 : pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) ))) );
2828 : }
2829 : else
2830 : {
2831 0 : for( long nY = 0L; nY < nHeight; nY++ )
2832 0 : for( long nX =0L; nX < nWidth; nX++ )
2833 0 : pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>(aOct.GetBestPaletteIndex( pRAcc->GetPixel( nY, nX ) )) );
2834 : }
2835 :
2836 0 : aNewBmp.ReleaseAccess( pWAcc );
2837 0 : bRet = sal_True;
2838 : }
2839 :
2840 0 : ReleaseAccess( pRAcc );
2841 : }
2842 :
2843 0 : if( bRet )
2844 : {
2845 0 : const MapMode aMap( maPrefMapMode );
2846 0 : const Size aSize( maPrefSize );
2847 :
2848 0 : *this = aNewBmp;
2849 0 : maPrefMapMode = aMap;
2850 0 : maPrefSize = aSize;
2851 : }
2852 :
2853 0 : return bRet;
2854 : }
2855 :
2856 : struct PopularColorCount
2857 : {
2858 : sal_uInt32 mnIndex;
2859 : sal_uInt32 mnCount;
2860 : };
2861 :
2862 0 : extern "C" int SAL_CALL ImplPopularCmpFnc( const void* p1, const void* p2 )
2863 : {
2864 : int nRet;
2865 :
2866 0 : if( ( (PopularColorCount*) p1 )->mnCount < ( (PopularColorCount*) p2 )->mnCount )
2867 0 : nRet = 1;
2868 0 : else if( ( (PopularColorCount*) p1 )->mnCount == ( (PopularColorCount*) p2 )->mnCount )
2869 0 : nRet = 0;
2870 : else
2871 0 : nRet = -1;
2872 :
2873 0 : return nRet;
2874 : }
2875 :
2876 0 : sal_Bool Bitmap::ImplReducePopular( sal_uInt16 nColCount )
2877 : {
2878 0 : BitmapReadAccess* pRAcc = AcquireReadAccess();
2879 : sal_uInt16 nBitCount;
2880 0 : sal_Bool bRet = sal_False;
2881 :
2882 0 : if( nColCount > 256 )
2883 0 : nColCount = 256;
2884 :
2885 0 : if( nColCount < 17 )
2886 0 : nBitCount = 4;
2887 : else
2888 0 : nBitCount = 8;
2889 :
2890 0 : if( pRAcc )
2891 : {
2892 0 : const sal_uInt32 nValidBits = 4;
2893 0 : const sal_uInt32 nRightShiftBits = 8 - nValidBits;
2894 0 : const sal_uInt32 nLeftShiftBits1 = nValidBits;
2895 0 : const sal_uInt32 nLeftShiftBits2 = nValidBits << 1;
2896 0 : const sal_uInt32 nColorsPerComponent = 1 << nValidBits;
2897 0 : const sal_uInt32 nColorOffset = 256 / nColorsPerComponent;
2898 0 : const sal_uInt32 nTotalColors = nColorsPerComponent * nColorsPerComponent * nColorsPerComponent;
2899 0 : const long nWidth = pRAcc->Width();
2900 0 : const long nHeight = pRAcc->Height();
2901 0 : PopularColorCount* pCountTable = new PopularColorCount[ nTotalColors ];
2902 : long nX, nY, nR, nG, nB, nIndex;
2903 :
2904 0 : memset( pCountTable, 0, nTotalColors * sizeof( PopularColorCount ) );
2905 :
2906 0 : for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
2907 : {
2908 0 : for( nG = 0; nG < 256; nG += nColorOffset )
2909 : {
2910 0 : for( nB = 0; nB < 256; nB += nColorOffset )
2911 : {
2912 0 : pCountTable[ nIndex ].mnIndex = nIndex;
2913 0 : nIndex++;
2914 : }
2915 : }
2916 : }
2917 :
2918 0 : if( pRAcc->HasPalette() )
2919 : {
2920 0 : for( nY = 0L; nY < nHeight; nY++ )
2921 : {
2922 0 : for( nX = 0L; nX < nWidth; nX++ )
2923 : {
2924 0 : const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
2925 0 : pCountTable[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
2926 0 : ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
2927 0 : ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
2928 : }
2929 : }
2930 : }
2931 : else
2932 : {
2933 0 : for( nY = 0L; nY < nHeight; nY++ )
2934 : {
2935 0 : for( nX = 0L; nX < nWidth; nX++ )
2936 : {
2937 0 : const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
2938 0 : pCountTable[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
2939 0 : ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
2940 0 : ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ].mnCount++;
2941 0 : }
2942 : }
2943 : }
2944 :
2945 0 : BitmapPalette aNewPal( nColCount );
2946 :
2947 0 : qsort( pCountTable, nTotalColors, sizeof( PopularColorCount ), ImplPopularCmpFnc );
2948 :
2949 0 : for( sal_uInt16 n = 0; n < nColCount; n++ )
2950 : {
2951 0 : const PopularColorCount& rPop = pCountTable[ n ];
2952 0 : aNewPal[ n ] = BitmapColor( (sal_uInt8) ( ( rPop.mnIndex >> nLeftShiftBits2 ) << nRightShiftBits ),
2953 : (sal_uInt8) ( ( ( rPop.mnIndex >> nLeftShiftBits1 ) & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ),
2954 0 : (sal_uInt8) ( ( rPop.mnIndex & ( nColorsPerComponent - 1 ) ) << nRightShiftBits ) );
2955 : }
2956 :
2957 0 : Bitmap aNewBmp( GetSizePixel(), nBitCount, &aNewPal );
2958 0 : BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
2959 :
2960 0 : if( pWAcc )
2961 : {
2962 0 : BitmapColor aDstCol( (sal_uInt8) 0 );
2963 0 : sal_uInt8* pIndexMap = new sal_uInt8[ nTotalColors ];
2964 :
2965 0 : for( nR = 0, nIndex = 0; nR < 256; nR += nColorOffset )
2966 0 : for( nG = 0; nG < 256; nG += nColorOffset )
2967 0 : for( nB = 0; nB < 256; nB += nColorOffset )
2968 0 : pIndexMap[ nIndex++ ] = (sal_uInt8) aNewPal.GetBestIndex( BitmapColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB ) );
2969 :
2970 0 : if( pRAcc->HasPalette() )
2971 : {
2972 0 : for( nY = 0L; nY < nHeight; nY++ )
2973 : {
2974 0 : for( nX = 0L; nX < nWidth; nX++ )
2975 : {
2976 0 : const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
2977 0 : aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) rCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
2978 0 : ( ( ( (sal_uInt32) rCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
2979 0 : ( ( (sal_uInt32) rCol.GetBlue() ) >> nRightShiftBits ) ] );
2980 0 : pWAcc->SetPixel( nY, nX, aDstCol );
2981 : }
2982 : }
2983 : }
2984 : else
2985 : {
2986 0 : for( nY = 0L; nY < nHeight; nY++ )
2987 : {
2988 0 : for( nX = 0L; nX < nWidth; nX++ )
2989 : {
2990 0 : const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
2991 0 : aDstCol.SetIndex( pIndexMap[ ( ( ( (sal_uInt32) aCol.GetRed() ) >> nRightShiftBits ) << nLeftShiftBits2 ) |
2992 0 : ( ( ( (sal_uInt32) aCol.GetGreen() ) >> nRightShiftBits ) << nLeftShiftBits1 ) |
2993 0 : ( ( (sal_uInt32) aCol.GetBlue() ) >> nRightShiftBits ) ] );
2994 0 : pWAcc->SetPixel( nY, nX, aDstCol );
2995 0 : }
2996 : }
2997 : }
2998 :
2999 0 : delete[] pIndexMap;
3000 0 : aNewBmp.ReleaseAccess( pWAcc );
3001 0 : bRet = sal_True;
3002 : }
3003 :
3004 0 : delete[] pCountTable;
3005 0 : ReleaseAccess( pRAcc );
3006 :
3007 0 : if( bRet )
3008 : {
3009 0 : const MapMode aMap( maPrefMapMode );
3010 0 : const Size aSize( maPrefSize );
3011 :
3012 0 : *this = aNewBmp;
3013 0 : maPrefMapMode = aMap;
3014 0 : maPrefSize = aSize;
3015 0 : }
3016 : }
3017 :
3018 0 : return bRet;
3019 : }
3020 :
3021 0 : sal_Bool Bitmap::ImplReduceMedian( sal_uInt16 nColCount )
3022 : {
3023 0 : BitmapReadAccess* pRAcc = AcquireReadAccess();
3024 : sal_uInt16 nBitCount;
3025 0 : sal_Bool bRet = sal_False;
3026 :
3027 0 : if( nColCount < 17 )
3028 0 : nBitCount = 4;
3029 0 : else if( nColCount < 257 )
3030 0 : nBitCount = 8;
3031 : else
3032 : {
3033 : OSL_FAIL( "Bitmap::ImplReduceMedian(): invalid color count!" );
3034 0 : nBitCount = 8;
3035 0 : nColCount = 256;
3036 : }
3037 :
3038 0 : if( pRAcc )
3039 : {
3040 0 : Bitmap aNewBmp( GetSizePixel(), nBitCount );
3041 0 : BitmapWriteAccess* pWAcc = aNewBmp.AcquireWriteAccess();
3042 :
3043 0 : if( pWAcc )
3044 : {
3045 0 : const sal_uLong nSize = 32768UL * sizeof( sal_uLong );
3046 0 : sal_uLong* pColBuf = (sal_uLong*) rtl_allocateMemory( nSize );
3047 0 : const long nWidth = pWAcc->Width();
3048 0 : const long nHeight = pWAcc->Height();
3049 0 : long nIndex = 0L;
3050 :
3051 0 : memset( (HPBYTE) pColBuf, 0, nSize );
3052 :
3053 : // create Buffer
3054 0 : if( pRAcc->HasPalette() )
3055 : {
3056 0 : for( long nY = 0L; nY < nHeight; nY++ )
3057 : {
3058 0 : for( long nX = 0L; nX < nWidth; nX++ )
3059 : {
3060 0 : const BitmapColor& rCol = pRAcc->GetPaletteColor( pRAcc->GetPixelIndex( nY, nX ) );
3061 0 : pColBuf[ RGB15( rCol.GetRed() >> 3, rCol.GetGreen() >> 3, rCol.GetBlue() >> 3 ) ]++;
3062 : }
3063 : }
3064 : }
3065 : else
3066 : {
3067 0 : for( long nY = 0L; nY < nHeight; nY++ )
3068 : {
3069 0 : for( long nX = 0L; nX < nWidth; nX++ )
3070 : {
3071 0 : const BitmapColor aCol( pRAcc->GetPixel( nY, nX ) );
3072 0 : pColBuf[ RGB15( aCol.GetRed() >> 3, aCol.GetGreen() >> 3, aCol.GetBlue() >> 3 ) ]++;
3073 0 : }
3074 : }
3075 : }
3076 :
3077 : // create palette via median cut
3078 0 : BitmapPalette aPal( pWAcc->GetPaletteEntryCount() );
3079 : ImplMedianCut( pColBuf, aPal, 0, 31, 0, 31, 0, 31,
3080 0 : nColCount, nWidth * nHeight, nIndex );
3081 :
3082 : // do mapping of colors to palette
3083 0 : InverseColorMap aMap( aPal );
3084 0 : pWAcc->SetPalette( aPal );
3085 0 : for( long nY = 0L; nY < nHeight; nY++ )
3086 0 : for( long nX = 0L; nX < nWidth; nX++ )
3087 0 : pWAcc->SetPixelIndex( nY, nX, static_cast<sal_uInt8>( aMap.GetBestPaletteIndex( pRAcc->GetColor( nY, nX ) )) );
3088 :
3089 0 : rtl_freeMemory( pColBuf );
3090 0 : aNewBmp.ReleaseAccess( pWAcc );
3091 0 : bRet = sal_True;
3092 : }
3093 :
3094 0 : ReleaseAccess( pRAcc );
3095 :
3096 0 : if( bRet )
3097 : {
3098 0 : const MapMode aMap( maPrefMapMode );
3099 0 : const Size aSize( maPrefSize );
3100 :
3101 0 : *this = aNewBmp;
3102 0 : maPrefMapMode = aMap;
3103 0 : maPrefSize = aSize;
3104 0 : }
3105 : }
3106 :
3107 0 : return bRet;
3108 : }
3109 :
3110 0 : void Bitmap::ImplMedianCut( sal_uLong* pColBuf, BitmapPalette& rPal,
3111 : long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
3112 : long nColors, long nPixels, long& rIndex )
3113 : {
3114 0 : if( !nPixels )
3115 0 : return;
3116 :
3117 0 : BitmapColor aCol;
3118 0 : const long nRLen = nR2 - nR1;
3119 0 : const long nGLen = nG2 - nG1;
3120 0 : const long nBLen = nB2 - nB1;
3121 0 : sal_uLong* pBuf = pColBuf;
3122 :
3123 0 : if( !nRLen && !nGLen && !nBLen )
3124 : {
3125 0 : if( pBuf[ RGB15( nR1, nG1, nB1 ) ] )
3126 : {
3127 0 : aCol.SetRed( (sal_uInt8) ( nR1 << 3 ) );
3128 0 : aCol.SetGreen( (sal_uInt8) ( nG1 << 3 ) );
3129 0 : aCol.SetBlue( (sal_uInt8) ( nB1 << 3 ) );
3130 0 : rPal[ (sal_uInt16) rIndex++ ] = aCol;
3131 : }
3132 : }
3133 : else
3134 : {
3135 0 : if( 1 == nColors || 1 == nPixels )
3136 : {
3137 0 : long nPixSum = 0, nRSum = 0, nGSum = 0, nBSum = 0;
3138 :
3139 0 : for( long nR = nR1; nR <= nR2; nR++ )
3140 : {
3141 0 : for( long nG = nG1; nG <= nG2; nG++ )
3142 : {
3143 0 : for( long nB = nB1; nB <= nB2; nB++ )
3144 : {
3145 0 : nPixSum = pBuf[ RGB15( nR, nG, nB ) ];
3146 :
3147 0 : if( nPixSum )
3148 : {
3149 0 : nRSum += nR * nPixSum;
3150 0 : nGSum += nG * nPixSum;
3151 0 : nBSum += nB * nPixSum;
3152 : }
3153 : }
3154 : }
3155 : }
3156 :
3157 0 : aCol.SetRed( (sal_uInt8) ( ( nRSum / nPixels ) << 3 ) );
3158 0 : aCol.SetGreen( (sal_uInt8) ( ( nGSum / nPixels ) << 3 ) );
3159 0 : aCol.SetBlue( (sal_uInt8) ( ( nBSum / nPixels ) << 3 ) );
3160 0 : rPal[ (sal_uInt16) rIndex++ ] = aCol;
3161 : }
3162 : else
3163 : {
3164 0 : const long nTest = ( nPixels >> 1 );
3165 0 : long nPixOld = 0;
3166 0 : long nPixNew = 0;
3167 :
3168 0 : if( nBLen > nGLen && nBLen > nRLen )
3169 : {
3170 0 : long nB = nB1 - 1;
3171 :
3172 0 : while( nPixNew < nTest )
3173 : {
3174 0 : nB++, nPixOld = nPixNew;
3175 0 : for( long nR = nR1; nR <= nR2; nR++ )
3176 0 : for( long nG = nG1; nG <= nG2; nG++ )
3177 0 : nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3178 : }
3179 :
3180 0 : if( nB < nB2 )
3181 : {
3182 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB, nColors >> 1, nPixNew, rIndex );
3183 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB + 1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3184 : }
3185 : else
3186 : {
3187 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB1, nB - 1, nColors >> 1, nPixOld, rIndex );
3188 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG2, nB, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3189 0 : }
3190 : }
3191 0 : else if( nGLen > nRLen )
3192 : {
3193 0 : long nG = nG1 - 1;
3194 :
3195 0 : while( nPixNew < nTest )
3196 : {
3197 0 : nG++, nPixOld = nPixNew;
3198 0 : for( long nR = nR1; nR <= nR2; nR++ )
3199 0 : for( long nB = nB1; nB <= nB2; nB++ )
3200 0 : nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3201 : }
3202 :
3203 0 : if( nG < nG2 )
3204 : {
3205 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3206 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG + 1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3207 : }
3208 : else
3209 : {
3210 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG1, nG - 1, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3211 0 : ImplMedianCut( pBuf, rPal, nR1, nR2, nG, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3212 : }
3213 : }
3214 : else
3215 : {
3216 0 : long nR = nR1 - 1;
3217 :
3218 0 : while( nPixNew < nTest )
3219 : {
3220 0 : nR++, nPixOld = nPixNew;
3221 0 : for( long nG = nG1; nG <= nG2; nG++ )
3222 0 : for( long nB = nB1; nB <= nB2; nB++ )
3223 0 : nPixNew += pBuf[ RGB15( nR, nG, nB ) ];
3224 : }
3225 :
3226 0 : if( nR < nR2 )
3227 : {
3228 0 : ImplMedianCut( pBuf, rPal, nR1, nR, nG1, nG2, nB1, nB2, nColors >> 1, nPixNew, rIndex );
3229 0 : ImplMedianCut( pBuf, rPal, nR1 + 1, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixNew, rIndex );
3230 : }
3231 : else
3232 : {
3233 0 : ImplMedianCut( pBuf, rPal, nR1, nR - 1, nG1, nG2, nB1, nB2, nColors >> 1, nPixOld, rIndex );
3234 0 : ImplMedianCut( pBuf, rPal, nR, nR2, nG1, nG2, nB1, nB2, nColors >> 1, nPixels - nPixOld, rIndex );
3235 : }
3236 : }
3237 : }
3238 0 : }
3239 : }
3240 :
3241 2 : sal_Bool Bitmap::Vectorize( PolyPolygon& rPolyPoly, sal_uLong nFlags, const Link* pProgress )
3242 : {
3243 2 : return ImplVectorizer().ImplVectorize( *this, rPolyPoly, nFlags, pProgress );
3244 : }
3245 :
3246 0 : sal_Bool Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
3247 : {
3248 0 : return ImplVectorizer().ImplVectorize( *this, rMtf, cReduce, nFlags, pProgress );
3249 : }
3250 :
3251 0 : sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
3252 : short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
3253 : double fGamma, sal_Bool bInvert )
3254 : {
3255 0 : sal_Bool bRet = sal_False;
3256 :
3257 : // nothing to do => return quickly
3258 0 : if( !nLuminancePercent && !nContrastPercent &&
3259 0 : !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
3260 0 : ( fGamma == 1.0 ) && !bInvert )
3261 : {
3262 0 : bRet = sal_True;
3263 : }
3264 : else
3265 : {
3266 0 : BitmapWriteAccess* pAcc = AcquireWriteAccess();
3267 :
3268 0 : if( pAcc )
3269 : {
3270 0 : BitmapColor aCol;
3271 0 : const long nW = pAcc->Width();
3272 0 : const long nH = pAcc->Height();
3273 0 : sal_uInt8* cMapR = new sal_uInt8[ 256 ];
3274 0 : sal_uInt8* cMapG = new sal_uInt8[ 256 ];
3275 0 : sal_uInt8* cMapB = new sal_uInt8[ 256 ];
3276 : long nX, nY;
3277 : double fM, fROff, fGOff, fBOff, fOff;
3278 :
3279 : // calculate slope
3280 0 : if( nContrastPercent >= 0 )
3281 0 : fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
3282 : else
3283 0 : fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
3284 :
3285 : // total offset = luminance offset + contrast offset
3286 0 : fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
3287 :
3288 : // channel offset = channel offset + total offset
3289 0 : fROff = nChannelRPercent * 2.55 + fOff;
3290 0 : fGOff = nChannelGPercent * 2.55 + fOff;
3291 0 : fBOff = nChannelBPercent * 2.55 + fOff;
3292 :
3293 : // calculate gamma value
3294 0 : fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
3295 0 : const bool bGamma = ( fGamma != 1.0 );
3296 :
3297 : // create mapping table
3298 0 : for( nX = 0L; nX < 256L; nX++ )
3299 : {
3300 0 : cMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
3301 0 : cMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
3302 0 : cMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
3303 :
3304 0 : if( bGamma )
3305 : {
3306 0 : cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
3307 0 : cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
3308 0 : cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
3309 : }
3310 :
3311 0 : if( bInvert )
3312 : {
3313 0 : cMapR[ nX ] = ~cMapR[ nX ];
3314 0 : cMapG[ nX ] = ~cMapG[ nX ];
3315 0 : cMapB[ nX ] = ~cMapB[ nX ];
3316 : }
3317 : }
3318 :
3319 : // do modifying
3320 0 : if( pAcc->HasPalette() )
3321 : {
3322 0 : BitmapColor aNewCol;
3323 :
3324 0 : for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
3325 : {
3326 0 : const BitmapColor& rCol = pAcc->GetPaletteColor( i );
3327 0 : aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
3328 0 : aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
3329 0 : aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
3330 0 : pAcc->SetPaletteColor( i, aNewCol );
3331 0 : }
3332 : }
3333 0 : else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
3334 : {
3335 0 : for( nY = 0L; nY < nH; nY++ )
3336 : {
3337 0 : Scanline pScan = pAcc->GetScanline( nY );
3338 :
3339 0 : for( nX = 0L; nX < nW; nX++ )
3340 : {
3341 0 : *pScan = cMapB[ *pScan ]; pScan++;
3342 0 : *pScan = cMapG[ *pScan ]; pScan++;
3343 0 : *pScan = cMapR[ *pScan ]; pScan++;
3344 : }
3345 : }
3346 : }
3347 0 : else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
3348 : {
3349 0 : for( nY = 0L; nY < nH; nY++ )
3350 : {
3351 0 : Scanline pScan = pAcc->GetScanline( nY );
3352 :
3353 0 : for( nX = 0L; nX < nW; nX++ )
3354 : {
3355 0 : *pScan = cMapR[ *pScan ]; pScan++;
3356 0 : *pScan = cMapG[ *pScan ]; pScan++;
3357 0 : *pScan = cMapB[ *pScan ]; pScan++;
3358 : }
3359 : }
3360 : }
3361 : else
3362 : {
3363 0 : for( nY = 0L; nY < nH; nY++ )
3364 : {
3365 0 : for( nX = 0L; nX < nW; nX++ )
3366 : {
3367 0 : aCol = pAcc->GetPixel( nY, nX );
3368 0 : aCol.SetRed( cMapR[ aCol.GetRed() ] );
3369 0 : aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
3370 0 : aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
3371 0 : pAcc->SetPixel( nY, nX, aCol );
3372 : }
3373 : }
3374 : }
3375 :
3376 0 : delete[] cMapR;
3377 0 : delete[] cMapG;
3378 0 : delete[] cMapB;
3379 0 : ReleaseAccess( pAcc );
3380 0 : bRet = sal_True;
3381 : }
3382 : }
3383 :
3384 0 : return bRet;
3385 : }
3386 :
3387 0 : bool Bitmap::ImplConvolutionPass(Bitmap& aNewBitmap, const int nNewSize, BitmapReadAccess* pReadAcc, int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount)
3388 : {
3389 0 : BitmapWriteAccess* pWriteAcc = aNewBitmap.AcquireWriteAccess();
3390 :
3391 0 : if (!pReadAcc || !pWriteAcc)
3392 0 : return false;
3393 :
3394 0 : const int nHeight = GetSizePixel().Height();
3395 :
3396 0 : BitmapColor aColor;
3397 : double aValueRed, aValueGreen, aValueBlue;
3398 : double aSum, aWeight;
3399 : int aBaseIndex, aIndex;
3400 :
3401 0 : for ( int y = 0; y < nHeight; y++ )
3402 : {
3403 0 : for ( int x = 0; x < nNewSize; x++ )
3404 : {
3405 0 : aBaseIndex = x * aNumberOfContributions;
3406 0 : aSum = aValueRed = aValueGreen = aValueBlue = 0.0;
3407 :
3408 0 : for ( int j=0; j < pCount[x]; j++ )
3409 : {
3410 0 : aIndex = aBaseIndex + j;
3411 0 : aSum += aWeight = pWeights[ aIndex ];
3412 :
3413 0 : aColor = pReadAcc->GetColor( y, pPixels[ aIndex ] );
3414 :
3415 0 : aValueRed += aWeight * aColor.GetRed();
3416 0 : aValueGreen += aWeight * aColor.GetGreen();
3417 0 : aValueBlue += aWeight * aColor.GetBlue();
3418 : }
3419 :
3420 : BitmapColor aResultColor(
3421 0 : (sal_uInt8) MinMax( aValueRed / aSum, 0, 255 ),
3422 0 : (sal_uInt8) MinMax( aValueGreen / aSum, 0, 255 ),
3423 0 : (sal_uInt8) MinMax( aValueBlue / aSum, 0, 255 ) );
3424 0 : pWriteAcc->SetPixel( x, y, aResultColor );
3425 0 : }
3426 : }
3427 0 : aNewBitmap.ReleaseAccess( pWriteAcc );
3428 0 : return true;
3429 465 : }
3430 :
3431 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|