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: bitmap4.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 <vos/macros.hxx>
36 #include <vcl/bmpacc.hxx>
37 #include <vcl/bitmap.hxx>
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);
55 BOOL
Bitmap::Filter( BmpFilter eFilter
, const BmpFilterParam
* pFilterParam
, const Link
* pProgress
)
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
);
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
);
75 case( BMP_FILTER_REMOVENOISE
):
76 bRet
= ImplMedianFilter( pFilterParam
, pProgress
);
79 case( BMP_FILTER_SOBEL_GREY
):
80 bRet
= ImplSobelGrey( pFilterParam
, pProgress
);
83 case( BMP_FILTER_SOLARIZE
):
84 bRet
= ImplSolarize( pFilterParam
, pProgress
);
87 case( BMP_FILTER_SEPIA
):
88 bRet
= ImplSepia( pFilterParam
, pProgress
);
91 case( BMP_FILTER_MOSAIC
):
92 bRet
= ImplMosaic( pFilterParam
, pProgress
);
95 case( BMP_FILTER_EMBOSS_GREY
):
96 bRet
= ImplEmbossGrey( pFilterParam
, pProgress
);
99 case( BMP_FILTER_POPART
):
100 bRet
= ImplPopArt( pFilterParam
, pProgress
);
104 DBG_ERROR( "Bitmap::Convert(): Unsupported filter" );
111 // -----------------------------------------------------------------------------
113 BOOL
Bitmap::ImplConvolute3( const long* pMatrix
, long nDivisor
,
114 const BmpFilterParam
* /*pFilterParam*/, const Link
* /*pProgress*/ )
116 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
121 Bitmap
aNewBmp( GetSizePixel(), 24 );
122 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
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
;
137 long nY
, nX
, i
, nSumR
, nSumG
, nSumB
, nMatrixVal
, nTmp
;
138 long (*pKoeff
)[ 256 ] = new long[ 9 ][ 256 ];
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
;
147 for( i
= 0; i
< nWidth2
; i
++ )
148 pColm
[ i
] = ( i
> 0 ) ? ( i
- 1 ) : 0;
150 pColm
[ nWidth
+ 1 ] = pColm
[ nWidth
];
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
] );
167 for( nY
= 0; nY
< nHeight
; )
169 for( nX
= 0; nX
< nWidth
; nX
++ )
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() ];
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() ];
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 ) ) );
218 if( pRowTmp1
== pColRow1
)
219 pRowTmp1
= pColRow2
, pRowTmp2
= pColRow3
, pRowTmp3
= pColRow1
;
220 else if( pRowTmp1
== pColRow2
)
221 pRowTmp1
= pColRow3
, pRowTmp2
= pColRow1
, pRowTmp3
= pColRow2
;
223 pRowTmp1
= pColRow1
, pRowTmp2
= pColRow2
, pRowTmp3
= pColRow3
;
225 for( i
= 0; i
< nWidth2
; i
++ )
226 pRowTmp3
[ i
] = pReadAcc
->GetColor( pRows
[ nY
+ 2 ], pColm
[ i
] );
231 delete[] (BYTE
*) pColRow1
;
232 delete[] (BYTE
*) pColRow2
;
233 delete[] (BYTE
*) pColRow3
;
237 aNewBmp
.ReleaseAccess( pWriteAcc
);
242 ReleaseAccess( pReadAcc
);
246 const MapMode
aMap( maPrefMapMode
);
247 const Size
aSize( maPrefSize
);
251 maPrefMapMode
= aMap
;
259 // -----------------------------------------------------------------------------
261 BOOL
Bitmap::ImplMedianFilter( const BmpFilterParam
* /*pFilterParam*/, const Link
* /*pProgress*/ )
263 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
268 Bitmap
aNewBmp( GetSizePixel(), 24 );
269 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
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
;
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
;
290 for( i
= 0; i
< nWidth2
; i
++ )
291 pColm
[ i
] = ( i
> 0 ) ? ( i
- 1 ) : 0;
293 pColm
[ nWidth
+ 1 ] = pColm
[ nWidth
];
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
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
) );
350 if( pRowTmp1
== pColRow1
)
351 pRowTmp1
= pColRow2
, pRowTmp2
= pColRow3
, pRowTmp3
= pColRow1
;
352 else if( pRowTmp1
== pColRow2
)
353 pRowTmp1
= pColRow3
, pRowTmp2
= pColRow1
, pRowTmp3
= pColRow2
;
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
;
368 aNewBmp
.ReleaseAccess( pWriteAcc
);
373 ReleaseAccess( pReadAcc
);
377 const MapMode
aMap( maPrefMapMode
);
378 const Size
aSize( maPrefSize
);
382 maPrefMapMode
= aMap
;
390 // -----------------------------------------------------------------------------
392 BOOL
Bitmap::ImplSobelGrey( const BmpFilterParam
* /*pFilterParam*/, const Link
* /*pProgress*/ )
394 BOOL bRet
= ImplMakeGreyscales( 256 );
400 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
404 Bitmap
aNewBmp( GetSizePixel(), 8, &pReadAcc
->GetPalette() );
405 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
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
427 for( nX
= 1; nX
<= nWidth
; nX
++ )
428 pHMap
[ nX
] = nX
- 1;
429 pHMap
[ nWidth
+ 1 ] = nWidth
- 1;
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
++ )
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();
496 aNewBmp
.ReleaseAccess( pWriteAcc
);
500 ReleaseAccess( pReadAcc
);
504 const MapMode
aMap( maPrefMapMode
);
505 const Size
aSize( maPrefSize
);
509 maPrefMapMode
= aMap
;
518 // -----------------------------------------------------------------------------
520 BOOL
Bitmap::ImplEmbossGrey( const BmpFilterParam
* pFilterParam
, const Link
* /*pProgress*/ )
522 BOOL bRet
= ImplMakeGreyscales( 256 );
528 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
532 Bitmap
aNewBmp( GetSizePixel(), 8, &pReadAcc
->GetPalette() );
533 BitmapWriteAccess
* pWriteAcc
= aNewBmp
.AcquireWriteAccess();
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
559 for( nX
= 1; nX
<= nWidth
; nX
++ )
560 pHMap
[ nX
] = nX
- 1;
561 pHMap
[ nWidth
+ 1 ] = nWidth
- 1;
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
;
586 aGrey
.SetIndex( cLz
);
587 else if( ( nDotL
= nNx
* nLx
+ nNy
* nLy
+nNzLz
) < 0 )
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();
610 aNewBmp
.ReleaseAccess( pWriteAcc
);
614 ReleaseAccess( pReadAcc
);
618 const MapMode
aMap( maPrefMapMode
);
619 const Size
aSize( maPrefSize
);
623 maPrefMapMode
= aMap
;
632 // -----------------------------------------------------------------------------
634 BOOL
Bitmap::ImplSolarize( const BmpFilterParam
* pFilterParam
, const Link
* /*pProgress*/ )
637 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
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() );
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
);
682 // -----------------------------------------------------------------------------
684 BOOL
Bitmap::ImplSepia( const BmpFilterParam
* pFilterParam
, const Link
* /*pProgress*/ )
686 BitmapReadAccess
* pReadAcc
= AcquireReadAccess();
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();
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
);
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
);
752 ReleaseAccess( pReadAcc
);
756 const MapMode
aMap( maPrefMapMode
);
757 const Size
aSize( maPrefSize
);
761 maPrefMapMode
= aMap
;
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;
785 if( nTileWidth
> 1 || nTileHeight
> 1 )
788 BitmapReadAccess
* pReadAcc
;
789 BitmapWriteAccess
* pWriteAcc
;
791 if( GetBitCount() > 8 )
794 pReadAcc
= pWriteAcc
= AcquireWriteAccess();
798 pNewBmp
= new Bitmap( GetSizePixel(), 24 );
799 pReadAcc
= AcquireReadAccess();
800 pWriteAcc
= pNewBmp
->AcquireWriteAccess();
803 if( pReadAcc
&& pWriteAcc
)
806 long nWidth
= pReadAcc
->Width();
807 long nHeight
= pReadAcc
->Height();
808 long nX
, nY
, nX1
, nX2
, nY1
, nY2
, nSumR
, nSumG
, nSumB
;
811 nY1
= 0; nY2
= nTileHeight
- 1;
818 nX1
= 0; nX2
= nTileWidth
- 1;
823 fArea_1
= 1.0 / ( ( nX2
- nX1
+ 1 ) * ( nY2
- nY1
+ 1 ) );
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
;
853 fArea_1
= 1.0 / ( ( nX2
- nX1
+ 1 ) * ( nY2
- nY1
+ 1 ) );
856 while( nX1
< nWidth
);
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
;
886 fArea_1
= 1.0 / ( ( nX2
- nX1
+ 1 ) * ( nY2
- nY1
+ 1 ) );
889 while( nX1
< nWidth
);
892 nY1
+= nTileHeight
; nY2
+= nTileHeight
;
897 while( nY1
< nHeight
);
902 ReleaseAccess( pReadAcc
);
906 pNewBmp
->ReleaseAccess( pWriteAcc
);
910 const MapMode
aMap( maPrefMapMode
);
911 const Size
aSize( maPrefSize
);
915 maPrefMapMode
= aMap
;
928 // -----------------------------------------------------------------------------
936 // ------------------------------------------------------------------------
938 extern "C" int __LOADONCALLAPI
ImplPopArtCmpFnc( const void* p1
, const void* p2
)
942 if( ( (PopArtEntry
*) p1
)->mnCount
< ( (PopArtEntry
*) p2
)->mnCount
)
944 else if( ( (PopArtEntry
*) p1
)->mnCount
== ( (PopArtEntry
*) p2
)->mnCount
)
952 // ------------------------------------------------------------------------
954 BOOL
Bitmap::ImplPopArt( const BmpFilterParam
* /*pFilterParam*/, const Link
* /*pProgress*/ )
956 BOOL bRet
= ( GetBitCount() > 8 ) ? Convert( BMP_CONVERSION_8BIT_COLORS
) : TRUE
;
962 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
966 const long nWidth
= pWriteAcc
->Width();
967 const long nHeight
= pWriteAcc
->Height();
968 const ULONG nEntryCount
= 1 << pWriteAcc
->GetBitCount();
970 PopArtEntry
* pPopArtTable
= new PopArtEntry
[ nEntryCount
];
972 for( n
= 0; n
< nEntryCount
; n
++ )
974 PopArtEntry
& rEntry
= pPopArtTable
[ n
];
975 rEntry
.mnIndex
= (sal_uInt16
) n
;
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
++;
985 qsort( pPopArtTable
, nEntryCount
, sizeof( PopArtEntry
), ImplPopArtCmpFnc
);
987 // get last used entry
989 ULONG nLastEntry
= 0;
991 for( n
= 0; n
< nEntryCount
; n
++ )
992 if( pPopArtTable
[ n
].mnCount
)
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
);
1005 delete[] pPopArtTable
;
1006 ReleaseAccess( pWriteAcc
);