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

Generated by: LCOV version 1.10