LCOV - code coverage report
Current view: top level - vcl/source/gdi - bitmap4.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 31 651 4.8 %
Date: 2015-06-13 12:38:46 Functions: 3 16 18.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11