Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <stdlib.h>
31 : : #include <vcl/bmpacc.hxx>
32 : : #include <vcl/bitmap.hxx>
33 : :
34 : : // -----------
35 : : // - Defines -
36 : : // -----------
37 : :
38 : : #define S2(a,b) { register long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } }
39 : : #define MN3(a,b,c) S2(a,b); S2(a,c);
40 : : #define MX3(a,b,c) S2(b,c); S2(a,c);
41 : : #define MNMX3(a,b,c) MX3(a,b,c); S2(a,b);
42 : : #define MNMX4(a,b,c,d) S2(a,b); S2(c,d); S2(a,c); S2(b,d);
43 : : #define MNMX5(a,b,c,d,e) S2(a,b); S2(c,d); MN3(a,c,e); MX3(b,d,e);
44 : : #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);
45 : :
46 : : // ----------
47 : : // - Bitmap -
48 : : // ----------
49 : :
50 : 0 : sal_Bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
51 : : {
52 : 0 : sal_Bool bRet = sal_False;
53 : :
54 [ # # # # : 0 : switch( eFilter )
# # # # #
# ]
55 : : {
56 : : case( BMP_FILTER_SMOOTH ):
57 : : {
58 : : // Blur for positive values of mnRadius
59 [ # # ]: 0 : if (pFilterParam->mnRadius > 0.0)
60 : : {
61 : 0 : bRet = ImplSeparableBlurFilter(pFilterParam->mnRadius);
62 : : }
63 : : // Unsharpen Mask for negative values of mnRadius
64 [ # # ]: 0 : else if (pFilterParam->mnRadius < 0.0)
65 : : {
66 : 0 : bRet = ImplSeparableUnsharpenFilter(pFilterParam->mnRadius);
67 : : }
68 : : else
69 : : {
70 : 0 : bRet = sal_False;
71 : : }
72 : : }
73 : 0 : break;
74 : :
75 : : case( BMP_FILTER_SHARPEN ):
76 : : {
77 : 0 : const long pSharpenMatrix[] = { -1, -1, -1, -1, 16, -1, -1, -1, -1 };
78 [ # # ]: 0 : bRet = ImplConvolute3( &pSharpenMatrix[ 0 ], 8, pFilterParam, pProgress );
79 : : }
80 : 0 : break;
81 : :
82 : : case( BMP_FILTER_REMOVENOISE ):
83 : 0 : bRet = ImplMedianFilter( pFilterParam, pProgress );
84 : 0 : break;
85 : :
86 : : case( BMP_FILTER_SOBEL_GREY ):
87 : 0 : bRet = ImplSobelGrey( pFilterParam, pProgress );
88 : 0 : break;
89 : :
90 : : case( BMP_FILTER_SOLARIZE ):
91 : 0 : bRet = ImplSolarize( pFilterParam, pProgress );
92 : 0 : break;
93 : :
94 : : case( BMP_FILTER_SEPIA ):
95 : 0 : bRet = ImplSepia( pFilterParam, pProgress );
96 : 0 : break;
97 : :
98 : : case( BMP_FILTER_MOSAIC ):
99 : 0 : bRet = ImplMosaic( pFilterParam, pProgress );
100 : 0 : break;
101 : :
102 : : case( BMP_FILTER_EMBOSS_GREY ):
103 : 0 : bRet = ImplEmbossGrey( pFilterParam, pProgress );
104 : 0 : break;
105 : :
106 : : case( BMP_FILTER_POPART ):
107 : 0 : bRet = ImplPopArt( pFilterParam, pProgress );
108 : 0 : break;
109 : :
110 : : default:
111 : : OSL_FAIL( "Bitmap::Convert(): Unsupported filter" );
112 : 0 : break;
113 : : }
114 : :
115 : 0 : return bRet;
116 : : }
117 : :
118 : : // -----------------------------------------------------------------------------
119 : :
120 : 0 : sal_Bool Bitmap::ImplConvolute3( const long* pMatrix, long nDivisor,
121 : : const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
122 : : {
123 : 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
124 : 0 : sal_Bool bRet = sal_False;
125 : :
126 [ # # ]: 0 : if( pReadAcc )
127 : : {
128 [ # # ][ # # ]: 0 : Bitmap aNewBmp( GetSizePixel(), 24 );
129 [ # # ]: 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
130 : :
131 [ # # ]: 0 : if( pWriteAcc )
132 : : {
133 : 0 : const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
134 : 0 : const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
135 [ # # ]: 0 : long* pColm = new long[ nWidth2 ];
136 [ # # ]: 0 : long* pRows = new long[ nHeight2 ];
137 [ # # ]: 0 : BitmapColor* pColRow1 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
138 [ # # ]: 0 : BitmapColor* pColRow2 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
139 [ # # ]: 0 : BitmapColor* pColRow3 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
140 : 0 : BitmapColor* pRowTmp1 = pColRow1;
141 : 0 : BitmapColor* pRowTmp2 = pColRow2;
142 : 0 : BitmapColor* pRowTmp3 = pColRow3;
143 : : BitmapColor* pColor;
144 : : long nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
145 [ # # ]: 0 : long (*pKoeff)[ 256 ] = new long[ 9 ][ 256 ];
146 : : long* pTmp;
147 : :
148 : : // create LUT of products of matrix value and possible color component values
149 [ # # ]: 0 : for( nY = 0; nY < 9; nY++ )
150 [ # # ]: 0 : for( nX = nTmp = 0, nMatrixVal = pMatrix[ nY ]; nX < 256; nX++, nTmp += nMatrixVal )
151 : 0 : pKoeff[ nY ][ nX ] = nTmp;
152 : :
153 : : // create column LUT
154 [ # # ]: 0 : for( i = 0; i < nWidth2; i++ )
155 [ # # ]: 0 : pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
156 : :
157 : 0 : pColm[ nWidth + 1 ] = pColm[ nWidth ];
158 : :
159 : : // create row LUT
160 [ # # ]: 0 : for( i = 0; i < nHeight2; i++ )
161 [ # # ]: 0 : pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
162 : :
163 : 0 : pRows[ nHeight + 1 ] = pRows[ nHeight ];
164 : :
165 : : // read first three rows of bitmap color
166 [ # # ]: 0 : for( i = 0; i < nWidth2; i++ )
167 : : {
168 [ # # ]: 0 : pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
169 [ # # ]: 0 : pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
170 [ # # ]: 0 : pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
171 : : }
172 : :
173 : : // do convolution
174 [ # # ]: 0 : for( nY = 0; nY < nHeight; )
175 : : {
176 [ # # ]: 0 : for( nX = 0; nX < nWidth; nX++ )
177 : : {
178 : : // first row
179 : 0 : nSumR = ( pTmp = pKoeff[ 0 ] )[ ( pColor = pRowTmp1 + nX )->GetRed() ];
180 : 0 : nSumG = pTmp[ pColor->GetGreen() ];
181 : 0 : nSumB = pTmp[ pColor->GetBlue() ];
182 : :
183 : 0 : nSumR += ( pTmp = pKoeff[ 1 ] )[ ( ++pColor )->GetRed() ];
184 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
185 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
186 : :
187 : 0 : nSumR += ( pTmp = pKoeff[ 2 ] )[ ( ++pColor )->GetRed() ];
188 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
189 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
190 : :
191 : : // second row
192 : 0 : nSumR += ( pTmp = pKoeff[ 3 ] )[ ( pColor = pRowTmp2 + nX )->GetRed() ];
193 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
194 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
195 : :
196 : 0 : nSumR += ( pTmp = pKoeff[ 4 ] )[ ( ++pColor )->GetRed() ];
197 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
198 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
199 : :
200 : 0 : nSumR += ( pTmp = pKoeff[ 5 ] )[ ( ++pColor )->GetRed() ];
201 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
202 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
203 : :
204 : : // third row
205 : 0 : nSumR += ( pTmp = pKoeff[ 6 ] )[ ( pColor = pRowTmp3 + nX )->GetRed() ];
206 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
207 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
208 : :
209 : 0 : nSumR += ( pTmp = pKoeff[ 7 ] )[ ( ++pColor )->GetRed() ];
210 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
211 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
212 : :
213 : 0 : nSumR += ( pTmp = pKoeff[ 8 ] )[ ( ++pColor )->GetRed() ];
214 : 0 : nSumG += pTmp[ pColor->GetGreen() ];
215 : 0 : nSumB += pTmp[ pColor->GetBlue() ];
216 : :
217 : : // calculate destination color
218 : 0 : pWriteAcc->SetPixel( nY, nX, BitmapColor( (sal_uInt8) MinMax( nSumR / nDivisor, 0, 255 ),
219 : 0 : (sal_uInt8) MinMax( nSumG / nDivisor, 0, 255 ),
220 [ # # ]: 0 : (sal_uInt8) MinMax( nSumB / nDivisor, 0, 255 ) ) );
221 : : }
222 : :
223 [ # # ]: 0 : if( ++nY < nHeight )
224 : : {
225 [ # # ]: 0 : if( pRowTmp1 == pColRow1 )
226 : 0 : pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
227 [ # # ]: 0 : else if( pRowTmp1 == pColRow2 )
228 : 0 : pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
229 : : else
230 : 0 : pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
231 : :
232 [ # # ]: 0 : for( i = 0; i < nWidth2; i++ )
233 [ # # ]: 0 : pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
234 : : }
235 : : }
236 : :
237 [ # # ]: 0 : delete[] pKoeff;
238 [ # # ]: 0 : delete[] (sal_uInt8*) pColRow1;
239 [ # # ]: 0 : delete[] (sal_uInt8*) pColRow2;
240 [ # # ]: 0 : delete[] (sal_uInt8*) pColRow3;
241 [ # # ]: 0 : delete[] pColm;
242 [ # # ]: 0 : delete[] pRows;
243 : :
244 [ # # ]: 0 : aNewBmp.ReleaseAccess( pWriteAcc );
245 : :
246 : 0 : bRet = sal_True;
247 : : }
248 : :
249 [ # # ]: 0 : ReleaseAccess( pReadAcc );
250 : :
251 [ # # ]: 0 : if( bRet )
252 : : {
253 [ # # ]: 0 : const MapMode aMap( maPrefMapMode );
254 : 0 : const Size aSize( maPrefSize );
255 : :
256 [ # # ]: 0 : *this = aNewBmp;
257 : :
258 [ # # ]: 0 : maPrefMapMode = aMap;
259 [ # # ]: 0 : maPrefSize = aSize;
260 [ # # ]: 0 : }
261 : : }
262 : :
263 : 0 : return bRet;
264 : : }
265 : :
266 : : // -----------------------------------------------------------------------------
267 : :
268 : 0 : sal_Bool Bitmap::ImplMedianFilter( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
269 : : {
270 : 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
271 : 0 : sal_Bool bRet = sal_False;
272 : :
273 [ # # ]: 0 : if( pReadAcc )
274 : : {
275 [ # # ][ # # ]: 0 : Bitmap aNewBmp( GetSizePixel(), 24 );
276 [ # # ]: 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
277 : :
278 [ # # ]: 0 : if( pWriteAcc )
279 : : {
280 : 0 : const long nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
281 : 0 : const long nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
282 [ # # ]: 0 : long* pColm = new long[ nWidth2 ];
283 [ # # ]: 0 : long* pRows = new long[ nHeight2 ];
284 [ # # ]: 0 : BitmapColor* pColRow1 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
285 [ # # ]: 0 : BitmapColor* pColRow2 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
286 [ # # ]: 0 : BitmapColor* pColRow3 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
287 : 0 : BitmapColor* pRowTmp1 = pColRow1;
288 : 0 : BitmapColor* pRowTmp2 = pColRow2;
289 : 0 : BitmapColor* pRowTmp3 = pColRow3;
290 : : BitmapColor* pColor;
291 : : long nY, nX, i;
292 : : long nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
293 : : long nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
294 : : long nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
295 : :
296 : : // create column LUT
297 [ # # ]: 0 : for( i = 0; i < nWidth2; i++ )
298 [ # # ]: 0 : pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
299 : :
300 : 0 : pColm[ nWidth + 1 ] = pColm[ nWidth ];
301 : :
302 : : // create row LUT
303 [ # # ]: 0 : for( i = 0; i < nHeight2; i++ )
304 [ # # ]: 0 : pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
305 : :
306 : 0 : pRows[ nHeight + 1 ] = pRows[ nHeight ];
307 : :
308 : : // read first three rows of bitmap color
309 [ # # ]: 0 : if (nHeight2 > 2)
310 : : {
311 [ # # ]: 0 : for( i = 0; i < nWidth2; i++ )
312 : : {
313 [ # # ]: 0 : pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
314 [ # # ]: 0 : pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
315 [ # # ]: 0 : pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
316 : : }
317 : : }
318 : :
319 : : // do median filtering
320 [ # # ]: 0 : for( nY = 0; nY < nHeight; )
321 : : {
322 [ # # ]: 0 : for( nX = 0; nX < nWidth; nX++ )
323 : : {
324 : 0 : nR1 = ( pColor = pRowTmp1 + nX )->GetRed(), nG1 = pColor->GetGreen(), nB1 = pColor->GetBlue();
325 : 0 : nR2 = ( ++pColor )->GetRed(), nG2 = pColor->GetGreen(), nB2 = pColor->GetBlue();
326 : 0 : nR3 = ( ++pColor )->GetRed(), nG3 = pColor->GetGreen(), nB3 = pColor->GetBlue();
327 : :
328 : 0 : nR4 = ( pColor = pRowTmp2 + nX )->GetRed(), nG4 = pColor->GetGreen(), nB4 = pColor->GetBlue();
329 : 0 : nR5 = ( ++pColor )->GetRed(), nG5 = pColor->GetGreen(), nB5 = pColor->GetBlue();
330 : 0 : nR6 = ( ++pColor )->GetRed(), nG6 = pColor->GetGreen(), nB6 = pColor->GetBlue();
331 : :
332 : 0 : nR7 = ( pColor = pRowTmp3 + nX )->GetRed(), nG7 = pColor->GetGreen(), nB7 = pColor->GetBlue();
333 : 0 : nR8 = ( ++pColor )->GetRed(), nG8 = pColor->GetGreen(), nB8 = pColor->GetBlue();
334 : 0 : nR9 = ( ++pColor )->GetRed(), nG9 = pColor->GetGreen(), nB9 = pColor->GetBlue();
335 : :
336 [ # # ][ # # ]: 0 : MNMX6( nR1, nR2, nR3, nR4, nR5, nR6 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
337 [ # # ][ # # ]: 0 : MNMX5( nR7, nR2, nR3, nR4, nR5 );
[ # # ][ # # ]
[ # # ][ # # ]
338 [ # # ][ # # ]: 0 : MNMX4( nR8, nR2, nR3, nR4 );
[ # # ][ # # ]
339 [ # # ][ # # ]: 0 : MNMX3( nR9, nR2, nR3 );
[ # # ]
340 : :
341 [ # # ][ # # ]: 0 : MNMX6( nG1, nG2, nG3, nG4, nG5, nG6 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
342 [ # # ][ # # ]: 0 : MNMX5( nG7, nG2, nG3, nG4, nG5 );
[ # # ][ # # ]
[ # # ][ # # ]
343 [ # # ][ # # ]: 0 : MNMX4( nG8, nG2, nG3, nG4 );
[ # # ][ # # ]
344 [ # # ][ # # ]: 0 : MNMX3( nG9, nG2, nG3 );
[ # # ]
345 : :
346 [ # # ][ # # ]: 0 : MNMX6( nB1, nB2, nB3, nB4, nB5, nB6 );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
347 [ # # ][ # # ]: 0 : MNMX5( nB7, nB2, nB3, nB4, nB5 );
[ # # ][ # # ]
[ # # ][ # # ]
348 [ # # ][ # # ]: 0 : MNMX4( nB8, nB2, nB3, nB4 );
[ # # ][ # # ]
349 [ # # ][ # # ]: 0 : MNMX3( nB9, nB2, nB3 );
[ # # ]
350 : :
351 : : // set destination color
352 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, BitmapColor( (sal_uInt8) nR2, (sal_uInt8) nG2, (sal_uInt8) nB2 ) );
353 : : }
354 : :
355 [ # # ]: 0 : if( ++nY < nHeight )
356 : : {
357 [ # # ]: 0 : if( pRowTmp1 == pColRow1 )
358 : 0 : pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
359 [ # # ]: 0 : else if( pRowTmp1 == pColRow2 )
360 : 0 : pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
361 : : else
362 : 0 : pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
363 : :
364 [ # # ]: 0 : for( i = 0; i < nWidth2; i++ )
365 [ # # ]: 0 : pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
366 : : }
367 : : }
368 : :
369 [ # # ]: 0 : delete[] (sal_uInt8*) pColRow1;
370 [ # # ]: 0 : delete[] (sal_uInt8*) pColRow2;
371 [ # # ]: 0 : delete[] (sal_uInt8*) pColRow3;
372 [ # # ]: 0 : delete[] pColm;
373 [ # # ]: 0 : delete[] pRows;
374 : :
375 [ # # ]: 0 : aNewBmp.ReleaseAccess( pWriteAcc );
376 : :
377 : 0 : bRet = sal_True;
378 : : }
379 : :
380 [ # # ]: 0 : ReleaseAccess( pReadAcc );
381 : :
382 [ # # ]: 0 : if( bRet )
383 : : {
384 [ # # ]: 0 : const MapMode aMap( maPrefMapMode );
385 : 0 : const Size aSize( maPrefSize );
386 : :
387 [ # # ]: 0 : *this = aNewBmp;
388 : :
389 [ # # ]: 0 : maPrefMapMode = aMap;
390 [ # # ]: 0 : maPrefSize = aSize;
391 [ # # ]: 0 : }
392 : : }
393 : :
394 : 0 : return bRet;
395 : : }
396 : :
397 : : // -----------------------------------------------------------------------------
398 : :
399 : 0 : sal_Bool Bitmap::ImplSobelGrey( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
400 : : {
401 : 0 : sal_Bool bRet = ImplMakeGreyscales( 256 );
402 : :
403 [ # # ]: 0 : if( bRet )
404 : : {
405 : 0 : bRet = sal_False;
406 : :
407 : 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
408 : :
409 [ # # ]: 0 : if( pReadAcc )
410 : : {
411 [ # # ][ # # ]: 0 : Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
412 [ # # ]: 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
413 : :
414 [ # # ]: 0 : if( pWriteAcc )
415 : : {
416 : 0 : BitmapColor aGrey( (sal_uInt8) 0 );
417 : 0 : const long nWidth = pWriteAcc->Width();
418 : 0 : const long nHeight = pWriteAcc->Height();
419 : 0 : const long nMask111 = -1, nMask121 = 0, nMask131 = 1;
420 : 0 : const long nMask211 = -2, nMask221 = 0, nMask231 = 2;
421 : 0 : const long nMask311 = -1, nMask321 = 0, nMask331 = 1;
422 : 0 : const long nMask112 = 1, nMask122 = 2, nMask132 = 1;
423 : 0 : const long nMask212 = 0, nMask222 = 0, nMask232 = 0;
424 : 0 : const long nMask312 = -1, nMask322 = -2, nMask332 = -1;
425 : : long nGrey11, nGrey12, nGrey13;
426 : : long nGrey21, nGrey22, nGrey23;
427 : : long nGrey31, nGrey32, nGrey33;
428 [ # # ]: 0 : long* pHMap = new long[ nWidth + 2 ];
429 [ # # ]: 0 : long* pVMap = new long[ nHeight + 2 ];
430 : : long nX, nY, nSum1, nSum2;
431 : :
432 : : // fill mapping tables
433 : 0 : pHMap[ 0 ] = 0;
434 [ # # ]: 0 : for( nX = 1; nX <= nWidth; nX++ )
435 : 0 : pHMap[ nX ] = nX - 1;
436 : 0 : pHMap[ nWidth + 1 ] = nWidth - 1;
437 : :
438 : 0 : pVMap[ 0 ] = 0;
439 [ # # ]: 0 : for( nY = 1; nY <= nHeight; nY++ )
440 : 0 : pVMap[ nY ] = nY - 1;
441 : 0 : pVMap[ nHeight + 1 ] = nHeight - 1;
442 : :
443 [ # # ]: 0 : for( nY = 0; nY < nHeight ; nY++ )
444 : : {
445 [ # # ]: 0 : nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
446 [ # # ]: 0 : nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
447 [ # # ]: 0 : nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
448 [ # # ]: 0 : nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
449 [ # # ]: 0 : nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
450 [ # # ]: 0 : nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
451 [ # # ]: 0 : nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
452 [ # # ]: 0 : nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
453 [ # # ]: 0 : nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
454 : :
455 [ # # ]: 0 : for( nX = 0; nX < nWidth; nX++ )
456 : : {
457 : 0 : nSum1 = nSum2 = 0;
458 : :
459 : 0 : nSum1 += nMask111 * nGrey11;
460 : 0 : nSum2 += nMask112 * nGrey11;
461 : :
462 : 0 : nSum1 += nMask121 * nGrey12;
463 : 0 : nSum2 += nMask122 * nGrey12;
464 : :
465 : 0 : nSum1 += nMask131 * nGrey13;
466 : 0 : nSum2 += nMask132 * nGrey13;
467 : :
468 : 0 : nSum1 += nMask211 * nGrey21;
469 : 0 : nSum2 += nMask212 * nGrey21;
470 : :
471 : 0 : nSum1 += nMask221 * nGrey22;
472 : 0 : nSum2 += nMask222 * nGrey22;
473 : :
474 : 0 : nSum1 += nMask231 * nGrey23;
475 : 0 : nSum2 += nMask232 * nGrey23;
476 : :
477 : 0 : nSum1 += nMask311 * nGrey31;
478 : 0 : nSum2 += nMask312 * nGrey31;
479 : :
480 : 0 : nSum1 += nMask321 * nGrey32;
481 : 0 : nSum2 += nMask322 * nGrey32;
482 : :
483 : 0 : nSum1 += nMask331 * nGrey33;
484 : 0 : nSum2 += nMask332 * nGrey33;
485 : :
486 : 0 : nSum1 = (long) sqrt( (double)( nSum1 * nSum1 + nSum2 * nSum2 ) );
487 [ # # ]: 0 : aGrey.SetIndex( ~(sal_uInt8) SAL_BOUND( nSum1, 0, 255 ) );
488 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aGrey );
489 : :
490 [ # # ]: 0 : if( nX < ( nWidth - 1 ) )
491 : : {
492 : 0 : const long nNextX = pHMap[ nX + 3 ];
493 : :
494 [ # # ]: 0 : nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
495 [ # # ]: 0 : nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
496 [ # # ]: 0 : nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
497 : : }
498 : : }
499 : : }
500 : :
501 [ # # ]: 0 : delete[] pHMap;
502 [ # # ]: 0 : delete[] pVMap;
503 [ # # ]: 0 : aNewBmp.ReleaseAccess( pWriteAcc );
504 : 0 : bRet = sal_True;
505 : : }
506 : :
507 [ # # ]: 0 : ReleaseAccess( pReadAcc );
508 : :
509 [ # # ]: 0 : if( bRet )
510 : : {
511 [ # # ]: 0 : const MapMode aMap( maPrefMapMode );
512 : 0 : const Size aSize( maPrefSize );
513 : :
514 [ # # ]: 0 : *this = aNewBmp;
515 : :
516 [ # # ]: 0 : maPrefMapMode = aMap;
517 [ # # ]: 0 : maPrefSize = aSize;
518 [ # # ]: 0 : }
519 : : }
520 : : }
521 : :
522 : 0 : return bRet;
523 : : }
524 : :
525 : : // -----------------------------------------------------------------------------
526 : :
527 : 0 : sal_Bool Bitmap::ImplEmbossGrey( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
528 : : {
529 : 0 : sal_Bool bRet = ImplMakeGreyscales( 256 );
530 : :
531 [ # # ]: 0 : if( bRet )
532 : : {
533 : 0 : bRet = sal_False;
534 : :
535 : 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
536 : :
537 [ # # ]: 0 : if( pReadAcc )
538 : : {
539 [ # # ][ # # ]: 0 : Bitmap aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
540 [ # # ]: 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
541 : :
542 [ # # ]: 0 : if( pWriteAcc )
543 : : {
544 : 0 : BitmapColor aGrey( (sal_uInt8) 0 );
545 : 0 : const long nWidth = pWriteAcc->Width();
546 : 0 : const long nHeight = pWriteAcc->Height();
547 : : long nGrey11, nGrey12, nGrey13;
548 : : long nGrey21, nGrey22, nGrey23;
549 : : long nGrey31, nGrey32, nGrey33;
550 : : double fAzim = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
551 [ # # ][ # # ]: 0 : ( pFilterParam->maEmbossAngles.mnAzimuthAngle100 * 0.01 ) : 0.0 ) * F_PI180;
552 : : double fElev = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
553 [ # # ][ # # ]: 0 : ( pFilterParam->maEmbossAngles.mnElevationAngle100 * 0.01 ) : 90.0 ) * F_PI180;
554 [ # # ]: 0 : long* pHMap = new long[ nWidth + 2 ];
555 [ # # ]: 0 : long* pVMap = new long[ nHeight + 2 ];
556 : : long nX, nY, nNx, nNy, nDotL;
557 : 0 : const long nLx = FRound( cos( fAzim ) * cos( fElev ) * 255.0 );
558 : 0 : const long nLy = FRound( sin( fAzim ) * cos( fElev ) * 255.0 );
559 : 0 : const long nLz = FRound( sin( fElev ) * 255.0 );
560 : 0 : const long nZ2 = ( ( 6 * 255 ) / 4 ) * ( ( 6 * 255 ) / 4 );
561 : 0 : const long nNzLz = ( ( 6 * 255 ) / 4 ) * nLz;
562 [ # # ]: 0 : const sal_uInt8 cLz = (sal_uInt8) SAL_BOUND( nLz, 0, 255 );
563 : :
564 : : // fill mapping tables
565 : 0 : pHMap[ 0 ] = 0;
566 [ # # ]: 0 : for( nX = 1; nX <= nWidth; nX++ )
567 : 0 : pHMap[ nX ] = nX - 1;
568 : 0 : pHMap[ nWidth + 1 ] = nWidth - 1;
569 : :
570 : 0 : pVMap[ 0 ] = 0;
571 [ # # ]: 0 : for( nY = 1; nY <= nHeight; nY++ )
572 : 0 : pVMap[ nY ] = nY - 1;
573 : 0 : pVMap[ nHeight + 1 ] = nHeight - 1;
574 : :
575 [ # # ]: 0 : for( nY = 0; nY < nHeight ; nY++ )
576 : : {
577 [ # # ]: 0 : nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
578 [ # # ]: 0 : nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
579 [ # # ]: 0 : nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
580 [ # # ]: 0 : nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
581 [ # # ]: 0 : nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
582 [ # # ]: 0 : nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
583 [ # # ]: 0 : nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
584 [ # # ]: 0 : nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
585 [ # # ]: 0 : nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
586 : :
587 [ # # ]: 0 : for( nX = 0; nX < nWidth; nX++ )
588 : : {
589 : 0 : nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
590 : 0 : nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
591 : :
592 [ # # ][ # # ]: 0 : if( !nNx && !nNy )
593 : 0 : aGrey.SetIndex( cLz );
594 [ # # ]: 0 : else if( ( nDotL = nNx * nLx + nNy * nLy +nNzLz ) < 0 )
595 : 0 : aGrey.SetIndex( 0 );
596 : : else
597 : : {
598 : 0 : const double fGrey = nDotL / sqrt( (double)(nNx * nNx + nNy * nNy + nZ2) );
599 [ # # ][ # # ]: 0 : aGrey.SetIndex( (sal_uInt8) SAL_BOUND( fGrey, 0, 255 ) );
600 : : }
601 : :
602 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aGrey );
603 : :
604 [ # # ]: 0 : if( nX < ( nWidth - 1 ) )
605 : : {
606 : 0 : const long nNextX = pHMap[ nX + 3 ];
607 : :
608 [ # # ]: 0 : nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
609 [ # # ]: 0 : nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
610 [ # # ]: 0 : nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
611 : : }
612 : : }
613 : : }
614 : :
615 [ # # ]: 0 : delete[] pHMap;
616 [ # # ]: 0 : delete[] pVMap;
617 [ # # ]: 0 : aNewBmp.ReleaseAccess( pWriteAcc );
618 : 0 : bRet = sal_True;
619 : : }
620 : :
621 [ # # ]: 0 : ReleaseAccess( pReadAcc );
622 : :
623 [ # # ]: 0 : if( bRet )
624 : : {
625 [ # # ]: 0 : const MapMode aMap( maPrefMapMode );
626 : 0 : const Size aSize( maPrefSize );
627 : :
628 [ # # ]: 0 : *this = aNewBmp;
629 : :
630 [ # # ]: 0 : maPrefMapMode = aMap;
631 [ # # ]: 0 : maPrefSize = aSize;
632 [ # # ]: 0 : }
633 : : }
634 : : }
635 : :
636 : 0 : return bRet;
637 : : }
638 : :
639 : : // -----------------------------------------------------------------------------
640 : :
641 : 0 : sal_Bool Bitmap::ImplSolarize( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
642 : : {
643 : 0 : sal_Bool bRet = sal_False;
644 : 0 : BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
645 : :
646 [ # # ]: 0 : if( pWriteAcc )
647 : : {
648 : : const sal_uInt8 cThreshold = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SOLARIZE ) ?
649 [ # # ][ # # ]: 0 : pFilterParam->mcSolarGreyThreshold : 128;
650 : :
651 [ # # ]: 0 : if( pWriteAcc->HasPalette() )
652 : : {
653 : 0 : const BitmapPalette& rPal = pWriteAcc->GetPalette();
654 : :
655 [ # # ]: 0 : for( sal_uInt16 i = 0, nCount = rPal.GetEntryCount(); i < nCount; i++ )
656 : : {
657 [ # # ]: 0 : if( rPal[ i ].GetLuminance() >= cThreshold )
658 : : {
659 : 0 : BitmapColor aCol( rPal[ i ] );
660 : 0 : pWriteAcc->SetPaletteColor( i, aCol.Invert() );
661 : : }
662 : : }
663 : : }
664 : : else
665 : : {
666 : 0 : BitmapColor aCol;
667 : 0 : const long nWidth = pWriteAcc->Width();
668 : 0 : const long nHeight = pWriteAcc->Height();
669 : :
670 [ # # ]: 0 : for( long nY = 0; nY < nHeight ; nY++ )
671 : : {
672 [ # # ]: 0 : for( long nX = 0; nX < nWidth; nX++ )
673 : : {
674 [ # # ]: 0 : aCol = pWriteAcc->GetPixel( nY, nX );
675 : :
676 [ # # ]: 0 : if( aCol.GetLuminance() >= cThreshold )
677 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aCol.Invert() );
678 : : }
679 : 0 : }
680 : : }
681 : :
682 : 0 : ReleaseAccess( pWriteAcc );
683 : 0 : bRet = sal_True;
684 : : }
685 : :
686 : 0 : return bRet;
687 : : }
688 : :
689 : : // -----------------------------------------------------------------------------
690 : :
691 : 0 : sal_Bool Bitmap::ImplSepia( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
692 : : {
693 : 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
694 : 0 : sal_Bool bRet = sal_False;
695 : :
696 [ # # ]: 0 : if( pReadAcc )
697 : : {
698 : : long nSepiaPercent = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SEPIA ) ?
699 [ # # ][ # # ]: 0 : pFilterParam->mcSolarGreyThreshold : 10;
700 [ # # ]: 0 : const long nSepia = 10000 - 100 * SAL_BOUND( nSepiaPercent, 0, 100 );
701 [ # # ]: 0 : BitmapPalette aSepiaPal( 256 );
702 : :
703 : : DBG_ASSERT( nSepiaPercent <= 100, "Bitmap::ImplSepia(): sepia value out of range; defaulting to 100%" );
704 : :
705 [ # # ]: 0 : for( sal_uInt16 i = 0; i < 256; i++ )
706 : : {
707 : 0 : BitmapColor& rCol = aSepiaPal[ i ];
708 : 0 : const sal_uInt8 cSepiaValue = (sal_uInt8) ( ( nSepia * i ) / 10000 );
709 : :
710 : 0 : rCol.SetRed( (sal_uInt8) i );
711 : 0 : rCol.SetGreen( cSepiaValue );
712 : 0 : rCol.SetBlue( cSepiaValue );
713 : : }
714 : :
715 [ # # ][ # # ]: 0 : Bitmap aNewBmp( GetSizePixel(), 8, &aSepiaPal );
716 [ # # ]: 0 : BitmapWriteAccess* pWriteAcc = aNewBmp.AcquireWriteAccess();
717 : :
718 [ # # ]: 0 : if( pWriteAcc )
719 : : {
720 : 0 : BitmapColor aCol( (sal_uInt8) 0 );
721 : 0 : const long nWidth = pWriteAcc->Width();
722 : 0 : const long nHeight = pWriteAcc->Height();
723 : :
724 [ # # ]: 0 : if( pReadAcc->HasPalette() )
725 : : {
726 [ # # ]: 0 : for( long nY = 0; nY < nHeight ; nY++ )
727 : : {
728 : 0 : const sal_uInt16 nPalCount = pReadAcc->GetPaletteEntryCount();
729 [ # # ]: 0 : sal_uInt8* pIndexMap = new sal_uInt8[ nPalCount ];
730 : :
731 [ # # ]: 0 : for( sal_uInt16 i = 0; i < nPalCount; i++ )
732 : 0 : pIndexMap[ i ] = pReadAcc->GetPaletteColor( i ).GetLuminance();
733 : :
734 [ # # ]: 0 : for( long nX = 0; nX < nWidth; nX++ )
735 : : {
736 [ # # ]: 0 : aCol.SetIndex( pIndexMap[ pReadAcc->GetPixel( nY, nX ).GetIndex() ] );
737 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aCol );
738 : : }
739 : :
740 [ # # ]: 0 : delete[] pIndexMap;
741 : : }
742 : : }
743 : : else
744 : : {
745 [ # # ]: 0 : for( long nY = 0; nY < nHeight ; nY++ )
746 : : {
747 [ # # ]: 0 : for( long nX = 0; nX < nWidth; nX++ )
748 : : {
749 [ # # ]: 0 : aCol.SetIndex( pReadAcc->GetPixel( nY, nX ).GetLuminance() );
750 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aCol );
751 : : }
752 : : }
753 : : }
754 : :
755 [ # # ]: 0 : aNewBmp.ReleaseAccess( pWriteAcc );
756 : 0 : bRet = sal_True;
757 : : }
758 : :
759 [ # # ]: 0 : ReleaseAccess( pReadAcc );
760 : :
761 [ # # ]: 0 : if( bRet )
762 : : {
763 [ # # ]: 0 : const MapMode aMap( maPrefMapMode );
764 : 0 : const Size aSize( maPrefSize );
765 : :
766 [ # # ]: 0 : *this = aNewBmp;
767 : :
768 [ # # ]: 0 : maPrefMapMode = aMap;
769 [ # # ]: 0 : maPrefSize = aSize;
770 [ # # ]: 0 : }
771 : : }
772 : :
773 : 0 : return bRet;
774 : : }
775 : :
776 : : // -----------------------------------------------------------------------------
777 : :
778 : 0 : sal_Bool Bitmap::ImplMosaic( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
779 : : {
780 : : sal_uLong nTileWidth = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
781 [ # # ][ # # ]: 0 : pFilterParam->maMosaicTileSize.mnTileWidth : 4;
782 : : sal_uLong nTileHeight = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
783 [ # # ][ # # ]: 0 : pFilterParam->maMosaicTileSize.mnTileHeight : 4;
784 : 0 : sal_Bool bRet = sal_False;
785 : :
786 [ # # ]: 0 : if( !nTileWidth )
787 : 0 : nTileWidth = 1;
788 : :
789 [ # # ]: 0 : if( !nTileHeight )
790 : 0 : nTileHeight = 1;
791 : :
792 [ # # ][ # # ]: 0 : if( nTileWidth > 1 || nTileHeight > 1 )
793 : : {
794 : : Bitmap* pNewBmp;
795 : : BitmapReadAccess* pReadAcc;
796 : : BitmapWriteAccess* pWriteAcc;
797 : :
798 [ # # ]: 0 : if( GetBitCount() > 8 )
799 : : {
800 : 0 : pNewBmp = NULL;
801 : 0 : pReadAcc = pWriteAcc = AcquireWriteAccess();
802 : : }
803 : : else
804 : : {
805 [ # # ][ # # ]: 0 : pNewBmp = new Bitmap( GetSizePixel(), 24 );
806 : 0 : pReadAcc = AcquireReadAccess();
807 : 0 : pWriteAcc = pNewBmp->AcquireWriteAccess();
808 : : }
809 : :
810 [ # # ][ # # ]: 0 : if( pReadAcc && pWriteAcc )
811 : : {
812 : 0 : BitmapColor aCol;
813 : 0 : long nWidth = pReadAcc->Width();
814 : 0 : long nHeight = pReadAcc->Height();
815 : : long nX, nY, nX1, nX2, nY1, nY2, nSumR, nSumG, nSumB;
816 : : double fArea_1;
817 : :
818 : 0 : nY1 = 0; nY2 = nTileHeight - 1;
819 : :
820 [ # # ]: 0 : if( nY2 >= nHeight )
821 : 0 : nY2 = nHeight - 1;
822 : :
823 [ # # ]: 0 : do
824 : : {
825 : 0 : nX1 = 0; nX2 = nTileWidth - 1;
826 : :
827 [ # # ]: 0 : if( nX2 >= nWidth )
828 : 0 : nX2 = nWidth - 1;
829 : :
830 : 0 : fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
831 : :
832 [ # # ]: 0 : if( !pNewBmp )
833 : : {
834 [ # # ]: 0 : do
835 : : {
836 [ # # ]: 0 : for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
837 : : {
838 [ # # ]: 0 : for( nX = nX1; nX <= nX2; nX++ )
839 : : {
840 [ # # ]: 0 : aCol = pReadAcc->GetPixel( nY, nX );
841 : 0 : nSumR += aCol.GetRed();
842 : 0 : nSumG += aCol.GetGreen();
843 : 0 : nSumB += aCol.GetBlue();
844 : : }
845 : : }
846 : :
847 : 0 : aCol.SetRed( (sal_uInt8) ( nSumR * fArea_1 ) );
848 : 0 : aCol.SetGreen( (sal_uInt8) ( nSumG * fArea_1 ) );
849 : 0 : aCol.SetBlue( (sal_uInt8) ( nSumB * fArea_1 ) );
850 : :
851 [ # # ]: 0 : for( nY = nY1; nY <= nY2; nY++ )
852 [ # # ]: 0 : for( nX = nX1; nX <= nX2; nX++ )
853 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aCol );
854 : :
855 : 0 : nX1 += nTileWidth; nX2 += nTileWidth;
856 : :
857 [ # # ]: 0 : if( nX2 >= nWidth )
858 : : {
859 : 0 : nX2 = nWidth - 1;
860 : 0 : fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
861 : : }
862 : : }
863 : : while( nX1 < nWidth );
864 : : }
865 : : else
866 : : {
867 [ # # ]: 0 : do
868 : : {
869 [ # # ]: 0 : for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
870 : : {
871 [ # # ]: 0 : for( nX = nX1; nX <= nX2; nX++ )
872 : : {
873 [ # # ]: 0 : const BitmapColor& rCol = pReadAcc->GetPaletteColor( (sal_uInt8) pReadAcc->GetPixel( nY, nX ) );
874 : 0 : nSumR += rCol.GetRed();
875 : 0 : nSumG += rCol.GetGreen();
876 : 0 : nSumB += rCol.GetBlue();
877 : : }
878 : : }
879 : :
880 : 0 : aCol.SetRed( (sal_uInt8) ( nSumR * fArea_1 ) );
881 : 0 : aCol.SetGreen( (sal_uInt8) ( nSumG * fArea_1 ) );
882 : 0 : aCol.SetBlue( (sal_uInt8) ( nSumB * fArea_1 ) );
883 : :
884 [ # # ]: 0 : for( nY = nY1; nY <= nY2; nY++ )
885 [ # # ]: 0 : for( nX = nX1; nX <= nX2; nX++ )
886 [ # # ]: 0 : pWriteAcc->SetPixel( nY, nX, aCol );
887 : :
888 : 0 : nX1 += nTileWidth; nX2 += nTileWidth;
889 : :
890 [ # # ]: 0 : if( nX2 >= nWidth )
891 : : {
892 : 0 : nX2 = nWidth - 1;
893 : 0 : fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
894 : : }
895 : : }
896 : : while( nX1 < nWidth );
897 : : }
898 : :
899 : 0 : nY1 += nTileHeight; nY2 += nTileHeight;
900 : :
901 [ # # ]: 0 : if( nY2 >= nHeight )
902 : 0 : nY2 = nHeight - 1;
903 : : }
904 : : while( nY1 < nHeight );
905 : :
906 : 0 : bRet = sal_True;
907 : : }
908 : :
909 : 0 : ReleaseAccess( pReadAcc );
910 : :
911 [ # # ]: 0 : if( pNewBmp )
912 : : {
913 : 0 : pNewBmp->ReleaseAccess( pWriteAcc );
914 : :
915 [ # # ]: 0 : if( bRet )
916 : : {
917 [ # # ]: 0 : const MapMode aMap( maPrefMapMode );
918 : 0 : const Size aSize( maPrefSize );
919 : :
920 [ # # ]: 0 : *this = *pNewBmp;
921 : :
922 [ # # ]: 0 : maPrefMapMode = aMap;
923 [ # # ]: 0 : maPrefSize = aSize;
924 : : }
925 : :
926 [ # # ]: 0 : delete pNewBmp;
927 : 0 : }
928 : : }
929 : : else
930 : 0 : bRet = sal_True;
931 : :
932 : 0 : return bRet;
933 : : }
934 : :
935 : : // -----------------------------------------------------------------------------
936 : :
937 : : struct PopArtEntry
938 : : {
939 : : sal_uInt32 mnIndex;
940 : : sal_uInt32 mnCount;
941 : : };
942 : :
943 : : // ------------------------------------------------------------------------
944 : :
945 : 0 : extern "C" int __LOADONCALLAPI ImplPopArtCmpFnc( const void* p1, const void* p2 )
946 : : {
947 : : int nRet;
948 : :
949 [ # # ]: 0 : if( ( (PopArtEntry*) p1 )->mnCount < ( (PopArtEntry*) p2 )->mnCount )
950 : 0 : nRet = 1;
951 [ # # ]: 0 : else if( ( (PopArtEntry*) p1 )->mnCount == ( (PopArtEntry*) p2 )->mnCount )
952 : 0 : nRet = 0;
953 : : else
954 : 0 : nRet = -1;
955 : :
956 : 0 : return nRet;
957 : : }
958 : :
959 : : // ------------------------------------------------------------------------
960 : :
961 : 0 : sal_Bool Bitmap::ImplPopArt( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
962 : : {
963 [ # # ]: 0 : sal_Bool bRet = ( GetBitCount() > 8 ) ? Convert( BMP_CONVERSION_8BIT_COLORS ) : sal_True;
964 : :
965 [ # # ]: 0 : if( bRet )
966 : : {
967 : 0 : bRet = sal_False;
968 : :
969 : 0 : BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
970 : :
971 [ # # ]: 0 : if( pWriteAcc )
972 : : {
973 : 0 : const long nWidth = pWriteAcc->Width();
974 : 0 : const long nHeight = pWriteAcc->Height();
975 : 0 : const sal_uLong nEntryCount = 1 << pWriteAcc->GetBitCount();
976 : : sal_uLong n;
977 [ # # ]: 0 : PopArtEntry* pPopArtTable = new PopArtEntry[ nEntryCount ];
978 : :
979 [ # # ]: 0 : for( n = 0; n < nEntryCount; n++ )
980 : : {
981 : 0 : PopArtEntry& rEntry = pPopArtTable[ n ];
982 : 0 : rEntry.mnIndex = (sal_uInt16) n;
983 : 0 : rEntry.mnCount = 0;
984 : : }
985 : :
986 : : // get pixel count for each palette entry
987 [ # # ]: 0 : for( long nY = 0; nY < nHeight ; nY++ )
988 [ # # ]: 0 : for( long nX = 0; nX < nWidth; nX++ )
989 [ # # ]: 0 : pPopArtTable[ pWriteAcc->GetPixel( nY, nX ).GetIndex() ].mnCount++;
990 : :
991 : : // sort table
992 [ # # ]: 0 : qsort( pPopArtTable, nEntryCount, sizeof( PopArtEntry ), ImplPopArtCmpFnc );
993 : :
994 : : // get last used entry
995 : : sal_uLong nFirstEntry;
996 : 0 : sal_uLong nLastEntry = 0;
997 : :
998 [ # # ]: 0 : for( n = 0; n < nEntryCount; n++ )
999 [ # # ]: 0 : if( pPopArtTable[ n ].mnCount )
1000 : 0 : nLastEntry = n;
1001 : :
1002 : : // rotate palette (one entry)
1003 : 0 : const BitmapColor aFirstCol( pWriteAcc->GetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ 0 ].mnIndex) ) );
1004 [ # # ]: 0 : for( nFirstEntry = 0; nFirstEntry < nLastEntry; nFirstEntry++ )
1005 : : {
1006 : 0 : pWriteAcc->SetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ nFirstEntry ].mnIndex),
1007 : 0 : pWriteAcc->GetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ nFirstEntry + 1 ].mnIndex) ) );
1008 : : }
1009 : 0 : pWriteAcc->SetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ nLastEntry ].mnIndex), aFirstCol );
1010 : :
1011 : : // cleanup
1012 [ # # ]: 0 : delete[] pPopArtTable;
1013 [ # # ]: 0 : ReleaseAccess( pWriteAcc );
1014 : 0 : bRet = sal_True;
1015 : : }
1016 : : }
1017 : :
1018 : 0 : return bRet;
1019 : : }
1020 : :
1021 : :
1022 : 0 : double* MakeBlurKernel(const double radius, int& rows) {
1023 : 0 : int intRadius = (int) radius + 1.0;
1024 : 0 : rows = intRadius * 2 + 1;
1025 : 0 : double* matrix = new double[rows];
1026 : :
1027 : 0 : double sigma = radius / 3;
1028 : 0 : double radius2 = radius * radius;
1029 : 0 : int index = 0;
1030 [ # # ]: 0 : for (int row = -intRadius; row <= intRadius; row++)
1031 : : {
1032 : 0 : double distance = row*row;
1033 [ # # ]: 0 : if (distance > radius2) {
1034 : 0 : matrix[index] = 0.0;
1035 : : }else {
1036 : 0 : matrix[index] = exp( -distance / (2.0 * sigma * sigma) ) / sqrt( 2.0 * M_PI * sigma );
1037 : : }
1038 : 0 : index++;
1039 : : }
1040 : 0 : return matrix;
1041 : : }
1042 : :
1043 : 0 : void Bitmap::ImplBlurContributions( const int aSize, const int aNumberOfContributions,
1044 : : double* pBlurVector, double*& pWeights, int*& pPixels, int*& pCount )
1045 : : {
1046 : 0 : pWeights = new double[ aSize*aNumberOfContributions ];
1047 : 0 : pPixels = new int[ aSize*aNumberOfContributions ];
1048 : 0 : pCount = new int[ aSize ];
1049 : :
1050 : : int aLeft, aRight, aCurrentCount, aPixelIndex;
1051 : : double aWeight;
1052 : :
1053 [ # # ]: 0 : for ( int i = 0; i < aSize; i++ )
1054 : : {
1055 : 0 : aLeft = (int) i - aNumberOfContributions / 2;
1056 : 0 : aRight = (int) i + aNumberOfContributions / 2;
1057 : 0 : aCurrentCount = 0;
1058 [ # # ]: 0 : for ( int j = aLeft; j <= aRight; j++ )
1059 : : {
1060 : 0 : aWeight = pBlurVector[aCurrentCount];
1061 : :
1062 : : // Mirror edges
1063 [ # # ]: 0 : if (j < 0)
1064 : : {
1065 : 0 : aPixelIndex = -j;
1066 : : }
1067 [ # # ]: 0 : else if ( j >= aSize )
1068 : : {
1069 : 0 : aPixelIndex = (aSize - j) + aSize - 1;
1070 : : }
1071 : : else
1072 : : {
1073 : 0 : aPixelIndex = j;
1074 : : }
1075 : :
1076 : : // Edge case for small bitmaps
1077 [ # # ][ # # ]: 0 : if ( aPixelIndex < 0 || aPixelIndex >= aSize )
1078 : : {
1079 : 0 : aWeight = 0.0;
1080 : : }
1081 : :
1082 : 0 : pWeights[ i*aNumberOfContributions + aCurrentCount ] = aWeight;
1083 : 0 : pPixels[ i*aNumberOfContributions + aCurrentCount ] = aPixelIndex;
1084 : :
1085 : 0 : aCurrentCount++;
1086 : : }
1087 : 0 : pCount[ i ] = aCurrentCount;
1088 : : }
1089 : 0 : }
1090 : :
1091 : : // Separable Gaussian Blur
1092 : : //
1093 : : // Separable Gaussian Blur filter and accepts a blur radius
1094 : : // as a parameter so the user can change the strength of the blur.
1095 : : // Radius of 1.0 is 3 * standard deviation of gauss function.
1096 : : //
1097 : : // Separable Blur implementation uses 2x separable 1D convolution
1098 : : // to process the image.
1099 : 0 : bool Bitmap::ImplSeparableBlurFilter(const double radius)
1100 : : {
1101 [ # # ]: 0 : const long nWidth = GetSizePixel().Width();
1102 [ # # ]: 0 : const long nHeight = GetSizePixel().Height();
1103 : :
1104 : : // Prepare Blur Vector
1105 : : int aNumberOfContributions;
1106 [ # # ]: 0 : double* pBlurVector = MakeBlurKernel(radius, aNumberOfContributions);
1107 : :
1108 : : double* pWeights;
1109 : : int* pPixels;
1110 : : int* pCount;
1111 : :
1112 : : // Do horizontal filtering
1113 [ # # ]: 0 : ImplBlurContributions( nWidth, aNumberOfContributions, pBlurVector, pWeights, pPixels, pCount);
1114 : :
1115 [ # # ]: 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
1116 : :
1117 : : // switch coordinates as convolution pass transposes result
1118 [ # # ]: 0 : Bitmap aNewBitmap( Size( nHeight, nWidth ), 24 );
1119 : :
1120 [ # # ]: 0 : bool bResult = ImplConvolutionPass( aNewBitmap, nWidth, pReadAcc, aNumberOfContributions, pWeights, pPixels, pCount );
1121 : :
1122 : : // Cleanup
1123 [ # # ]: 0 : ReleaseAccess( pReadAcc );
1124 [ # # ]: 0 : delete[] pWeights;
1125 [ # # ]: 0 : delete[] pPixels;
1126 [ # # ]: 0 : delete[] pCount;
1127 : :
1128 [ # # ]: 0 : if ( !bResult )
1129 : 0 : return bResult;
1130 : :
1131 : : // Swap current bitmap with new bitmap
1132 [ # # ]: 0 : ImplAssignWithSize( aNewBitmap );
1133 : :
1134 : : // Do vertical filtering
1135 [ # # ]: 0 : ImplBlurContributions(nHeight, aNumberOfContributions, pBlurVector, pWeights, pPixels, pCount );
1136 : :
1137 [ # # ]: 0 : pReadAcc = AcquireReadAccess();
1138 [ # # ][ # # ]: 0 : aNewBitmap = Bitmap( Size( nWidth, nHeight ), 24 );
[ # # ]
1139 [ # # ]: 0 : bResult = ImplConvolutionPass( aNewBitmap, nHeight, pReadAcc, aNumberOfContributions, pWeights, pPixels, pCount );
1140 : :
1141 : : // Cleanup
1142 [ # # ]: 0 : ReleaseAccess( pReadAcc );
1143 [ # # ]: 0 : delete[] pWeights;
1144 [ # # ]: 0 : delete[] pCount;
1145 [ # # ]: 0 : delete[] pPixels;
1146 [ # # ]: 0 : delete[] pBlurVector;
1147 : :
1148 [ # # ]: 0 : if ( !bResult )
1149 : 0 : return bResult;
1150 : :
1151 : : // Swap current bitmap with new bitmap
1152 [ # # ]: 0 : ImplAssignWithSize( aNewBitmap );
1153 : :
1154 [ # # ]: 0 : return true;
1155 : : }
1156 : :
1157 : : // Separable Unsharepn Mask filter is actually a substracted blured
1158 : : // image from the original image.
1159 : 0 : bool Bitmap::ImplSeparableUnsharpenFilter(const double radius) {
1160 [ # # ]: 0 : const long nWidth = GetSizePixel().Width();
1161 [ # # ]: 0 : const long nHeight = GetSizePixel().Height();
1162 : :
1163 [ # # ]: 0 : Bitmap aBlur( *this );
1164 [ # # ]: 0 : aBlur.ImplSeparableBlurFilter(-radius);
1165 : :
1166 : : // Amount of unsharpening effect on image - currently set to a fixed value
1167 : 0 : double aAmount = 2.0;
1168 : :
1169 [ # # ]: 0 : Bitmap aResultBitmap( Size( nWidth, nHeight ), 24);
1170 : :
1171 [ # # ]: 0 : BitmapReadAccess* pReadAccBlur = aBlur.AcquireReadAccess();
1172 [ # # ]: 0 : BitmapReadAccess* pReadAcc = AcquireReadAccess();
1173 [ # # ]: 0 : BitmapWriteAccess* pWriteAcc = aResultBitmap.AcquireWriteAccess();
1174 : :
1175 : 0 : BitmapColor aColor, aColorBlur;
1176 : :
1177 : : // For all pixels in original image substract pixels values from blured image.
1178 [ # # ]: 0 : for( int x = 0; x < nWidth; x++ )
1179 : : {
1180 [ # # ]: 0 : for( int y = 0; y < nHeight; y++ )
1181 : : {
1182 [ # # ]: 0 : aColorBlur = pReadAccBlur->GetPixel( y , x );
1183 [ # # ]: 0 : if( pReadAccBlur->HasPalette() )
1184 : : {
1185 : 0 : pReadAccBlur->GetPaletteColor( aColorBlur );
1186 : : }
1187 : :
1188 [ # # ]: 0 : aColor = pReadAcc->GetPixel( y , x );
1189 [ # # ]: 0 : if( pReadAcc->HasPalette() )
1190 : : {
1191 : 0 : aColor = pReadAcc->GetPaletteColor( aColor );
1192 : : }
1193 : :
1194 : : BitmapColor aResultColor(
1195 : 0 : (sal_uInt8) MinMax( aColor.GetRed() + (aColor.GetRed() - aColorBlur.GetRed()) * aAmount, 0, 255 ),
1196 : 0 : (sal_uInt8) MinMax( aColor.GetGreen() + (aColor.GetGreen() - aColorBlur.GetGreen()) * aAmount, 0, 255 ),
1197 : 0 : (sal_uInt8) MinMax( aColor.GetBlue() + (aColor.GetBlue() - aColorBlur.GetBlue()) * aAmount, 0, 255 ) );
1198 : :
1199 [ # # ]: 0 : pWriteAcc->SetPixel( y, x, aResultColor );
1200 : 0 : }
1201 : : }
1202 : :
1203 [ # # ]: 0 : ReleaseAccess( pWriteAcc );
1204 [ # # ]: 0 : ReleaseAccess( pReadAcc );
1205 [ # # ]: 0 : ReleaseAccess( pReadAccBlur );
1206 [ # # ]: 0 : ImplAssignWithSize ( aResultBitmap );
1207 [ # # ][ # # ]: 0 : return true;
1208 : : }
1209 : :
1210 : :
1211 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|