xref: /AOO41X/main/vcl/source/gdi/bitmap4.cxx (revision d3e0dd8eb215533c15e891ee35bd141abe9397ee)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <stdlib.h>
28 #include <vos/macros.hxx>
29 #include <vcl/bmpacc.hxx>
30 #include <vcl/bitmap.hxx>
31 
32 // -----------
33 // - Defines -
34 // -----------
35 
36 #define S2(a,b)             { register long t; if( ( t = b - a ) < 0 ) { a += t; b -= t; } }
37 #define MN3(a,b,c)          S2(a,b); S2(a,c);
38 #define MX3(a,b,c)          S2(b,c); S2(a,c);
39 #define MNMX3(a,b,c)        MX3(a,b,c); S2(a,b);
40 #define MNMX4(a,b,c,d)      S2(a,b); S2(c,d); S2(a,c); S2(b,d);
41 #define MNMX5(a,b,c,d,e)    S2(a,b); S2(c,d); MN3(a,c,e); MX3(b,d,e);
42 #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);
43 
44 // ----------
45 // - Bitmap -
46 // ----------
47 
Filter(BmpFilter eFilter,const BmpFilterParam * pFilterParam,const Link * pProgress)48 sal_Bool Bitmap::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
49 {
50     sal_Bool bRet = sal_False;
51 
52     switch( eFilter )
53     {
54         case( BMP_FILTER_SMOOTH ):
55         {
56             const long pSmoothMatrix[] = { 1, 2, 1, 2, 5, 2, 1, 2, 1 };
57             bRet = ImplConvolute3( &pSmoothMatrix[ 0 ], 17, pFilterParam, pProgress );
58         }
59         break;
60 
61         case( BMP_FILTER_SHARPEN ):
62         {
63             const long pSharpenMatrix[] = { -1, -1,  -1, -1, 16, -1, -1, -1,  -1 };
64             bRet = ImplConvolute3( &pSharpenMatrix[ 0 ], 8, pFilterParam, pProgress );
65         }
66         break;
67 
68         case( BMP_FILTER_REMOVENOISE ):
69             bRet = ImplMedianFilter( pFilterParam, pProgress );
70         break;
71 
72         case( BMP_FILTER_SOBEL_GREY ):
73             bRet = ImplSobelGrey( pFilterParam, pProgress );
74         break;
75 
76         case( BMP_FILTER_SOLARIZE ):
77             bRet = ImplSolarize( pFilterParam, pProgress );
78         break;
79 
80         case( BMP_FILTER_SEPIA ):
81             bRet = ImplSepia( pFilterParam, pProgress );
82         break;
83 
84         case( BMP_FILTER_MOSAIC ):
85             bRet = ImplMosaic( pFilterParam, pProgress );
86         break;
87 
88         case( BMP_FILTER_EMBOSS_GREY ):
89             bRet = ImplEmbossGrey( pFilterParam, pProgress );
90         break;
91 
92         case( BMP_FILTER_POPART ):
93             bRet = ImplPopArt( pFilterParam, pProgress );
94         break;
95 
96         default:
97             DBG_ERROR( "Bitmap::Convert(): Unsupported filter" );
98         break;
99     }
100 
101     return bRet;
102 }
103 
104 // -----------------------------------------------------------------------------
105 
ImplConvolute3(const long * pMatrix,long nDivisor,const BmpFilterParam *,const Link *)106 sal_Bool Bitmap::ImplConvolute3( const long* pMatrix, long nDivisor,
107                              const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
108 {
109     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
110     sal_Bool                bRet = sal_False;
111 
112     if( pReadAcc )
113     {
114         Bitmap              aNewBmp( GetSizePixel(), 24 );
115         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
116 
117         if( pWriteAcc )
118         {
119             const long      nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
120             const long      nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
121             long*           pColm = new long[ nWidth2 ];
122             long*           pRows = new long[ nHeight2 ];
123             BitmapColor*    pColRow1 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
124             BitmapColor*    pColRow2 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
125             BitmapColor*    pColRow3 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
126             BitmapColor*    pRowTmp1 = pColRow1;
127             BitmapColor*    pRowTmp2 = pColRow2;
128             BitmapColor*    pRowTmp3 = pColRow3;
129             BitmapColor*    pColor;
130             long            nY, nX, i, nSumR, nSumG, nSumB, nMatrixVal, nTmp;
131             long            (*pKoeff)[ 256 ] = new long[ 9 ][ 256 ];
132             long*           pTmp;
133 
134             // create LUT of products of matrix value and possible color component values
135             for( nY = 0; nY < 9; nY++ )
136                 for( nX = nTmp = 0, nMatrixVal = pMatrix[ nY ]; nX < 256; nX++, nTmp += nMatrixVal )
137                     pKoeff[ nY ][ nX ] = nTmp;
138 
139             // create column LUT
140             for( i = 0; i < nWidth2; i++ )
141                 pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
142 
143             pColm[ nWidth + 1 ] = pColm[ nWidth ];
144 
145             // create row LUT
146             for( i = 0; i < nHeight2; i++ )
147                 pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
148 
149             pRows[ nHeight + 1 ] = pRows[ nHeight ];
150 
151             // read first three rows of bitmap color
152             for( i = 0; i < nWidth2; i++ )
153             {
154                 pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
155                 pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
156                 pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
157             }
158 
159             // do convolution
160             for( nY = 0; nY < nHeight; )
161             {
162                 for( nX = 0; nX < nWidth; nX++ )
163                 {
164                     // first row
165                     nSumR = ( pTmp = pKoeff[ 0 ] )[ ( pColor = pRowTmp1 + nX )->GetRed() ];
166                     nSumG = pTmp[ pColor->GetGreen() ];
167                     nSumB = pTmp[ pColor->GetBlue() ];
168 
169                     nSumR += ( pTmp = pKoeff[ 1 ] )[ ( ++pColor )->GetRed() ];
170                     nSumG += pTmp[ pColor->GetGreen() ];
171                     nSumB += pTmp[ pColor->GetBlue() ];
172 
173                     nSumR += ( pTmp = pKoeff[ 2 ] )[ ( ++pColor )->GetRed() ];
174                     nSumG += pTmp[ pColor->GetGreen() ];
175                     nSumB += pTmp[ pColor->GetBlue() ];
176 
177                     // second row
178                     nSumR += ( pTmp = pKoeff[ 3 ] )[ ( pColor = pRowTmp2 + nX )->GetRed() ];
179                     nSumG += pTmp[ pColor->GetGreen() ];
180                     nSumB += pTmp[ pColor->GetBlue() ];
181 
182                     nSumR += ( pTmp = pKoeff[ 4 ] )[ ( ++pColor )->GetRed() ];
183                     nSumG += pTmp[ pColor->GetGreen() ];
184                     nSumB += pTmp[ pColor->GetBlue() ];
185 
186                     nSumR += ( pTmp = pKoeff[ 5 ] )[ ( ++pColor )->GetRed() ];
187                     nSumG += pTmp[ pColor->GetGreen() ];
188                     nSumB += pTmp[ pColor->GetBlue() ];
189 
190                     // third row
191                     nSumR += ( pTmp = pKoeff[ 6 ] )[ ( pColor = pRowTmp3 + nX )->GetRed() ];
192                     nSumG += pTmp[ pColor->GetGreen() ];
193                     nSumB += pTmp[ pColor->GetBlue() ];
194 
195                     nSumR += ( pTmp = pKoeff[ 7 ] )[ ( ++pColor )->GetRed() ];
196                     nSumG += pTmp[ pColor->GetGreen() ];
197                     nSumB += pTmp[ pColor->GetBlue() ];
198 
199                     nSumR += ( pTmp = pKoeff[ 8 ] )[ ( ++pColor )->GetRed() ];
200                     nSumG += pTmp[ pColor->GetGreen() ];
201                     nSumB += pTmp[ pColor->GetBlue() ];
202 
203                     // calculate destination color
204                     pWriteAcc->SetPixel( nY, nX, BitmapColor( (sal_uInt8) MinMax( nSumR / nDivisor, 0, 255 ),
205                                                               (sal_uInt8) MinMax( nSumG / nDivisor, 0, 255 ),
206                                                               (sal_uInt8) MinMax( nSumB / nDivisor, 0, 255 ) ) );
207                 }
208 
209                 if( ++nY < nHeight )
210                 {
211                     if( pRowTmp1 == pColRow1 )
212                         pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
213                     else if( pRowTmp1 == pColRow2 )
214                         pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
215                     else
216                         pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
217 
218                     for( i = 0; i < nWidth2; i++ )
219                         pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
220                 }
221             }
222 
223             delete[] pKoeff;
224             delete[] (sal_uInt8*) pColRow1;
225             delete[] (sal_uInt8*) pColRow2;
226             delete[] (sal_uInt8*) pColRow3;
227             delete[] pColm;
228             delete[] pRows;
229 
230             aNewBmp.ReleaseAccess( pWriteAcc );
231 
232             bRet = sal_True;
233         }
234 
235         ReleaseAccess( pReadAcc );
236 
237         if( bRet )
238         {
239             const MapMode   aMap( maPrefMapMode );
240             const Size      aSize( maPrefSize );
241 
242             *this = aNewBmp;
243 
244             maPrefMapMode = aMap;
245             maPrefSize = aSize;
246         }
247     }
248 
249     return bRet;
250 }
251 
252 // -----------------------------------------------------------------------------
253 
ImplMedianFilter(const BmpFilterParam *,const Link *)254 sal_Bool Bitmap::ImplMedianFilter( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
255 {
256     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
257     sal_Bool                bRet = sal_False;
258 
259     if( pReadAcc )
260     {
261         Bitmap              aNewBmp( GetSizePixel(), 24 );
262         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
263 
264         if( pWriteAcc )
265         {
266             const long      nWidth = pWriteAcc->Width(), nWidth2 = nWidth + 2;
267             const long      nHeight = pWriteAcc->Height(), nHeight2 = nHeight + 2;
268             long*           pColm = new long[ nWidth2 ];
269             long*           pRows = new long[ nHeight2 ];
270             BitmapColor*    pColRow1 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
271             BitmapColor*    pColRow2 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
272             BitmapColor*    pColRow3 = (BitmapColor*) new sal_uInt8[ sizeof( BitmapColor ) * nWidth2 ];
273             BitmapColor*    pRowTmp1 = pColRow1;
274             BitmapColor*    pRowTmp2 = pColRow2;
275             BitmapColor*    pRowTmp3 = pColRow3;
276             BitmapColor*    pColor;
277             long            nY, nX, i;
278             long            nR1, nR2, nR3, nR4, nR5, nR6, nR7, nR8, nR9;
279             long            nG1, nG2, nG3, nG4, nG5, nG6, nG7, nG8, nG9;
280             long            nB1, nB2, nB3, nB4, nB5, nB6, nB7, nB8, nB9;
281 
282             // create column LUT
283             for( i = 0; i < nWidth2; i++ )
284                 pColm[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
285 
286             pColm[ nWidth + 1 ] = pColm[ nWidth ];
287 
288             // create row LUT
289             for( i = 0; i < nHeight2; i++ )
290                 pRows[ i ] = ( i > 0 ) ? ( i - 1 ) : 0;
291 
292             pRows[ nHeight + 1 ] = pRows[ nHeight ];
293 
294             // read first three rows of bitmap color
295             if (nHeight2 > 2)
296             {
297                 for( i = 0; i < nWidth2; i++ )
298                 {
299                     pColRow1[ i ] = pReadAcc->GetColor( pRows[ 0 ], pColm[ i ] );
300                     pColRow2[ i ] = pReadAcc->GetColor( pRows[ 1 ], pColm[ i ] );
301                     pColRow3[ i ] = pReadAcc->GetColor( pRows[ 2 ], pColm[ i ] );
302                 }
303             }
304 
305             // do median filtering
306             for( nY = 0; nY < nHeight; )
307             {
308                 for( nX = 0; nX < nWidth; nX++ )
309                 {
310                     nR1 = ( pColor = pRowTmp1 + nX )->GetRed(), nG1 = pColor->GetGreen(), nB1 = pColor->GetBlue();
311                     nR2 = ( ++pColor )->GetRed(), nG2 = pColor->GetGreen(), nB2 = pColor->GetBlue();
312                     nR3 = ( ++pColor )->GetRed(), nG3 = pColor->GetGreen(), nB3 = pColor->GetBlue();
313 
314                     nR4 = ( pColor = pRowTmp2 + nX )->GetRed(), nG4 = pColor->GetGreen(), nB4 = pColor->GetBlue();
315                     nR5 = ( ++pColor )->GetRed(), nG5 = pColor->GetGreen(), nB5 = pColor->GetBlue();
316                     nR6 = ( ++pColor )->GetRed(), nG6 = pColor->GetGreen(), nB6 = pColor->GetBlue();
317 
318                     nR7 = ( pColor = pRowTmp3 + nX )->GetRed(), nG7 = pColor->GetGreen(), nB7 = pColor->GetBlue();
319                     nR8 = ( ++pColor )->GetRed(), nG8 = pColor->GetGreen(), nB8 = pColor->GetBlue();
320                     nR9 = ( ++pColor )->GetRed(), nG9 = pColor->GetGreen(), nB9 = pColor->GetBlue();
321 
322                     MNMX6( nR1, nR2, nR3, nR4, nR5, nR6 );
323                     MNMX5( nR7, nR2, nR3, nR4, nR5 );
324                     MNMX4( nR8, nR2, nR3, nR4 );
325                     MNMX3( nR9, nR2, nR3 );
326 
327                     MNMX6( nG1, nG2, nG3, nG4, nG5, nG6 );
328                     MNMX5( nG7, nG2, nG3, nG4, nG5 );
329                     MNMX4( nG8, nG2, nG3, nG4 );
330                     MNMX3( nG9, nG2, nG3 );
331 
332                     MNMX6( nB1, nB2, nB3, nB4, nB5, nB6 );
333                     MNMX5( nB7, nB2, nB3, nB4, nB5 );
334                     MNMX4( nB8, nB2, nB3, nB4 );
335                     MNMX3( nB9, nB2, nB3 );
336 
337                     // set destination color
338                     pWriteAcc->SetPixel( nY, nX, BitmapColor( (sal_uInt8) nR2, (sal_uInt8) nG2, (sal_uInt8) nB2 ) );
339                 }
340 
341                 if( ++nY < nHeight )
342                 {
343                     if( pRowTmp1 == pColRow1 )
344                         pRowTmp1 = pColRow2, pRowTmp2 = pColRow3, pRowTmp3 = pColRow1;
345                     else if( pRowTmp1 == pColRow2 )
346                         pRowTmp1 = pColRow3, pRowTmp2 = pColRow1, pRowTmp3 = pColRow2;
347                     else
348                         pRowTmp1 = pColRow1, pRowTmp2 = pColRow2, pRowTmp3 = pColRow3;
349 
350                     for( i = 0; i < nWidth2; i++ )
351                         pRowTmp3[ i ] = pReadAcc->GetColor( pRows[ nY + 2 ], pColm[ i ] );
352                 }
353             }
354 
355             delete[] (sal_uInt8*) pColRow1;
356             delete[] (sal_uInt8*) pColRow2;
357             delete[] (sal_uInt8*) pColRow3;
358             delete[] pColm;
359             delete[] pRows;
360 
361             aNewBmp.ReleaseAccess( pWriteAcc );
362 
363             bRet = sal_True;
364         }
365 
366         ReleaseAccess( pReadAcc );
367 
368         if( bRet )
369         {
370             const MapMode   aMap( maPrefMapMode );
371             const Size      aSize( maPrefSize );
372 
373             *this = aNewBmp;
374 
375             maPrefMapMode = aMap;
376             maPrefSize = aSize;
377         }
378     }
379 
380     return bRet;
381 }
382 
383 // -----------------------------------------------------------------------------
384 
ImplSobelGrey(const BmpFilterParam *,const Link *)385 sal_Bool Bitmap::ImplSobelGrey( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
386 {
387     sal_Bool bRet = ImplMakeGreyscales( 256 );
388 
389     if( bRet )
390     {
391         bRet = sal_False;
392 
393         BitmapReadAccess* pReadAcc = AcquireReadAccess();
394 
395         if( pReadAcc )
396         {
397             Bitmap              aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
398             BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
399 
400             if( pWriteAcc )
401             {
402                 BitmapColor aGrey( (sal_uInt8) 0 );
403                 const long  nWidth = pWriteAcc->Width();
404                 const long  nHeight = pWriteAcc->Height();
405                 const long  nMask111 = -1, nMask121 =  0, nMask131 =  1;
406                 const long  nMask211 = -2, nMask221 =  0, nMask231 =  2;
407                 const long  nMask311 = -1, nMask321 =  0, nMask331 =  1;
408                 const long  nMask112 =  1, nMask122 =  2, nMask132 =  1;
409                 const long  nMask212 =  0, nMask222 =  0, nMask232 =  0;
410                 const long  nMask312 = -1, nMask322 = -2, nMask332 = -1;
411                 long        nGrey11, nGrey12, nGrey13;
412                 long        nGrey21, nGrey22, nGrey23;
413                 long        nGrey31, nGrey32, nGrey33;
414                 long*       pHMap = new long[ nWidth + 2 ];
415                 long*       pVMap = new long[ nHeight + 2 ];
416                 long        nX, nY, nSum1, nSum2;
417 
418                 // fill mapping tables
419                 pHMap[ 0 ] = 0;
420                 for( nX = 1; nX <= nWidth; nX++ )
421                     pHMap[ nX ] = nX - 1;
422                 pHMap[ nWidth + 1 ] = nWidth - 1;
423 
424                 pVMap[ 0 ] = 0;
425                 for( nY = 1; nY <= nHeight; nY++ )
426                     pVMap[ nY ] = nY - 1;
427                 pVMap[ nHeight + 1 ] = nHeight - 1;
428 
429                 for( nY = 0; nY < nHeight ; nY++ )
430                 {
431                     nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
432                     nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
433                     nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
434                     nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
435                     nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
436                     nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
437                     nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
438                     nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
439                     nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
440 
441                     for( nX = 0; nX < nWidth; nX++ )
442                     {
443                         nSum1 = nSum2 = 0;
444 
445                         nSum1 += nMask111 * nGrey11;
446                         nSum2 += nMask112 * nGrey11;
447 
448                         nSum1 += nMask121 * nGrey12;
449                         nSum2 += nMask122 * nGrey12;
450 
451                         nSum1 += nMask131 * nGrey13;
452                         nSum2 += nMask132 * nGrey13;
453 
454                         nSum1 += nMask211 * nGrey21;
455                         nSum2 += nMask212 * nGrey21;
456 
457                         nSum1 += nMask221 * nGrey22;
458                         nSum2 += nMask222 * nGrey22;
459 
460                         nSum1 += nMask231 * nGrey23;
461                         nSum2 += nMask232 * nGrey23;
462 
463                         nSum1 += nMask311 * nGrey31;
464                         nSum2 += nMask312 * nGrey31;
465 
466                         nSum1 += nMask321 * nGrey32;
467                         nSum2 += nMask322 * nGrey32;
468 
469                         nSum1 += nMask331 * nGrey33;
470                         nSum2 += nMask332 * nGrey33;
471 
472                         nSum1 = (long) sqrt( (double)( nSum1 * nSum1 + nSum2 * nSum2 ) );
473                         aGrey.SetIndex( ~(sal_uInt8) VOS_BOUND( nSum1, 0, 255 ) );
474                         pWriteAcc->SetPixel( nY, nX, aGrey );
475 
476                         if( nX < ( nWidth - 1 ) )
477                         {
478                             const long nNextX = pHMap[ nX + 3 ];
479 
480                             nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
481                             nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
482                             nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
483                         }
484                     }
485                 }
486 
487                 delete[] pHMap;
488                 delete[] pVMap;
489                 aNewBmp.ReleaseAccess( pWriteAcc );
490                 bRet = sal_True;
491             }
492 
493             ReleaseAccess( pReadAcc );
494 
495             if( bRet )
496             {
497                 const MapMode   aMap( maPrefMapMode );
498                 const Size      aSize( maPrefSize );
499 
500                 *this = aNewBmp;
501 
502                 maPrefMapMode = aMap;
503                 maPrefSize = aSize;
504             }
505         }
506     }
507 
508     return bRet;
509 }
510 
511 // -----------------------------------------------------------------------------
512 
ImplEmbossGrey(const BmpFilterParam * pFilterParam,const Link *)513 sal_Bool Bitmap::ImplEmbossGrey( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
514 {
515     sal_Bool bRet = ImplMakeGreyscales( 256 );
516 
517     if( bRet )
518     {
519         bRet = sal_False;
520 
521         BitmapReadAccess* pReadAcc = AcquireReadAccess();
522 
523         if( pReadAcc )
524         {
525             Bitmap              aNewBmp( GetSizePixel(), 8, &pReadAcc->GetPalette() );
526             BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
527 
528             if( pWriteAcc )
529             {
530                 BitmapColor aGrey( (sal_uInt8) 0 );
531                 const long  nWidth = pWriteAcc->Width();
532                 const long  nHeight = pWriteAcc->Height();
533                 long        nGrey11, nGrey12, nGrey13;
534                 long        nGrey21, nGrey22, nGrey23;
535                 long        nGrey31, nGrey32, nGrey33;
536                 double      fAzim = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
537                                       ( pFilterParam->maEmbossAngles.mnAzimuthAngle100 * 0.01 ) : 0.0 ) * F_PI180;
538                 double      fElev = ( ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_EMBOSS_GREY ) ?
539                                       ( pFilterParam->maEmbossAngles.mnElevationAngle100 * 0.01 ) : 90.0 ) * F_PI180;
540                 long*       pHMap = new long[ nWidth + 2 ];
541                 long*       pVMap = new long[ nHeight + 2 ];
542                 long        nX, nY, nNx, nNy, nDotL;
543                 const long  nLx = FRound( cos( fAzim ) * cos( fElev ) * 255.0 );
544                 const long  nLy = FRound( sin( fAzim ) * cos( fElev ) * 255.0 );
545                 const long  nLz = FRound( sin( fElev ) * 255.0 );
546                 const long  nZ2 = ( ( 6 * 255 ) / 4 ) * ( ( 6 * 255 ) / 4 );
547                 const long  nNzLz = ( ( 6 * 255 ) / 4 ) * nLz;
548                 const sal_uInt8 cLz = (sal_uInt8) VOS_BOUND( nLz, 0, 255 );
549 
550                 // fill mapping tables
551                 pHMap[ 0 ] = 0;
552                 for( nX = 1; nX <= nWidth; nX++ )
553                     pHMap[ nX ] = nX - 1;
554                 pHMap[ nWidth + 1 ] = nWidth - 1;
555 
556                 pVMap[ 0 ] = 0;
557                 for( nY = 1; nY <= nHeight; nY++ )
558                     pVMap[ nY ] = nY - 1;
559                 pVMap[ nHeight + 1 ] = nHeight - 1;
560 
561                 for( nY = 0; nY < nHeight ; nY++ )
562                 {
563                     nGrey11 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 0 ] ).GetIndex();
564                     nGrey12 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 1 ] ).GetIndex();
565                     nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], pHMap[ 2 ] ).GetIndex();
566                     nGrey21 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 0 ] ).GetIndex();
567                     nGrey22 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 1 ] ).GetIndex();
568                     nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], pHMap[ 2 ] ).GetIndex();
569                     nGrey31 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 0 ] ).GetIndex();
570                     nGrey32 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 1 ] ).GetIndex();
571                     nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], pHMap[ 2 ] ).GetIndex();
572 
573                     for( nX = 0; nX < nWidth; nX++ )
574                     {
575                         nNx = nGrey11 + nGrey21 + nGrey31 - nGrey13 - nGrey23 - nGrey33;
576                         nNy = nGrey31 + nGrey32 + nGrey33 - nGrey11 - nGrey12 - nGrey13;
577 
578                         if( !nNx && !nNy )
579                             aGrey.SetIndex( cLz );
580                         else if( ( nDotL = nNx * nLx + nNy * nLy +nNzLz ) < 0 )
581                             aGrey.SetIndex( 0 );
582                         else
583                         {
584                             const double fGrey = nDotL / sqrt( (double)(nNx * nNx + nNy * nNy + nZ2) );
585                             aGrey.SetIndex( (sal_uInt8) VOS_BOUND( fGrey, 0, 255 ) );
586                         }
587 
588                         pWriteAcc->SetPixel( nY, nX, aGrey );
589 
590                         if( nX < ( nWidth - 1 ) )
591                         {
592                             const long nNextX = pHMap[ nX + 3 ];
593 
594                             nGrey11 = nGrey12; nGrey12 = nGrey13; nGrey13 = pReadAcc->GetPixel( pVMap[ nY ], nNextX ).GetIndex();
595                             nGrey21 = nGrey22; nGrey22 = nGrey23; nGrey23 = pReadAcc->GetPixel( pVMap[ nY + 1 ], nNextX ).GetIndex();
596                             nGrey31 = nGrey32; nGrey32 = nGrey33; nGrey33 = pReadAcc->GetPixel( pVMap[ nY + 2 ], nNextX ).GetIndex();
597                         }
598                     }
599                 }
600 
601                 delete[] pHMap;
602                 delete[] pVMap;
603                 aNewBmp.ReleaseAccess( pWriteAcc );
604                 bRet = sal_True;
605             }
606 
607             ReleaseAccess( pReadAcc );
608 
609             if( bRet )
610             {
611                 const MapMode   aMap( maPrefMapMode );
612                 const Size      aSize( maPrefSize );
613 
614                 *this = aNewBmp;
615 
616                 maPrefMapMode = aMap;
617                 maPrefSize = aSize;
618             }
619         }
620     }
621 
622     return bRet;
623 }
624 
625 // -----------------------------------------------------------------------------
626 
ImplSolarize(const BmpFilterParam * pFilterParam,const Link *)627 sal_Bool Bitmap::ImplSolarize( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
628 {
629     sal_Bool                bRet = sal_False;
630     BitmapWriteAccess*  pWriteAcc = AcquireWriteAccess();
631 
632     if( pWriteAcc )
633     {
634         const sal_uInt8 cThreshold = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SOLARIZE ) ?
635                                 pFilterParam->mcSolarGreyThreshold : 128;
636 
637         if( pWriteAcc->HasPalette() )
638         {
639             const BitmapPalette& rPal = pWriteAcc->GetPalette();
640 
641             for( sal_uInt16 i = 0, nCount = rPal.GetEntryCount(); i < nCount; i++ )
642             {
643                 if( rPal[ i ].GetLuminance() >= cThreshold )
644                 {
645                     BitmapColor aCol( rPal[ i ] );
646                     pWriteAcc->SetPaletteColor( i, aCol.Invert() );
647                 }
648             }
649         }
650         else
651         {
652             BitmapColor aCol;
653             const long  nWidth = pWriteAcc->Width();
654             const long  nHeight = pWriteAcc->Height();
655 
656             for( long nY = 0; nY < nHeight ; nY++ )
657             {
658                 for( long nX = 0; nX < nWidth; nX++ )
659                 {
660                     aCol = pWriteAcc->GetPixel( nY, nX );
661 
662                     if( aCol.GetLuminance() >= cThreshold )
663                         pWriteAcc->SetPixel( nY, nX, aCol.Invert() );
664                 }
665             }
666         }
667 
668         ReleaseAccess( pWriteAcc );
669         bRet = sal_True;
670     }
671 
672     return bRet;
673 }
674 
675 // -----------------------------------------------------------------------------
676 
ImplSepia(const BmpFilterParam * pFilterParam,const Link *)677 sal_Bool Bitmap::ImplSepia( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
678 {
679     BitmapReadAccess*   pReadAcc = AcquireReadAccess();
680     sal_Bool                bRet = sal_False;
681 
682     if( pReadAcc )
683     {
684         long            nSepiaPercent = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_SEPIA ) ?
685                                         pFilterParam->mcSolarGreyThreshold : 10;
686         const long      nSepia = 10000 - 100 * VOS_BOUND( nSepiaPercent, 0, 100 );
687         BitmapPalette   aSepiaPal( 256 );
688 
689         DBG_ASSERT( nSepiaPercent <= 100, "Bitmap::ImplSepia(): sepia value out of range; defaulting to 100%" );
690 
691         for( sal_uInt16 i = 0; i < 256; i++ )
692         {
693             BitmapColor&    rCol = aSepiaPal[ i ];
694             const sal_uInt8     cSepiaValue = (sal_uInt8) ( ( nSepia * i ) / 10000 );
695 
696             rCol.SetRed( (sal_uInt8) i );
697             rCol.SetGreen( cSepiaValue );
698             rCol.SetBlue( cSepiaValue );
699         }
700 
701         Bitmap              aNewBmp( GetSizePixel(), 8, &aSepiaPal );
702         BitmapWriteAccess*  pWriteAcc = aNewBmp.AcquireWriteAccess();
703 
704         if( pWriteAcc )
705         {
706             BitmapColor aCol( (sal_uInt8) 0 );
707             const long  nWidth = pWriteAcc->Width();
708             const long  nHeight = pWriteAcc->Height();
709 
710             if( pReadAcc->HasPalette() )
711             {
712                 for( long nY = 0; nY < nHeight ; nY++ )
713                 {
714                     const sal_uInt16    nPalCount = pReadAcc->GetPaletteEntryCount();
715                     sal_uInt8*          pIndexMap = new sal_uInt8[ nPalCount ];
716 
717                     for( sal_uInt16 i = 0; i < nPalCount; i++ )
718                         pIndexMap[ i ] = pReadAcc->GetPaletteColor( i ).GetLuminance();
719 
720                     for( long nX = 0; nX < nWidth; nX++ )
721                     {
722                         aCol.SetIndex( pIndexMap[ pReadAcc->GetPixel( nY, nX ).GetIndex() ] );
723                         pWriteAcc->SetPixel( nY, nX, aCol );
724                     }
725 
726                     delete[] pIndexMap;
727                 }
728             }
729             else
730             {
731                 for( long nY = 0; nY < nHeight ; nY++ )
732                 {
733                     for( long nX = 0; nX < nWidth; nX++ )
734                     {
735                         aCol.SetIndex( pReadAcc->GetPixel( nY, nX ).GetLuminance() );
736                         pWriteAcc->SetPixel( nY, nX, aCol );
737                     }
738                 }
739             }
740 
741             aNewBmp.ReleaseAccess( pWriteAcc );
742             bRet = sal_True;
743         }
744 
745         ReleaseAccess( pReadAcc );
746 
747         if( bRet )
748         {
749             const MapMode   aMap( maPrefMapMode );
750             const Size      aSize( maPrefSize );
751 
752             *this = aNewBmp;
753 
754             maPrefMapMode = aMap;
755             maPrefSize = aSize;
756         }
757     }
758 
759     return bRet;
760 }
761 
762 // -----------------------------------------------------------------------------
763 
ImplMosaic(const BmpFilterParam * pFilterParam,const Link *)764 sal_Bool Bitmap::ImplMosaic( const BmpFilterParam* pFilterParam, const Link* /*pProgress*/ )
765 {
766     sal_uLong               nTileWidth = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
767                                      pFilterParam->maMosaicTileSize.mnTileWidth : 4;
768     sal_uLong               nTileHeight = ( pFilterParam && pFilterParam->meFilter == BMP_FILTER_MOSAIC ) ?
769                                       pFilterParam->maMosaicTileSize.mnTileHeight : 4;
770     sal_Bool                bRet = sal_False;
771 
772     if( !nTileWidth )
773         nTileWidth = 1;
774 
775     if( !nTileHeight )
776         nTileHeight = 1;
777 
778     if( nTileWidth > 1 || nTileHeight > 1 )
779     {
780         Bitmap*             pNewBmp;
781         BitmapReadAccess*   pReadAcc;
782         BitmapWriteAccess*  pWriteAcc;
783 
784         if( GetBitCount() > 8 )
785         {
786             pNewBmp = NULL;
787             pReadAcc = pWriteAcc = AcquireWriteAccess();
788         }
789         else
790         {
791             pNewBmp = new Bitmap( GetSizePixel(), 24 );
792             pReadAcc = AcquireReadAccess();
793             pWriteAcc = pNewBmp->AcquireWriteAccess();
794         }
795 
796         if( pReadAcc && pWriteAcc )
797         {
798             BitmapColor aCol;
799             long        nWidth = pReadAcc->Width();
800             long        nHeight = pReadAcc->Height();
801             long        nX, nY, nX1, nX2, nY1, nY2, nSumR, nSumG, nSumB;
802             double      fArea_1;
803 
804             nY1 = 0; nY2 = nTileHeight - 1;
805 
806             if( nY2 >= nHeight )
807                 nY2 = nHeight - 1;
808 
809             do
810             {
811                 nX1 = 0; nX2 = nTileWidth - 1;
812 
813                 if( nX2 >= nWidth )
814                     nX2 = nWidth - 1;
815 
816                 fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
817 
818                 if( !pNewBmp )
819                 {
820                     do
821                     {
822                         for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
823                         {
824                             for( nX = nX1; nX <= nX2; nX++ )
825                             {
826                                 aCol = pReadAcc->GetPixel( nY, nX );
827                                 nSumR += aCol.GetRed();
828                                 nSumG += aCol.GetGreen();
829                                 nSumB += aCol.GetBlue();
830                             }
831                         }
832 
833                         aCol.SetRed( (sal_uInt8) ( nSumR * fArea_1 ) );
834                         aCol.SetGreen( (sal_uInt8) ( nSumG * fArea_1 ) );
835                         aCol.SetBlue( (sal_uInt8) ( nSumB * fArea_1 ) );
836 
837                         for( nY = nY1; nY <= nY2; nY++ )
838                             for( nX = nX1; nX <= nX2; nX++ )
839                                 pWriteAcc->SetPixel( nY, nX, aCol );
840 
841                         nX1 += nTileWidth; nX2 += nTileWidth;
842 
843                         if( nX2 >= nWidth )
844                         {
845                             nX2 = nWidth - 1;
846                             fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
847                         }
848                     }
849                     while( nX1 < nWidth );
850                 }
851                 else
852                 {
853                     do
854                     {
855                         for( nY = nY1, nSumR = nSumG = nSumB = 0; nY <= nY2; nY++ )
856                         {
857                             for( nX = nX1; nX <= nX2; nX++ )
858                             {
859                                 const BitmapColor& rCol = pReadAcc->GetPaletteColor( pReadAcc->GetPixelIndex( nY, nX ) );
860                                 nSumR += rCol.GetRed();
861                                 nSumG += rCol.GetGreen();
862                                 nSumB += rCol.GetBlue();
863                             }
864                         }
865 
866                         aCol.SetRed( (sal_uInt8) ( nSumR * fArea_1 ) );
867                         aCol.SetGreen( (sal_uInt8) ( nSumG * fArea_1 ) );
868                         aCol.SetBlue( (sal_uInt8) ( nSumB * fArea_1 ) );
869 
870                         for( nY = nY1; nY <= nY2; nY++ )
871                             for( nX = nX1; nX <= nX2; nX++ )
872                                 pWriteAcc->SetPixel( nY, nX, aCol );
873 
874                         nX1 += nTileWidth; nX2 += nTileWidth;
875 
876                         if( nX2 >= nWidth )
877                         {
878                             nX2 = nWidth - 1;
879                             fArea_1 = 1.0 / ( ( nX2 - nX1 + 1 ) * ( nY2 - nY1 + 1 ) );
880                         }
881                     }
882                     while( nX1 < nWidth );
883                 }
884 
885                 nY1 += nTileHeight; nY2 += nTileHeight;
886 
887                 if( nY2 >= nHeight )
888                     nY2 = nHeight - 1;
889             }
890             while( nY1 < nHeight );
891 
892             bRet = sal_True;
893         }
894 
895         ReleaseAccess( pReadAcc );
896 
897         if( pNewBmp )
898         {
899             pNewBmp->ReleaseAccess( pWriteAcc );
900 
901             if( bRet )
902             {
903                 const MapMode   aMap( maPrefMapMode );
904                 const Size      aSize( maPrefSize );
905 
906                 *this = *pNewBmp;
907 
908                 maPrefMapMode = aMap;
909                 maPrefSize = aSize;
910             }
911 
912             delete pNewBmp;
913         }
914     }
915     else
916         bRet = sal_True;
917 
918     return bRet;
919 }
920 
921 // -----------------------------------------------------------------------------
922 
923 struct PopArtEntry
924 {
925     sal_uInt32  mnIndex;
926     sal_uInt32  mnCount;
927 };
928 
929 // ------------------------------------------------------------------------
930 
ImplPopArtCmpFnc(const void * p1,const void * p2)931 extern "C" int __LOADONCALLAPI ImplPopArtCmpFnc( const void* p1, const void* p2 )
932 {
933     int nRet;
934 
935     if( ( (PopArtEntry*) p1 )->mnCount < ( (PopArtEntry*) p2 )->mnCount )
936         nRet = 1;
937     else if( ( (PopArtEntry*) p1 )->mnCount == ( (PopArtEntry*) p2 )->mnCount )
938         nRet = 0;
939     else
940         nRet = -1;
941 
942     return nRet;
943 }
944 
945 // ------------------------------------------------------------------------
946 
ImplPopArt(const BmpFilterParam *,const Link *)947 sal_Bool Bitmap::ImplPopArt( const BmpFilterParam* /*pFilterParam*/, const Link* /*pProgress*/ )
948 {
949     sal_Bool bRet = ( GetBitCount() > 8 ) ? Convert( BMP_CONVERSION_8BIT_COLORS ) : sal_True;
950 
951     if( bRet )
952     {
953         bRet = sal_False;
954 
955         BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
956 
957         if( pWriteAcc )
958         {
959             const long      nWidth = pWriteAcc->Width();
960             const long      nHeight = pWriteAcc->Height();
961             const sal_uLong     nEntryCount = 1 << pWriteAcc->GetBitCount();
962             sal_uLong           n;
963             PopArtEntry*    pPopArtTable = new PopArtEntry[ nEntryCount ];
964 
965             for( n = 0; n < nEntryCount; n++ )
966             {
967                 PopArtEntry& rEntry = pPopArtTable[ n ];
968                 rEntry.mnIndex = (sal_uInt16) n;
969                 rEntry.mnCount = 0;
970             }
971 
972             // get pixel count for each palette entry
973             for( long nY = 0; nY < nHeight ; nY++ )
974                 for( long nX = 0; nX < nWidth; nX++ )
975                     pPopArtTable[ pWriteAcc->GetPixel( nY, nX ).GetIndex() ].mnCount++;
976 
977             // sort table
978             qsort( pPopArtTable, nEntryCount, sizeof( PopArtEntry ), ImplPopArtCmpFnc );
979 
980             // get last used entry
981             sal_uLong nFirstEntry;
982             sal_uLong nLastEntry = 0;
983 
984             for( n = 0; n < nEntryCount; n++ )
985                 if( pPopArtTable[ n ].mnCount )
986                     nLastEntry = n;
987 
988             // rotate palette (one entry)
989             const BitmapColor aFirstCol( pWriteAcc->GetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ 0 ].mnIndex) ) );
990             for( nFirstEntry = 0; nFirstEntry < nLastEntry; nFirstEntry++ )
991             {
992                 pWriteAcc->SetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ nFirstEntry ].mnIndex),
993                                             pWriteAcc->GetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ nFirstEntry + 1 ].mnIndex) ) );
994             }
995             pWriteAcc->SetPaletteColor( sal::static_int_cast<sal_uInt16>(pPopArtTable[ nLastEntry ].mnIndex), aFirstCol );
996 
997             // cleanup
998             delete[] pPopArtTable;
999             ReleaseAccess( pWriteAcc );
1000             bRet = sal_True;
1001         }
1002     }
1003 
1004     return bRet;
1005 }
1006 
1007 // -----------------------------------------------------------------------------
1008 // eof
1009