LCOV - code coverage report
Current view: top level - vcl/source/gdi - pngread.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 696 0.0 %
Date: 2014-04-14 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10