1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bitmap3.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 #include <vcl/bmpacc.hxx>
36 #include <vcl/impoct.hxx>
37 #include <vcl/octree.hxx>
38 #include <impvect.hxx>
39 #include <vcl/bitmapex.hxx>
40 #include <vcl/bitmap.hxx>
46 #define RGB15( _def_cR, _def_cG, _def_cB ) (((ULONG)(_def_cR)<<10UL)|((ULONG)(_def_cG)<<5UL)|(ULONG)(_def_cB))
47 #define GAMMA( _def_cVal, _def_InvGamma ) ((BYTE)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
50 nTemp = p1T[nX++] >> 12; \
51 nBErr = MinMax( nTemp, 0, 255 ); \
52 nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
53 nTemp = p1T[nX++] >> 12; \
54 nGErr = MinMax( nTemp, 0, 255 ); \
55 nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
56 nTemp = p1T[nX] >> 12; \
57 nRErr = MinMax( nTemp, 0, 255 ); \
58 nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
60 #define CALC_TABLES3 \
61 p2T[nX++] += FloydError3[nBErr]; \
62 p2T[nX++] += FloydError3[nGErr]; \
63 p2T[nX++] += FloydError3[nRErr];
65 #define CALC_TABLES5 \
66 p2T[nX++] += FloydError5[nBErr]; \
67 p2T[nX++] += FloydError5[nGErr]; \
68 p2T[nX++] += FloydError5[nRErr];
70 #define CALC_TABLES7 \
71 p1T[++nX] += FloydError7[nBErr]; \
72 p2T[nX++] += FloydError1[nBErr]; \
73 p1T[nX] += FloydError7[nGErr]; \
74 p2T[nX++] += FloydError1[nGErr]; \
75 p1T[nX] += FloydError7[nRErr]; \
76 p2T[nX] += FloydError1[nRErr];
82 ULONG nVCLRLut
[ 6 ] = { 16, 17, 18, 19, 20, 21 };
83 ULONG nVCLGLut
[ 6 ] = { 0, 6, 12, 18, 24, 30 };
84 ULONG nVCLBLut
[ 6 ] = { 0, 36, 72, 108, 144, 180 };
86 // ------------------------------------------------------------------------
88 ULONG nVCLDitherLut
[ 256 ] =
90 0, 49152, 12288, 61440, 3072, 52224, 15360, 64512, 768, 49920, 13056,
91 62208, 3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
92 48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
93 57344, 4096, 53248, 11264, 60416, 7168, 56320, 8960, 58112, 4864, 54016,
94 12032, 61184, 7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
95 23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
96 14336, 63488, 1024, 50176, 13312, 62464, 2816, 51968, 15104, 64256, 1792,
97 50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
98 35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392, 6144,
99 55296, 9216, 58368, 5120, 54272, 11008, 60160, 6912, 56064, 9984, 59136,
100 5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
101 27392, 39680, 23296, 42752, 26368, 38656, 22272, 512, 49664, 12800, 61952,
102 3584, 52736, 15872, 65024, 256, 49408, 12544, 61696, 3328, 52480, 15616,
103 64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
104 45312, 28928, 36096, 19712, 48384, 32000, 8704, 57856, 4608, 53760, 11776,
105 60928, 7680, 56832, 8448, 57600, 4352, 53504, 11520, 60672, 7424, 56576,
106 41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
107 20736, 44288, 27904, 40192, 23808, 2560, 51712, 14848, 64000, 1536, 50688,
108 13824, 62976, 2304, 51456, 14592, 63744, 1280, 50432, 13568, 62720, 35328,
109 18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
110 34048, 17664, 46336, 29952, 10752, 59904, 6656, 55808, 9728, 58880, 5632,
111 54784, 10496, 59648, 6400, 55552, 9472, 58624, 5376, 54528, 43520, 27136,
112 39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
116 // ------------------------------------------------------------------------
118 ULONG nVCLLut
[ 256 ] =
120 0, 1286, 2572, 3858, 5144, 6430, 7716, 9002,
121 10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
122 20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
123 30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
124 41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
125 51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
126 61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
127 72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
128 82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
129 92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
130 102880,104166,105452,106738,108024,109310,110596,111882,
131 113168,114454,115740,117026,118312,119598,120884,122170,
132 123456,124742,126028,127314,128600,129886,131172,132458,
133 133744,135030,136316,137602,138888,140174,141460,142746,
134 144032,145318,146604,147890,149176,150462,151748,153034,
135 154320,155606,156892,158178,159464,160750,162036,163322,
136 164608,165894,167180,168466,169752,171038,172324,173610,
137 174896,176182,177468,178754,180040,181326,182612,183898,
138 185184,186470,187756,189042,190328,191614,192900,194186,
139 195472,196758,198044,199330,200616,201902,203188,204474,
140 205760,207046,208332,209618,210904,212190,213476,214762,
141 216048,217334,218620,219906,221192,222478,223764,225050,
142 226336,227622,228908,230194,231480,232766,234052,235338,
143 236624,237910,239196,240482,241768,243054,244340,245626,
144 246912,248198,249484,250770,252056,253342,254628,255914,
145 257200,258486,259772,261058,262344,263630,264916,266202,
146 267488,268774,270060,271346,272632,273918,275204,276490,
147 277776,279062,280348,281634,282920,284206,285492,286778,
148 288064,289350,290636,291922,293208,294494,295780,297066,
149 298352,299638,300924,302210,303496,304782,306068,307354,
150 308640,309926,311212,312498,313784,315070,316356,317642,
151 318928,320214,321500,322786,324072,325358,326644,327930
154 // ------------------------------------------------------------------------
158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
160 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
161 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
162 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
163 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
164 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
165 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
166 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
167 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
168 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
169 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
170 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
171 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
172 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
173 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
176 // ------------------------------------------------------------------------
178 long FloydError1
[61] =
180 -7680, -7424, -7168, -6912, -6656, -6400, -6144,
181 -5888, -5632, -5376, -5120, -4864, -4608, -4352,
182 -4096, -3840, -3584, -3328, -3072, -2816, -2560,
183 -2304, -2048, -1792, -1536, -1280, -1024, -768,
184 -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
185 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
186 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
187 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
190 // ------------------------------------------------------------------------
192 long FloydError3
[61] =
194 -23040, -22272, -21504, -20736, -19968, -19200,
195 -18432, -17664, -16896, -16128, -15360, -14592,
196 -13824, -13056, -12288, -11520, -10752, -9984,
197 -9216, -8448, -7680, -6912, -6144, -5376, -4608,
198 -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
199 2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
200 8448, 9216, 9984, 10752, 11520, 12288, 13056,
201 13824, 14592, 15360, 16128, 16896, 17664, 18432,
202 19200, 19968, 20736, 21504, 22272, 23040
205 // ------------------------------------------------------------------------
207 long FloydError5
[61] =
209 -38400, -37120, -35840, -34560, -33280, -32000,
210 -30720, -29440, -28160, -26880, -25600, -24320,
211 -23040, -21760, -20480, -19200, -17920, -16640,
212 -15360, -14080, -12800, -11520, -10240, -8960,
213 -7680, -6400, -5120, -3840, -2560, -1280, 0,
214 1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
215 11520, 12800, 14080, 15360, 16640, 17920, 19200,
216 20480, 21760, 23040, 24320, 25600, 26880, 28160,
217 29440, 30720, 32000, 33280, 34560, 35840, 37120,
221 // ------------------------------------------------------------------------
223 long FloydError7
[61] =
225 -53760, -51968, -50176, -48384, -46592, -44800,
226 -43008, -41216, -39424, -37632, -35840, -34048,
227 -32256, -30464, -28672, -26880, -25088, -23296,
228 -21504, -19712, -17920, -16128, -14336, -12544,
229 -10752, -8960, -7168, -5376, -3584, -1792, 0,
230 1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
231 16128, 17920, 19712, 21504, 23296, 25088, 26880,
232 28672, 30464, 32256, 34048, 35840, 37632, 39424,
233 41216, 43008, 44800, 46592, 48384, 50176, 51968,
237 // ------------------------------------------------------------------------
239 long FloydIndexMap
[6] =
241 -30, 21, 72, 123, 174, 225
244 // --------------------------
245 // - ImplCreateDitherMatrix -
246 // --------------------------
248 void ImplCreateDitherMatrix( BYTE (*pDitherMatrix
)[16][16] )
251 const double fVal16
= fVal
/ 16.;
253 USHORT pMtx
[ 16 ][ 16 ];
255 static BYTE pMagic
[4][4] = { { 0, 14, 3, 13, },
260 // MagicSquare aufbauen
261 for ( i
= 0; i
< 4; i
++ )
262 for ( j
= 0; j
< 4; j
++ )
263 for ( k
= 0; k
< 4; k
++ )
264 for ( l
= 0; l
< 4; l
++ )
265 nMax
= Max ( pMtx
[ (k
<<2) + i
][(l
<<2 ) + j
] =
266 (USHORT
) ( 0.5 + pMagic
[i
][j
]*fVal
+ pMagic
[k
][l
]*fVal16
), nMax
);
268 // auf Intervall [0;254] skalieren
269 for ( i
= 0, fVal
= 254. / nMax
; i
< 16; i
++ )
270 for( j
= 0; j
< 16; j
++ )
271 (*pDitherMatrix
)[i
][j
] = (BYTE
) ( fVal
* pMtx
[i
][j
] );
278 BOOL
Bitmap::Convert( BmpConversion eConversion
)
280 const USHORT nBitCount
= GetBitCount();
283 switch( eConversion
)
285 case( BMP_CONVERSION_1BIT_THRESHOLD
):
286 bRet
= ImplMakeMono( 128 );
289 case( BMP_CONVERSION_1BIT_MATRIX
):
290 bRet
= ImplMakeMonoDither();
293 case( BMP_CONVERSION_4BIT_GREYS
):
294 bRet
= ImplMakeGreyscales( 16 );
297 case( BMP_CONVERSION_4BIT_COLORS
):
300 bRet
= ImplConvertUp( 4, NULL
);
301 else if( nBitCount
> 4 )
302 bRet
= ImplConvertDown( 4, NULL
);
308 case( BMP_CONVERSION_4BIT_TRANS
):
310 Color
aTrans( BMP_COL_TRANS
);
313 bRet
= ImplConvertUp( 4, &aTrans
);
315 bRet
= ImplConvertDown( 4, &aTrans
);
319 case( BMP_CONVERSION_8BIT_GREYS
):
320 bRet
= ImplMakeGreyscales( 256 );
323 case( BMP_CONVERSION_8BIT_COLORS
):
326 bRet
= ImplConvertUp( 8 );
327 else if( nBitCount
> 8 )
328 bRet
= ImplConvertDown( 8 );
334 case( BMP_CONVERSION_8BIT_TRANS
):
336 Color
aTrans( BMP_COL_TRANS
);
339 bRet
= ImplConvertUp( 8, &aTrans
);
341 bRet
= ImplConvertDown( 8, &aTrans
);
345 case( BMP_CONVERSION_24BIT
):
348 bRet
= ImplConvertUp( 24, FALSE
);
354 case( BMP_CONVERSION_GHOSTED
):
355 bRet
= ImplConvertGhosted();
359 DBG_ERROR( "Bitmap::Convert(): Unsupported conversion" );
366 // ------------------------------------------------------------------------
368 BOOL
Bitmap::ImplMakeMono( BYTE cThreshold
)
370 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
375 Bitmap
aNewBmp( GetSizePixel(), 1 );
376 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
380 const BitmapColor
aBlack( pWriteAcc
->GetBestMatchingColor( Color( COL_BLACK
) ) );
381 const BitmapColor
aWhite( pWriteAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
382 const long nWidth
= pWriteAcc
->Width();
383 const long nHeight
= pWriteAcc
->Height();
385 if( pReadAcc
->HasPalette() )
387 for( long nY
= 0L; nY
< nHeight
; nY
++ )
389 for( long nX
= 0L; nX
< nWidth
; nX
++ )
391 if( pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nX
) ).GetLuminance() >=
394 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
397 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
403 for( long nY
= 0L; nY
< nHeight
; nY
++ )
405 for( long nX
= 0L; nX
< nWidth
; nX
++ )
407 if( pReadAcc
->GetPixel( nY
, nX
).GetLuminance() >=
410 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
413 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
418 aNewBmp
.ReleaseAccess( pWriteAcc
);
422 ReleaseAccess( pReadAcc
);
426 const MapMode
aMap( maPrefMapMode
);
427 const Size
aSize( maPrefSize
);
431 maPrefMapMode
= aMap
;
439 // ------------------------------------------------------------------------
441 BOOL
Bitmap::ImplMakeMonoDither()
443 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
448 Bitmap
aNewBmp( GetSizePixel(), 1 );
449 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
453 const BitmapColor
aBlack( pWriteAcc
->GetBestMatchingColor( Color( COL_BLACK
) ) );
454 const BitmapColor
aWhite( pWriteAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
455 const long nWidth
= pWriteAcc
->Width();
456 const long nHeight
= pWriteAcc
->Height();
457 BYTE pDitherMatrix
[ 16 ][ 16 ];
459 ImplCreateDitherMatrix( &pDitherMatrix
);
461 if( pReadAcc
->HasPalette() )
463 for( long nY
= 0L; nY
< nHeight
; nY
++ )
465 for( long nX
= 0L, nModY
= nY
% 16; nX
< nWidth
; nX
++ )
467 if( pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nX
) ).GetLuminance() >
468 pDitherMatrix
[ nModY
][ nX
% 16 ] )
470 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
473 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
479 for( long nY
= 0L; nY
< nHeight
; nY
++ )
481 for( long nX
= 0L, nModY
= nY
% 16; nX
< nWidth
; nX
++ )
483 if( pReadAcc
->GetPixel( nY
, nX
).GetLuminance() >
484 pDitherMatrix
[ nModY
][ nX
% 16 ] )
486 pWriteAcc
->SetPixel( nY
, nX
, aWhite
);
489 pWriteAcc
->SetPixel( nY
, nX
, aBlack
);
494 aNewBmp
.ReleaseAccess( pWriteAcc
);
498 ReleaseAccess( pReadAcc
);
502 const MapMode
aMap( maPrefMapMode
);
503 const Size
aSize( maPrefSize
);
507 maPrefMapMode
= aMap
;
515 // ------------------------------------------------------------------------
517 BOOL
Bitmap::ImplMakeGreyscales( USHORT nGreys
)
519 DBG_ASSERT( nGreys
== 16 || nGreys
== 256, "Only 16 or 256 greyscales are supported!" );
521 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
526 const BitmapPalette
& rPal
= GetGreyPalette( nGreys
);
527 ULONG nShift
= ( ( nGreys
== 16 ) ? 4UL : 0UL );
528 BOOL bPalDiffers
= !pReadAcc
->HasPalette() || ( rPal
.GetEntryCount() != pReadAcc
->GetPaletteEntryCount() );
531 bPalDiffers
= ( (BitmapPalette
&) rPal
!= pReadAcc
->GetPalette() );
535 Bitmap
aNewBmp( GetSizePixel(), ( nGreys
== 16 ) ? 4 : 8, &rPal
);
536 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
540 const long nWidth
= pWriteAcc
->Width();
541 const long nHeight
= pWriteAcc
->Height();
543 if( pReadAcc
->HasPalette() )
545 for( long nY
= 0L; nY
< nHeight
; nY
++ )
547 for( long nX
= 0L; nX
< nWidth
; nX
++ )
549 pWriteAcc
->SetPixel( nY
, nX
,
550 (BYTE
) ( pReadAcc
->GetPaletteColor(
551 pReadAcc
->GetPixel( nY
, nX
) ).GetLuminance() >> nShift
) );
555 else if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR
&&
556 pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
)
560 for( long nY
= 0L; nY
< nHeight
; nY
++ )
562 Scanline pReadScan
= pReadAcc
->GetScanline( nY
);
563 Scanline pWriteScan
= pWriteAcc
->GetScanline( nY
);
565 for( long nX
= 0L; nX
< nWidth
; nX
++ )
567 const ULONG nB
= *pReadScan
++;
568 const ULONG nG
= *pReadScan
++;
569 const ULONG nR
= *pReadScan
++;
571 *pWriteScan
++ = (BYTE
) ( ( nB
* 28UL + nG
* 151UL + nR
* 77UL ) >> nShift
);
575 else if( pReadAcc
->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB
&&
576 pWriteAcc
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
)
580 for( long nY
= 0L; nY
< nHeight
; nY
++ )
582 Scanline pReadScan
= pReadAcc
->GetScanline( nY
);
583 Scanline pWriteScan
= pWriteAcc
->GetScanline( nY
);
585 for( long nX
= 0L; nX
< nWidth
; nX
++ )
587 const ULONG nR
= *pReadScan
++;
588 const ULONG nG
= *pReadScan
++;
589 const ULONG nB
= *pReadScan
++;
591 *pWriteScan
++ = (BYTE
) ( ( nB
* 28UL + nG
* 151UL + nR
* 77UL ) >> nShift
);
597 for( long nY
= 0L; nY
< nHeight
; nY
++ )
598 for( long nX
= 0L; nX
< nWidth
; nX
++ )
599 pWriteAcc
->SetPixel( nY
, nX
, sal::static_int_cast
<BYTE
>(( pReadAcc
->GetPixel( nY
, nX
) ).GetLuminance() >> nShift
) );
602 aNewBmp
.ReleaseAccess( pWriteAcc
);
606 ReleaseAccess( pReadAcc
);
610 const MapMode
aMap( maPrefMapMode
);
611 const Size
aSize( maPrefSize
);
615 maPrefMapMode
= aMap
;
621 ReleaseAccess( pReadAcc
);
629 // ------------------------------------------------------------------------
631 BOOL
Bitmap::ImplConvertUp( USHORT nBitCount
, Color
* pExtColor
)
633 DBG_ASSERT( nBitCount
> GetBitCount(), "New BitCount must be greater!" );
635 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
641 Bitmap
aNewBmp( GetSizePixel(), nBitCount
, pReadAcc
->HasPalette() ? &pReadAcc
->GetPalette() : &aPal
);
642 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
646 const long nWidth
= pWriteAcc
->Width();
647 const long nHeight
= pWriteAcc
->Height();
649 if( pWriteAcc
->HasPalette() )
651 const USHORT nOldCount
= 1 << GetBitCount();
652 const BitmapPalette
& rOldPal
= pReadAcc
->GetPalette();
654 aPal
.SetEntryCount( 1 << nBitCount
);
656 for( USHORT i
= 0; i
< nOldCount
; i
++ )
657 aPal
[ i
] = rOldPal
[ i
];
660 aPal
[ aPal
.GetEntryCount() - 1 ] = *pExtColor
;
662 pWriteAcc
->SetPalette( aPal
);
664 for( long nY
= 0L; nY
< nHeight
; nY
++ )
665 for( long nX
= 0L; nX
< nWidth
; nX
++ )
666 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nY
, nX
) );
670 if( pReadAcc
->HasPalette() )
672 for( long nY
= 0L; nY
< nHeight
; nY
++ )
673 for( long nX
= 0L; nX
< nWidth
; nX
++ )
674 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nX
) ) );
678 for( long nY
= 0L; nY
< nHeight
; nY
++ )
679 for( long nX
= 0L; nX
< nWidth
; nX
++ )
680 pWriteAcc
->SetPixel( nY
, nX
, pReadAcc
->GetPixel( nY
, nX
) );
684 aNewBmp
.ReleaseAccess( pWriteAcc
);
688 ReleaseAccess( pReadAcc
);
692 const MapMode
aMap( maPrefMapMode
);
693 const Size
aSize( maPrefSize
);
697 maPrefMapMode
= aMap
;
705 // ------------------------------------------------------------------------
707 BOOL
Bitmap::ImplConvertDown( USHORT nBitCount
, Color
* pExtColor
)
709 DBG_ASSERT( nBitCount
<= GetBitCount(), "New BitCount must be lower ( or equal when pExtColor is set )!" );
711 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
717 Bitmap
aNewBmp( GetSizePixel(), nBitCount
, &aPal
);
718 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
722 const USHORT nCount
= 1 << nBitCount
;
723 const long nWidth
= pWriteAcc
->Width();
724 const long nWidth1
= nWidth
- 1L;
725 const long nHeight
= pWriteAcc
->Height();
726 Octree
aOctree( *pReadAcc
, pExtColor
? ( nCount
- 1 ) : nCount
);
727 InverseColorMap
aColorMap( aPal
= aOctree
.GetPalette() );
729 ImpErrorQuad aErrQuad
;
730 ImpErrorQuad
* pErrQuad1
= new ImpErrorQuad
[ nWidth
];
731 ImpErrorQuad
* pErrQuad2
= new ImpErrorQuad
[ nWidth
];
732 ImpErrorQuad
* pQLine1
= pErrQuad1
;
733 ImpErrorQuad
* pQLine2
= 0;
741 aPal
.SetEntryCount( aPal
.GetEntryCount() + 1 );
742 aPal
[ aPal
.GetEntryCount() - 1 ] = *pExtColor
;
745 // set Black/White always, if we have enough space
746 if( aPal
.GetEntryCount() < ( nCount
- 1 ) )
748 aPal
.SetEntryCount( aPal
.GetEntryCount() + 2 );
749 aPal
[ aPal
.GetEntryCount() - 2 ] = Color( COL_BLACK
);
750 aPal
[ aPal
.GetEntryCount() - 1 ] = Color( COL_WHITE
);
753 pWriteAcc
->SetPalette( aPal
);
755 for( nY
= 0L; nY
< Min( nHeight
, 2L ); nY
++, nYTmp
++ )
757 for( nX
= 0L, pQLine2
= !nY
? pErrQuad1
: pErrQuad2
; nX
< nWidth
; nX
++ )
759 if( pReadAcc
->HasPalette() )
760 pQLine2
[ nX
] = pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nYTmp
, nX
) );
762 pQLine2
[ nX
] = pReadAcc
->GetPixel( nYTmp
, nX
);
766 for( nY
= 0L; nY
< nHeight
; nY
++, nYTmp
++ )
768 // erstes ZeilenPixel
769 cIndex
= (BYTE
) aColorMap
.GetBestPaletteIndex( pQLine1
[ 0 ].ImplGetColor() );
770 pWriteAcc
->SetPixel( nY
, 0, cIndex
);
772 for( nX
= 1L; nX
< nWidth1
; nX
++ )
774 cIndex
= (BYTE
) aColorMap
.GetBestPaletteIndex( aColor
= pQLine1
[ nX
].ImplGetColor() );
775 aErrQuad
= ( ImpErrorQuad( aColor
) -= pWriteAcc
->GetPaletteColor( cIndex
) );
776 pQLine1
[ ++nX
].ImplAddColorError7( aErrQuad
);
777 pQLine2
[ nX
-- ].ImplAddColorError1( aErrQuad
);
778 pQLine2
[ nX
-- ].ImplAddColorError5( aErrQuad
);
779 pQLine2
[ nX
++ ].ImplAddColorError3( aErrQuad
);
780 pWriteAcc
->SetPixel( nY
, nX
, cIndex
);
783 // letztes ZeilenPixel
786 cIndex
= (BYTE
) aColorMap
.GetBestPaletteIndex( pQLine1
[ nWidth1
].ImplGetColor() );
787 pWriteAcc
->SetPixel( nY
, nX
, cIndex
);
790 // Zeilenpuffer neu fuellen/kopieren
792 pQLine2
= ( bQ1
= !bQ1
) != FALSE
? pErrQuad2
: pErrQuad1
;
794 if( nYTmp
< nHeight
)
796 for( nX
= 0L; nX
< nWidth
; nX
++ )
798 if( pReadAcc
->HasPalette() )
799 pQLine2
[ nX
] = pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nYTmp
, nX
) );
801 pQLine2
[ nX
] = pReadAcc
->GetPixel( nYTmp
, nX
);
806 // Zeilenpuffer zerstoeren
810 aNewBmp
.ReleaseAccess( pWriteAcc
);
814 ReleaseAccess( pReadAcc
);
818 const MapMode
aMap( maPrefMapMode
);
819 const Size
aSize( maPrefSize
);
823 maPrefMapMode
= aMap
;
831 // ------------------------------------------------------------------------
833 BOOL
Bitmap::ImplConvertGhosted()
836 BitmapReadAccess
* pR
= AcquireReadAccess();
841 if( pR
->HasPalette() )
843 BitmapPalette
aNewPal( pR
->GetPaletteEntryCount() );
845 for( long i
= 0, nCount
= aNewPal
.GetEntryCount(); i
< nCount
; i
++ )
847 const BitmapColor
& rOld
= pR
->GetPaletteColor( (USHORT
) i
);
848 aNewPal
[ (USHORT
) i
] = BitmapColor( ( rOld
.GetRed() >> 1 ) | 0x80,
849 ( rOld
.GetGreen() >> 1 ) | 0x80,
850 ( rOld
.GetBlue() >> 1 ) | 0x80 );
853 aNewBmp
= Bitmap( GetSizePixel(), GetBitCount(), &aNewPal
);
854 BitmapWriteAccess
* pW
= aNewBmp
.AcquireWriteAccess();
858 pW
->CopyBuffer( *pR
);
859 aNewBmp
.ReleaseAccess( pW
);
865 aNewBmp
= Bitmap( GetSizePixel(), 24 );
867 BitmapWriteAccess
* pW
= aNewBmp
.AcquireWriteAccess();
871 const long nWidth
= pR
->Width(), nHeight
= pR
->Height();
873 for( long nY
= 0; nY
< nHeight
; nY
++ )
875 for( long nX
= 0; nX
< nWidth
; nX
++ )
877 const BitmapColor
aOld( pR
->GetPixel( nY
, nX
) );
878 pW
->SetPixel( nY
, nX
, BitmapColor( ( aOld
.GetRed() >> 1 ) | 0x80,
879 ( aOld
.GetGreen() >> 1 ) | 0x80,
880 ( aOld
.GetBlue() >> 1 ) | 0x80 ) );
885 aNewBmp
.ReleaseAccess( pW
);
895 const MapMode
aMap( maPrefMapMode
);
896 const Size
aSize( maPrefSize
);
900 maPrefMapMode
= aMap
;
907 // ------------------------------------------------------------------------
909 BOOL
Bitmap::Scale( const double& rScaleX
, const double& rScaleY
, ULONG nScaleFlag
)
913 if( ( rScaleX
!= 1.0 ) || ( rScaleY
!= 1.0 ) )
915 if( BMP_SCALE_FAST
== nScaleFlag
)
916 bRet
= ImplScaleFast( rScaleX
, rScaleY
);
917 else if( BMP_SCALE_INTERPOLATE
== nScaleFlag
)
918 bRet
= ImplScaleInterpolate( rScaleX
, rScaleY
);
928 // ------------------------------------------------------------------------
930 BOOL
Bitmap::Scale( const Size
& rNewSize
, ULONG nScaleFlag
)
932 const Size
aSize( GetSizePixel() );
935 if( aSize
.Width() && aSize
.Height() )
937 bRet
= Scale( (double) rNewSize
.Width() / aSize
.Width(),
938 (double) rNewSize
.Height() / aSize
.Height(),
947 // ------------------------------------------------------------------------
949 BOOL
Bitmap::ImplScaleFast( const double& rScaleX
, const double& rScaleY
)
951 const Size
aSizePix( GetSizePixel() );
952 const long nNewWidth
= FRound( aSizePix
.Width() * rScaleX
);
953 const long nNewHeight
= FRound( aSizePix
.Height() * rScaleY
);
956 if( nNewWidth
&& nNewHeight
)
958 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
959 Bitmap
aNewBmp( Size( nNewWidth
, nNewHeight
), GetBitCount(), &pReadAcc
->GetPalette() );
960 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
962 if( pReadAcc
&& pWriteAcc
)
964 const long nScanlineSize
= pWriteAcc
->GetScanlineSize();
965 const long nNewWidth1
= nNewWidth
- 1L;
966 const long nNewHeight1
= nNewHeight
- 1L;
967 const long nWidth1
= pReadAcc
->Width() - 1L;
968 const long nHeight1
= pReadAcc
->Height() - 1L;
969 long* pLutX
= new long[ nNewWidth
];
970 long* pLutY
= new long[ nNewHeight
];
971 long nX
, nY
, nMapY
, nActY
= 0L;
973 if( nNewWidth1
&& nNewHeight1
)
975 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
976 pLutX
[ nX
] = nX
* nWidth1
/ nNewWidth1
;
978 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
979 pLutY
[ nY
] = nY
* nHeight1
/ nNewHeight1
;
981 while( nActY
< nNewHeight
)
983 nMapY
= pLutY
[ nActY
];
985 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
986 pWriteAcc
->SetPixel( nActY
, nX
, pReadAcc
->GetPixel( nMapY
, pLutX
[ nX
] ) );
988 while( ( nActY
< nNewHeight1
) && ( pLutY
[ nActY
+ 1 ] == nMapY
) )
990 memcpy( pWriteAcc
->GetScanline( nActY
+ 1L ),
991 pWriteAcc
->GetScanline( nActY
), nScanlineSize
);
1005 ReleaseAccess( pReadAcc
);
1006 aNewBmp
.ReleaseAccess( pWriteAcc
);
1009 ImplAssignWithSize( aNewBmp
);
1015 // ------------------------------------------------------------------------
1017 BOOL
Bitmap::ImplScaleInterpolate( const double& rScaleX
, const double& rScaleY
)
1019 const Size
aSizePix( GetSizePixel() );
1020 const long nNewWidth
= FRound( aSizePix
.Width() * rScaleX
);
1021 const long nNewHeight
= FRound( aSizePix
.Height() * rScaleY
);
1024 if( ( nNewWidth
> 1L ) && ( nNewHeight
> 1L ) )
1028 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1029 long nWidth
= pReadAcc
->Width();
1030 long nHeight
= pReadAcc
->Height();
1031 Bitmap
aNewBmp( Size( nNewWidth
, nHeight
), 24 );
1032 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1036 long lXB0
, lXB1
, lXG0
, lXG1
, lXR0
, lXR1
;
1040 if( pReadAcc
&& pWriteAcc
)
1042 const long nNewWidth1
= nNewWidth
- 1L;
1043 const long nWidth1
= pReadAcc
->Width() - 1L;
1044 const double fRevScaleX
= (double) nWidth1
/ nNewWidth1
;
1046 pLutInt
= new long[ nNewWidth
];
1047 pLutFrac
= new long[ nNewWidth
];
1049 for( nX
= 0L, nTemp
= nWidth
- 2L; nX
< nNewWidth
; nX
++ )
1051 fTemp
= nX
* fRevScaleX
;
1052 pLutInt
[ nX
] = MinMax( (long) fTemp
, 0, nTemp
);
1053 fTemp
-= pLutInt
[ nX
];
1054 pLutFrac
[ nX
] = (long) ( fTemp
* 1024. );
1057 if( pReadAcc
->HasPalette() )
1059 for( nY
= 0L; nY
< nHeight
; nY
++ )
1063 aCol0
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, 0 ) );
1065 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
1066 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1070 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
1072 nTemp
= pLutInt
[ nX
];
1074 aCol0
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nTemp
++ ) );
1075 aCol1
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nTemp
) );
1077 nTemp
= pLutFrac
[ nX
];
1079 lXR1
= aCol1
.GetRed() - ( lXR0
= aCol0
.GetRed() );
1080 lXG1
= aCol1
.GetGreen() - ( lXG0
= aCol0
.GetGreen() );
1081 lXB1
= aCol1
.GetBlue() - ( lXB0
= aCol0
.GetBlue() );
1083 aCol0
.SetRed( (BYTE
) ( ( lXR1
* nTemp
+ ( lXR0
<< 10 ) ) >> 10 ) );
1084 aCol0
.SetGreen( (BYTE
) ( ( lXG1
* nTemp
+ ( lXG0
<< 10 ) ) >> 10 ) );
1085 aCol0
.SetBlue( (BYTE
) ( ( lXB1
* nTemp
+ ( lXB0
<< 10 ) ) >> 10 ) );
1087 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1094 for( nY
= 0L; nY
< nHeight
; nY
++ )
1098 aCol0
= pReadAcc
->GetPixel( nY
, 0 );
1100 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
1101 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1105 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
1107 nTemp
= pLutInt
[ nX
];
1109 aCol0
= pReadAcc
->GetPixel( nY
, nTemp
++ );
1110 aCol1
= pReadAcc
->GetPixel( nY
, nTemp
);
1112 nTemp
= pLutFrac
[ nX
];
1114 lXR1
= aCol1
.GetRed() - ( lXR0
= aCol0
.GetRed() );
1115 lXG1
= aCol1
.GetGreen() - ( lXG0
= aCol0
.GetGreen() );
1116 lXB1
= aCol1
.GetBlue() - ( lXB0
= aCol0
.GetBlue() );
1118 aCol0
.SetRed( (BYTE
) ( ( lXR1
* nTemp
+ ( lXR0
<< 10 ) ) >> 10 ) );
1119 aCol0
.SetGreen( (BYTE
) ( ( lXG1
* nTemp
+ ( lXG0
<< 10 ) ) >> 10 ) );
1120 aCol0
.SetBlue( (BYTE
) ( ( lXB1
* nTemp
+ ( lXB0
<< 10 ) ) >> 10 ) );
1122 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1133 ReleaseAccess( pReadAcc
);
1134 aNewBmp
.ReleaseAccess( pWriteAcc
);
1139 ImplAssignWithSize( aNewBmp
);
1140 pReadAcc
= AcquireReadAccess();
1141 aNewBmp
= Bitmap( Size( nNewWidth
, nNewHeight
), 24 );
1142 pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1144 if( pReadAcc
&& pWriteAcc
)
1146 const long nNewHeight1
= nNewHeight
- 1L;
1147 const long nHeight1
= pReadAcc
->Height() - 1L;
1148 const double fRevScaleY
= (double) nHeight1
/ nNewHeight1
;
1150 pLutInt
= new long[ nNewHeight
];
1151 pLutFrac
= new long[ nNewHeight
];
1153 for( nY
= 0L, nTemp
= nHeight
- 2L; nY
< nNewHeight
; nY
++ )
1155 fTemp
= nY
* fRevScaleY
;
1156 pLutInt
[ nY
] = MinMax( (long) fTemp
, 0, nTemp
);
1157 fTemp
-= pLutInt
[ nY
];
1158 pLutFrac
[ nY
] = (long) ( fTemp
* 1024. );
1161 if( pReadAcc
->HasPalette() )
1163 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
1167 aCol0
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( 0, nX
) );
1169 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
1170 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1174 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
1176 nTemp
= pLutInt
[ nY
];
1178 aCol0
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nTemp
++, nX
) );
1179 aCol1
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nTemp
, nX
) );
1181 nTemp
= pLutFrac
[ nY
];
1183 lXR1
= aCol1
.GetRed() - ( lXR0
= aCol0
.GetRed() );
1184 lXG1
= aCol1
.GetGreen() - ( lXG0
= aCol0
.GetGreen() );
1185 lXB1
= aCol1
.GetBlue() - ( lXB0
= aCol0
.GetBlue() );
1187 aCol0
.SetRed( (BYTE
) ( ( lXR1
* nTemp
+ ( lXR0
<< 10 ) ) >> 10 ) );
1188 aCol0
.SetGreen( (BYTE
) ( ( lXG1
* nTemp
+ ( lXG0
<< 10 ) ) >> 10 ) );
1189 aCol0
.SetBlue( (BYTE
) ( ( lXB1
* nTemp
+ ( lXB0
<< 10 ) ) >> 10 ) );
1191 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1198 for( nX
= 0L; nX
< nNewWidth
; nX
++ )
1202 aCol0
= pReadAcc
->GetPixel( 0, nX
);
1204 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
1205 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1209 for( nY
= 0L; nY
< nNewHeight
; nY
++ )
1211 nTemp
= pLutInt
[ nY
];
1213 aCol0
= pReadAcc
->GetPixel( nTemp
++, nX
);
1214 aCol1
= pReadAcc
->GetPixel( nTemp
, nX
);
1216 nTemp
= pLutFrac
[ nY
];
1218 lXR1
= aCol1
.GetRed() - ( lXR0
= aCol0
.GetRed() );
1219 lXG1
= aCol1
.GetGreen() - ( lXG0
= aCol0
.GetGreen() );
1220 lXB1
= aCol1
.GetBlue() - ( lXB0
= aCol0
.GetBlue() );
1222 aCol0
.SetRed( (BYTE
) ( ( lXR1
* nTemp
+ ( lXR0
<< 10 ) ) >> 10 ) );
1223 aCol0
.SetGreen( (BYTE
) ( ( lXG1
* nTemp
+ ( lXG0
<< 10 ) ) >> 10 ) );
1224 aCol0
.SetBlue( (BYTE
) ( ( lXB1
* nTemp
+ ( lXB0
<< 10 ) ) >> 10 ) );
1226 pWriteAcc
->SetPixel( nY
, nX
, aCol0
);
1237 ReleaseAccess( pReadAcc
);
1238 aNewBmp
.ReleaseAccess( pWriteAcc
);
1241 ImplAssignWithSize( aNewBmp
);
1246 bRet
= ImplScaleFast( rScaleX
, rScaleY
);
1251 // ------------------------------------------------------------------------
1253 BOOL
Bitmap::Dither( ULONG nDitherFlags
)
1257 const Size
aSizePix( GetSizePixel() );
1259 if( aSizePix
.Width() == 1 || aSizePix
.Height() == 1 )
1261 else if( nDitherFlags
& BMP_DITHER_MATRIX
)
1262 bRet
= ImplDitherMatrix();
1263 else if( nDitherFlags
& BMP_DITHER_FLOYD
)
1264 bRet
= ImplDitherFloyd();
1265 else if( ( nDitherFlags
& BMP_DITHER_FLOYD_16
) && ( GetBitCount() == 24 ) )
1266 bRet
= ImplDitherFloyd16();
1271 // ------------------------------------------------------------------------
1273 BOOL
Bitmap::ImplDitherMatrix()
1275 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1276 Bitmap
aNewBmp( GetSizePixel(), 8 );
1277 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1280 if( pReadAcc
&& pWriteAcc
)
1282 const ULONG nWidth
= pReadAcc
->Width();
1283 const ULONG nHeight
= pReadAcc
->Height();
1284 BitmapColor
aIndex( (BYTE
) 0 );
1286 if( pReadAcc
->HasPalette() )
1288 for( ULONG nY
= 0UL; nY
< nHeight
; nY
++ )
1290 for( ULONG nX
= 0UL, nModY
= ( nY
& 0x0FUL
) << 4UL; nX
< nWidth
; nX
++ )
1292 const BitmapColor
aCol( pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nX
) ) );
1293 const ULONG nD
= nVCLDitherLut
[ nModY
+ ( nX
& 0x0FUL
) ];
1294 const ULONG nR
= ( nVCLLut
[ aCol
.GetRed() ] + nD
) >> 16UL;
1295 const ULONG nG
= ( nVCLLut
[ aCol
.GetGreen() ] + nD
) >> 16UL;
1296 const ULONG nB
= ( nVCLLut
[ aCol
.GetBlue() ] + nD
) >> 16UL;
1298 aIndex
.SetIndex( (BYTE
) ( nVCLRLut
[ nR
] + nVCLGLut
[ nG
] + nVCLBLut
[ nB
] ) );
1299 pWriteAcc
->SetPixel( nY
, nX
, aIndex
);
1305 for( ULONG nY
= 0UL; nY
< nHeight
; nY
++ )
1307 for( ULONG nX
= 0UL, nModY
= ( nY
& 0x0FUL
) << 4UL; nX
< nWidth
; nX
++ )
1309 const BitmapColor
aCol( pReadAcc
->GetPixel( nY
, nX
) );
1310 const ULONG nD
= nVCLDitherLut
[ nModY
+ ( nX
& 0x0FUL
) ];
1311 const ULONG nR
= ( nVCLLut
[ aCol
.GetRed() ] + nD
) >> 16UL;
1312 const ULONG nG
= ( nVCLLut
[ aCol
.GetGreen() ] + nD
) >> 16UL;
1313 const ULONG nB
= ( nVCLLut
[ aCol
.GetBlue() ] + nD
) >> 16UL;
1315 aIndex
.SetIndex( (BYTE
) ( nVCLRLut
[ nR
] + nVCLGLut
[ nG
] + nVCLBLut
[ nB
] ) );
1316 pWriteAcc
->SetPixel( nY
, nX
, aIndex
);
1324 ReleaseAccess( pReadAcc
);
1325 aNewBmp
.ReleaseAccess( pWriteAcc
);
1329 const MapMode
aMap( maPrefMapMode
);
1330 const Size
aSize( maPrefSize
);
1334 maPrefMapMode
= aMap
;
1341 // ------------------------------------------------------------------------
1343 BOOL
Bitmap::ImplDitherFloyd()
1345 const Size
aSize( GetSizePixel() );
1348 if( ( aSize
.Width() > 3 ) && ( aSize
.Height() > 2 ) )
1350 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1351 Bitmap
aNewBmp( GetSizePixel(), 8 );
1352 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1354 if( pReadAcc
&& pWriteAcc
)
1357 long nWidth
= pReadAcc
->Width();
1358 long nWidth1
= nWidth
- 1L;
1359 long nHeight
= pReadAcc
->Height();
1361 long nW
= nWidth
* 3L;
1363 long nRErr
, nGErr
, nBErr
;
1367 long* p1
= new long[ nW
];
1368 long* p2
= new long[ nW
];
1372 BOOL bPal
= pReadAcc
->HasPalette();
1378 for( nZ
= 0; nZ
< nWidth
; nZ
++ )
1380 aColor
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( 0, nZ
) );
1382 *pTmp
++ = (long) aColor
.GetBlue() << 12;
1383 *pTmp
++ = (long) aColor
.GetGreen() << 12;
1384 *pTmp
++ = (long) aColor
.GetRed() << 12;
1389 for( nZ
= 0; nZ
< nWidth
; nZ
++ )
1391 aColor
= pReadAcc
->GetPixel( 0, nZ
);
1393 *pTmp
++ = (long) aColor
.GetBlue() << 12;
1394 *pTmp
++ = (long) aColor
.GetGreen() << 12;
1395 *pTmp
++ = (long) aColor
.GetRed() << 12;
1399 for( long nY
= 1, nYAcc
= 0L; nY
<= nHeight
; nY
++, nYAcc
++ )
1409 for( nZ
= 0; nZ
< nWidth
; nZ
++ )
1411 aColor
= pReadAcc
->GetPaletteColor( pReadAcc
->GetPixel( nY
, nZ
) );
1413 *pTmp
++ = (long) aColor
.GetBlue() << 12;
1414 *pTmp
++ = (long) aColor
.GetGreen() << 12;
1415 *pTmp
++ = (long) aColor
.GetRed() << 12;
1420 for( nZ
= 0; nZ
< nWidth
; nZ
++ )
1422 aColor
= pReadAcc
->GetPixel( nY
, nZ
);
1424 *pTmp
++ = (long) aColor
.GetBlue() << 12;
1425 *pTmp
++ = (long) aColor
.GetGreen() << 12;
1426 *pTmp
++ = (long) aColor
.GetRed() << 12;
1431 // erstes Pixel gesondert betrachten
1437 pWriteAcc
->SetPixel( nYAcc
, 0, BitmapColor( (BYTE
) ( nVCLBLut
[ nBC
] + nVCLGLut
[nGC
] + nVCLRLut
[nRC
] ) ) );
1439 // mittlere Pixel ueber Schleife
1441 for ( nX
= 3L, nXAcc
= 1L; nX
< nW2
; nXAcc
++ )
1448 pWriteAcc
->SetPixel( nYAcc
, nXAcc
, BitmapColor( (BYTE
) ( nVCLBLut
[ nBC
] + nVCLGLut
[nGC
] + nVCLRLut
[nRC
] ) ) );
1451 // letztes Pixel gesondert betrachten
1456 pWriteAcc
->SetPixel( nYAcc
, nWidth1
, BitmapColor( (BYTE
) ( nVCLBLut
[ nBC
] + nVCLGLut
[nGC
] + nVCLRLut
[nRC
] ) ) );
1464 ReleaseAccess( pReadAcc
);
1465 aNewBmp
.ReleaseAccess( pWriteAcc
);
1469 const MapMode
aMap( maPrefMapMode
);
1470 const Size
aPrefSize( maPrefSize
);
1474 maPrefMapMode
= aMap
;
1475 maPrefSize
= aPrefSize
;
1482 // ------------------------------------------------------------------------
1484 BOOL
Bitmap::ImplDitherFloyd16()
1486 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
1487 Bitmap
aNewBmp( GetSizePixel(), 24 );
1488 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
1491 if( pReadAcc
&& pWriteAcc
)
1493 const long nWidth
= pWriteAcc
->Width();
1494 const long nWidth1
= nWidth
- 1L;
1495 const long nHeight
= pWriteAcc
->Height();
1497 BitmapColor aBestCol
;
1498 ImpErrorQuad aErrQuad
;
1499 ImpErrorQuad
* pErrQuad1
= new ImpErrorQuad
[ nWidth
];
1500 ImpErrorQuad
* pErrQuad2
= new ImpErrorQuad
[ nWidth
];
1501 ImpErrorQuad
* pQLine1
= pErrQuad1
;
1502 ImpErrorQuad
* pQLine2
= 0;
1507 for( nY
= 0L; nY
< Min( nHeight
, 2L ); nY
++, nYTmp
++ )
1508 for( nX
= 0L, pQLine2
= !nY
? pErrQuad1
: pErrQuad2
; nX
< nWidth
; nX
++ )
1509 pQLine2
[ nX
] = pReadAcc
->GetPixel( nYTmp
, nX
);
1511 for( nY
= 0L; nY
< nHeight
; nY
++, nYTmp
++ )
1513 // erstes ZeilenPixel
1514 aBestCol
= pQLine1
[ 0 ].ImplGetColor();
1515 aBestCol
.SetRed( ( aBestCol
.GetRed() & 248 ) | 7 );
1516 aBestCol
.SetGreen( ( aBestCol
.GetGreen() & 248 ) | 7 );
1517 aBestCol
.SetBlue( ( aBestCol
.GetBlue() & 248 ) | 7 );
1518 pWriteAcc
->SetPixel( nY
, 0, aBestCol
);
1520 for( nX
= 1L; nX
< nWidth1
; nX
++ )
1522 aColor
= pQLine1
[ nX
].ImplGetColor();
1523 aBestCol
.SetRed( ( aColor
.GetRed() & 248 ) | 7 );
1524 aBestCol
.SetGreen( ( aColor
.GetGreen() & 248 ) | 7 );
1525 aBestCol
.SetBlue( ( aColor
.GetBlue() & 248 ) | 7 );
1526 aErrQuad
= ( ImpErrorQuad( aColor
) -= aBestCol
);
1527 pQLine1
[ ++nX
].ImplAddColorError7( aErrQuad
);
1528 pQLine2
[ nX
-- ].ImplAddColorError1( aErrQuad
);
1529 pQLine2
[ nX
-- ].ImplAddColorError5( aErrQuad
);
1530 pQLine2
[ nX
++ ].ImplAddColorError3( aErrQuad
);
1531 pWriteAcc
->SetPixel( nY
, nX
, aBestCol
);
1534 // letztes ZeilenPixel
1535 aBestCol
= pQLine1
[ nWidth1
].ImplGetColor();
1536 aBestCol
.SetRed( ( aBestCol
.GetRed() & 248 ) | 7 );
1537 aBestCol
.SetGreen( ( aBestCol
.GetGreen() & 248 ) | 7 );
1538 aBestCol
.SetBlue( ( aBestCol
.GetBlue() & 248 ) | 7 );
1539 pWriteAcc
->SetPixel( nY
, nX
, aBestCol
);
1541 // Zeilenpuffer neu fuellen/kopieren
1543 pQLine2
= ( bQ1
= !bQ1
) != FALSE
? pErrQuad2
: pErrQuad1
;
1545 if( nYTmp
< nHeight
)
1546 for( nX
= 0L; nX
< nWidth
; nX
++ )
1547 pQLine2
[ nX
] = pReadAcc
->GetPixel( nYTmp
, nX
);
1550 // Zeilenpuffer zerstoeren
1556 ReleaseAccess( pReadAcc
);
1557 aNewBmp
.ReleaseAccess( pWriteAcc
);
1561 const MapMode
aMap( maPrefMapMode
);
1562 const Size
aSize( maPrefSize
);
1566 maPrefMapMode
= aMap
;
1573 // ------------------------------------------------------------------------
1575 BOOL
Bitmap::ReduceColors( USHORT nColorCount
, BmpReduce eReduce
)
1579 if( GetColorCount() <= (ULONG
) nColorCount
)
1581 else if( nColorCount
)
1583 if( BMP_REDUCE_SIMPLE
== eReduce
)
1584 bRet
= ImplReduceSimple( nColorCount
);
1585 else if( BMP_REDUCE_POPULAR
== eReduce
)
1586 bRet
= ImplReducePopular( nColorCount
);
1588 bRet
= ImplReduceMedian( nColorCount
);
1596 // ------------------------------------------------------------------------
1598 BOOL
Bitmap::ImplReduceSimple( USHORT nColorCount
)
1601 BitmapReadAccess
* pRAcc
= AcquireReadAccess();
1602 const USHORT nColCount
= Min( nColorCount
, (USHORT
) 256 );
1606 if( nColCount
<= 2 )
1608 else if( nColCount
<= 16 )
1615 Octree
aOct( *pRAcc
, nColCount
);
1616 const BitmapPalette
& rPal
= aOct
.GetPalette();
1617 BitmapWriteAccess
* pWAcc
;
1619 aNewBmp
= Bitmap( GetSizePixel(), nBitCount
, &rPal
);
1620 pWAcc
= aNewBmp
.AcquireWriteAccess();
1624 const long nWidth
= pRAcc
->Width();
1625 const long nHeight
= pRAcc
->Height();
1627 if( pRAcc
->HasPalette() )
1629 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1630 for( long nX
=0L; nX
< nWidth
; nX
++ )
1631 pWAcc
->SetPixel( nY
, nX
, (BYTE
) aOct
.GetBestPaletteIndex( pRAcc
->GetPaletteColor( pRAcc
->GetPixel( nY
, nX
) ) ) );
1635 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1636 for( long nX
=0L; nX
< nWidth
; nX
++ )
1637 pWAcc
->SetPixel( nY
, nX
, (BYTE
) aOct
.GetBestPaletteIndex( pRAcc
->GetPixel( nY
, nX
) ) );
1640 aNewBmp
.ReleaseAccess( pWAcc
);
1644 ReleaseAccess( pRAcc
);
1649 const MapMode
aMap( maPrefMapMode
);
1650 const Size
aSize( maPrefSize
);
1653 maPrefMapMode
= aMap
;
1660 // ------------------------------------------------------------------------
1662 struct PopularColorCount
1668 // ------------------------------------------------------------------------
1670 extern "C" int __LOADONCALLAPI
ImplPopularCmpFnc( const void* p1
, const void* p2
)
1674 if( ( (PopularColorCount
*) p1
)->mnCount
< ( (PopularColorCount
*) p2
)->mnCount
)
1676 else if( ( (PopularColorCount
*) p1
)->mnCount
== ( (PopularColorCount
*) p2
)->mnCount
)
1684 // ------------------------------------------------------------------------
1686 BOOL
Bitmap::ImplReducePopular( USHORT nColCount
)
1688 BitmapReadAccess
* pRAcc
= AcquireReadAccess();
1692 if( nColCount
> 256 )
1695 if( nColCount
< 17 )
1702 const sal_uInt32 nValidBits
= 4;
1703 const sal_uInt32 nRightShiftBits
= 8 - nValidBits
;
1704 const sal_uInt32 nLeftShiftBits1
= nValidBits
;
1705 const sal_uInt32 nLeftShiftBits2
= nValidBits
<< 1;
1706 const sal_uInt32 nColorsPerComponent
= 1 << nValidBits
;
1707 const sal_uInt32 nColorOffset
= 256 / nColorsPerComponent
;
1708 const sal_uInt32 nTotalColors
= nColorsPerComponent
* nColorsPerComponent
* nColorsPerComponent
;
1709 const long nWidth
= pRAcc
->Width();
1710 const long nHeight
= pRAcc
->Height();
1711 PopularColorCount
* pCountTable
= new PopularColorCount
[ nTotalColors
];
1712 long nX
, nY
, nR
, nG
, nB
, nIndex
;
1714 rtl_zeroMemory( pCountTable
, nTotalColors
* sizeof( PopularColorCount
) );
1716 for( nR
= 0, nIndex
= 0; nR
< 256; nR
+= nColorOffset
)
1718 for( nG
= 0; nG
< 256; nG
+= nColorOffset
)
1720 for( nB
= 0; nB
< 256; nB
+= nColorOffset
)
1722 pCountTable
[ nIndex
].mnIndex
= nIndex
;
1728 if( pRAcc
->HasPalette() )
1730 for( nY
= 0L; nY
< nHeight
; nY
++ )
1732 for( nX
= 0L; nX
< nWidth
; nX
++ )
1734 const BitmapColor
& rCol
= pRAcc
->GetPaletteColor( pRAcc
->GetPixel( nY
, nX
) );
1735 pCountTable
[ ( ( ( (sal_uInt32
) rCol
.GetRed() ) >> nRightShiftBits
) << nLeftShiftBits2
) |
1736 ( ( ( (sal_uInt32
) rCol
.GetGreen() ) >> nRightShiftBits
) << nLeftShiftBits1
) |
1737 ( ( (sal_uInt32
) rCol
.GetBlue() ) >> nRightShiftBits
) ].mnCount
++;
1743 for( nY
= 0L; nY
< nHeight
; nY
++ )
1745 for( nX
= 0L; nX
< nWidth
; nX
++ )
1747 const BitmapColor
aCol( pRAcc
->GetPixel( nY
, nX
) );
1748 pCountTable
[ ( ( ( (sal_uInt32
) aCol
.GetRed() ) >> nRightShiftBits
) << nLeftShiftBits2
) |
1749 ( ( ( (sal_uInt32
) aCol
.GetGreen() ) >> nRightShiftBits
) << nLeftShiftBits1
) |
1750 ( ( (sal_uInt32
) aCol
.GetBlue() ) >> nRightShiftBits
) ].mnCount
++;
1755 BitmapPalette
aNewPal( nColCount
);
1757 qsort( pCountTable
, nTotalColors
, sizeof( PopularColorCount
), ImplPopularCmpFnc
);
1759 for( USHORT n
= 0; n
< nColCount
; n
++ )
1761 const PopularColorCount
& rPop
= pCountTable
[ n
];
1762 aNewPal
[ n
] = BitmapColor( (BYTE
) ( ( rPop
.mnIndex
>> nLeftShiftBits2
) << nRightShiftBits
),
1763 (BYTE
) ( ( ( rPop
.mnIndex
>> nLeftShiftBits1
) & ( nColorsPerComponent
- 1 ) ) << nRightShiftBits
),
1764 (BYTE
) ( ( rPop
.mnIndex
& ( nColorsPerComponent
- 1 ) ) << nRightShiftBits
) );
1767 Bitmap
aNewBmp( GetSizePixel(), nBitCount
, &aNewPal
);
1768 BitmapWriteAccess
* pWAcc
= aNewBmp
.AcquireWriteAccess();
1772 BitmapColor
aDstCol( (BYTE
) 0 );
1773 BYTE
* pIndexMap
= new BYTE
[ nTotalColors
];
1775 for( nR
= 0, nIndex
= 0; nR
< 256; nR
+= nColorOffset
)
1776 for( nG
= 0; nG
< 256; nG
+= nColorOffset
)
1777 for( nB
= 0; nB
< 256; nB
+= nColorOffset
)
1778 pIndexMap
[ nIndex
++ ] = (BYTE
) aNewPal
.GetBestIndex( BitmapColor( (BYTE
) nR
, (BYTE
) nG
, (BYTE
) nB
) );
1780 if( pRAcc
->HasPalette() )
1782 for( nY
= 0L; nY
< nHeight
; nY
++ )
1784 for( nX
= 0L; nX
< nWidth
; nX
++ )
1786 const BitmapColor
& rCol
= pRAcc
->GetPaletteColor( pRAcc
->GetPixel( nY
, nX
) );
1787 aDstCol
.SetIndex( pIndexMap
[ ( ( ( (sal_uInt32
) rCol
.GetRed() ) >> nRightShiftBits
) << nLeftShiftBits2
) |
1788 ( ( ( (sal_uInt32
) rCol
.GetGreen() ) >> nRightShiftBits
) << nLeftShiftBits1
) |
1789 ( ( (sal_uInt32
) rCol
.GetBlue() ) >> nRightShiftBits
) ] );
1790 pWAcc
->SetPixel( nY
, nX
, aDstCol
);
1796 for( nY
= 0L; nY
< nHeight
; nY
++ )
1798 for( nX
= 0L; nX
< nWidth
; nX
++ )
1800 const BitmapColor
aCol( pRAcc
->GetPixel( nY
, nX
) );
1801 aDstCol
.SetIndex( pIndexMap
[ ( ( ( (sal_uInt32
) aCol
.GetRed() ) >> nRightShiftBits
) << nLeftShiftBits2
) |
1802 ( ( ( (sal_uInt32
) aCol
.GetGreen() ) >> nRightShiftBits
) << nLeftShiftBits1
) |
1803 ( ( (sal_uInt32
) aCol
.GetBlue() ) >> nRightShiftBits
) ] );
1804 pWAcc
->SetPixel( nY
, nX
, aDstCol
);
1810 aNewBmp
.ReleaseAccess( pWAcc
);
1814 delete[] pCountTable
;
1815 ReleaseAccess( pRAcc
);
1819 const MapMode
aMap( maPrefMapMode
);
1820 const Size
aSize( maPrefSize
);
1823 maPrefMapMode
= aMap
;
1831 // ------------------------------------------------------------------------
1833 BOOL
Bitmap::ImplReduceMedian( USHORT nColCount
)
1835 BitmapReadAccess
* pRAcc
= AcquireReadAccess();
1839 if( nColCount
< 17 )
1841 else if( nColCount
< 257 )
1845 DBG_ERROR( "Bitmap::ImplReduceMedian(): invalid color count!" );
1852 Bitmap
aNewBmp( GetSizePixel(), nBitCount
);
1853 BitmapWriteAccess
* pWAcc
= aNewBmp
.AcquireWriteAccess();
1857 const ULONG nSize
= 32768UL * sizeof( ULONG
);
1858 ULONG
* pColBuf
= (ULONG
*) rtl_allocateMemory( nSize
);
1859 const long nWidth
= pWAcc
->Width();
1860 const long nHeight
= pWAcc
->Height();
1863 memset( (HPBYTE
) pColBuf
, 0, nSize
);
1866 if( pRAcc
->HasPalette() )
1868 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1870 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1872 const BitmapColor
& rCol
= pRAcc
->GetPaletteColor( pRAcc
->GetPixel( nY
, nX
) );
1873 pColBuf
[ RGB15( rCol
.GetRed() >> 3, rCol
.GetGreen() >> 3, rCol
.GetBlue() >> 3 ) ]++;
1879 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1881 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1883 const BitmapColor
aCol( pRAcc
->GetPixel( nY
, nX
) );
1884 pColBuf
[ RGB15( aCol
.GetRed() >> 3, aCol
.GetGreen() >> 3, aCol
.GetBlue() >> 3 ) ]++;
1889 // create palette via median cut
1890 BitmapPalette
aPal( pWAcc
->GetPaletteEntryCount() );
1891 ImplMedianCut( pColBuf
, aPal
, 0, 31, 0, 31, 0, 31,
1892 nColCount
, nWidth
* nHeight
, nIndex
);
1894 // do mapping of colors to palette
1895 InverseColorMap
aMap( aPal
);
1896 pWAcc
->SetPalette( aPal
);
1897 for( long nY
= 0L; nY
< nHeight
; nY
++ )
1898 for( long nX
= 0L; nX
< nWidth
; nX
++ )
1899 pWAcc
->SetPixel( nY
, nX
, (BYTE
) aMap
.GetBestPaletteIndex( pRAcc
->GetColor( nY
, nX
) ) );
1901 rtl_freeMemory( pColBuf
);
1902 aNewBmp
.ReleaseAccess( pWAcc
);
1906 ReleaseAccess( pRAcc
);
1910 const MapMode
aMap( maPrefMapMode
);
1911 const Size
aSize( maPrefSize
);
1914 maPrefMapMode
= aMap
;
1922 // ------------------------------------------------------------------------
1924 void Bitmap::ImplMedianCut( ULONG
* pColBuf
, BitmapPalette
& rPal
,
1925 long nR1
, long nR2
, long nG1
, long nG2
, long nB1
, long nB2
,
1926 long nColors
, long nPixels
, long& rIndex
)
1932 const long nRLen
= nR2
- nR1
;
1933 const long nGLen
= nG2
- nG1
;
1934 const long nBLen
= nB2
- nB1
;
1936 ULONG
* pBuf
= pColBuf
;
1938 if( !nRLen
&& !nGLen
&& !nBLen
)
1940 if( pBuf
[ RGB15( nR1
, nG1
, nB1
) ] )
1942 aCol
.SetRed( (BYTE
) ( nR1
<< 3 ) );
1943 aCol
.SetGreen( (BYTE
) ( nG1
<< 3 ) );
1944 aCol
.SetBlue( (BYTE
) ( nB1
<< 3 ) );
1945 rPal
[ (USHORT
) rIndex
++ ] = aCol
;
1950 if( 1 == nColors
|| 1 == nPixels
)
1952 long nPixSum
= 0, nRSum
= 0, nGSum
= 0, nBSum
= 0;
1954 for( nR
= nR1
; nR
<= nR2
; nR
++ )
1956 for( nG
= nG1
; nG
<= nG2
; nG
++ )
1958 for( nB
= nB1
; nB
<= nB2
; nB
++ )
1960 nPixSum
= pBuf
[ RGB15( nR
, nG
, nB
) ];
1964 nRSum
+= nR
* nPixSum
;
1965 nGSum
+= nG
* nPixSum
;
1966 nBSum
+= nB
* nPixSum
;
1972 aCol
.SetRed( (BYTE
) ( ( nRSum
/ nPixels
) << 3 ) );
1973 aCol
.SetGreen( (BYTE
) ( ( nGSum
/ nPixels
) << 3 ) );
1974 aCol
.SetBlue( (BYTE
) ( ( nBSum
/ nPixels
) << 3 ) );
1975 rPal
[ (USHORT
) rIndex
++ ] = aCol
;
1979 const long nTest
= ( nPixels
>> 1 );
1983 if( nBLen
> nGLen
&& nBLen
> nRLen
)
1987 while( nPixNew
< nTest
)
1989 nB
++, nPixOld
= nPixNew
;
1990 for( nR
= nR1
; nR
<= nR2
; nR
++ )
1991 for( nG
= nG1
; nG
<= nG2
; nG
++ )
1992 nPixNew
+= pBuf
[ RGB15( nR
, nG
, nB
) ];
1997 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG1
, nG2
, nB1
, nB
, nColors
>> 1, nPixNew
, rIndex
);
1998 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG1
, nG2
, nB
+ 1, nB2
, nColors
>> 1, nPixels
- nPixNew
, rIndex
);
2002 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG1
, nG2
, nB1
, nB
- 1, nColors
>> 1, nPixOld
, rIndex
);
2003 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG1
, nG2
, nB
, nB2
, nColors
>> 1, nPixels
- nPixOld
, rIndex
);
2006 else if( nGLen
> nRLen
)
2010 while( nPixNew
< nTest
)
2012 nG
++, nPixOld
= nPixNew
;
2013 for( nR
= nR1
; nR
<= nR2
; nR
++ )
2014 for( nB
= nB1
; nB
<= nB2
; nB
++ )
2015 nPixNew
+= pBuf
[ RGB15( nR
, nG
, nB
) ];
2020 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG1
, nG
, nB1
, nB2
, nColors
>> 1, nPixNew
, rIndex
);
2021 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG
+ 1, nG2
, nB1
, nB2
, nColors
>> 1, nPixels
- nPixNew
, rIndex
);
2025 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG1
, nG
- 1, nB1
, nB2
, nColors
>> 1, nPixOld
, rIndex
);
2026 ImplMedianCut( pBuf
, rPal
, nR1
, nR2
, nG
, nG2
, nB1
, nB2
, nColors
>> 1, nPixels
- nPixOld
, rIndex
);
2033 while( nPixNew
< nTest
)
2035 nR
++, nPixOld
= nPixNew
;
2036 for( nG
= nG1
; nG
<= nG2
; nG
++ )
2037 for( nB
= nB1
; nB
<= nB2
; nB
++ )
2038 nPixNew
+= pBuf
[ RGB15( nR
, nG
, nB
) ];
2043 ImplMedianCut( pBuf
, rPal
, nR1
, nR
, nG1
, nG2
, nB1
, nB2
, nColors
>> 1, nPixNew
, rIndex
);
2044 ImplMedianCut( pBuf
, rPal
, nR1
+ 1, nR2
, nG1
, nG2
, nB1
, nB2
, nColors
>> 1, nPixels
- nPixNew
, rIndex
);
2048 ImplMedianCut( pBuf
, rPal
, nR1
, nR
- 1, nG1
, nG2
, nB1
, nB2
, nColors
>> 1, nPixOld
, rIndex
);
2049 ImplMedianCut( pBuf
, rPal
, nR
, nR2
, nG1
, nG2
, nB1
, nB2
, nColors
>> 1, nPixels
- nPixOld
, rIndex
);
2056 // ------------------------------------------------------------------------
2058 BOOL
Bitmap::Vectorize( PolyPolygon
& rPolyPoly
, ULONG nFlags
, const Link
* pProgress
)
2060 return ImplVectorizer().ImplVectorize( *this, rPolyPoly
, nFlags
, pProgress
);
2063 // ------------------------------------------------------------------------
2065 BOOL
Bitmap::Vectorize( GDIMetaFile
& rMtf
, BYTE cReduce
, ULONG nFlags
, const Link
* pProgress
)
2067 return ImplVectorizer().ImplVectorize( *this, rMtf
, cReduce
, nFlags
, pProgress
);
2070 // ------------------------------------------------------------------------
2072 BOOL
Bitmap::Adjust( short nLuminancePercent
, short nContrastPercent
,
2073 short nChannelRPercent
, short nChannelGPercent
, short nChannelBPercent
,
2074 double fGamma
, BOOL bInvert
)
2078 // nothing to do => return quickly
2079 if( !nLuminancePercent
&& !nContrastPercent
&&
2080 !nChannelRPercent
&& !nChannelGPercent
&& !nChannelBPercent
&&
2081 ( fGamma
== 1.0 ) && !bInvert
)
2087 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
2092 const long nW
= pAcc
->Width();
2093 const long nH
= pAcc
->Height();
2094 BYTE
* cMapR
= new BYTE
[ 256 ];
2095 BYTE
* cMapG
= new BYTE
[ 256 ];
2096 BYTE
* cMapB
= new BYTE
[ 256 ];
2098 double fM
, fROff
, fGOff
, fBOff
, fOff
;
2101 if( nContrastPercent
>= 0 )
2102 fM
= 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent
, 0L, 100L ) );
2104 fM
= ( 128.0 + 1.27 * MinMax( nContrastPercent
, -100L, 0L ) ) / 128.0;
2106 // total offset = luminance offset + contrast offset
2107 fOff
= MinMax( nLuminancePercent
, -100L, 100L ) * 2.55 + 128.0 - fM
* 128.0;
2109 // channel offset = channel offset + total offset
2110 fROff
= nChannelRPercent
* 2.55 + fOff
;
2111 fGOff
= nChannelGPercent
* 2.55 + fOff
;
2112 fBOff
= nChannelBPercent
* 2.55 + fOff
;
2114 // calculate gamma value
2115 fGamma
= ( fGamma
<= 0.0 || fGamma
> 10.0 ) ? 1.0 : ( 1.0 / fGamma
);
2116 const BOOL bGamma
= ( fGamma
!= 1.0 );
2118 // create mapping table
2119 for( nX
= 0L; nX
< 256L; nX
++ )
2121 cMapR
[ nX
] = (BYTE
) MinMax( FRound( nX
* fM
+ fROff
), 0L, 255L );
2122 cMapG
[ nX
] = (BYTE
) MinMax( FRound( nX
* fM
+ fGOff
), 0L, 255L );
2123 cMapB
[ nX
] = (BYTE
) MinMax( FRound( nX
* fM
+ fBOff
), 0L, 255L );
2127 cMapR
[ nX
] = GAMMA( cMapR
[ nX
], fGamma
);
2128 cMapG
[ nX
] = GAMMA( cMapG
[ nX
], fGamma
);
2129 cMapB
[ nX
] = GAMMA( cMapB
[ nX
], fGamma
);
2134 cMapR
[ nX
] = ~cMapR
[ nX
];
2135 cMapG
[ nX
] = ~cMapG
[ nX
];
2136 cMapB
[ nX
] = ~cMapB
[ nX
];
2141 if( pAcc
->HasPalette() )
2143 BitmapColor aNewCol
;
2145 for( USHORT i
= 0, nCount
= pAcc
->GetPaletteEntryCount(); i
< nCount
; i
++ )
2147 const BitmapColor
& rCol
= pAcc
->GetPaletteColor( i
);
2148 aNewCol
.SetRed( cMapR
[ rCol
.GetRed() ] );
2149 aNewCol
.SetGreen( cMapG
[ rCol
.GetGreen() ] );
2150 aNewCol
.SetBlue( cMapB
[ rCol
.GetBlue() ] );
2151 pAcc
->SetPaletteColor( i
, aNewCol
);
2154 else if( pAcc
->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR
)
2156 for( nY
= 0L; nY
< nH
; nY
++ )
2158 Scanline pScan
= pAcc
->GetScanline( nY
);
2160 for( nX
= 0L; nX
< nW
; nX
++ )
2162 *pScan
= cMapB
[ *pScan
]; pScan
++;
2163 *pScan
= cMapG
[ *pScan
]; pScan
++;
2164 *pScan
= cMapR
[ *pScan
]; pScan
++;
2168 else if( pAcc
->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB
)
2170 for( nY
= 0L; nY
< nH
; nY
++ )
2172 Scanline pScan
= pAcc
->GetScanline( nY
);
2174 for( nX
= 0L; nX
< nW
; nX
++ )
2176 *pScan
= cMapR
[ *pScan
]; pScan
++;
2177 *pScan
= cMapG
[ *pScan
]; pScan
++;
2178 *pScan
= cMapB
[ *pScan
]; pScan
++;
2184 for( nY
= 0L; nY
< nH
; nY
++ )
2186 for( nX
= 0L; nX
< nW
; nX
++ )
2188 aCol
= pAcc
->GetPixel( nY
, nX
);
2189 aCol
.SetRed( cMapR
[ aCol
.GetRed() ] );
2190 aCol
.SetGreen( cMapG
[ aCol
.GetGreen() ] );
2191 aCol
.SetBlue( cMapB
[ aCol
.GetBlue() ] );
2192 pAcc
->SetPixel( nY
, nX
, aCol
);
2200 ReleaseAccess( pAcc
);