LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/source/gdi - pngread.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 571 658 86.8 %
Date: 2013-07-09 Functions: 31 31 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10