LCOV - code coverage report
Current view: top level - vcl/source/gdi - pngread.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 538 655 82.1 %
Date: 2012-08-25 Functions: 27 29 93.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 383 657 58.3 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <vcl/pngread.hxx>
      31                 :            : 
      32                 :            : #include <cmath>
      33                 :            : #include <rtl/crc.h>
      34                 :            : #include <rtl/alloc.h>
      35                 :            : #include <tools/zcodec.hxx>
      36                 :            : #include <tools/stream.hxx>
      37                 :            : #include <vcl/bmpacc.hxx>
      38                 :            : #include <vcl/svapp.hxx>
      39                 :            : #include <vcl/alpha.hxx>
      40                 :            : #include <osl/endian.h>
      41                 :            : 
      42                 :            : // -----------
      43                 :            : // - Defines -
      44                 :            : // -----------
      45                 :            : 
      46                 :            : #define PNGCHUNK_IHDR       0x49484452
      47                 :            : #define PNGCHUNK_PLTE       0x504c5445
      48                 :            : #define PNGCHUNK_IDAT       0x49444154
      49                 :            : #define PNGCHUNK_IEND       0x49454e44
      50                 :            : #define PNGCHUNK_bKGD       0x624b4744
      51                 :            : #define PNGCHUNK_gAMA       0x67414d41
      52                 :            : #define PNGCHUNK_pHYs       0x70485973
      53                 :            : #define PNGCHUNK_tRNS       0x74524e53
      54                 :            : 
      55                 :            : #define VIEWING_GAMMA       2.35
      56                 :            : #define DISPLAY_GAMMA       1.0
      57                 :            : 
      58                 :            : namespace vcl
      59                 :            : {
      60                 :            : // -----------
      61                 :            : // - statics -
      62                 :            : // -----------
      63                 :            : 
      64                 :            : // ------------------------------------------------------------------------------
      65                 :            : 
      66                 :            : static const sal_uInt8 mpDefaultColorTable[ 256 ] =
      67                 :            : {   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
      68                 :            :     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
      69                 :            :     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
      70                 :            :     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
      71                 :            :     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
      72                 :            :     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
      73                 :            :     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
      74                 :            :     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
      75                 :            :     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
      76                 :            :     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
      77                 :            :     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
      78                 :            :     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
      79                 :            :     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
      80                 :            :     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
      81                 :            :     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
      82                 :            :     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
      83                 :            : };
      84                 :            : 
      85                 :            : // -------------
      86                 :            : // - PNGReaderImpl -
      87                 :            : // -------------
      88                 :            : 
      89                 :            : class PNGReaderImpl
      90                 :            : {
      91                 :            : private:
      92                 :            :     SvStream&           mrPNGStream;
      93                 :            :     sal_uInt16          mnOrigStreamMode;
      94                 :            : 
      95                 :            :     std::vector< vcl::PNGReader::ChunkData >    maChunkSeq;
      96                 :            :     std::vector< vcl::PNGReader::ChunkData >::iterator maChunkIter;
      97                 :            :     std::vector< sal_uInt8 >::iterator          maDataIter;
      98                 :            : 
      99                 :            :     Bitmap*             mpBmp;
     100                 :            :     BitmapWriteAccess*  mpAcc;
     101                 :            :     Bitmap*             mpMaskBmp;
     102                 :            :     AlphaMask*          mpAlphaMask;
     103                 :            :     BitmapWriteAccess*  mpMaskAcc;
     104                 :            :     ZCodec*             mpZCodec;
     105                 :            :     sal_uInt8*              mpInflateInBuf; // as big as the size of a scanline + alphachannel + 1
     106                 :            :     sal_uInt8*              mpScanPrior;    // pointer to the latest scanline
     107                 :            :     sal_uInt8*              mpTransTab;     // for transparency in images with palette colortype
     108                 :            :     sal_uInt8*              mpScanCurrent;  // pointer into the current scanline
     109                 :            :     sal_uInt8*              mpColorTable;   //
     110                 :            :     sal_Size            mnStreamSize;   // estimate of PNG file size
     111                 :            :     sal_uInt32          mnChunkType;    // Type of current PNG chunk
     112                 :            :     sal_Int32           mnChunkLen;     // Length of current PNG chunk
     113                 :            :     Size                maOrigSize;     // pixel size of the full image
     114                 :            :     Size                maTargetSize;   // pixel size of the result image
     115                 :            :     Size                maPhysSize;     // prefered size in MAP_100TH_MM units
     116                 :            :     sal_uInt32          mnBPP;          // number of bytes per pixel
     117                 :            :     sal_uInt32          mnScansize;     // max size of scanline
     118                 :            :     sal_uInt32          mnYpos;         // latest y position in full image
     119                 :            :     int                 mnPass;         // if interlaced the latest pass ( 1..7 ) else 7
     120                 :            :     sal_uInt32          mnXStart;       // the starting X for the current pass
     121                 :            :     sal_uInt32          mnXAdd;         // the increment for input images X coords for the current pass
     122                 :            :     sal_uInt32          mnYAdd;         // the increment for input images Y coords for the current pass
     123                 :            :     int                 mnPreviewShift; // shift to convert orig image coords into preview image coords
     124                 :            :     int                 mnPreviewMask;  // == ((1 << mnPreviewShift) - 1)
     125                 :            :     sal_uInt16              mnTargetDepth;      // pixel depth of target bitmap
     126                 :            :     sal_uInt8               mnTransRed;
     127                 :            :     sal_uInt8               mnTransGreen;
     128                 :            :     sal_uInt8               mnTransBlue;
     129                 :            :     sal_uInt8               mnPngDepth;     // pixel depth of PNG data
     130                 :            :     sal_uInt8               mnColorType;
     131                 :            :     sal_uInt8               mnCompressionType;
     132                 :            :     sal_uInt8               mnFilterType;
     133                 :            :     sal_uInt8               mnInterlaceType;
     134                 :            :     BitmapColor         mcTranspColor;  // transparency mask's transparency "color"
     135                 :            :     BitmapColor         mcOpaqueColor;  // transparency mask's opaque "color"
     136                 :            :     sal_Bool                mbTransparent;  // graphic includes an tRNS Chunk or an alpha Channel
     137                 :            :     sal_Bool                mbAlphaChannel; // is true for ColorType 4 and 6
     138                 :            :     sal_Bool                mbRGBTriple;
     139                 :            :     sal_Bool                mbPalette;      // sal_False if we need a Palette
     140                 :            :     sal_Bool                mbGrayScale;
     141                 :            :     sal_Bool                mbzCodecInUse;
     142                 :            :     sal_Bool                mbStatus;
     143                 :            :     sal_Bool                mbIDAT;         // sal_True if finished with enough IDAT chunks
     144                 :            :     sal_Bool                mbGamma;        // sal_True if Gamma Correction available
     145                 :            :     sal_Bool                mbpHYs;         // sal_True if pysical size of pixel available
     146                 :            :     sal_Bool            mbIgnoreGammaChunk;
     147                 :            : 
     148                 :            :     bool                ReadNextChunk();
     149                 :            :     void                ReadRemainingChunks();
     150                 :            : 
     151                 :            :     void                ImplSetPixel( sal_uInt32 y, sal_uInt32 x, const BitmapColor & );
     152                 :            :     void                ImplSetPixel( sal_uInt32 y, sal_uInt32 x, sal_uInt8 nPalIndex );
     153                 :            :     void                ImplSetTranspPixel( sal_uInt32 y, sal_uInt32 x, const BitmapColor &, sal_Bool bTrans );
     154                 :            :     void                ImplSetAlphaPixel( sal_uInt32 y, sal_uInt32 x, sal_uInt8 nPalIndex, sal_uInt8 nAlpha );
     155                 :            :     void                ImplSetAlphaPixel( sal_uInt32 y, sal_uInt32 x, const BitmapColor&, sal_uInt8 nAlpha );
     156                 :            :     void                ImplReadIDAT();
     157                 :            :     bool                ImplPreparePass();
     158                 :            :     void                ImplApplyFilter();
     159                 :            :     void                ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd );
     160                 :            :     sal_Bool                ImplReadTransparent();
     161                 :            :     void                ImplGetGamma();
     162                 :            :     void                ImplGetBackground();
     163                 :            :     sal_uInt8               ImplScaleColor();
     164                 :            :     sal_Bool                ImplReadHeader( const Size& rPreviewSizeHint );
     165                 :            :     sal_Bool                ImplReadPalette();
     166                 :            :     void                ImplGetGrayPalette( sal_uInt16 );
     167                 :            :     sal_uInt32          ImplReadsal_uInt32();
     168                 :            : 
     169                 :            : public:
     170                 :            : 
     171                 :            :                         PNGReaderImpl( SvStream& );
     172                 :            :                         ~PNGReaderImpl();
     173                 :            : 
     174                 :            :     BitmapEx            GetBitmapEx( const Size& rPreviewSizeHint );
     175                 :            :     const std::vector< PNGReader::ChunkData >& GetAllChunks();
     176                 :       7392 :     void                SetIgnoreGammaChunk( sal_Bool bIgnore ){ mbIgnoreGammaChunk = bIgnore; };
     177                 :            : };
     178                 :            : 
     179                 :            : // ------------------------------------------------------------------------------
     180                 :            : 
     181                 :       9430 : PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream )
     182                 :            : :   mrPNGStream( rPNGStream ),
     183                 :            :     mpBmp           ( NULL ),
     184                 :            :     mpAcc           ( NULL ),
     185                 :            :     mpMaskBmp       ( NULL ),
     186                 :            :     mpAlphaMask     ( NULL ),
     187                 :            :     mpMaskAcc       ( NULL ),
     188         [ +  - ]:       9430 :     mpZCodec        ( new ZCodec( DEFAULT_IN_BUFSIZE, DEFAULT_OUT_BUFSIZE, MAX_MEM_USAGE ) ),
     189                 :            :     mpInflateInBuf  ( NULL ),
     190                 :            :     mpScanPrior     ( NULL ),
     191                 :            :     mpTransTab      ( NULL ),
     192                 :            :     mpScanCurrent   ( NULL ),
     193                 :            :     mpColorTable    ( (sal_uInt8*) mpDefaultColorTable ),
     194                 :            :     mnPass ( 0 ),
     195                 :            :     mbPalette( sal_False ),
     196                 :            :     mbzCodecInUse   ( sal_False ),
     197                 :            :     mbStatus( sal_True),
     198                 :            :     mbIDAT( sal_False ),
     199                 :            :     mbGamma             ( sal_False ),
     200                 :            :     mbpHYs              ( sal_False ),
     201         [ +  - ]:      18860 :     mbIgnoreGammaChunk  ( sal_False )
     202                 :            : {
     203                 :            :     // prepare the PNG data stream
     204                 :       9430 :     mnOrigStreamMode = mrPNGStream.GetNumberFormatInt();
     205         [ +  - ]:       9430 :     mrPNGStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
     206                 :            : 
     207                 :            :     // prepare the chunk reader
     208         [ +  - ]:       9430 :     maChunkSeq.reserve( 16 );
     209                 :       9430 :     maChunkIter = maChunkSeq.begin();
     210                 :            : 
     211                 :            :     // estimate PNG file size (to allow sanity checks)
     212                 :       9430 :     const sal_Size nStreamPos = mrPNGStream.Tell();
     213         [ +  - ]:       9430 :     mrPNGStream.Seek( STREAM_SEEK_TO_END );
     214                 :       9430 :     mnStreamSize = mrPNGStream.Tell();
     215         [ +  - ]:       9430 :     mrPNGStream.Seek( nStreamPos );
     216                 :            : 
     217                 :            :     // check the PNG header magic
     218                 :       9430 :     sal_uInt32 nDummy = 0;
     219         [ +  - ]:       9430 :     mrPNGStream >> nDummy;
     220                 :       9430 :     mbStatus = (nDummy == 0x89504e47);
     221         [ +  - ]:       9430 :     mrPNGStream >> nDummy;
     222                 :       9430 :     mbStatus &= (nDummy == 0x0d0a1a0a);
     223                 :            : 
     224                 :       9430 :     mnPreviewShift = 0;
     225                 :       9430 :     mnPreviewMask = (1 << mnPreviewShift) - 1;
     226                 :       9430 : }
     227                 :            : 
     228                 :            : // ------------------------------------------------------------------------
     229                 :            : 
     230                 :       9430 : PNGReaderImpl::~PNGReaderImpl()
     231                 :            : {
     232         [ +  - ]:       9430 :     mrPNGStream.SetNumberFormatInt( mnOrigStreamMode );
     233                 :            : 
     234         [ -  + ]:       9430 :     if ( mbzCodecInUse )
     235         [ #  # ]:          0 :         mpZCodec->EndCompression();
     236                 :            : 
     237         [ -  + ]:       9430 :     if( mpColorTable != mpDefaultColorTable )
     238         [ #  # ]:          0 :         delete[] mpColorTable;
     239                 :            : 
     240 [ +  + ][ +  - ]:       9430 :     delete mpBmp;
     241 [ +  + ][ +  - ]:       9430 :     delete mpAlphaMask;
     242 [ +  + ][ +  - ]:       9430 :     delete mpMaskBmp;
     243         [ +  + ]:       9430 :     delete[] mpTransTab;
     244         [ +  + ]:       9430 :     delete[] mpInflateInBuf;
     245         [ +  + ]:       9430 :     delete[] mpScanPrior;
     246 [ +  - ][ +  - ]:       9430 :     delete mpZCodec;
     247                 :       9430 : }
     248                 :            : 
     249                 :            : // ------------------------------------------------------------------------
     250                 :            : 
     251                 :      45325 : bool PNGReaderImpl::ReadNextChunk()
     252                 :            : {
     253 [ +  - ][ +  + ]:      45325 :     if( maChunkIter == maChunkSeq.end() )
     254                 :            :     {
     255                 :            :         // get the next chunk from the stream
     256                 :            : 
     257                 :            :         // unless we are at the end of the PNG stream
     258 [ +  - ][ -  + ]:      37397 :         if( mrPNGStream.IsEof() || (mrPNGStream.GetError() != ERRCODE_NONE) )
                 [ -  + ]
     259                 :          0 :             return false;
     260 [ +  + ][ +  - ]:      37397 :         if( !maChunkSeq.empty() && (maChunkSeq.back().nType == PNGCHUNK_IEND) )
         [ -  + ][ -  + ]
     261                 :          0 :             return false;
     262                 :            : 
     263         [ +  - ]:      37397 :         PNGReader::ChunkData aDummyChunk;
     264         [ +  - ]:      37397 :         maChunkIter = maChunkSeq.insert( maChunkSeq.end(), aDummyChunk );
     265         [ +  - ]:      37397 :         PNGReader::ChunkData& rChunkData = *maChunkIter;
     266                 :            : 
     267                 :            :         // read the chunk header
     268 [ +  - ][ +  - ]:      37397 :         mrPNGStream >> mnChunkLen >> mnChunkType;
     269                 :      37397 :         rChunkData.nType = mnChunkType;
     270                 :            : 
     271                 :            :         // #128377#/#149343# sanity check for chunk length
     272         [ +  + ]:      37397 :         if( mnChunkLen < 0 )
     273                 :          9 :             return false;
     274                 :      37388 :         const sal_Size nStreamPos = mrPNGStream.Tell();
     275         [ +  + ]:      37388 :         if( nStreamPos + mnChunkLen >= mnStreamSize )
     276                 :          9 :             return false;
     277                 :            : 
     278                 :            :         // calculate chunktype CRC (swap it back to original byte order)
     279                 :      37379 :         sal_uInt32 nChunkType = mnChunkType;
     280                 :            :         #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
     281                 :      37379 :         nChunkType = OSL_SWAPDWORD( nChunkType );
     282                 :            :         #endif
     283                 :      37379 :         sal_uInt32 nCRC32 = rtl_crc32( 0, &nChunkType, 4 );
     284                 :            : 
     285                 :            :         // read the chunk data and check the CRC
     286 [ +  - ][ +  + ]:      37379 :         if( mnChunkLen && !mrPNGStream.IsEof() )
                 [ +  + ]
     287                 :            :         {
     288         [ +  - ]:      35362 :             rChunkData.aData.resize( mnChunkLen );
     289                 :            : 
     290                 :      35362 :             sal_Int32 nBytesRead = 0;
     291   [ -  +  #  # ]:      35362 :             do {
                 [ -  + ]
     292         [ +  - ]:      35362 :                 sal_uInt8* pPtr = &rChunkData.aData[ nBytesRead ];
     293         [ +  - ]:      35362 :                 nBytesRead += mrPNGStream.Read( pPtr, mnChunkLen - nBytesRead );
     294                 :          0 :             } while ( ( nBytesRead < mnChunkLen ) && ( mrPNGStream.GetError() == ERRCODE_NONE ) );
     295                 :            : 
     296         [ +  - ]:      35362 :             nCRC32 = rtl_crc32( nCRC32, &rChunkData.aData[ 0 ], mnChunkLen );
     297                 :      35362 :             maDataIter = rChunkData.aData.begin();
     298                 :            :         }
     299                 :      37379 :         sal_uInt32 nCheck(0);
     300         [ +  - ]:      37379 :         mrPNGStream >> nCheck;
     301         [ +  + ]:      37379 :         if( nCRC32 != nCheck )
     302         [ +  + ]:      37397 :             return false;
     303                 :            :     }
     304                 :            :     else
     305                 :            :     {
     306                 :            :         // the next chunk was already read
     307                 :       7928 :         mnChunkType = (*maChunkIter).nType;
     308                 :       7928 :         mnChunkLen = (*maChunkIter).aData.size();
     309                 :       7928 :         maDataIter = (*maChunkIter).aData.begin();
     310                 :            :     }
     311                 :            : 
     312                 :      45298 :     ++maChunkIter;
     313         [ +  + ]:      45298 :     if( mnChunkType == PNGCHUNK_IEND )
     314                 :       2017 :         return false;
     315                 :      45325 :     return true;
     316                 :            : }
     317                 :            : 
     318                 :            : // ------------------------------------------------------------------------
     319                 :            : 
     320                 :            : // read the remaining chunks from mrPNGStream
     321                 :       2032 : void PNGReaderImpl::ReadRemainingChunks()
     322                 :            : {
     323         [ +  + ]:       9945 :     while( ReadNextChunk() ) ;
     324                 :       2032 : }
     325                 :            : 
     326                 :            : // ------------------------------------------------------------------------
     327                 :            : 
     328                 :       2032 : const std::vector< vcl::PNGReader::ChunkData >& PNGReaderImpl::GetAllChunks()
     329                 :            : {
     330                 :       2032 :     ReadRemainingChunks();
     331                 :       2032 :     return maChunkSeq;
     332                 :            : }
     333                 :            : 
     334                 :            : // ------------------------------------------------------------------------
     335                 :            : 
     336                 :       9430 : BitmapEx PNGReaderImpl::GetBitmapEx( const Size& rPreviewSizeHint )
     337                 :            : {
     338                 :            :     // reset to the first chunk
     339                 :       9430 :     maChunkIter = maChunkSeq.begin();
     340                 :            : 
     341                 :            :     // first chunk must be IDHR
     342 [ +  - ][ +  - ]:       9430 :     if( mbStatus && ReadNextChunk() )
                 [ +  - ]
     343                 :            :     {
     344         [ +  - ]:       9430 :         if (mnChunkType == PNGCHUNK_IHDR)
     345                 :       9430 :             mbStatus = ImplReadHeader( rPreviewSizeHint );
     346                 :            :         else
     347                 :          0 :             mbStatus = false;
     348                 :            :     }
     349                 :            : 
     350                 :            :     // parse the remaining chunks
     351 [ +  + ][ +  + ]:      35368 :     while( mbStatus && !mbIDAT && ReadNextChunk() )
         [ +  + ][ +  + ]
     352                 :            :     {
     353   [ -  +  +  +  :      25938 :         switch( mnChunkType )
             +  +  +  -  
                      + ]
     354                 :            :         {
     355                 :            :             case PNGCHUNK_IHDR :
     356                 :            :             {
     357                 :          0 :                 mbStatus = false; //IHDR should only appear as the first chunk
     358                 :            :             }
     359                 :          0 :             break;
     360                 :            : 
     361                 :            :             case PNGCHUNK_gAMA :                                // the gamma chunk must precede
     362                 :            :             {                                                   // the 'IDAT' and also the 'PLTE'(if available )
     363 [ -  + ][ #  # ]:        522 :                 if ( !mbIgnoreGammaChunk && ( mbIDAT == sal_False ) )
     364                 :          0 :                     ImplGetGamma();
     365                 :            :             }
     366                 :        522 :             break;
     367                 :            : 
     368                 :            :             case PNGCHUNK_PLTE :
     369                 :            :             {
     370         [ +  - ]:       1197 :                 if ( !mbPalette )
     371                 :       1197 :                     mbStatus = ImplReadPalette();
     372                 :            :             }
     373                 :       1197 :             break;
     374                 :            : 
     375                 :            :             case PNGCHUNK_tRNS :
     376                 :            :             {
     377         [ +  - ]:       1115 :                 if ( !mbIDAT )                                  // the tRNS chunk must precede the IDAT
     378                 :       1115 :                     mbStatus = ImplReadTransparent();
     379                 :            :             }
     380                 :       1115 :             break;
     381                 :            : 
     382                 :            :             case PNGCHUNK_bKGD :                                // the background chunk must appear
     383                 :            :             {
     384 [ +  - ][ +  - ]:        424 :                 if ( ( mbIDAT == sal_False ) && mbPalette )         // before the 'IDAT' and after the
     385                 :        424 :                     ImplGetBackground();                        // PLTE(if available ) chunk.
     386                 :            :             }
     387                 :        424 :             break;
     388                 :            : 
     389                 :            :             case PNGCHUNK_IDAT :
     390                 :            :             {
     391         [ -  + ]:       9424 :                 if ( !mpInflateInBuf )  // taking care that the header has properly been read
     392                 :          0 :                     mbStatus = sal_False;
     393         [ +  - ]:       9424 :                 else if ( !mbIDAT )     // the gfx is finished, but there may be left a zlibCRC of about 4Bytes
     394                 :       9424 :                     ImplReadIDAT();
     395                 :            :             }
     396                 :       9424 :             break;
     397                 :            : 
     398                 :            :             case PNGCHUNK_pHYs :
     399                 :            :             {
     400 [ +  - ][ +  + ]:       2931 :                 if ( !mbIDAT && mnChunkLen == 9 )
     401                 :            :                 {
     402                 :       2928 :                     sal_uInt32 nXPixelPerMeter = ImplReadsal_uInt32();
     403                 :       2928 :                     sal_uInt32 nYPixelPerMeter = ImplReadsal_uInt32();
     404                 :            : 
     405         [ +  - ]:       2928 :                     sal_uInt8 nUnitSpecifier = *maDataIter++;
     406 [ +  + ][ +  - ]:       2928 :                     if( (nUnitSpecifier == 1) && nXPixelPerMeter && nYPixelPerMeter )
                 [ +  - ]
     407                 :            :                     {
     408                 :       2916 :                         mbpHYs = sal_True;
     409                 :            : 
     410                 :            :                         // convert into MAP_100TH_MM
     411                 :       2916 :                         maPhysSize.Width()  = (sal_Int32)( (100000.0 * maOrigSize.Width()) / nXPixelPerMeter );
     412                 :       2916 :                         maPhysSize.Height() = (sal_Int32)( (100000.0 * maOrigSize.Height()) / nYPixelPerMeter );
     413                 :            :                     }
     414                 :            :                 }
     415                 :            :             }
     416                 :       2931 :             break;
     417                 :            : 
     418                 :            :             case PNGCHUNK_IEND:
     419                 :          0 :                 mbStatus = mbIDAT;  // there is a problem if the image is not complete yet
     420                 :          0 :             break;
     421                 :            :         }
     422                 :            :     }
     423                 :            : 
     424                 :            :     // release write access of the bitmaps
     425         [ +  + ]:       9430 :     if ( mpAcc )
     426                 :       9427 :         mpBmp->ReleaseAccess( mpAcc ), mpAcc = NULL;
     427                 :            : 
     428         [ +  + ]:       9430 :     if ( mpMaskAcc )
     429                 :            :     {
     430         [ +  + ]:       8907 :         if ( mpAlphaMask )
     431                 :       8688 :             mpAlphaMask->ReleaseAccess( mpMaskAcc );
     432         [ +  - ]:        219 :         else if ( mpMaskBmp )
     433                 :        219 :             mpMaskBmp->ReleaseAccess( mpMaskAcc );
     434                 :            : 
     435                 :       8907 :         mpMaskAcc = NULL;
     436                 :            :     }
     437                 :            : 
     438                 :            :     // return the resulting BitmapEx
     439                 :       9430 :     BitmapEx aRet;
     440                 :            : 
     441 [ +  + ][ +  + ]:       9430 :     if( !mbStatus || !mbIDAT )
     442         [ +  - ]:         15 :         aRet.Clear();
     443                 :            :     else
     444                 :            :     {
     445         [ +  + ]:       9415 :         if ( mpAlphaMask )
     446 [ +  - ][ +  - ]:       8688 :             aRet = BitmapEx( *mpBmp, *mpAlphaMask );
                 [ +  - ]
     447         [ +  + ]:        727 :         else if ( mpMaskBmp )
     448 [ +  - ][ +  - ]:        216 :             aRet = BitmapEx( *mpBmp, *mpMaskBmp );
                 [ +  - ]
     449                 :            :         else
     450 [ +  - ][ +  - ]:        511 :             aRet = *mpBmp;
                 [ +  - ]
     451                 :            : 
     452 [ +  + ][ +  - ]:       9415 :         if ( mbpHYs && maPhysSize.Width() && maPhysSize.Height() )
         [ +  - ][ +  + ]
     453                 :            :         {
     454 [ +  - ][ +  - ]:       2916 :             aRet.SetPrefMapMode( MAP_100TH_MM );
                 [ +  - ]
     455                 :       2916 :             aRet.SetPrefSize( maPhysSize );
     456                 :            :         }
     457                 :            : 
     458                 :            :     }
     459                 :            : 
     460                 :       9430 :     return aRet;
     461                 :            : }
     462                 :            : 
     463                 :            : // ------------------------------------------------------------------------
     464                 :            : 
     465                 :       9430 : sal_Bool PNGReaderImpl::ImplReadHeader( const Size& rPreviewSizeHint )
     466                 :            : {
     467         [ -  + ]:       9430 :     if( mnChunkLen < 13 )
     468                 :          0 :         return sal_False;
     469                 :            : 
     470                 :       9430 :     maOrigSize.Width()  = ImplReadsal_uInt32();
     471                 :       9430 :     maOrigSize.Height() = ImplReadsal_uInt32();
     472                 :            : 
     473 [ -  + ][ -  + ]:       9430 :     if (maOrigSize.Width() <= 0 || maOrigSize.Height() <= 0)
                 [ +  - ]
     474                 :          0 :         return sal_False;
     475                 :            : 
     476         [ +  - ]:       9430 :     mnPngDepth = *(maDataIter++);
     477         [ +  - ]:       9430 :     mnColorType = *(maDataIter++);
     478                 :            : 
     479         [ +  - ]:       9430 :     mnCompressionType = *(maDataIter++);
     480         [ -  + ]:       9430 :     if( mnCompressionType != 0 )    // unknown compression type
     481                 :          0 :         return sal_False;
     482                 :            : 
     483         [ +  - ]:       9430 :     mnFilterType = *(maDataIter++);
     484         [ -  + ]:       9430 :     if( mnFilterType != 0 )         // unknown filter type
     485                 :          0 :         return sal_False;
     486                 :            : 
     487         [ +  - ]:       9430 :     mnInterlaceType = *(maDataIter++);
     488      [ +  +  - ]:       9430 :     switch ( mnInterlaceType ) // filter type valid ?
     489                 :            :     {
     490                 :            :         case 0 :  // progressive image
     491                 :       9427 :             mnPass = 7;
     492                 :       9427 :             break;
     493                 :            :         case 1 :  // Adam7-interlaced image
     494                 :          3 :             mnPass = 0;
     495                 :          3 :             break;
     496                 :            :         default:
     497                 :          0 :             return sal_False;
     498                 :            :     }
     499                 :            : 
     500                 :       9430 :     mbPalette = sal_True;
     501                 :       9430 :     mbIDAT = mbAlphaChannel = mbTransparent = sal_False;
     502                 :       9430 :     mbGrayScale = mbRGBTriple = sal_False;
     503                 :       9430 :     mnTargetDepth = mnPngDepth;
     504                 :       9430 :     sal_uInt64 nScansize64 = ( ( static_cast< sal_uInt64 >( maOrigSize.Width() ) * mnPngDepth ) + 7 ) >> 3;
     505                 :            : 
     506                 :            :     // valid color types are 0,2,3,4 & 6
     507   [ +  +  +  +  :       9430 :     switch ( mnColorType )
                   +  - ]
     508                 :            :     {
     509                 :            :         case 0 :    // each pixel is a grayscale
     510                 :            :         {
     511   [ -  -  +  - ]:        142 :             switch ( mnPngDepth )
     512                 :            :             {
     513                 :            :                 case 2 : // 2bit target not available -> use four bits
     514                 :          0 :                     mnTargetDepth = 4;  // we have to expand the bitmap
     515                 :          0 :                     mbGrayScale = sal_True;
     516                 :          0 :                     break;
     517                 :            :                 case 16 :
     518                 :          0 :                     mnTargetDepth = 8;  // we have to reduce the bitmap
     519                 :            :                     // fall through
     520                 :            :                 case 1 :
     521                 :            :                 case 4 :
     522                 :            :                 case 8 :
     523                 :        142 :                     mbGrayScale = sal_True;
     524                 :        142 :                     break;
     525                 :            :                 default :
     526                 :          0 :                     return sal_False;
     527                 :            :             }
     528                 :            :         }
     529                 :        142 :         break;
     530                 :            : 
     531                 :            :         case 2 :    // each pixel is an RGB triple
     532                 :            :         {
     533                 :        290 :             mbRGBTriple = sal_True;
     534                 :        290 :             nScansize64 *= 3;
     535         [ +  - ]:        290 :             switch ( mnPngDepth )
     536                 :            :             {
     537                 :            :                 case 16 :           // we have to reduce the bitmap
     538                 :            :                 case 8 :
     539                 :        290 :                     mnTargetDepth = 24;
     540                 :        290 :                     break;
     541                 :            :                 default :
     542                 :          0 :                     return sal_False;
     543                 :            :             }
     544                 :            :         }
     545                 :        290 :         break;
     546                 :            : 
     547                 :            :         case 3 :    // each pixel is a palette index
     548                 :            :         {
     549      [ +  +  - ]:       1206 :             switch ( mnPngDepth )
     550                 :            :             {
     551                 :            :                 case 2 :
     552                 :         82 :                     mnTargetDepth = 4;  // we have to expand the bitmap
     553                 :            :                     // fall through
     554                 :            :                 case 1 :
     555                 :            :                 case 4 :
     556                 :            :                 case 8 :
     557                 :       1206 :                     mbPalette = sal_False;
     558                 :       1206 :                     break;
     559                 :            :                 default :
     560                 :          0 :                     return sal_False;
     561                 :            :             }
     562                 :            :         }
     563                 :       1206 :         break;
     564                 :            : 
     565                 :            :         case 4 :    // each pixel is a grayscale sample followed by an alpha sample
     566                 :            :         {
     567                 :        341 :             nScansize64 *= 2;
     568                 :        341 :             mbAlphaChannel = sal_True;
     569      [ -  +  - ]:        341 :             switch ( mnPngDepth )
     570                 :            :             {
     571                 :            :                 case 16 :
     572                 :          0 :                     mnTargetDepth = 8;  // we have to reduce the bitmap
     573                 :            :                 case 8 :
     574                 :        341 :                     mbGrayScale = sal_True;
     575                 :        341 :                     break;
     576                 :            :                 default :
     577                 :          0 :                     return sal_False;
     578                 :            :             }
     579                 :            :         }
     580                 :        341 :         break;
     581                 :            : 
     582                 :            :         case 6 :    // each pixel is an RGB triple followed by an alpha sample
     583                 :            :         {
     584                 :       7451 :             mbRGBTriple = sal_True;
     585                 :       7451 :             nScansize64 *= 4;
     586                 :       7451 :             mbAlphaChannel = sal_True;
     587         [ +  - ]:       7451 :             switch (mnPngDepth )
     588                 :            :             {
     589                 :            :                 case 16 :           // we have to reduce the bitmap
     590                 :            :                 case 8 :
     591                 :       7451 :                     mnTargetDepth = 24;
     592                 :       7451 :                     break;
     593                 :            :                 default :
     594                 :          0 :                     return sal_False;
     595                 :            :             }
     596                 :            :         }
     597                 :       7451 :         break;
     598                 :            : 
     599                 :            :         default :
     600                 :          0 :             return sal_False;
     601                 :            :     }
     602                 :            : 
     603                 :       9430 :     mnBPP = static_cast< sal_uInt32 >( nScansize64 / maOrigSize.Width() );
     604         [ +  + ]:       9430 :     if ( !mnBPP )
     605                 :        243 :         mnBPP = 1;
     606                 :            : 
     607                 :       9430 :     nScansize64++;       // each scanline includes one filterbyte
     608                 :            : 
     609         [ -  + ]:       9430 :     if ( nScansize64 > SAL_MAX_UINT32 )
     610                 :          0 :         return sal_False;
     611                 :            : 
     612                 :       9430 :     mnScansize = static_cast< sal_uInt32 >( nScansize64 );
     613                 :            : 
     614                 :            :     // calculate target size from original size and the preview hint
     615 [ +  - ][ -  + ]:       9430 :     if( rPreviewSizeHint.Width() || rPreviewSizeHint.Height() )
                 [ -  + ]
     616                 :            :     {
     617                 :          0 :         Size aPreviewSize( rPreviewSizeHint.Width(), rPreviewSizeHint.Height() );
     618                 :          0 :         maTargetSize = maOrigSize;
     619                 :            : 
     620         [ #  # ]:          0 :         if( aPreviewSize.Width() == 0 ) {
     621                 :          0 :             aPreviewSize.setWidth( ( maOrigSize.Width()*aPreviewSize.Height() )/maOrigSize.Height() );
     622         [ #  # ]:          0 :             if( aPreviewSize.Width() <= 0 )
     623                 :          0 :                 aPreviewSize.setWidth( 1 );
     624         [ #  # ]:          0 :         } else if( aPreviewSize.Height() == 0 ) {
     625                 :          0 :             aPreviewSize.setHeight( ( maOrigSize.Height()*aPreviewSize.Width() )/maOrigSize.Width() );
     626         [ #  # ]:          0 :             if( aPreviewSize.Height() <= 0 )
     627                 :          0 :                 aPreviewSize.setHeight( 1 );
     628                 :            :         }
     629                 :            : 
     630 [ #  # ][ #  # ]:          0 :         if( aPreviewSize.Width() < maOrigSize.Width() && aPreviewSize.Height() < maOrigSize.Height() ) {
                 [ #  # ]
     631                 :            :             OSL_TRACE("preview size %dx%d", aPreviewSize.Width(), aPreviewSize.Height() );
     632                 :            : 
     633         [ #  # ]:          0 :             for( int i = 1; i < 5; ++i )
     634                 :            :                 {
     635         [ #  # ]:          0 :                     if( (maTargetSize.Width() >> i) < aPreviewSize.Width() )
     636                 :          0 :                         break;
     637         [ #  # ]:          0 :                     if( (maTargetSize.Height() >> i) < aPreviewSize.Height() )
     638                 :          0 :                         break;
     639                 :          0 :                     mnPreviewShift = i;
     640                 :            :                 }
     641                 :          0 :             mnPreviewMask = (1 << mnPreviewShift) - 1;
     642                 :            :         }
     643                 :            :     }
     644                 :            : 
     645                 :       9430 :     maTargetSize.Width()  = (maOrigSize.Width() + mnPreviewMask) >> mnPreviewShift;
     646                 :       9430 :     maTargetSize.Height() = (maOrigSize.Height() + mnPreviewMask) >> mnPreviewShift;
     647                 :            : 
     648                 :            :     //round bits up to nearest multiple of 8 and divide by 8 to get num of bytes per pixel
     649                 :       9430 :     int nBytesPerPixel = ((mnTargetDepth + 7) & ~7)/8;
     650                 :            : 
     651                 :            :     //stupidly big, forget about it
     652         [ +  + ]:       9430 :     if (maTargetSize.Width() >= SAL_MAX_INT32 / nBytesPerPixel / maTargetSize.Height())
     653                 :            :     {
     654                 :            :         SAL_WARN( "vcl", "overlarge png dimensions: " <<
     655                 :            :             maTargetSize.Width() << " x " << maTargetSize.Height() << " depth: " << mnTargetDepth);
     656                 :          3 :         return sal_False;
     657                 :            :     }
     658                 :            : 
     659                 :            :     // TODO: switch between both scanlines instead of copying
     660                 :       9427 :     mpInflateInBuf = new (std::nothrow) sal_uInt8[ mnScansize ];
     661                 :       9427 :     mpScanCurrent = mpInflateInBuf;
     662                 :       9427 :     mpScanPrior = new (std::nothrow) sal_uInt8[ mnScansize ];
     663                 :            : 
     664 [ -  + ][ +  - ]:       9427 :     if ( !mpInflateInBuf || !mpScanPrior )
     665                 :          0 :         return sal_False;
     666                 :            : 
     667         [ +  - ]:       9427 :     mpBmp = new Bitmap( maTargetSize, mnTargetDepth );
     668                 :       9427 :     mpAcc = mpBmp->AcquireWriteAccess();
     669         [ -  + ]:       9427 :     if( !mpAcc )
     670                 :          0 :         return sal_False;
     671                 :            : 
     672                 :       9427 :     mpBmp->SetSourceSizePixel( maOrigSize );
     673                 :            : 
     674         [ +  + ]:       9427 :     if ( mbAlphaChannel )
     675                 :            :     {
     676         [ +  - ]:       7792 :         mpAlphaMask = new AlphaMask( maTargetSize );
     677                 :       7792 :         mpAlphaMask->Erase( 128 );
     678                 :       7792 :         mpMaskAcc = mpAlphaMask->AcquireWriteAccess();
     679         [ -  + ]:       7792 :         if( !mpMaskAcc )
     680                 :          0 :             return sal_False;
     681                 :            :     }
     682                 :            : 
     683         [ +  + ]:       9427 :     if ( mbGrayScale )
     684                 :        480 :         ImplGetGrayPalette( mnPngDepth );
     685                 :            : 
     686                 :       9427 :     ImplPreparePass();
     687                 :            : 
     688                 :       9430 :     return sal_True;
     689                 :            : }
     690                 :            : 
     691                 :            : // ------------------------------------------------------------------------
     692                 :            : 
     693                 :        480 : void PNGReaderImpl::ImplGetGrayPalette( sal_uInt16 nBitDepth )
     694                 :            : {
     695         [ -  + ]:        480 :     if( nBitDepth > 8 )
     696                 :          0 :         nBitDepth = 8;
     697                 :            : 
     698                 :        480 :     sal_uInt16  nPaletteEntryCount = 1 << nBitDepth;
     699         [ +  - ]:        480 :     sal_uInt32  nAdd = nBitDepth ? 256 / (nPaletteEntryCount - 1) : 0;
     700                 :            : 
     701                 :            :     // no bitdepth==2 available
     702                 :            :     // but bitdepth==4 with two unused bits is close enough
     703         [ -  + ]:        480 :     if( nBitDepth == 2 )
     704                 :          0 :         nPaletteEntryCount = 16;
     705                 :            : 
     706                 :        480 :     mpAcc->SetPaletteEntryCount( nPaletteEntryCount );
     707         [ +  + ]:     101685 :     for ( sal_uInt32 i = 0, nStart = 0; nStart < 256; i++, nStart += nAdd )
     708                 :     101205 :         mpAcc->SetPaletteColor( (sal_uInt16)i, BitmapColor( mpColorTable[ nStart ],
     709                 :     101205 :             mpColorTable[ nStart ], mpColorTable[ nStart ] ) );
     710                 :        480 : }
     711                 :            : 
     712                 :            : // ------------------------------------------------------------------------
     713                 :            : 
     714                 :       1197 : sal_Bool PNGReaderImpl::ImplReadPalette()
     715                 :            : {
     716                 :       1197 :     sal_uInt16 nCount = static_cast<sal_uInt16>( mnChunkLen / 3 );
     717                 :            : 
     718 [ +  - ][ +  - ]:       1197 :     if ( ( ( mnChunkLen % 3 ) == 0 ) && ( ( 0 < nCount ) && ( nCount <= 256 ) ) && mpAcc )
         [ +  - ][ +  - ]
     719                 :            :     {
     720                 :       1197 :         mbPalette = sal_True;
     721                 :       1197 :         mpAcc->SetPaletteEntryCount( (sal_uInt16) nCount );
     722                 :            : 
     723         [ +  + ]:     103208 :         for ( sal_uInt16 i = 0; i < nCount; i++ )
     724                 :            :         {
     725         [ +  - ]:     102011 :             sal_uInt8 nRed =   mpColorTable[ *maDataIter++ ];
     726         [ +  - ]:     102011 :             sal_uInt8 nGreen = mpColorTable[ *maDataIter++ ];
     727         [ +  - ]:     102011 :             sal_uInt8 nBlue =  mpColorTable[ *maDataIter++ ];
     728                 :     102011 :             mpAcc->SetPaletteColor( i, Color( nRed, nGreen, nBlue ) );
     729                 :       1197 :         }
     730                 :            :     }
     731                 :            :     else
     732                 :          0 :         mbStatus = sal_False;
     733                 :            : 
     734                 :       1197 :     return mbStatus;
     735                 :            : }
     736                 :            : 
     737                 :            : // ------------------------------------------------------------------------
     738                 :            : 
     739                 :       1115 : sal_Bool PNGReaderImpl::ImplReadTransparent()
     740                 :            : {
     741                 :       1115 :     bool bNeedAlpha = false;
     742                 :            : 
     743         [ +  - ]:       1115 :     if ( mpTransTab == NULL )
     744                 :            :     {
     745   [ +  +  +  - ]:       1115 :         switch ( mnColorType )
     746                 :            :         {
     747                 :            :             case 0 :
     748                 :            :             {
     749         [ +  - ]:         58 :                 if ( mnChunkLen == 2 )
     750                 :            :                 {
     751                 :         58 :                     mpTransTab = new sal_uInt8[ 256 ];
     752                 :         58 :                     memset( mpTransTab, 0xff, 256);
     753                 :            :                     // color type 0 and 4 is always greyscale,
     754                 :            :                     // so the return value can be used as index
     755                 :         58 :                     sal_uInt8 nIndex = ImplScaleColor();
     756                 :         58 :                     mpTransTab[ nIndex ] = 0;
     757                 :         58 :                     mbTransparent = true;
     758                 :            :                 }
     759                 :            :             }
     760                 :         58 :             break;
     761                 :            : 
     762                 :            :             case 2 :
     763                 :            :             {
     764         [ +  - ]:         36 :                 if ( mnChunkLen == 6 )
     765                 :            :                 {
     766                 :         36 :                     mnTransRed = ImplScaleColor();
     767                 :         36 :                     mnTransGreen = ImplScaleColor();
     768                 :         36 :                     mnTransBlue = ImplScaleColor();
     769                 :         36 :                     mbTransparent = true;
     770                 :            :                 }
     771                 :            :             }
     772                 :         36 :             break;
     773                 :            : 
     774                 :            :             case 3 :
     775                 :            :             {
     776         [ +  - ]:       1021 :                 if ( mnChunkLen <= 256 )
     777                 :            :                 {
     778                 :       1021 :                     mbTransparent = true;
     779                 :       1021 :                     mpTransTab = new sal_uInt8 [ 256 ];
     780                 :       1021 :                     memset( mpTransTab, 0xff, 256 );
     781         [ +  + ]:       1021 :                     if (mnChunkLen > 0)
     782                 :            :                     {
     783                 :       1018 :                         memcpy( mpTransTab, &(*maDataIter), mnChunkLen );
     784         [ +  - ]:       1018 :                         maDataIter += mnChunkLen;
     785                 :            :                         // need alpha transparency if not on/off masking
     786         [ +  + ]:      20266 :                         for( int i = 0; i < mnChunkLen; ++i )
     787 [ +  + ][ +  + ]:      19248 :                            bNeedAlpha |= (mpTransTab[i]!=0x00) && (mpTransTab[i]!=0xFF);
     788                 :            :                     }
     789                 :            :                 }
     790                 :            :             }
     791                 :       1115 :             break;
     792                 :            :         }
     793                 :            :     }
     794                 :            : 
     795 [ +  - ][ +  - ]:       1115 :     if( mbTransparent && !mbAlphaChannel && !mpMaskBmp )
                 [ +  - ]
     796                 :            :     {
     797         [ +  + ]:       1115 :         if( bNeedAlpha)
     798                 :            :         {
     799         [ +  - ]:        896 :             mpAlphaMask = new AlphaMask( maTargetSize );
     800                 :        896 :             mpMaskAcc = mpAlphaMask->AcquireWriteAccess();
     801                 :            :         }
     802                 :            :         else
     803                 :            :         {
     804         [ +  - ]:        219 :             mpMaskBmp = new Bitmap( maTargetSize, 1 );
     805                 :        219 :             mpMaskAcc = mpMaskBmp->AcquireWriteAccess();
     806                 :            :         }
     807                 :       1115 :         mbTransparent = (mpMaskAcc != NULL);
     808         [ -  + ]:       1115 :         if( !mbTransparent )
     809                 :          0 :             return sal_False;
     810                 :       1115 :         mcOpaqueColor = BitmapColor( 0x00 );
     811                 :       1115 :         mcTranspColor = BitmapColor( 0xFF );
     812         [ +  - ]:       1115 :         mpMaskAcc->Erase( 0x00 );
     813                 :            :     }
     814                 :            : 
     815                 :       1115 :     return sal_True;
     816                 :            : }
     817                 :            : 
     818                 :            : // ------------------------------------------------------------------------
     819                 :            : 
     820                 :          0 : void PNGReaderImpl::ImplGetGamma()
     821                 :            : {
     822         [ #  # ]:          0 :     if( mnChunkLen < 4 )
     823                 :          0 :         return;
     824                 :            : 
     825                 :          0 :     sal_uInt32  nGammaValue = ImplReadsal_uInt32();
     826                 :          0 :     double      fGamma = ( ( VIEWING_GAMMA / DISPLAY_GAMMA ) * ( (double)nGammaValue / 100000 ) );
     827 [ #  # ][ #  # ]:          0 :     double      fInvGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
     828                 :            : 
     829         [ #  # ]:          0 :     if ( fInvGamma != 1.0 )
     830                 :            :     {
     831                 :          0 :         mbGamma = sal_True;
     832                 :            : 
     833         [ #  # ]:          0 :         if ( mpColorTable == mpDefaultColorTable )
     834                 :          0 :             mpColorTable = new sal_uInt8[ 256 ];
     835                 :            : 
     836         [ #  # ]:          0 :         for ( sal_Int32 i = 0; i < 256; i++ )
     837                 :          0 :             mpColorTable[ i ] = (sal_uInt8)(pow((double)i/255.0, fInvGamma) * 255.0 + 0.5);
     838                 :            : 
     839         [ #  # ]:          0 :         if ( mbGrayScale )
     840                 :          0 :             ImplGetGrayPalette( mnPngDepth );
     841                 :            :     }
     842                 :            : }
     843                 :            : 
     844                 :            : // ------------------------------------------------------------------------
     845                 :            : 
     846                 :        424 : void PNGReaderImpl::ImplGetBackground()
     847                 :            : {
     848   [ +  +  +  - ]:        424 :     switch ( mnColorType )
     849                 :            :     {
     850                 :            :         case 3 :
     851                 :            :         {
     852         [ +  - ]:         72 :             if ( mnChunkLen == 1 )
     853                 :            :             {
     854         [ +  - ]:         72 :                 sal_uInt16 nCol = *maDataIter++;
     855         [ +  - ]:         72 :                 if ( nCol < mpAcc->GetPaletteEntryCount() )
     856                 :            :                 {
     857         [ +  - ]:         72 :                     mpAcc->Erase( mpAcc->GetPaletteColor( (sal_uInt8)nCol ) );
     858                 :         72 :                     break;
     859                 :            :                 }
     860                 :            :             }
     861                 :            :         }
     862                 :          0 :         break;
     863                 :            : 
     864                 :            :         case 0 :
     865                 :            :         case 4 :
     866                 :            :         {
     867         [ +  - ]:         38 :             if ( mnChunkLen == 2 )
     868                 :            :             {
     869                 :            :                 // the color type 0 and 4 is always greyscale,
     870                 :            :                 // so the return value can be used as index
     871                 :         38 :                 sal_uInt8 nIndex = ImplScaleColor();
     872         [ +  - ]:         38 :                 mpAcc->Erase( mpAcc->GetPaletteColor( nIndex ) );
     873                 :            :             }
     874                 :            :         }
     875                 :         38 :         break;
     876                 :            : 
     877                 :            :         case 2 :
     878                 :            :         case 6 :
     879                 :            :         {
     880         [ +  - ]:        314 :             if ( mnChunkLen == 6 )
     881                 :            :             {
     882                 :        314 :                 sal_uInt8 nRed = ImplScaleColor();
     883                 :        314 :                 sal_uInt8 nGreen = ImplScaleColor();
     884                 :        314 :                 sal_uInt8 nBlue = ImplScaleColor();
     885         [ +  - ]:        314 :                 mpAcc->Erase( Color( nRed, nGreen, nBlue ) );
     886                 :            :             }
     887                 :            :         }
     888                 :        314 :         break;
     889                 :            :     }
     890                 :        424 : }
     891                 :            : 
     892                 :            : // ------------------------------------------------------------------------
     893                 :            : 
     894                 :            : // for color type 0 and 4 (greyscale) the return value is always index to the color
     895                 :            : //                2 and 6 (RGB)       the return value is always the 8 bit color component
     896                 :       1146 : sal_uInt8 PNGReaderImpl::ImplScaleColor()
     897                 :            : {
     898                 :       1146 :     sal_uInt32 nMask = ( ( 1 << mnPngDepth ) - 1 );
     899         [ +  - ]:       1146 :     sal_uInt16 nCol = ( *maDataIter++ << 8 );
     900                 :            : 
     901         [ +  - ]:       1146 :     nCol += *maDataIter++ & (sal_uInt16)nMask;
     902                 :            : 
     903         [ -  + ]:       1146 :     if ( mnPngDepth > 8 )   // convert 16bit graphics to 8
     904                 :          0 :         nCol >>= 8;
     905                 :            : 
     906                 :       1146 :     return (sal_uInt8) nCol;
     907                 :            : }
     908                 :            : 
     909                 :            : // ------------------------------------------------------------------------
     910                 :            : // ImplReadIDAT reads as much image data as needed
     911                 :            : 
     912                 :       9424 : void PNGReaderImpl::ImplReadIDAT()
     913                 :            : {
     914         [ +  - ]:       9424 :     if( mnChunkLen > 0 )
     915                 :            :     {
     916         [ +  + ]:       9424 :         if ( mbzCodecInUse == sal_False )
     917                 :            :         {
     918                 :       9415 :             mbzCodecInUse = sal_True;
     919         [ +  - ]:       9415 :             mpZCodec->BeginCompression( ZCODEC_PNG_DEFAULT );
     920                 :            :         }
     921         [ +  - ]:       9424 :         mpZCodec->SetBreak( mnChunkLen );
     922 [ +  - ][ +  - ]:       9424 :         SvMemoryStream aIStrm( &(*maDataIter), mnChunkLen, STREAM_READ );
     923                 :            : 
     924 [ +  - ][ +  - ]:     182131 :         while ( ( mpZCodec->GetBreak() ) )
     925                 :            :         {
     926                 :            :             // get bytes needed to fill the current scanline
     927                 :     182131 :             sal_Int32 nToRead = mnScansize - (mpScanCurrent - mpInflateInBuf);
     928         [ +  - ]:     182131 :             sal_Int32 nRead = mpZCodec->ReadAsynchron( aIStrm, mpScanCurrent, nToRead );
     929         [ -  + ]:     182131 :             if ( nRead < 0 )
     930                 :            :             {
     931                 :          0 :                 mbStatus = sal_False;
     932                 :          0 :                 break;
     933                 :            :             }
     934         [ +  + ]:     182131 :             if ( nRead < nToRead )
     935                 :            :             {
     936                 :          9 :                 mpScanCurrent += nRead; // more ZStream data in the next IDAT chunk
     937                 :          9 :                 break;
     938                 :            :             }
     939                 :            :             else  // this scanline is Finished
     940                 :            :             {
     941                 :     182122 :                 mpScanCurrent = mpInflateInBuf;
     942                 :     182122 :                 ImplApplyFilter();
     943                 :            : 
     944         [ +  - ]:     182122 :                 ImplDrawScanline( mnXStart, mnXAdd );
     945                 :     182122 :                 mnYpos += mnYAdd;
     946                 :            :             }
     947                 :            : 
     948         [ +  + ]:     182122 :             if ( mnYpos >= (sal_uInt32)maOrigSize.Height() )
     949                 :            :             {
     950 [ -  + ][ #  # ]:       9415 :                 if( (mnPass < 7) && mnInterlaceType )
     951         [ #  # ]:          0 :                     if( ImplPreparePass() )
     952                 :          0 :                         continue;
     953                 :       9415 :                 mbIDAT = true;
     954                 :       9415 :                 break;
     955                 :            :             }
     956         [ +  - ]:       9424 :         }
     957                 :            :     }
     958                 :            : 
     959         [ +  + ]:       9424 :     if( mbIDAT )
     960                 :            :     {
     961                 :       9415 :         mpZCodec->EndCompression();
     962                 :       9415 :         mbzCodecInUse = sal_False;
     963                 :            :     }
     964                 :       9424 : }
     965                 :            : 
     966                 :            : // ---------------------------------------------------------------------------------------------------
     967                 :            : 
     968                 :       9427 : bool PNGReaderImpl::ImplPreparePass()
     969                 :            : {
     970                 :            :     struct InterlaceParams{ int mnXStart, mnYStart, mnXAdd, mnYAdd; };
     971                 :            :     static const InterlaceParams aInterlaceParams[8] =
     972                 :            :     {
     973                 :            :         // non-interlaced
     974                 :            :         { 0, 0, 1, 1 },
     975                 :            :         // Adam7-interlaced
     976                 :            :         { 0, 0, 8, 8 },    // pass 1
     977                 :            :         { 4, 0, 8, 8 },    // pass 2
     978                 :            :         { 0, 4, 4, 8 },    // pass 3
     979                 :            :         { 2, 0, 4, 4 },    // pass 4
     980                 :            :         { 0, 2, 2, 4 },    // pass 5
     981                 :            :         { 1, 0, 2, 2 },    // pass 6
     982                 :            :         { 0, 1, 1, 2 }     // pass 7
     983                 :            :     };
     984                 :            : 
     985                 :       9427 :     const InterlaceParams* pParam = &aInterlaceParams[ 0 ];
     986         [ +  + ]:       9427 :     if( mnInterlaceType )
     987                 :            :     {
     988         [ +  - ]:          3 :         while( ++mnPass <= 7 )
     989                 :            :         {
     990                 :          3 :             pParam = &aInterlaceParams[ mnPass ];
     991                 :            : 
     992                 :            :             // skip this pass if the original image is too small for it
     993   [ +  -  +  - ]:          6 :             if( (pParam->mnXStart < maOrigSize.Width())
                 [ +  - ]
     994                 :          3 :             &&  (pParam->mnYStart < maOrigSize.Height()) )
     995                 :          3 :                 break;
     996                 :            :         }
     997         [ -  + ]:          3 :         if( mnPass > 7 )
     998                 :          0 :             return false;
     999                 :            : 
    1000                 :            :         // skip the last passes if possible (for scaled down target images)
    1001         [ -  + ]:          3 :         if( mnPreviewMask & (pParam->mnXStart | pParam->mnYStart) )
    1002                 :          0 :             return false;
    1003                 :            :     }
    1004                 :            : 
    1005                 :       9427 :     mnYpos      = pParam->mnYStart;
    1006                 :       9427 :     mnXStart    = pParam->mnXStart;
    1007                 :       9427 :     mnXAdd      = pParam->mnXAdd;
    1008                 :       9427 :     mnYAdd      = pParam->mnYAdd;
    1009                 :            : 
    1010                 :            :     // in Interlace mode the size of scanline is not constant
    1011                 :            :     // so first we calculate the number of entrys
    1012                 :       9427 :     long nScanWidth = (maOrigSize.Width() - mnXStart + mnXAdd - 1) / mnXAdd;
    1013                 :       9427 :     mnScansize = nScanWidth;
    1014                 :            : 
    1015         [ +  + ]:       9427 :     if( mbRGBTriple )
    1016                 :       7741 :         mnScansize = 3 * nScanWidth;
    1017                 :            : 
    1018         [ +  + ]:       9427 :     if( mbAlphaChannel )
    1019                 :       7792 :         mnScansize += nScanWidth;
    1020                 :            : 
    1021                 :            :     // convert to width in bytes
    1022                 :       9427 :     mnScansize = ( mnScansize*mnPngDepth + 7 ) >> 3;
    1023                 :            : 
    1024                 :       9427 :     ++mnScansize; // scan size also needs room for the filtertype byte
    1025                 :       9427 :     memset( mpScanPrior, 0, mnScansize );
    1026                 :            : 
    1027                 :       9427 :     return true;
    1028                 :            : }
    1029                 :            : 
    1030                 :            : // ----------------------------------------------------------------------------
    1031                 :            : // ImplApplyFilter writes the complete Scanline (nY)
    1032                 :            : // in interlace mode the parameter nXStart and nXAdd are non-zero
    1033                 :            : 
    1034                 :     182122 : void PNGReaderImpl::ImplApplyFilter()
    1035                 :            : {
    1036                 :            :     OSL_ASSERT( mnScansize >= mnBPP + 1 );
    1037                 :     182122 :     const sal_uInt8* const pScanEnd = mpInflateInBuf + mnScansize;
    1038                 :            : 
    1039                 :     182122 :     sal_uInt8 nFilterType = *mpInflateInBuf; // the filter type may change each scanline
    1040   [ +  +  +  +  :     182122 :     switch ( nFilterType )
                      + ]
    1041                 :            :     {
    1042                 :            :         default: // unknown Scanline Filter Type
    1043                 :            :         case 0: // Filter Type "None"
    1044                 :            :             // we let the pixels pass and display the data unfiltered
    1045                 :     110123 :             break;
    1046                 :            : 
    1047                 :            :         case 1: // Scanline Filter Type "Sub"
    1048                 :            :         {
    1049                 :      13885 :             sal_uInt8* p1 = mpInflateInBuf + 1;
    1050                 :      13885 :             const sal_uInt8* p2 = p1;
    1051                 :      13885 :             p1 += mnBPP;
    1052                 :            : 
    1053                 :            :             // use left pixels
    1054         [ +  + ]:    1253029 :             do
    1055                 :    1253029 :                 *p1 = static_cast<sal_uInt8>( *p1 + *(p2++) );
    1056                 :            :             while( ++p1 < pScanEnd );
    1057                 :            :         }
    1058                 :      13885 :         break;
    1059                 :            : 
    1060                 :            :         case 2: // Scanline Filter Type "Up"
    1061                 :            :         {
    1062                 :      33554 :             sal_uInt8* p1 = mpInflateInBuf + 1;
    1063                 :      33554 :             const sal_uInt8* p2 = mpScanPrior + 1;
    1064                 :            : 
    1065                 :            :             // use pixels from prior line
    1066         [ +  + ]:    6330369 :             while( p1 < pScanEnd )
    1067                 :            :             {
    1068                 :    6296815 :                 *p1 = static_cast<sal_uInt8>( *p1 + *(p2++) );
    1069                 :    6296815 :                 ++p1;
    1070                 :            :             }
    1071                 :            :         }
    1072                 :      33554 :         break;
    1073                 :            : 
    1074                 :            :         case 3: // Scanline Filter Type "Average"
    1075                 :            :         {
    1076                 :        351 :             sal_uInt8* p1 = mpInflateInBuf + 1;
    1077                 :        351 :             const sal_uInt8* p2 = mpScanPrior + 1;
    1078                 :        351 :             const sal_uInt8* p3 = p1;
    1079                 :            : 
    1080                 :            :             // use one pixel from prior line
    1081         [ +  + ]:       1710 :             for( int n = mnBPP; --n >= 0; ++p1, ++p2)
    1082                 :       1359 :                 *p1 = static_cast<sal_uInt8>( *p1 + (*p2 >> 1) );
    1083                 :            : 
    1084                 :            :             // predict by averaging the left and prior line pixels
    1085         [ +  + ]:      30400 :             while( p1 < pScanEnd )
    1086                 :            :             {
    1087                 :      30049 :                 *p1 = static_cast<sal_uInt8>( *p1 + ((*(p2++) + *(p3++)) >> 1) );
    1088                 :      30049 :                 ++p1;
    1089                 :            :             }
    1090                 :            :         }
    1091                 :        351 :         break;
    1092                 :            : 
    1093                 :            :         case 4: // Scanline Filter Type "PaethPredictor"
    1094                 :            :         {
    1095                 :      24209 :             sal_uInt8* p1 = mpInflateInBuf + 1;
    1096                 :      24209 :             const sal_uInt8* p2 = mpScanPrior + 1;
    1097                 :      24209 :             const sal_uInt8* p3 = p1;
    1098                 :      24209 :             const sal_uInt8* p4 = p2;
    1099                 :            : 
    1100                 :            :             // use one pixel from prior line
    1101         [ +  + ]:     113732 :             for( int n = mnBPP; --n >= 0; ++p1)
    1102                 :      89523 :                 *p1 = static_cast<sal_uInt8>( *p1 + *(p2++) );
    1103                 :            : 
    1104                 :            :             // predict by using the left and the prior line pixels
    1105         [ +  + ]:    2449045 :             while( p1 < pScanEnd )
    1106                 :            :             {
    1107                 :    2424836 :                 int na = *(p2++);
    1108                 :    2424836 :                 int nb = *(p3++);
    1109                 :    2424836 :                 int nc = *(p4++);
    1110                 :            : 
    1111                 :    2424836 :                 int npa = nb - (int)nc;
    1112                 :    2424836 :                 int npb = na - (int)nc;
    1113                 :    2424836 :                 int npc = npa + npb;
    1114                 :            : 
    1115         [ +  + ]:    2424836 :                 if( npa < 0 )
    1116                 :     696002 :                     npa =-npa;
    1117         [ +  + ]:    2424836 :                 if( npb < 0 )
    1118                 :     470959 :                     npb =-npb;
    1119         [ +  + ]:    2424836 :                 if( npc < 0 )
    1120                 :     774835 :                     npc =-npc;
    1121                 :            : 
    1122         [ +  + ]:    2424836 :                 if( npa > npb )
    1123                 :     754815 :                     na = nb, npa = npb;
    1124         [ +  + ]:    2424836 :                 if( npa > npc )
    1125                 :      70457 :                     na = nc;
    1126                 :            : 
    1127                 :    2424836 :                 *p1 = static_cast<sal_uInt8>( *p1 + na );
    1128                 :    2424836 :                 ++p1;
    1129                 :            :             }
    1130                 :            :         }
    1131                 :      24209 :         break;
    1132                 :            :     }
    1133                 :            : 
    1134                 :     182122 :     memcpy( mpScanPrior, mpInflateInBuf, mnScansize );
    1135                 :     182122 : }
    1136                 :            : 
    1137                 :            : // ---------------------------------------------------------------------------------------------------
    1138                 :            : // ImplDrawScanlines draws the complete Scanline (nY) into the target bitmap
    1139                 :            : // In interlace mode the parameter nXStart and nXAdd append to the currently used pass
    1140                 :            : 
    1141                 :     182122 : void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
    1142                 :            : {
    1143                 :            :     // optimization for downscaling
    1144         [ -  + ]:     182122 :     if( mnYpos & mnPreviewMask )
    1145                 :          0 :         return;
    1146         [ -  + ]:     182122 :     if( nXStart & mnPreviewMask )
    1147                 :          0 :         return;
    1148                 :            : 
    1149                 :            :     // convert nY to pixel units in the target image
    1150                 :            :     // => TODO; also do this for nX here instead of in the ImplSet*Pixel() methods
    1151                 :     182122 :     const sal_uInt32 nY = mnYpos >> mnPreviewShift;
    1152                 :            : 
    1153                 :     182122 :     const sal_uInt8* pTmp = mpInflateInBuf + 1;
    1154         [ +  + ]:     182122 :     if ( mpAcc->HasPalette() ) // alphachannel is not allowed by pictures including palette entries
    1155                 :            :     {
    1156   [ +  +  +  - ]:      42508 :         switch ( mpAcc->GetBitCount() )
    1157                 :            :         {
    1158                 :            :             case 1 :
    1159                 :            :             {
    1160         [ +  + ]:       1044 :                 if ( mbTransparent )
    1161                 :            :                 {
    1162         [ +  + ]:      10846 :                     for ( sal_Int32 nX = nXStart, nShift = 0; nX < maOrigSize.Width(); nX += nXAdd )
    1163                 :            :                     {
    1164                 :            :                         sal_uInt8 nCol;
    1165                 :      10208 :                         nShift = (nShift - 1) & 7;
    1166         [ +  + ]:      10208 :                         if ( nShift == 0 )
    1167                 :       1276 :                             nCol = *(pTmp++);
    1168                 :            :                         else
    1169                 :       8932 :                             nCol = static_cast<sal_uInt8>( *pTmp >> nShift );
    1170                 :      10208 :                         nCol &= 1;
    1171                 :            : 
    1172                 :      10208 :                         ImplSetAlphaPixel( nY, nX, nCol, mpTransTab[ nCol ] );
    1173                 :            :                     }
    1174                 :            :                 }
    1175                 :            :                 else
    1176                 :            :                 {   // BMP_FORMAT_1BIT_MSB_PAL
    1177         [ +  + ]:      30756 :                     for ( sal_Int32 nX = nXStart, nShift = 0; nX < maOrigSize.Width(); nX += nXAdd )
    1178                 :            :                     {
    1179                 :      30350 :                         nShift = (nShift - 1) & 7;
    1180                 :            : 
    1181                 :            :                         sal_uInt8 nCol;
    1182         [ +  + ]:      30350 :                         if ( nShift == 0 )
    1183                 :       3700 :                             nCol = *(pTmp++);
    1184                 :            :                         else
    1185                 :      26650 :                             nCol = static_cast<sal_uInt8>( *pTmp >> nShift );
    1186                 :      30350 :                         nCol &= 1;
    1187                 :            : 
    1188                 :      30350 :                         ImplSetPixel( nY, nX, nCol );
    1189                 :            :                     }
    1190                 :            :                 }
    1191                 :            :             }
    1192                 :       1044 :             break;
    1193                 :            : 
    1194                 :            :             case 4 :
    1195                 :            :             {
    1196         [ +  + ]:       4116 :                 if ( mbTransparent )
    1197                 :            :                 {
    1198         [ +  + ]:       2580 :                     if ( mnPngDepth == 4 )  // check if source has a two bit pixel format
    1199                 :            :                     {
    1200         [ +  + ]:       9900 :                         for ( sal_Int32 nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, ++nXIndex )
    1201                 :            :                         {
    1202         [ +  + ]:       9240 :                             if( nXIndex & 1 )
    1203                 :            :                             {
    1204                 :       4620 :                                 ImplSetAlphaPixel( nY, nX, *pTmp & 0x0f, mpTransTab[ *pTmp & 0x0f ] );
    1205                 :       4620 :                                 pTmp++;
    1206                 :            :                             }
    1207                 :            :                             else
    1208                 :            :                             {
    1209                 :       4620 :                                 ImplSetAlphaPixel( nY, nX, ( *pTmp >> 4 ) & 0x0f, mpTransTab[ *pTmp >> 4 ] );
    1210                 :            :                             }
    1211                 :            :                         }
    1212                 :            :                     }
    1213                 :            :                     else // if ( mnPngDepth == 2 )
    1214                 :            :                     {
    1215         [ +  + ]:      48000 :                         for ( sal_Int32 nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, nXIndex++ )
    1216                 :            :                         {
    1217                 :            :                             sal_uInt8 nCol;
    1218   [ +  +  +  +  :      46080 :                             switch( nXIndex & 3 )
                      - ]
    1219                 :            :                             {
    1220                 :            :                                 case 0 :
    1221                 :      11520 :                                     nCol = *pTmp >> 6;
    1222                 :      11520 :                                 break;
    1223                 :            : 
    1224                 :            :                                 case 1 :
    1225                 :      11520 :                                     nCol = ( *pTmp >> 4 ) & 0x03 ;
    1226                 :      11520 :                                 break;
    1227                 :            : 
    1228                 :            :                                 case 2 :
    1229                 :      11520 :                                     nCol = ( *pTmp >> 2 ) & 0x03;
    1230                 :      11520 :                                 break;
    1231                 :            : 
    1232                 :            :                                 case 3 :
    1233                 :      11520 :                                     nCol = ( *pTmp++ ) & 0x03;
    1234                 :      11520 :                                 break;
    1235                 :            : 
    1236                 :            :                                 default:    // get rid of nCol uninitialized warning
    1237                 :          0 :                                     nCol = 0;
    1238                 :          0 :                                     break;
    1239                 :            :                             }
    1240                 :            : 
    1241                 :      46080 :                             ImplSetAlphaPixel( nY, nX, nCol, mpTransTab[ nCol ] );
    1242                 :            :                         }
    1243                 :            :                     }
    1244                 :            :                 }
    1245                 :            :                 else
    1246                 :            :                 {
    1247         [ +  + ]:       1536 :                     if ( mnPngDepth == 4 )  // maybe the source is a two bitmap graphic
    1248                 :            :                     {   // BMP_FORMAT_4BIT_LSN_PAL
    1249         [ +  + ]:     142880 :                         for ( sal_Int32 nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, nXIndex++ )
    1250                 :            :                         {
    1251         [ +  + ]:     141376 :                             if( nXIndex & 1 )
    1252                 :      70688 :                                 ImplSetPixel( nY, nX, *pTmp++ & 0x0f );
    1253                 :            :                             else
    1254                 :      70688 :                                 ImplSetPixel( nY, nX, ( *pTmp >> 4 ) & 0x0f );
    1255                 :            :                         }
    1256                 :            :                     }
    1257                 :            :                     else // if ( mnPngDepth == 2 )
    1258                 :            :                     {
    1259         [ +  + ]:        544 :                         for ( sal_Int32 nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, nXIndex++ )
    1260                 :            :                         {
    1261   [ +  +  +  +  :        512 :                             switch( nXIndex & 3 )
                      - ]
    1262                 :            :                             {
    1263                 :            :                                 case 0 :
    1264                 :        128 :                                     ImplSetPixel( nY, nX, *pTmp >> 6 );
    1265                 :        128 :                                 break;
    1266                 :            : 
    1267                 :            :                                 case 1 :
    1268                 :        128 :                                     ImplSetPixel( nY, nX, ( *pTmp >> 4 ) & 0x03 );
    1269                 :        128 :                                 break;
    1270                 :            : 
    1271                 :            :                                 case 2 :
    1272                 :        128 :                                     ImplSetPixel( nY, nX, ( *pTmp >> 2 ) & 0x03 );
    1273                 :        128 :                                 break;
    1274                 :            : 
    1275                 :            :                                 case 3 :
    1276                 :        128 :                                     ImplSetPixel( nY, nX, *pTmp++ & 0x03 );
    1277                 :        128 :                                 break;
    1278                 :            :                             }
    1279                 :            :                         }
    1280                 :            :                     }
    1281                 :            :                 }
    1282                 :            :             }
    1283                 :       4116 :             break;
    1284                 :            : 
    1285                 :            :             case 8 :
    1286                 :            :             {
    1287         [ +  + ]:      37348 :                 if ( mbAlphaChannel )
    1288                 :            :                 {
    1289         [ +  - ]:       5532 :                     if ( mnPngDepth == 8 )  // maybe the source is a 16 bit grayscale
    1290                 :            :                     {
    1291         [ +  + ]:      95916 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 2 )
    1292                 :      90384 :                             ImplSetAlphaPixel( nY, nX, pTmp[ 0 ], pTmp[ 1 ] );
    1293                 :            :                     }
    1294                 :            :                     else
    1295                 :            :                     {
    1296         [ #  # ]:          0 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
    1297                 :          0 :                             ImplSetAlphaPixel( nY, nX, pTmp[ 0 ], pTmp[ 2 ] );
    1298                 :            :                     }
    1299                 :            :                 }
    1300         [ +  + ]:      31816 :                 else if ( mbTransparent )
    1301                 :            :                 {
    1302         [ +  - ]:      16144 :                     if ( mnPngDepth == 8 )  // maybe the source is a 16 bit grayscale
    1303                 :            :                     {
    1304         [ +  + ]:     624752 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp++ )
    1305                 :     608608 :                             ImplSetAlphaPixel( nY, nX, *pTmp, mpTransTab[ *pTmp ] );
    1306                 :            :                     }
    1307                 :            :                     else
    1308                 :            :                     {
    1309         [ #  # ]:          0 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 2 )
    1310                 :          0 :                             ImplSetAlphaPixel( nY, nX, *pTmp, mpTransTab[ *pTmp ] );
    1311                 :            :                     }
    1312                 :            :                 }
    1313                 :            :                 else // neither alpha nor transparency
    1314                 :            :                 {
    1315         [ +  - ]:      15672 :                     if ( mnPngDepth == 8 )  // maybe the source is a 16 bit grayscale
    1316                 :            :                     {
    1317 [ +  - ][ +  - ]:      15672 :                         if( nXAdd == 1 && mnPreviewShift == 0 )  // copy raw line data if possible
    1318                 :            :                         {
    1319                 :      15672 :                             int nLineBytes = maOrigSize.Width();
    1320                 :      15672 :                             mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_8BIT_PAL, nLineBytes );
    1321                 :      15672 :                             pTmp += nLineBytes;
    1322                 :            :                         }
    1323                 :            :                         else
    1324                 :            :                         {
    1325         [ #  # ]:      15672 :                             for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd )
    1326                 :          0 :                                 ImplSetPixel( nY, nX, *pTmp++ );
    1327                 :            :                         }
    1328                 :            :                     }
    1329                 :            :                     else
    1330                 :            :                     {
    1331         [ #  # ]:          0 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 2 )
    1332                 :          0 :                             ImplSetPixel( nY, nX, *pTmp );
    1333                 :            :                     }
    1334                 :            :                 }
    1335                 :            :             }
    1336                 :      37348 :             break;
    1337                 :            : 
    1338                 :            :             default :
    1339                 :          0 :                 mbStatus = sal_False;
    1340                 :      42508 :             break;
    1341                 :            :         }
    1342                 :            :     }
    1343                 :            :     else // no palette => truecolor
    1344                 :            :     {
    1345         [ +  + ]:     139614 :         if( mbAlphaChannel ) // has RGB + alpha
    1346                 :            :         {   // BMP_FORMAT_32BIT_TC_RGBA
    1347         [ +  - ]:     132624 :             if ( mnPngDepth == 8 )  // maybe the source has 16 bit per sample
    1348                 :            :             {
    1349         [ -  + ]:     132624 :                 if ( mpColorTable != mpDefaultColorTable )
    1350                 :            :                 {
    1351         [ #  # ]:          0 :                     for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
    1352                 :          0 :                        ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
    1353                 :          0 :                                                                mpColorTable[ pTmp[ 1 ] ],
    1354         [ #  # ]:          0 :                                                                mpColorTable[ pTmp[ 2 ] ] ), pTmp[ 3 ] );
    1355                 :            :                 }
    1356                 :            :                 else
    1357                 :            :                 {
    1358                 :            : //                  if ( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible
    1359                 :            : //                  {
    1360                 :            : //                      int nLineBytes = 4 * maOrigSize.Width();
    1361                 :            : //                      mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_32BIT_TC_RGBA, nLineBytes );
    1362                 :            : //                      pTmp += nLineBytes;
    1363                 :            : //                  }
    1364                 :            : //                  else
    1365                 :            :                     {
    1366         [ +  + ]:    4214444 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
    1367         [ +  - ]:    4081820 :                             ImplSetAlphaPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ), pTmp[3] );
    1368                 :            :                     }
    1369                 :            :                 }
    1370                 :            :             }
    1371                 :            :             else
    1372                 :            :             {   // BMP_FORMAT_64BIT_TC_RGBA
    1373         [ #  # ]:          0 :                 for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 8 )
    1374                 :          0 :                     ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
    1375                 :          0 :                                                         mpColorTable[ pTmp[ 2 ] ],
    1376         [ #  # ]:          0 :                                                         mpColorTable[ pTmp[ 4 ] ] ), pTmp[6] );
    1377                 :            :             }
    1378                 :            :         }
    1379         [ +  + ]:       6990 :         else if( mbTransparent ) // has RGB + transparency
    1380                 :            :         {   // BMP_FORMAT_24BIT_TC_RGB
    1381         [ +  - ]:       1944 :             if ( mnPngDepth == 8 )  // maybe the source has 16 bit per sample
    1382                 :            :             {
    1383         [ +  + ]:     134136 :                 for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
    1384                 :            :                 {
    1385                 :     132192 :                     sal_uInt8 nRed = pTmp[ 0 ];
    1386                 :     132192 :                     sal_uInt8 nGreen = pTmp[ 1 ];
    1387                 :     132192 :                     sal_uInt8 nBlue = pTmp[ 2 ];
    1388                 :            :                     sal_Bool bTransparent = ( ( nRed == mnTransRed )
    1389                 :            :                                          && ( nGreen == mnTransGreen )
    1390 [ +  + ][ +  - ]:     132192 :                                         && ( nBlue == mnTransBlue ) );
                 [ +  - ]
    1391                 :            : 
    1392                 :     132192 :                     ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ],
    1393                 :     132192 :                                                         mpColorTable[ nGreen ],
    1394         [ +  - ]:     132192 :                                                         mpColorTable[ nBlue ] ), bTransparent );
    1395                 :            :                 }
    1396                 :            :             }
    1397                 :            :             else
    1398                 :            :             {   // BMP_FORMAT_48BIT_TC_RGB
    1399         [ #  # ]:          0 :                 for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
    1400                 :            :                 {
    1401                 :          0 :                     sal_uInt8 nRed = pTmp[ 0 ];
    1402                 :          0 :                     sal_uInt8 nGreen = pTmp[ 2 ];
    1403                 :          0 :                     sal_uInt8 nBlue = pTmp[ 4 ];
    1404                 :            :                     sal_Bool bTransparent = ( ( nRed == mnTransRed )
    1405                 :            :                                         && ( nGreen == mnTransGreen )
    1406 [ #  # ][ #  # ]:          0 :                                         && ( nBlue == mnTransBlue ) );
                 [ #  # ]
    1407                 :            : 
    1408                 :          0 :                     ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ],
    1409                 :          0 :                                                         mpColorTable[ nGreen ],
    1410         [ #  # ]:          0 :                                                         mpColorTable[ nBlue ] ), bTransparent );
    1411                 :            :                 }
    1412                 :            :             }
    1413                 :            :         }
    1414                 :            :         else  // has RGB but neither alpha nor transparency
    1415                 :            :         {   // BMP_FORMAT_24BIT_TC_RGB
    1416         [ +  - ]:       5046 :             if ( mnPngDepth == 8 )   // maybe the source has 16 bit per sample
    1417                 :            :             {
    1418         [ -  + ]:       5046 :                 if ( mpColorTable != mpDefaultColorTable )
    1419                 :            :                 {
    1420         [ #  # ]:          0 :                     for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
    1421                 :          0 :                         ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
    1422                 :          0 :                                                             mpColorTable[ pTmp[ 1 ] ],
    1423         [ #  # ]:          0 :                                                             mpColorTable[ pTmp[ 2 ] ] ) );
    1424                 :            :                 }
    1425                 :            :                 else
    1426                 :            :                 {
    1427 [ +  - ][ +  - ]:       5046 :                     if( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible
    1428                 :            :                     {
    1429                 :       5046 :                         int nLineBytes = maOrigSize.Width() * 3;
    1430                 :       5046 :                         mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_24BIT_TC_RGB, nLineBytes );
    1431                 :       5046 :                         pTmp += nLineBytes;
    1432                 :            :                     }
    1433                 :            :                     else
    1434                 :            :                     {
    1435         [ #  # ]:       5046 :                         for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
    1436         [ #  # ]:          0 :                             ImplSetPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ) );
    1437                 :            :                     }
    1438                 :            :                 }
    1439                 :            :             }
    1440                 :            :             else
    1441                 :            :             {   // BMP_FORMAT_48BIT_TC_RGB
    1442         [ #  # ]:     182122 :                 for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
    1443                 :          0 :                     ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
    1444                 :          0 :                                                         mpColorTable[ pTmp[ 2 ] ],
    1445         [ #  # ]:          0 :                                                         mpColorTable[ pTmp[ 4 ] ] ) );
    1446                 :            :             }
    1447                 :            :         }
    1448                 :            :     }
    1449                 :            : }
    1450                 :            : 
    1451                 :            : // ------------------------------------------------------------------------
    1452                 :            : 
    1453                 :          0 : void PNGReaderImpl::ImplSetPixel( sal_uInt32 nY, sal_uInt32 nX, const BitmapColor& rBitmapColor )
    1454                 :            : {
    1455                 :            :     // TODO: get preview mode checks out of inner loop
    1456         [ #  # ]:          0 :     if( nX & mnPreviewMask )
    1457                 :          0 :         return;
    1458                 :          0 :     nX >>= mnPreviewShift;
    1459                 :            : 
    1460                 :          0 :     mpAcc->SetPixel( nY, nX, rBitmapColor );
    1461                 :            : }
    1462                 :            : 
    1463                 :            : // ------------------------------------------------------------------------
    1464                 :            : 
    1465                 :     172238 : void PNGReaderImpl::ImplSetPixel( sal_uInt32 nY, sal_uInt32 nX, sal_uInt8 nPalIndex )
    1466                 :            : {
    1467                 :            :     // TODO: get preview mode checks out of inner loop
    1468         [ -  + ]:     172238 :     if( nX & mnPreviewMask )
    1469                 :     172238 :         return;
    1470                 :     172238 :     nX >>= mnPreviewShift;
    1471                 :            : 
    1472         [ +  - ]:     172238 :     mpAcc->SetPixel( nY, nX, nPalIndex );
    1473                 :            : }
    1474                 :            : 
    1475                 :            : // ------------------------------------------------------------------------
    1476                 :            : 
    1477                 :     132192 : void PNGReaderImpl::ImplSetTranspPixel( sal_uInt32 nY, sal_uInt32 nX, const BitmapColor& rBitmapColor, sal_Bool bTrans )
    1478                 :            : {
    1479                 :            :     // TODO: get preview mode checks out of inner loop
    1480         [ -  + ]:     132192 :     if( nX & mnPreviewMask )
    1481                 :     132192 :         return;
    1482                 :     132192 :     nX >>= mnPreviewShift;
    1483                 :            : 
    1484                 :     132192 :     mpAcc->SetPixel( nY, nX, rBitmapColor );
    1485                 :            : 
    1486         [ +  + ]:     132192 :     if ( bTrans )
    1487                 :      28980 :         mpMaskAcc->SetPixel( nY, nX, mcTranspColor );
    1488                 :            :     else
    1489                 :     103212 :         mpMaskAcc->SetPixel( nY, nX, mcOpaqueColor );
    1490                 :            : }
    1491                 :            : 
    1492                 :            : // ------------------------------------------------------------------------
    1493                 :            : 
    1494                 :     764520 : void PNGReaderImpl::ImplSetAlphaPixel( sal_uInt32 nY, sal_uInt32 nX,
    1495                 :            :     sal_uInt8 nPalIndex, sal_uInt8 nAlpha )
    1496                 :            : {
    1497                 :            :     // TODO: get preview mode checks out of inner loop
    1498         [ -  + ]:     764520 :     if( nX & mnPreviewMask )
    1499                 :     764520 :         return;
    1500                 :     764520 :     nX >>= mnPreviewShift;
    1501                 :            : 
    1502         [ +  - ]:     764520 :     mpAcc->SetPixel( nY, nX, nPalIndex );
    1503         [ +  - ]:     764520 :     mpMaskAcc->SetPixel( nY, nX, ~nAlpha );
    1504                 :            : }
    1505                 :            : 
    1506                 :            : // ------------------------------------------------------------------------
    1507                 :            : 
    1508                 :    4081820 : void PNGReaderImpl::ImplSetAlphaPixel( sal_uInt32 nY, sal_uInt32 nX,
    1509                 :            :     const BitmapColor& rBitmapColor, sal_uInt8 nAlpha )
    1510                 :            : {
    1511                 :            :     // TODO: get preview mode checks out of inner loop
    1512         [ -  + ]:    4081820 :     if( nX & mnPreviewMask )
    1513                 :    4081820 :         return;
    1514                 :    4081820 :     nX >>= mnPreviewShift;
    1515                 :            : 
    1516                 :    4081820 :     mpAcc->SetPixel( nY, nX, rBitmapColor );
    1517         [ +  - ]:    4081820 :     mpMaskAcc->SetPixel( nY, nX, ~nAlpha );
    1518                 :            : }
    1519                 :            : 
    1520                 :            : // ------------------------------------------------------------------------
    1521                 :            : 
    1522                 :      24716 : sal_uInt32 PNGReaderImpl::ImplReadsal_uInt32()
    1523                 :            : {
    1524                 :            :     sal_uInt32 nRet;
    1525         [ +  - ]:      24716 :     nRet = *maDataIter++;
    1526                 :      24716 :     nRet <<= 8;
    1527         [ +  - ]:      24716 :     nRet |= *maDataIter++;
    1528                 :      24716 :     nRet <<= 8;
    1529         [ +  - ]:      24716 :     nRet |= *maDataIter++;
    1530                 :      24716 :     nRet <<= 8;
    1531         [ +  - ]:      24716 :     nRet |= *maDataIter++;
    1532                 :      24716 :     return nRet;
    1533                 :            : }
    1534                 :            : 
    1535                 :            : // ------------------------------------------------------------------------
    1536                 :            : 
    1537                 :            : // -------------
    1538                 :            : // - PNGReader -
    1539                 :            : // -------------
    1540                 :            : 
    1541                 :       9430 : PNGReader::PNGReader( SvStream& rIStm ) :
    1542         [ +  - ]:       9430 :     mpImpl( new ::vcl::PNGReaderImpl( rIStm ) )
    1543                 :            : {
    1544                 :       9430 : }
    1545                 :            : 
    1546                 :            : // ------------------------------------------------------------------------
    1547                 :            : 
    1548                 :       9430 : PNGReader::~PNGReader()
    1549                 :            : {
    1550         [ +  - ]:       9430 :     delete mpImpl;
    1551                 :       9430 : }
    1552                 :            : 
    1553                 :            : // ------------------------------------------------------------------------
    1554                 :            : 
    1555                 :       9430 : BitmapEx PNGReader::Read( const Size& i_rPreviewSizeHint )
    1556                 :            : {
    1557                 :       9430 :     return mpImpl->GetBitmapEx( i_rPreviewSizeHint );
    1558                 :            : }
    1559                 :            : 
    1560                 :            : // ------------------------------------------------------------------------
    1561                 :            : 
    1562                 :       2032 : const std::vector< vcl::PNGReader::ChunkData >& PNGReader::GetChunks() const
    1563                 :            : {
    1564                 :       2032 :     return mpImpl->GetAllChunks();
    1565                 :            : }
    1566                 :            : 
    1567                 :            : // ------------------------------------------------------------------------
    1568                 :            : 
    1569                 :       7392 : void PNGReader::SetIgnoreGammaChunk( sal_Bool b )
    1570                 :            : {
    1571                 :       7392 :     mpImpl->SetIgnoreGammaChunk( b );
    1572                 :       7392 : }
    1573                 :            : 
    1574                 :            : 
    1575                 :            : } // namespace vcl
    1576                 :            : 
    1577                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10