LCOV - code coverage report
Current view: top level - vcl/source/gdi - pngwrite.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 334 0.0 %
Date: 2014-04-14 Functions: 0 20 0.0 %
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 <vcl/pngwrite.hxx>
      21             : 
      22             : #include <cmath>
      23             : #include <limits>
      24             : #include <rtl/crc.h>
      25             : #include <rtl/alloc.h>
      26             : #include <tools/zcodec.hxx>
      27             : #include <tools/stream.hxx>
      28             : #include <vcl/bmpacc.hxx>
      29             : #include <vcl/svapp.hxx>
      30             : #include <vcl/alpha.hxx>
      31             : #include <osl/endian.h>
      32             : #include <boost/scoped_array.hpp>
      33             : 
      34             : #define PNG_DEF_COMPRESSION 6
      35             : 
      36             : #define PNGCHUNK_IHDR 0x49484452
      37             : #define PNGCHUNK_PLTE 0x504c5445
      38             : #define PNGCHUNK_IDAT 0x49444154
      39             : #define PNGCHUNK_IEND 0x49454e44
      40             : #define PNGCHUNK_pHYs 0x70485973
      41             : #define PNGCHUNK_tRNS 0x74524e53
      42             : 
      43             : namespace vcl
      44             : {
      45             : 
      46             : class PNGWriterImpl
      47             : {
      48             : public:
      49             : 
      50             :                 PNGWriterImpl( const BitmapEx& BmpEx,
      51             :                     const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData = NULL );
      52             :                 ~PNGWriterImpl();
      53             : 
      54             :     bool    Write( SvStream& rOStm );
      55             : 
      56             :     std::vector< vcl::PNGWriter::ChunkData >&   GetChunks();
      57             : 
      58             : private:
      59             : 
      60             :     std::vector< vcl::PNGWriter::ChunkData >    maChunkSeq;
      61             : 
      62             :     sal_Int32           mnCompLevel;
      63             :     sal_Int32           mnInterlaced;
      64             :     sal_uInt32          mnMaxChunkSize;
      65             :     bool                mbStatus;
      66             : 
      67             :     BitmapReadAccess*   mpAccess;
      68             :     BitmapReadAccess*   mpMaskAccess;
      69             :     ZCodec*             mpZCodec;
      70             : 
      71             :     sal_uInt8*              mpDeflateInBuf;         // as big as the size of a scanline + alphachannel + 1
      72             :     sal_uInt8*              mpPreviousScan;         // as big as mpDeflateInBuf
      73             :     sal_uInt8*              mpCurrentScan;
      74             :     sal_uLong               mnDeflateInSize;
      75             : 
      76             :     sal_uLong               mnWidth, mnHeight;
      77             :     sal_uInt8               mnBitsPerPixel;
      78             :     sal_uInt8               mnFilterType;           // 0 oder 4;
      79             :     sal_uLong               mnBBP;                  // bytes per pixel ( needed for filtering )
      80             :     bool                mbTrueAlpha;
      81             :     sal_uLong               mnCRC;
      82             : 
      83             :     void                ImplWritepHYs( const BitmapEx& rBitmapEx );
      84             :     void                ImplWriteIDAT();
      85             :     sal_uLong               ImplGetFilter( sal_uLong nY, sal_uLong nXStart=0, sal_uLong nXAdd=1 );
      86             :     void                ImplClearFirstScanline();
      87             :     void                ImplWriteTransparent();
      88             :     bool                ImplWriteHeader();
      89             :     void                ImplWritePalette();
      90             :     void                ImplOpenChunk( sal_uLong nChunkType );
      91             :     void                ImplWriteChunk( sal_uInt8 nNumb );
      92             :     void                ImplWriteChunk( sal_uInt32 nNumb );
      93             :     void                ImplWriteChunk( unsigned char* pSource, sal_uInt32 nDatSize );
      94             :     void                ImplCloseChunk( void ) const;
      95             : };
      96             : 
      97           0 : PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
      98             :     const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) :
      99             :         mnCompLevel     ( PNG_DEF_COMPRESSION ),
     100             :         mbStatus        ( true ),
     101             :         mpAccess        ( NULL ),
     102             :         mpMaskAccess    ( NULL ),
     103           0 :         mpZCodec        ( new ZCodec( DEFAULT_IN_BUFSIZE, DEFAULT_OUT_BUFSIZE, MAX_MEM_USAGE ) ),
     104           0 :         mnCRC(0UL)
     105             : {
     106           0 :     if ( !rBmpEx.IsEmpty() )
     107             :     {
     108           0 :         Bitmap aBmp( rBmpEx.GetBitmap() );
     109             : 
     110           0 :         mnInterlaced = 0;   // ( aBmp.GetSizePixel().Width() > 128 ) || ( aBmp.GetSizePixel().Height() > 128 ) ? 1 : 0; #i67236#
     111             : 
     112             :         // #i67234# defaulting max chunk size to 256kb when using interlace mode
     113           0 :         mnMaxChunkSize = mnInterlaced == 0 ? std::numeric_limits< sal_uInt32 >::max() : 0x40000;
     114             : 
     115           0 :         if ( pFilterData )
     116             :         {
     117           0 :             sal_Int32 i = 0;
     118           0 :             for ( i = 0; i < pFilterData->getLength(); i++ )
     119             :             {
     120           0 :                 if ( (*pFilterData)[ i ].Name == "Compression" )
     121           0 :                     (*pFilterData)[ i ].Value >>= mnCompLevel;
     122           0 :                 else if ( (*pFilterData)[ i ].Name == "Interlaced" )
     123           0 :                     (*pFilterData)[ i ].Value >>= mnInterlaced;
     124           0 :                 else if ( (*pFilterData)[ i ].Name == "MaxChunkSize" )
     125             :                 {
     126           0 :                     sal_Int32 nVal = 0;
     127           0 :                     if ( (*pFilterData)[ i ].Value >>= nVal )
     128           0 :                         mnMaxChunkSize = (sal_uInt32)nVal;
     129             :                 }
     130             :             }
     131             :         }
     132           0 :         mnBitsPerPixel = (sal_uInt8)aBmp.GetBitCount();
     133             : 
     134           0 :         if( rBmpEx.IsTransparent() )
     135             :         {
     136           0 :             if ( mnBitsPerPixel <= 8 && rBmpEx.IsAlpha() )
     137             :             {
     138           0 :                 aBmp.Convert( BMP_CONVERSION_24BIT );
     139           0 :                 mnBitsPerPixel = 24;
     140             :             }
     141             : 
     142           0 :             if ( mnBitsPerPixel <= 8 )                  // transparent palette
     143             :             {
     144           0 :                 aBmp.Convert( BMP_CONVERSION_8BIT_TRANS );
     145           0 :                 aBmp.Replace( rBmpEx.GetMask(), BMP_COL_TRANS );
     146           0 :                 mnBitsPerPixel = 8;
     147           0 :                 mpAccess = aBmp.AcquireReadAccess();
     148           0 :                 if ( mpAccess )
     149             :                 {
     150           0 :                     if ( ImplWriteHeader() )
     151             :                     {
     152           0 :                         ImplWritepHYs( rBmpEx );
     153           0 :                         ImplWritePalette();
     154           0 :                         ImplWriteTransparent();
     155           0 :                         ImplWriteIDAT();
     156             :                     }
     157           0 :                     aBmp.ReleaseAccess( mpAccess ), mpAccess = 0;
     158             :                 }
     159             :                 else
     160           0 :                     mbStatus = false;
     161             :             }
     162             :             else
     163             :             {
     164           0 :                 mpAccess = aBmp.AcquireReadAccess();    // true RGB with alphachannel
     165           0 :                 if( mpAccess )
     166             :                 {
     167           0 :                     if ( ( mbTrueAlpha = rBmpEx.IsAlpha() ) )
     168             :                     {
     169           0 :                         AlphaMask aMask( rBmpEx.GetAlpha() );
     170           0 :                         mpMaskAccess = aMask.AcquireReadAccess();
     171           0 :                         if ( mpMaskAccess )
     172             :                         {
     173           0 :                             if ( ImplWriteHeader() )
     174             :                             {
     175           0 :                                 ImplWritepHYs( rBmpEx );
     176           0 :                                 ImplWriteIDAT();
     177             :                             }
     178           0 :                             aMask.ReleaseAccess( mpMaskAccess ), mpMaskAccess = 0;
     179             :                         }
     180             :                         else
     181           0 :                             mbStatus = false;
     182             :                     }
     183             :                     else
     184             :                     {
     185           0 :                         Bitmap aMask( rBmpEx.GetMask() );
     186           0 :                         mpMaskAccess = aMask.AcquireReadAccess();
     187           0 :                         if( mpMaskAccess )
     188             :                         {
     189           0 :                             if ( ImplWriteHeader() )
     190             :                             {
     191           0 :                                 ImplWritepHYs( rBmpEx );
     192           0 :                                 ImplWriteIDAT();
     193             :                             }
     194           0 :                             aMask.ReleaseAccess( mpMaskAccess ), mpMaskAccess = 0;
     195             :                         }
     196             :                         else
     197           0 :                             mbStatus = false;
     198             :                     }
     199           0 :                     aBmp.ReleaseAccess( mpAccess ), mpAccess = 0;
     200             :                 }
     201             :                 else
     202           0 :                     mbStatus = false;
     203             :             }
     204             :         }
     205             :         else
     206             :         {
     207           0 :             mpAccess = aBmp.AcquireReadAccess();        // palette + RGB without alphachannel
     208           0 :             if( mpAccess )
     209             :             {
     210           0 :                 if ( ImplWriteHeader() )
     211             :                 {
     212           0 :                     ImplWritepHYs( rBmpEx );
     213           0 :                     if( mpAccess->HasPalette() )
     214           0 :                         ImplWritePalette();
     215             : 
     216           0 :                     ImplWriteIDAT();
     217             :                 }
     218           0 :                 aBmp.ReleaseAccess( mpAccess ), mpAccess = 0;
     219             :             }
     220             :             else
     221           0 :                 mbStatus = false;
     222             :         }
     223           0 :         if ( mbStatus )
     224             :         {
     225           0 :             ImplOpenChunk( PNGCHUNK_IEND );     // create an IEND chunk
     226           0 :             ImplCloseChunk();
     227           0 :         }
     228             :     }
     229           0 : }
     230             : 
     231           0 : PNGWriterImpl::~PNGWriterImpl()
     232             : {
     233           0 :     delete mpZCodec;
     234           0 : }
     235             : 
     236           0 : bool PNGWriterImpl::Write( SvStream& rOStm )
     237             : {
     238             :    /* png signature is always an array of 8 bytes */
     239           0 :     sal_uInt16 nOldMode = rOStm.GetNumberFormatInt();
     240           0 :     rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
     241           0 :     rOStm.WriteUInt32( static_cast<sal_uInt32>(0x89504e47) );
     242           0 :     rOStm.WriteUInt32( static_cast<sal_uInt32>(0x0d0a1a0a) );
     243             : 
     244           0 :     std::vector< vcl::PNGWriter::ChunkData >::iterator aBeg( maChunkSeq.begin() );
     245           0 :     std::vector< vcl::PNGWriter::ChunkData >::iterator aEnd( maChunkSeq.end() );
     246           0 :     while( aBeg != aEnd )
     247             :     {
     248           0 :         sal_uInt32 nType = aBeg->nType;
     249             :     #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
     250           0 :         nType = OSL_SWAPDWORD( nType );
     251             :     #endif
     252           0 :         sal_uInt32 nCRC = rtl_crc32( 0, &nType, 4 );
     253           0 :         sal_uInt32 nDataSize = aBeg->aData.size();
     254           0 :         if ( nDataSize )
     255           0 :             nCRC = rtl_crc32( nCRC, &aBeg->aData[ 0 ], nDataSize );
     256           0 :         rOStm.WriteUInt32( nDataSize )
     257           0 :              .WriteUInt32( aBeg->nType );
     258           0 :         if ( nDataSize )
     259           0 :             rOStm.Write( &aBeg->aData[ 0 ], nDataSize );
     260           0 :         rOStm.WriteUInt32( nCRC );
     261           0 :         ++aBeg;
     262             :     }
     263           0 :     rOStm.SetNumberFormatInt( nOldMode );
     264           0 :     return mbStatus;
     265             : }
     266             : 
     267           0 : std::vector< vcl::PNGWriter::ChunkData >& PNGWriterImpl::GetChunks()
     268             : {
     269           0 :     return maChunkSeq;
     270             : }
     271             : 
     272           0 : bool PNGWriterImpl::ImplWriteHeader()
     273             : {
     274           0 :     ImplOpenChunk(PNGCHUNK_IHDR);
     275           0 :     ImplWriteChunk( sal_uInt32( mnWidth =  mpAccess->Width() ) );
     276           0 :     ImplWriteChunk( sal_uInt32( mnHeight = mpAccess->Height() ) );
     277             : 
     278           0 :     if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus )
     279             :     {
     280           0 :         sal_uInt8 nBitDepth = mnBitsPerPixel;
     281           0 :         if ( mnBitsPerPixel <= 8 )
     282           0 :             mnFilterType = 0;
     283             :         else
     284           0 :             mnFilterType = 4;
     285             : 
     286           0 :         sal_uInt8 nColorType = 2;                   // colortype:
     287             :                                                 // bit 0 -> palette is used
     288           0 :         if ( mpAccess->HasPalette() )           // bit 1 -> color is used
     289           0 :             nColorType |= 1;                    // bit 2 -> alpha channel is used
     290             :         else
     291           0 :             nBitDepth /= 3;
     292             : 
     293           0 :         if ( mpMaskAccess )
     294           0 :             nColorType |= 4;
     295             : 
     296           0 :         ImplWriteChunk( nBitDepth );
     297           0 :         ImplWriteChunk( nColorType );           // colortype
     298           0 :         ImplWriteChunk((sal_uInt8) 0 );             // compression type
     299           0 :         ImplWriteChunk((sal_uInt8) 0 );             // filter type - is not supported in this version
     300           0 :         ImplWriteChunk((sal_uInt8) mnInterlaced );  // interlace type
     301           0 :         ImplCloseChunk();
     302             :     }
     303             :     else
     304           0 :         mbStatus = false;
     305           0 :     return mbStatus;
     306             : }
     307             : 
     308           0 : void PNGWriterImpl::ImplWritePalette()
     309             : {
     310           0 :     const sal_uLong nCount = mpAccess->GetPaletteEntryCount();
     311           0 :     boost::scoped_array<sal_uInt8> pTempBuf(new sal_uInt8[ nCount*3 ]);
     312           0 :     sal_uInt8*      pTmp = pTempBuf.get();
     313             : 
     314           0 :     ImplOpenChunk( PNGCHUNK_PLTE );
     315             : 
     316           0 :     for ( sal_uInt16 i = 0; i < nCount; i++ )
     317             :     {
     318           0 :         const BitmapColor& rColor = mpAccess->GetPaletteColor( i );
     319           0 :         *pTmp++ = rColor.GetRed();
     320           0 :         *pTmp++ = rColor.GetGreen();
     321           0 :         *pTmp++ = rColor.GetBlue();
     322             :     }
     323           0 :     ImplWriteChunk( pTempBuf.get(), nCount*3 );
     324           0 :     ImplCloseChunk();
     325           0 : }
     326             : 
     327           0 : void PNGWriterImpl::ImplWriteTransparent ()
     328             : {
     329           0 :     const sal_uLong nTransIndex = mpAccess->GetBestPaletteIndex( BMP_COL_TRANS );
     330             : 
     331           0 :     ImplOpenChunk( PNGCHUNK_tRNS );
     332             : 
     333           0 :     for ( sal_uLong n = 0UL; n <= nTransIndex; n++ )
     334           0 :         ImplWriteChunk( ( nTransIndex == n ) ? (sal_uInt8) 0x0 : (sal_uInt8) 0xff );
     335             : 
     336           0 :     ImplCloseChunk();
     337           0 : }
     338             : 
     339           0 : void PNGWriterImpl::ImplWritepHYs( const BitmapEx& rBmpEx )
     340             : {
     341           0 :     if ( rBmpEx.GetPrefMapMode() == MAP_100TH_MM )
     342             :     {
     343           0 :         Size aPrefSize( rBmpEx.GetPrefSize() );
     344           0 :         if ( aPrefSize.Width() && aPrefSize.Height() )
     345             :         {
     346           0 :             ImplOpenChunk( PNGCHUNK_pHYs );
     347           0 :             sal_uInt8 nMapUnit = 1;
     348           0 :             sal_uInt32 nPrefSizeX = (sal_uInt32)( (double)100000.0 / ( (double)aPrefSize.Width() / mnWidth ) + 0.5 );
     349           0 :             sal_uInt32 nPrefSizeY = (sal_uInt32)( (double)100000.0 / ( (double)aPrefSize.Height() / mnHeight ) + 0.5 );
     350           0 :             ImplWriteChunk( nPrefSizeX );
     351           0 :             ImplWriteChunk( nPrefSizeY );
     352           0 :             ImplWriteChunk( nMapUnit );
     353           0 :             ImplCloseChunk();
     354             :         }
     355             :     }
     356           0 : }
     357             : 
     358           0 : void PNGWriterImpl::ImplWriteIDAT ()
     359             : {
     360           0 :     mnDeflateInSize = mnBitsPerPixel;
     361             : 
     362           0 :     if( mpMaskAccess )
     363           0 :         mnDeflateInSize += 8;
     364             : 
     365           0 :     mnBBP = ( mnDeflateInSize + 7 ) >> 3;
     366             : 
     367           0 :     mnDeflateInSize = mnBBP * mnWidth + 1;
     368             : 
     369           0 :     mpDeflateInBuf = new sal_uInt8[ mnDeflateInSize ];
     370             : 
     371           0 :     if ( mnFilterType )         // using filter type 4 we need memory for the scanline 3 times
     372             :     {
     373           0 :         mpPreviousScan = new sal_uInt8[ mnDeflateInSize ];
     374           0 :         mpCurrentScan = new sal_uInt8[ mnDeflateInSize ];
     375           0 :         ImplClearFirstScanline();
     376             :     }
     377           0 :     mpZCodec->BeginCompression( ZCODEC_PNG_DEFAULT + mnCompLevel );
     378           0 :     mpZCodec->SetCRC( mnCRC );
     379           0 :     SvMemoryStream aOStm;
     380           0 :     if ( mnInterlaced == 0 )
     381             :     {
     382           0 :         for ( sal_uLong nY = 0; nY < mnHeight; nY++ )
     383           0 :             mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter( nY ) );
     384             :     }
     385             :     else
     386             :     {
     387             :         // interlace mode
     388             :         sal_uLong nY;
     389           0 :         for ( nY = 0; nY < mnHeight; nY+=8 )                                                // pass 1
     390           0 :             mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 8 ) );
     391           0 :         ImplClearFirstScanline();
     392             : 
     393           0 :         for ( nY = 0; nY < mnHeight; nY+=8 )                                                // pass 2
     394           0 :             mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 4, 8 ) );
     395           0 :         ImplClearFirstScanline();
     396             : 
     397           0 :         if ( mnHeight >= 5 )                                                                // pass 3
     398             :         {
     399           0 :             for ( nY = 4; nY < mnHeight; nY+=8 )
     400           0 :                 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 4 ) );
     401           0 :             ImplClearFirstScanline();
     402             :         }
     403             : 
     404           0 :         for ( nY = 0; nY < mnHeight; nY+=4 )                                                // pass 4
     405           0 :             mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 2, 4 ) );
     406           0 :         ImplClearFirstScanline();
     407             : 
     408           0 :         if ( mnHeight >= 3 )                                                                // pass 5
     409             :         {
     410           0 :             for ( nY = 2; nY < mnHeight; nY+=4 )
     411           0 :                 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 2 ) );
     412           0 :             ImplClearFirstScanline();
     413             :         }
     414             : 
     415           0 :         for ( nY = 0; nY < mnHeight; nY+=2 )                                                // pass 6
     416           0 :             mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 1, 2 ) );
     417           0 :         ImplClearFirstScanline();
     418             : 
     419           0 :         if ( mnHeight >= 2 )                                                                // pass 7
     420             :         {
     421           0 :             for ( nY = 1; nY < mnHeight; nY+=2 )
     422           0 :                 mpZCodec->Write( aOStm, mpDeflateInBuf, ImplGetFilter ( nY, 0, 1 ) );
     423             :         }
     424             :     }
     425           0 :     mpZCodec->EndCompression();
     426           0 :     mnCRC = mpZCodec->GetCRC();
     427             : 
     428           0 :     if ( mnFilterType )         // using filter type 4 we need memory for the scanline 3 times
     429             :     {
     430           0 :         delete[] mpCurrentScan;
     431           0 :         delete[] mpPreviousScan;
     432             :     }
     433           0 :     delete[] mpDeflateInBuf;
     434             : 
     435           0 :     sal_uInt32 nIDATSize = aOStm.Tell();
     436           0 :     sal_uInt32 nBytes, nBytesToWrite = nIDATSize;
     437           0 :     while( nBytesToWrite )
     438             :     {
     439           0 :         nBytes = nBytesToWrite <= mnMaxChunkSize ? nBytesToWrite : mnMaxChunkSize;
     440           0 :         ImplOpenChunk( PNGCHUNK_IDAT );
     441           0 :         ImplWriteChunk( (unsigned char*)aOStm.GetData() + ( nIDATSize - nBytesToWrite ), nBytes );
     442           0 :         ImplCloseChunk();
     443           0 :         nBytesToWrite -= nBytes;
     444           0 :     }
     445           0 : }
     446             : 
     447             : // ImplGetFilter writes the complete Scanline (nY) - in interlace mode the parameter nXStart and nXAdd
     448             : // appends to the currently used pass
     449             : // the complete size of scanline will be returned - in interlace mode zero is possible!
     450             : 
     451           0 : sal_uLong PNGWriterImpl::ImplGetFilter ( sal_uLong nY, sal_uLong nXStart, sal_uLong nXAdd )
     452             : {
     453             :     sal_uInt8* pDest;
     454             : 
     455           0 :     if ( mnFilterType )
     456           0 :         pDest = mpCurrentScan;
     457             :     else
     458           0 :         pDest = mpDeflateInBuf;
     459             : 
     460           0 :     if ( nXStart < mnWidth )
     461             :     {
     462           0 :         *pDest++ = mnFilterType;        // in this version the filter type is either 0 or 4
     463             : 
     464           0 :         if ( mpAccess->HasPalette() )   // alphachannel is not allowed by pictures including palette entries
     465             :         {
     466           0 :             switch ( mnBitsPerPixel )
     467             :             {
     468             :                 case( 1 ):
     469             :                 {
     470             :                     sal_uLong nX, nXIndex;
     471           0 :                     for ( nX = nXStart, nXIndex = 0; nX < mnWidth; nX+=nXAdd, nXIndex++ )
     472             :                     {
     473           0 :                         sal_uLong nShift = ( nXIndex & 7 ) ^ 7;
     474           0 :                         if ( nShift == 7)
     475           0 :                             *pDest = mpAccess->GetPixelIndex( nY, nX ) << nShift;
     476           0 :                         else if  ( nShift == 0 )
     477           0 :                             *pDest++ |= mpAccess->GetPixelIndex( nY, nX ) << nShift;
     478             :                         else
     479           0 :                             *pDest |= mpAccess->GetPixelIndex( nY, nX ) << nShift;
     480             :                     }
     481           0 :                     if ( ( nXIndex & 7 ) != 0 ) pDest++;    // byte is not completely used, so the
     482             :                 }                                           // bufferpointer is to correct
     483           0 :                 break;
     484             : 
     485             :                 case( 4 ):
     486             :                 {
     487             :                     sal_uLong nX, nXIndex;
     488           0 :                     for ( nX = nXStart, nXIndex = 0; nX < mnWidth; nX+= nXAdd, nXIndex++ )
     489             :                     {
     490           0 :                         if( nXIndex & 1 )
     491           0 :                             *pDest++ |= mpAccess->GetPixelIndex( nY, nX );
     492             :                         else
     493           0 :                             *pDest = mpAccess->GetPixelIndex( nY, nX ) << 4;
     494             :                     }
     495           0 :                     if ( nXIndex & 1 ) pDest++;
     496             :                 }
     497           0 :                 break;
     498             : 
     499             :                 case( 8 ):
     500             :                 {
     501           0 :                     for ( sal_uLong nX = nXStart; nX < mnWidth; nX+=nXAdd )
     502           0 :                         *pDest++ = mpAccess->GetPixelIndex( nY, nX );
     503             :                 }
     504           0 :                 break;
     505             : 
     506             :                 default :
     507           0 :                     mbStatus = false;
     508           0 :                 break;
     509             :             }
     510             :         }
     511             :         else
     512             :         {
     513           0 :             if ( mpMaskAccess )             // mpMaskAccess != NULL -> alphachannel is to create
     514             :             {
     515           0 :                 if ( mbTrueAlpha )
     516             :                 {
     517           0 :                     for ( sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd )
     518             :                     {
     519           0 :                         const BitmapColor& rColor = mpAccess->GetPixel( nY, nX );
     520           0 :                         *pDest++ = rColor.GetRed();
     521           0 :                         *pDest++ = rColor.GetGreen();
     522           0 :                         *pDest++ = rColor.GetBlue();
     523           0 :                         *pDest++ = 255 - mpMaskAccess->GetPixelIndex( nY, nX );
     524           0 :                     }
     525             :                 }
     526             :                 else
     527             :                 {
     528           0 :                     const BitmapColor aTrans( mpMaskAccess->GetBestMatchingColor( Color( COL_WHITE ) ) );
     529             : 
     530           0 :                     for ( sal_uLong nX = nXStart; nX < mnWidth; nX+=nXAdd )
     531             :                     {
     532           0 :                         const BitmapColor& rColor = mpAccess->GetPixel( nY, nX );
     533           0 :                         *pDest++ = rColor.GetRed();
     534           0 :                         *pDest++ = rColor.GetGreen();
     535           0 :                         *pDest++ = rColor.GetBlue();
     536             : 
     537           0 :                         if( mpMaskAccess->GetPixel( nY, nX ) == aTrans )
     538           0 :                             *pDest++ = 0;
     539             :                         else
     540           0 :                             *pDest++ = 0xff;
     541           0 :                     }
     542             :                 }
     543             :             }
     544             :             else
     545             :             {
     546           0 :                 for ( sal_uLong nX = nXStart; nX < mnWidth; nX+=nXAdd )
     547             :                 {
     548           0 :                     const BitmapColor& rColor = mpAccess->GetPixel( nY, nX );
     549           0 :                     *pDest++ = rColor.GetRed();
     550           0 :                     *pDest++ = rColor.GetGreen();
     551           0 :                     *pDest++ = rColor.GetBlue();
     552           0 :                 }
     553             :             }
     554             :         }
     555             :     }
     556             :     // filter type4 ( PAETH ) will be used only for 24bit graphics
     557           0 :     if ( mnFilterType )
     558             :     {
     559           0 :         mnDeflateInSize = pDest - mpCurrentScan;
     560           0 :         pDest = mpDeflateInBuf;
     561           0 :         *pDest++ = 4;                                   // filter type
     562             : 
     563             :         sal_uLong na, nb, nc;
     564             :         long  np, npa, npb, npc;
     565             : 
     566           0 :         sal_uInt8* p1 = mpCurrentScan + 1;                  // Current Pixel
     567           0 :         sal_uInt8* p2 = p1 - mnBBP;                         // left pixel
     568           0 :         sal_uInt8* p3 = mpPreviousScan;                     // upper pixel
     569           0 :         sal_uInt8* p4 = p3 - mnBBP;                         // upperleft Pixel;
     570             : 
     571           0 :         while ( pDest < mpDeflateInBuf + mnDeflateInSize )
     572             :         {
     573           0 :             nb = *p3++;
     574           0 :             if ( p2 >= mpCurrentScan + 1 )
     575             :             {
     576           0 :                 na = *p2;
     577           0 :                 nc = *p4;
     578             :             }
     579             :             else
     580           0 :                 na = nc = 0;
     581             : 
     582           0 :             np = na + nb;
     583           0 :             np -= nc;
     584           0 :             npa = np - na;
     585           0 :             npb = np - nb;
     586           0 :             npc = np - nc;
     587           0 :             if ( npa < 0 )
     588           0 :                 npa =-npa;
     589           0 :             if ( npb < 0 )
     590           0 :                 npb =-npb;
     591           0 :             if ( npc < 0 )
     592           0 :                 npc =-npc;
     593           0 :             if ( ( npa <= npb ) && ( npa <= npc ) ) *pDest++ = *p1++ - (sal_uInt8)na;
     594           0 :             else if ( npb <= npc ) *pDest++ = *p1++ - (sal_uInt8)nb;
     595           0 :             else *pDest++ = *p1++ - (sal_uInt8)nc;
     596           0 :             p4++;
     597           0 :             p2++;
     598             :         }
     599           0 :         for ( long i = 0; i < (long)( mnDeflateInSize - 1 ); i++ )
     600           0 :             mpPreviousScan[ i ] = mpCurrentScan[ i + 1 ];
     601             :     }
     602             :     else
     603           0 :         mnDeflateInSize = pDest - mpDeflateInBuf;
     604           0 :     return ( mnDeflateInSize );
     605             : }
     606             : 
     607           0 : void PNGWriterImpl::ImplClearFirstScanline()
     608             : {
     609           0 :     if ( mnFilterType )
     610           0 :         memset( mpPreviousScan, 0, mnDeflateInSize );
     611           0 : }
     612             : 
     613           0 : void PNGWriterImpl::ImplOpenChunk ( sal_uLong nChunkType )
     614             : {
     615           0 :     maChunkSeq.resize( maChunkSeq.size() + 1 );
     616           0 :     maChunkSeq.back().nType = nChunkType;
     617           0 : }
     618             : 
     619           0 : void PNGWriterImpl::ImplWriteChunk ( sal_uInt8 nSource )
     620             : {
     621           0 :     maChunkSeq.back().aData.push_back( nSource );
     622           0 : }
     623             : 
     624           0 : void PNGWriterImpl::ImplWriteChunk ( sal_uInt32 nSource )
     625             : {
     626           0 :     vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
     627           0 :     rChunkData.aData.push_back( (sal_uInt8)( nSource >> 24 ) );
     628           0 :     rChunkData.aData.push_back( (sal_uInt8)( nSource >> 16 ) );
     629           0 :     rChunkData.aData.push_back( (sal_uInt8)( nSource >> 8 ) );
     630           0 :     rChunkData.aData.push_back( (sal_uInt8)( nSource ) );
     631           0 : }
     632             : 
     633           0 : void PNGWriterImpl::ImplWriteChunk ( unsigned char* pSource, sal_uInt32 nDatSize )
     634             : {
     635           0 :     if ( nDatSize )
     636             :     {
     637           0 :         vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
     638           0 :         sal_uInt32 nSize = rChunkData.aData.size();
     639           0 :         rChunkData.aData.resize( nSize + nDatSize );
     640           0 :         memcpy( &rChunkData.aData[ nSize ], pSource, nDatSize );
     641             :     }
     642           0 : }
     643             : 
     644             : // nothing to do
     645           0 : void PNGWriterImpl::ImplCloseChunk ( void ) const
     646             : {
     647           0 : }
     648             : 
     649           0 : PNGWriter::PNGWriter( const BitmapEx& rBmpEx,
     650             :     const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) :
     651           0 :     mpImpl( new ::vcl::PNGWriterImpl( rBmpEx, pFilterData ) )
     652             : {
     653           0 : }
     654             : 
     655           0 : PNGWriter::~PNGWriter()
     656             : {
     657           0 :     delete mpImpl;
     658           0 : }
     659             : 
     660           0 : bool PNGWriter::Write( SvStream& rIStm )
     661             : {
     662           0 :     return mpImpl->Write( rIStm );
     663             : }
     664             : 
     665           0 : std::vector< vcl::PNGWriter::ChunkData >& PNGWriter::GetChunks()
     666             : {
     667           0 :     return mpImpl->GetChunks();
     668             : }
     669             : 
     670             : } // namespace vcl
     671             : 
     672             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10