LCOV - code coverage report
Current view: top level - vcl/source/gdi - pngread.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 592 697 84.9 %
Date: 2014-11-03 Functions: 30 31 96.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10