merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / gdi / bitmap4.cxx
bloba2060ebbd982773202ca8aa84429e7833f113583
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bitmap4.cxx,v $
10 * $Revision: 1.12 $
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"
34 #include <stdlib.h>
35 #include <vos/macros.hxx>
36 #include <vcl/bmpacc.hxx>
37 #include <vcl/bitmap.hxx>
39 // -----------
40 // - Defines -
41 // -----------
43 #define S2(a,b) { register long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } }
44 #define MN3(a,b,c) S2(a,b); S2(a,c);
45 #define MX3(a,b,c) S2(b,c); S2(a,c);
46 #define MNMX3(a,b,c) MX3(a,b,c); S2(a,b);
47 #define MNMX4(a,b,c,d) S2(a,b); S2(c,d); S2(a,c); S2(b,d);
48 #define MNMX5(a,b,c,d,e) S2(a,b); S2(c,d); MN3(a,c,e); MX3(b,d,e);
49 #define MNMX6(a,b,c,d,e,f) S2(a,d); S2(b,e); S2(c,f); MN3(a,b,c); MX3(d,e,f);
51 // ----------
52 // - Bitmap -
53 // ----------
55 BOOL Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
57 BOOL bRet = FALSE;
59 switch( eFilter )
61 case( BMP_FILTER_SMOOTH ):
63 const long pSmoothMatrix[] = { 1, 2, 1, 2, 5, 2, 1, 2, 1 };
64 bRet = ImplConvolute3( &pSmoothMatrix[ 0 ], 17, pFilterParam, pProgress );
66 break;
68 case( BMP_FILTER_SHARPEN ):
70 const long pSharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
71 bRet = ImplConvolute3( &pSharpenMatrix[ 0 ], 8, pFilterParam, pProgress );
73 break;
75 case( BMP_FILTER_REMOVENOISE ):
76 bRet = ImplMedianFilter( pFilterParam, pProgress );
77 break;
79 case( BMP_FILTER_SOBEL_GREY ):
80 bRet = ImplSobelGrey( pFilterParam, pProgress );
81 break;
83 case( BMP_FILTER_SOLARIZE ):
84 bRet = ImplSolarize( pFilterParam, pProgress );
85 break;
87 case( BMP_FILTER_SEPIA ):
88 bRet = ImplSepia( pFilterParam, pProgress );
89 break;
91 case( BMP_FILTER_MOSAIC ):
92 bRet = ImplMosaic( pFilterParam, pProgress );
93 break;
95 case( BMP_FILTER_EMBOSS_GREY ):
96 bRet = ImplEmbossGrey( pFilterParam, pProgress );
97 break;
99 case( BMP_FILTER_POPART ):
100 bRet = ImplPopArt( pFilterParam, pProgress );
101 break;
103 default:
104 DBG_ERROR( "Bitmap::Convert(): Unsupported filter" );
105 break;
108 return bRet;
111 // -----------------------------------------------------------------------------
113 BOOL Bitmap::ImplConvolute3( const long* pMatrix, long nDivisor,
114 const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
116 BitmapReadAccess* pReadAcc = AcquireReadAccess();
117 BOOL bRet = FALSE;
119 if( pReadAcc )
121 Bitmap aNewBmp( GetSizePixel(), 24 );
122 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
124 if( pWriteAcc )
126 const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
127 const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
128 long* pColm = new long[ nWidth2 ];
129 long* pRows = new long[ nHeight2 ];
130 BitmapColor* pColRow1 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
131 BitmapColor* pColRow2 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
132 BitmapColor* pColRow3 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
133 BitmapColor* pRowTmp1 = pColRow1;
134 BitmapColor* pRowTmp2 = pColRow2;
135 BitmapColor* pRowTmp3 = pColRow3;
136 BitmapColor* pColor;
137 long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
138 long (*pKoeff)[ 256 ] = new long[ 9 ][ 256 ];
139 long* pTmp;
141 // create LUT of products of matrix value and possible color component values
142 for( nY = 0; nY < 9; nY++ )
143 for( nX = nTmp = 0, nMatrixVal = pMatrix[ nY ]; nX < 256; nX++, nTmp += nMatrixVal )
144 pKoeff[ nY ][ nX ] = nTmp;
146 // create column LUT
147 for( i = 0; i < nWidth2; i++ )
148 pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
150 pColm[ nWidth + 1 ] = pColm[ nWidth ];
152 // create row LUT
153 for( i = 0; i < nHeight2; i++ )
154 pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
156 pRows[ nHeight + 1 ] = pRows[ nHeight ];
158 // read first three rows of bitmap color
159 for( i = 0; i < nWidth2; i++ )
161 pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
162 pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
163 pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
166 // do convolution
167 for( nY = 0; nY < nHeight; )
169 for( nX = 0; nX < nWidth; nX++ )
171 // first row
172 nSumR = ( pTmp = pKoeff[ 0 ] )[ ( pColor = pRowTmp1 + nX )->GetRed() ];
173 nSumG = pTmp[ pColor->GetGreen() ];
174 nSumB = pTmp[ pColor->GetBlue() ];
176 nSumR += ( pTmp = pKoeff[ 1 ] )[ ( ++pColor )->GetRed() ];
177 nSumG += pTmp[ pColor->GetGreen() ];
178 nSumB += pTmp[ pColor->GetBlue() ];
180 nSumR += ( pTmp = pKoeff[ 2 ] )[ ( ++pColor )->GetRed() ];
181 nSumG += pTmp[ pColor->GetGreen() ];
182 nSumB += pTmp[ pColor->GetBlue() ];
184 // second row
185 nSumR += ( pTmp = pKoeff[ 3 ] )[ ( pColor = pRowTmp2 + nX )->GetRed() ];
186 nSumG += pTmp[ pColor->GetGreen() ];
187 nSumB += pTmp[ pColor->GetBlue() ];
189 nSumR += ( pTmp = pKoeff[ 4 ] )[ ( ++pColor )->GetRed() ];
190 nSumG += pTmp[ pColor->GetGreen() ];
191 nSumB += pTmp[ pColor->GetBlue() ];
193 nSumR += ( pTmp = pKoeff[ 5 ] )[ ( ++pColor )->GetRed() ];
194 nSumG += pTmp[ pColor->GetGreen() ];
195 nSumB += pTmp[ pColor->GetBlue() ];
197 // third row
198 nSumR += ( pTmp = pKoeff[ 6 ] )[ ( pColor = pRowTmp3 + nX )->GetRed() ];
199 nSumG += pTmp[ pColor->GetGreen() ];
200 nSumB += pTmp[ pColor->GetBlue() ];
202 nSumR += ( pTmp = pKoeff[ 7 ] )[ ( ++pColor )->GetRed() ];
203 nSumG += pTmp[ pColor->GetGreen() ];
204 nSumB += pTmp[ pColor->GetBlue() ];
206 nSumR += ( pTmp = pKoeff[ 8 ] )[ ( ++pColor )->GetRed() ];
207 nSumG += pTmp[ pColor->GetGreen() ];
208 nSumB += pTmp[ pColor->GetBlue() ];
210 // calculate destination color
211 pWriteAcc->SetPixel( nY, nX, BitmapColor( (BYTE) MinMax( nSumR / nDivisor, 0, 255 ),
212 (BYTE) MinMax( nSumG / nDivisor, 0, 255 ),
213 (BYTE) MinMax( nSumB / nDivisor, 0, 255 ) ) );
216 if( ++nY < nHeight )
218 if( pRowTmp1 == pColRow1 )
219 pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
220 else if( pRowTmp1 == pColRow2 )
221 pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
222 else
223 pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
225 for( i = 0; i < nWidth2; i++ )
226 pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
230 delete[] pKoeff;
231 delete[] (BYTE*) pColRow1;
232 delete[] (BYTE*) pColRow2;
233 delete[] (BYTE*) pColRow3;
234 delete[] pColm;
235 delete[] pRows;
237 aNewBmp.ReleaseAccess( pWriteAcc );
239 bRet = TRUE;
242 ReleaseAccess( pReadAcc );
244 if( bRet )
246 const MapMode aMap( maPrefMapMode );
247 const Size aSize( maPrefSize );
249 *this = aNewBmp;
251 maPrefMapMode = aMap;
252 maPrefSize = aSize;
256 return bRet;
259 // -----------------------------------------------------------------------------
261 BOOL Bitmap::ImplMedianFilter( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
263 BitmapReadAccess* pReadAcc = AcquireReadAccess();
264 BOOL bRet = FALSE;
266 if( pReadAcc )
268 Bitmap aNewBmp( GetSizePixel(), 24 );
269 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
271 if( pWriteAcc )
273 const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
274 const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
275 long* pColm = new long[ nWidth2 ];
276 long* pRows = new long[ nHeight2 ];
277 BitmapColor* pColRow1 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
278 BitmapColor* pColRow2 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
279 BitmapColor* pColRow3 = (BitmapColor*) new BYTE[ sizeof( BitmapColor ) * nWidth2 ];
280 BitmapColor* pRowTmp1 = pColRow1;
281 BitmapColor* pRowTmp2 = pColRow2;
282 BitmapColor* pRowTmp3 = pColRow3;
283 BitmapColor* pColor;
284 long nY, nX, i;
285 long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
286 long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
287 long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
289 // create column LUT
290 for( i = 0; i < nWidth2; i++ )
291 pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
293 pColm[ nWidth + 1 ] = pColm[ nWidth ];
295 // create row LUT
296 for( i = 0; i < nHeight2; i++ )
297 pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
299 pRows[ nHeight + 1 ] = pRows[ nHeight ];
301 // read first three rows of bitmap color
302 if (nHeight2 > 2)
304 for( i = 0; i < nWidth2; i++ )
306 pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
307 pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
308 pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
312 // do median filtering
313 for( nY = 0; nY < nHeight; )
315 for( nX = 0; nX < nWidth; nX++ )
317 nR1 = ( pColor = pRowTmp1 + nX )->GetRed(), nG1 = pColor->GetGreen(), nB1 = pColor->GetBlue();
318 nR2 = ( ++pColor )->GetRed(), nG2 = pColor->GetGreen(), nB2 = pColor->GetBlue();
319 nR3 = ( ++pColor )->GetRed(), nG3 = pColor->GetGreen(), nB3 = pColor->GetBlue();
321 nR4 = ( pColor = pRowTmp2 + nX )->GetRed(), nG4 = pColor->GetGreen(), nB4 = pColor->GetBlue();
322 nR5 = ( ++pColor )->GetRed(), nG5 = pColor->GetGreen(), nB5 = pColor->GetBlue();
323 nR6 = ( ++pColor )->GetRed(), nG6 = pColor->GetGreen(), nB6 = pColor->GetBlue();
325 nR7 = ( pColor = pRowTmp3 + nX )->GetRed(), nG7 = pColor->GetGreen(), nB7 = pColor->GetBlue();
326 nR8 = ( ++pColor )->GetRed(), nG8 = pColor->GetGreen(), nB8 = pColor->GetBlue();
327 nR9 = ( ++pColor )->GetRed(), nG9 = pColor->GetGreen(), nB9 = pColor->GetBlue();
329 MNMX6( nR1, nR2, nR3, nR4, nR5, nR6 );
330 MNMX5( nR7, nR2, nR3, nR4, nR5 );
331 MNMX4( nR8, nR2, nR3, nR4 );
332 MNMX3( nR9, nR2, nR3 );
334 MNMX6( nG1, nG2, nG3, nG4, nG5, nG6 );
335 MNMX5( nG7, nG2, nG3, nG4, nG5 );
336 MNMX4( nG8, nG2, nG3, nG4 );
337 MNMX3( nG9, nG2, nG3 );
339 MNMX6( nB1, nB2, nB3, nB4, nB5, nB6 );
340 MNMX5( nB7, nB2, nB3, nB4, nB5 );
341 MNMX4( nB8, nB2, nB3, nB4 );
342 MNMX3( nB9, nB2, nB3 );
344 // set destination color
345 pWriteAcc->SetPixel( nY, nX, BitmapColor( (BYTE) nR2, (BYTE) nG2, (BYTE) nB2 ) );
348 if( ++nY < nHeight )
350 if( pRowTmp1 == pColRow1 )
351 pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
352 else if( pRowTmp1 == pColRow2 )
353 pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
354 else
355 pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
357 for( i = 0; i < nWidth2; i++ )
358 pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
362 delete[] (BYTE*) pColRow1;
363 delete[] (BYTE*) pColRow2;
364 delete[] (BYTE*) pColRow3;
365 delete[] pColm;
366 delete[] pRows;
368 aNewBmp.ReleaseAccess( pWriteAcc );
370 bRet = TRUE;
373 ReleaseAccess( pReadAcc );
375 if( bRet )
377 const MapMode aMap( maPrefMapMode );
378 const Size aSize( maPrefSize );
380 *this = aNewBmp;
382 maPrefMapMode = aMap;
383 maPrefSize = aSize;
387 return bRet;
390 // -----------------------------------------------------------------------------
392 BOOL Bitmap::ImplSobelGrey( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
394 BOOL bRet = ImplMakeGreyscales( 256 );
396 if( bRet )
398 bRet = FALSE;
400 BitmapReadAccess* pReadAcc = AcquireReadAccess();
402 if( pReadAcc )
404 Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
405 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
407 if( pWriteAcc )
409 BitmapColor aGrey( (BYTE) 0 );
410 const long nWidth = pWriteAcc->Width();
411 const long nHeight = pWriteAcc->Height();
412 const long nMask111 = -1, nMask121 = 0, nMask131 = 1;
413 const long nMask211 = -2, nMask221 = 0, nMask231 = 2;
414 const long nMask311 = -1, nMask321 = 0, nMask331 = 1;
415 const long nMask112 = 1, nMask122 = 2, nMask132 = 1;
416 const long nMask212 = 0, nMask222 = 0, nMask232 = 0;
417 const long nMask312 = -1, nMask322 = -2, nMask332 = -1;
418 long nGrey11, nGrey12, nGrey13;
419 long nGrey21, nGrey22, nGrey23;
420 long nGrey31, nGrey32, nGrey33;
421 long* pHMap = new long[ nWidth + 2 ];
422 long* pVMap = new long[ nHeight + 2 ];
423 long nX, nY, nSum1, nSum2;
425 // fill mapping tables
426 pHMap[ 0 ] = 0;
427 for( nX = 1; nX <= nWidth; nX++ )
428 pHMap[ nX ] = nX - 1;
429 pHMap[ nWidth + 1 ] = nWidth - 1;
431 pVMap[ 0 ] = 0;
432 for( nY = 1; nY <= nHeight; nY++ )
433 pVMap[ nY ] = nY - 1;
434 pVMap[ nHeight + 1 ] = nHeight - 1;
436 for( nY = 0; nY < nHeight ; nY++ )
438 nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
439 nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
440 nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
441 nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
442 nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
443 nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
444 nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
445 nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
446 nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
448 for( nX = 0; nX < nWidth; nX++ )
450 nSum1 = nSum2 = 0;
452 nSum1 += nMask111 * nGrey11;
453 nSum2 += nMask112 * nGrey11;
455 nSum1 += nMask121 * nGrey12;
456 nSum2 += nMask122 * nGrey12;
458 nSum1 += nMask131 * nGrey13;
459 nSum2 += nMask132 * nGrey13;
461 nSum1 += nMask211 * nGrey21;
462 nSum2 += nMask212 * nGrey21;
464 nSum1 += nMask221 * nGrey22;
465 nSum2 += nMask222 * nGrey22;
467 nSum1 += nMask231 * nGrey23;
468 nSum2 += nMask232 * nGrey23;
470 nSum1 += nMask311 * nGrey31;
471 nSum2 += nMask312 * nGrey31;
473 nSum1 += nMask321 * nGrey32;
474 nSum2 += nMask322 * nGrey32;
476 nSum1 += nMask331 * nGrey33;
477 nSum2 += nMask332 * nGrey33;
479 nSum1 = (long) sqrt( (double)( nSum1 * nSum1 + nSum2 * nSum2 ) );
480 aGrey.SetIndex( ~(BYTE) VOS_BOUND( nSum1, 0, 255 ) );
481 pWriteAcc->SetPixel( nY, nX, aGrey );
483 if( nX < ( nWidth - 1 ) )
485 const long nNextX = pHMap[ nX + 3 ];
487 nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
488 nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
489 nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
494 delete[] pHMap;
495 delete[] pVMap;
496 aNewBmp.ReleaseAccess( pWriteAcc );
497 bRet = TRUE;
500 ReleaseAccess( pReadAcc );
502 if( bRet )
504 const MapMode aMap( maPrefMapMode );
505 const Size aSize( maPrefSize );
507 *this = aNewBmp;
509 maPrefMapMode = aMap;
510 maPrefSize = aSize;
515 return bRet;
518 // -----------------------------------------------------------------------------
520 BOOL Bitmap::ImplEmbossGrey( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
522 BOOL bRet = ImplMakeGreyscales( 256 );
524 if( bRet )
526 bRet = FALSE;
528 BitmapReadAccess* pReadAcc = AcquireReadAccess();
530 if( pReadAcc )
532 Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
533 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
535 if( pWriteAcc )
537 BitmapColor aGrey( (BYTE) 0 );
538 const long nWidth = pWriteAcc->Width();
539 const long nHeight = pWriteAcc->Height();
540 long nGrey11, nGrey12, nGrey13;
541 long nGrey21, nGrey22, nGrey23;
542 long nGrey31, nGrey32, nGrey33;
543 double fAzim = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
544 ( pFilterParam->maEmbossAngles.mnAzimuthAngle100 * 0.01 ) : 0.0 ) * F_PI180;
545 double fElev = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
546 ( pFilterParam->maEmbossAngles.mnElevationAngle100 * 0.01 ) : 90.0 ) * F_PI180;
547 long* pHMap = new long[ nWidth + 2 ];
548 long* pVMap = new long[ nHeight + 2 ];
549 long nX, nY, nNx, nNy, nDotL;
550 const long nLx = FRound( cos( fAzim ) * cos( fElev ) * 255.0 );
551 const long nLy = FRound( sin( fAzim ) * cos( fElev ) * 255.0 );
552 const long nLz = FRound( sin( fElev ) * 255.0 );
553 const long nZ2 = ( ( 6 * 255 ) / 4 ) * ( ( 6 * 255 ) / 4 );
554 const long nNzLz = ( ( 6 * 255 ) / 4 ) * nLz;
555 const BYTE cLz = (BYTE) VOS_BOUND( nLz, 0, 255 );
557 // fill mapping tables
558 pHMap[ 0 ] = 0;
559 for( nX = 1; nX <= nWidth; nX++ )
560 pHMap[ nX ] = nX - 1;
561 pHMap[ nWidth + 1 ] = nWidth - 1;
563 pVMap[ 0 ] = 0;
564 for( nY = 1; nY <= nHeight; nY++ )
565 pVMap[ nY ] = nY - 1;
566 pVMap[ nHeight + 1 ] = nHeight - 1;
568 for( nY = 0; nY < nHeight ; nY++ )
570 nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
571 nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
572 nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
573 nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
574 nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
575 nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
576 nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
577 nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
578 nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
580 for( nX = 0; nX < nWidth; nX++ )
582 nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
583 nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
585 if( !nNx && !nNy )
586 aGrey.SetIndex( cLz );
587 else if( ( nDotL = nNx * nLx + nNy * nLy +nNzLz ) < 0 )
588 aGrey.SetIndex( 0 );
589 else
591 const double fGrey = nDotL / sqrt( (double)(nNx * nNx + nNy * nNy + nZ2) );
592 aGrey.SetIndex( (BYTE) VOS_BOUND( fGrey, 0, 255 ) );
595 pWriteAcc->SetPixel( nY, nX, aGrey );
597 if( nX < ( nWidth - 1 ) )
599 const long nNextX = pHMap[ nX + 3 ];
601 nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
602 nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
603 nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
608 delete[] pHMap;
609 delete[] pVMap;
610 aNewBmp.ReleaseAccess( pWriteAcc );
611 bRet = TRUE;
614 ReleaseAccess( pReadAcc );
616 if( bRet )
618 const MapMode aMap( maPrefMapMode );
619 const Size aSize( maPrefSize );
621 *this = aNewBmp;
623 maPrefMapMode = aMap;
624 maPrefSize = aSize;
629 return bRet;
632 // -----------------------------------------------------------------------------
634 BOOL Bitmap::ImplSolarize( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
636 BOOL bRet = FALSE;
637 BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
639 if( pWriteAcc )
641 const BYTE cThreshold = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SOLARIZE ) ?
642 pFilterParam->mcSolarGreyThreshold : 128;
644 if( pWriteAcc->HasPalette() )
646 const BitmapPalette& rPal = pWriteAcc->GetPalette();
648 for( USHORT i = 0, nCount = rPal.GetEntryCount(); i < nCount; i++ )
650 if( rPal[ i ].GetLuminance() >= cThreshold )
652 BitmapColor aCol( rPal[ i ] );
653 pWriteAcc->SetPaletteColor( i, aCol.Invert() );
657 else
659 BitmapColor aCol;
660 const long nWidth = pWriteAcc->Width();
661 const long nHeight = pWriteAcc->Height();
663 for( long nY = 0; nY < nHeight ; nY++ )
665 for( long nX = 0; nX < nWidth; nX++ )
667 aCol = pWriteAcc->GetPixel( nY, nX );
669 if( aCol.GetLuminance() >= cThreshold )
670 pWriteAcc->SetPixel( nY, nX, aCol.Invert() );
675 ReleaseAccess( pWriteAcc );
676 bRet = TRUE;
679 return bRet;
682 // -----------------------------------------------------------------------------
684 BOOL Bitmap::ImplSepia( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
686 BitmapReadAccess* pReadAcc = AcquireReadAccess();
687 BOOL bRet = FALSE;
689 if( pReadAcc )
691 long nSepiaPercent = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SEPIA ) ?
692 pFilterParam->mcSolarGreyThreshold : 10;
693 const long nSepia = 10000 - 100 * VOS_BOUND( nSepiaPercent, 0, 100 );
694 BitmapPalette aSepiaPal( 256 );
696 DBG_ASSERT( nSepiaPercent <= 100, "Bitmap::ImplSepia(): sepia value out of range; defaulting to 100%" );
698 for( USHORT i = 0; i < 256; i++ )
700 BitmapColor& rCol = aSepiaPal[ i ];
701 const BYTE cSepiaValue = (BYTE) ( ( nSepia * i ) / 10000 );
703 rCol.SetRed( (BYTE) i );
704 rCol.SetGreen( cSepiaValue );
705 rCol.SetBlue( cSepiaValue );
708 Bitmap aNewBmp( GetSizePixel(), 8, &aSepiaPal );
709 BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
711 if( pWriteAcc )
713 BitmapColor aCol( (BYTE) 0 );
714 const long nWidth = pWriteAcc->Width();
715 const long nHeight = pWriteAcc->Height();
717 if( pReadAcc->HasPalette() )
719 for( long nY = 0; nY < nHeight ; nY++ )
721 const USHORT nPalCount = pReadAcc->GetPaletteEntryCount();
722 BYTE* pIndexMap = new BYTE[ nPalCount ];
724 for( USHORT i = 0; i < nPalCount; i++ )
725 pIndexMap[ i ] = pReadAcc->GetPaletteColor( i ).GetLuminance();
727 for( long nX = 0; nX < nWidth; nX++ )
729 aCol.SetIndex( pIndexMap[ pReadAcc->GetPixel( nY, nX ).GetIndex() ] );
730 pWriteAcc->SetPixel( nY, nX, aCol );
733 delete[] pIndexMap;
736 else
738 for( long nY = 0; nY < nHeight ; nY++ )
740 for( long nX = 0; nX < nWidth; nX++ )
742 aCol.SetIndex( pReadAcc->GetPixel( nY, nX ).GetLuminance() );
743 pWriteAcc->SetPixel( nY, nX, aCol );
748 aNewBmp.ReleaseAccess( pWriteAcc );
749 bRet = TRUE;
752 ReleaseAccess( pReadAcc );
754 if( bRet )
756 const MapMode aMap( maPrefMapMode );
757 const Size aSize( maPrefSize );
759 *this = aNewBmp;
761 maPrefMapMode = aMap;
762 maPrefSize = aSize;
766 return bRet;
769 // -----------------------------------------------------------------------------
771 BOOL Bitmap::ImplMosaic( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
773 ULONG nTileWidth = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
774 pFilterParam->maMosaicTileSize.mnTileWidth : 4;
775 ULONG nTileHeight = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
776 pFilterParam->maMosaicTileSize.mnTileHeight : 4;
777 BOOL bRet = FALSE;
779 if( !nTileWidth )
780 nTileWidth = 1;
782 if( !nTileHeight )
783 nTileHeight = 1;
785 if( nTileWidth > 1 || nTileHeight > 1 )
787 Bitmap* pNewBmp;
788 BitmapReadAccess* pReadAcc;
789 BitmapWriteAccess* pWriteAcc;
791 if( GetBitCount() > 8 )
793 pNewBmp = NULL;
794 pReadAcc = pWriteAcc = AcquireWriteAccess();
796 else
798 pNewBmp = new Bitmap( GetSizePixel(), 24 );
799 pReadAcc = AcquireReadAccess();
800 pWriteAcc = pNewBmp->AcquireWriteAccess();
803 if( pReadAcc && pWriteAcc )
805 BitmapColor aCol;
806 long nWidth = pReadAcc->Width();
807 long nHeight = pReadAcc->Height();
808 long nX, nY, nX1, nX2, nY1, nY2, nSumR, nSumG, nSumB;
809 double fArea_1;
811 nY1 = 0; nY2 = nTileHeight - 1;
813 if( nY2 >= nHeight )
814 nY2 = nHeight - 1;
818 nX1 = 0; nX2 = nTileWidth - 1;
820 if( nX2 >= nWidth )
821 nX2 = nWidth - 1;
823 fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
825 if( !pNewBmp )
829 for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
831 for( nX = nX1; nX <= nX2; nX++ )
833 aCol = pReadAcc->GetPixel( nY, nX );
834 nSumR += aCol.GetRed();
835 nSumG += aCol.GetGreen();
836 nSumB += aCol.GetBlue();
840 aCol.SetRed( (BYTE) ( nSumR * fArea_1 ) );
841 aCol.SetGreen( (BYTE) ( nSumG * fArea_1 ) );
842 aCol.SetBlue( (BYTE) ( nSumB * fArea_1 ) );
844 for( nY = nY1; nY <= nY2; nY++ )
845 for( nX = nX1; nX <= nX2; nX++ )
846 pWriteAcc->SetPixel( nY, nX, aCol );
848 nX1 += nTileWidth; nX2 += nTileWidth;
850 if( nX2 >= nWidth )
852 nX2 = nWidth - 1;
853 fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
856 while( nX1 < nWidth );
858 else
862 for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
864 for( nX = nX1; nX <= nX2; nX++ )
866 const BitmapColor& rCol = pReadAcc->GetPaletteColor( (BYTE) pReadAcc->GetPixel( nY, nX ) );
867 nSumR += rCol.GetRed();
868 nSumG += rCol.GetGreen();
869 nSumB += rCol.GetBlue();
873 aCol.SetRed( (BYTE) ( nSumR * fArea_1 ) );
874 aCol.SetGreen( (BYTE) ( nSumG * fArea_1 ) );
875 aCol.SetBlue( (BYTE) ( nSumB * fArea_1 ) );
877 for( nY = nY1; nY <= nY2; nY++ )
878 for( nX = nX1; nX <= nX2; nX++ )
879 pWriteAcc->SetPixel( nY, nX, aCol );
881 nX1 += nTileWidth; nX2 += nTileWidth;
883 if( nX2 >= nWidth )
885 nX2 = nWidth - 1;
886 fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
889 while( nX1 < nWidth );
892 nY1 += nTileHeight; nY2 += nTileHeight;
894 if( nY2 >= nHeight )
895 nY2 = nHeight - 1;
897 while( nY1 < nHeight );
899 bRet = TRUE;
902 ReleaseAccess( pReadAcc );
904 if( pNewBmp )
906 pNewBmp->ReleaseAccess( pWriteAcc );
908 if( bRet )
910 const MapMode aMap( maPrefMapMode );
911 const Size aSize( maPrefSize );
913 *this = *pNewBmp;
915 maPrefMapMode = aMap;
916 maPrefSize = aSize;
919 delete pNewBmp;
922 else
923 bRet = TRUE;
925 return bRet;
928 // -----------------------------------------------------------------------------
930 struct PopArtEntry
932 sal_uInt32 mnIndex;
933 sal_uInt32 mnCount;
936 // ------------------------------------------------------------------------
938 extern "C" int __LOADONCALLAPI ImplPopArtCmpFnc( const void* p1, const void* p2 )
940 int nRet;
942 if( ( (PopArtEntry*) p1 )->mnCount < ( (PopArtEntry*) p2 )->mnCount )
943 nRet = 1;
944 else if( ( (PopArtEntry*) p1 )->mnCount == ( (PopArtEntry*) p2 )->mnCount )
945 nRet = 0;
946 else
947 nRet = -1;
949 return nRet;
952 // ------------------------------------------------------------------------
954 BOOL Bitmap::ImplPopArt( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
956 BOOL bRet = ( GetBitCount() > 8 ) ? Convert( BMP_CONVERSION_8BIT_COLORS ) : TRUE;
958 if( bRet )
960 bRet = FALSE;
962 BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
964 if( pWriteAcc )
966 const long nWidth = pWriteAcc->Width();
967 const long nHeight = pWriteAcc->Height();
968 const ULONG nEntryCount = 1 << pWriteAcc->GetBitCount();
969 ULONG n;
970 PopArtEntry* pPopArtTable = new PopArtEntry[ nEntryCount ];
972 for( n = 0; n < nEntryCount; n++ )
974 PopArtEntry& rEntry = pPopArtTable[ n ];
975 rEntry.mnIndex = (sal_uInt16) n;
976 rEntry.mnCount = 0;
979 // get pixel count for each palette entry
980 for( long nY = 0; nY < nHeight ; nY++ )
981 for( long nX = 0; nX < nWidth; nX++ )
982 pPopArtTable[ pWriteAcc->GetPixel( nY, nX ).GetIndex() ].mnCount++;
984 // sort table
985 qsort( pPopArtTable, nEntryCount, sizeof( PopArtEntry ), ImplPopArtCmpFnc );
987 // get last used entry
988 ULONG nFirstEntry;
989 ULONG nLastEntry = 0;
991 for( n = 0; n < nEntryCount; n++ )
992 if( pPopArtTable[ n ].mnCount )
993 nLastEntry = n;
995 // rotate palette (one entry)
996 const BitmapColor aFirstCol( pWriteAcc->GetPaletteColor( sal::static_int_cast<USHORT>(pPopArtTable[ 0 ].mnIndex) ) );
997 for( nFirstEntry = 0; nFirstEntry < nLastEntry; nFirstEntry++ )
999 pWriteAcc->SetPaletteColor( sal::static_int_cast<USHORT>(pPopArtTable[ nFirstEntry ].mnIndex),
1000 pWriteAcc->GetPaletteColor( sal::static_int_cast<USHORT>(pPopArtTable[ nFirstEntry + 1 ].mnIndex) ) );
1002 pWriteAcc->SetPaletteColor( sal::static_int_cast<USHORT>(pPopArtTable[ nLastEntry ].mnIndex), aFirstCol );
1004 // cleanup
1005 delete[] pPopArtTable;
1006 ReleaseAccess( pWriteAcc );
1007 bRet = TRUE;
1011 return bRet;