LCOV - code coverage report
Current view: top level - libreoffice/vcl/source/gdi - bitmap2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 321 581 55.2 %
Date: 2012-12-27 Functions: 18 19 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <tools/zcodec.hxx>
      22             : #include <tools/stream.hxx>
      23             : #include <vcl/salbtype.hxx>
      24             : #include <vcl/bmpacc.hxx>
      25             : #include <vcl/outdev.hxx>
      26             : #include <vcl/bitmap.hxx>
      27             : 
      28             : #include <utility>
      29             : 
      30             : #if defined HAVE_VALGRIND_HEADERS
      31             : #include <valgrind/memcheck.h>
      32             : #endif
      33             : 
      34             : 
      35             : // -----------
      36             : // - Defines -
      37             : // -----------
      38             : 
      39             : #define DIBCOREHEADERSIZE           ( 12UL )
      40             : #define DIBINFOHEADERSIZE           ( sizeof( DIBInfoHeader ) )
      41             : #define BITMAPINFOHEADER                        0x28
      42             : 
      43             : // ----------------------
      44             : // - Compression defines
      45             : // ----------------------
      46             : 
      47             : #define COMPRESS_OWN                ('S'|('D'<<8UL))
      48             : #define COMPRESS_NONE               ( 0UL )
      49             : #define RLE_8                       ( 1UL )
      50             : #define RLE_4                       ( 2UL )
      51             : #define BITFIELDS                   ( 3UL )
      52             : #define ZCOMPRESS                   ( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
      53             : 
      54             : // -----------------
      55             : // - DIBInfoHeader -
      56             : // -----------------
      57             : 
      58             : struct DIBInfoHeader
      59             : {
      60             :     sal_uInt32      nSize;
      61             :     sal_Int32       nWidth;
      62             :     sal_Int32       nHeight;
      63             :     sal_uInt16      nPlanes;
      64             :     sal_uInt16      nBitCount;
      65             :     sal_uInt32      nCompression;
      66             :     sal_uInt32      nSizeImage;
      67             :     sal_Int32       nXPelsPerMeter;
      68             :     sal_Int32       nYPelsPerMeter;
      69             :     sal_uInt32      nColsUsed;
      70             :     sal_uInt32      nColsImportant;
      71             : 
      72          38 :                     DIBInfoHeader() :
      73             :                         nSize( 0UL ),
      74             :                         nWidth( 0UL ),
      75             :                         nHeight( 0UL ),
      76             :                         nPlanes( 0 ),
      77             :                         nBitCount( 0 ),
      78             :                         nCompression( 0 ),
      79             :                         nSizeImage( 0 ),
      80             :                         nXPelsPerMeter( 0UL ),
      81             :                         nYPelsPerMeter( 0UL ),
      82             :                         nColsUsed( 0UL ),
      83          38 :                         nColsImportant( 0UL ) {}
      84             : 
      85          38 :                     ~DIBInfoHeader() {}
      86             : };
      87             : 
      88             : namespace
      89             : {
      90           8 :     inline sal_uInt16 discretizeBitcount( sal_uInt16 nInputCount )
      91             :     {
      92             :         return ( nInputCount <= 1 ) ? 1 :
      93             :                ( nInputCount <= 4 ) ? 4 :
      94           8 :                ( nInputCount <= 8 ) ? 8 : 24;
      95             :     }
      96             : 
      97           1 :     inline bool isBitfieldCompression( sal_uLong nScanlineFormat )
      98             :     {
      99             :         return nScanlineFormat == BMP_FORMAT_16BIT_TC_LSB_MASK ||
     100           1 :             nScanlineFormat == BMP_FORMAT_32BIT_TC_MASK;
     101             :     }
     102             : }
     103             : 
     104             : // ----------
     105             : // - Bitmap -
     106             : // ----------
     107             : 
     108        2294 : SvStream& operator>>( SvStream& rIStm, Bitmap& rBitmap )
     109             : {
     110        2294 :     rBitmap.Read( rIStm, sal_True );
     111        2294 :     return rIStm;
     112             : }
     113             : 
     114             : // ------------------------------------------------------------------
     115             : 
     116           1 : SvStream& operator<<( SvStream& rOStm, const Bitmap& rBitmap )
     117             : {
     118           1 :     rBitmap.Write( rOStm, sal_False, sal_True );
     119           1 :     return rOStm;
     120             : }
     121             : 
     122             : // ------------------------------------------------------------------
     123             : 
     124        2326 : sal_Bool Bitmap::Read( SvStream& rIStm, sal_Bool bFileHeader, sal_Bool bIsMSOFormat )
     125             : {
     126        2326 :     const sal_uInt16    nOldFormat = rIStm.GetNumberFormatInt();
     127        2326 :     const sal_uLong     nOldPos = rIStm.Tell();
     128        2326 :     sal_uLong           nOffset = 0UL;
     129        2326 :     sal_Bool            bRet = sal_False;
     130             : 
     131        2326 :     rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
     132             : 
     133        2326 :     if( bFileHeader )
     134             :     {
     135        2326 :         if( ImplReadDIBFileHeader( rIStm, nOffset ) )
     136          37 :             bRet = ImplReadDIB( rIStm, *this, nOffset );
     137             :     }
     138             :     else
     139           0 :         bRet = ImplReadDIB( rIStm, *this, nOffset, bIsMSOFormat );
     140             : 
     141        2326 :     if( !bRet )
     142             :     {
     143        2321 :         if( !rIStm.GetError() )
     144          32 :             rIStm.SetError( SVSTREAM_GENERALERROR );
     145             : 
     146        2321 :         rIStm.Seek( nOldPos );
     147             :     }
     148             : 
     149        2326 :     rIStm.SetNumberFormatInt( nOldFormat );
     150             : 
     151        2326 :     return bRet;
     152             : }
     153             : 
     154             : // ------------------------------------------------------------------
     155             : 
     156          37 : sal_Bool Bitmap::ImplReadDIB( SvStream& rIStm, Bitmap& rBmp, sal_uLong nOffset, sal_Bool bIsMSOFormat )
     157             : {
     158          37 :     DIBInfoHeader   aHeader;
     159          37 :     const sal_uLong     nStmPos = rIStm.Tell();
     160          37 :     sal_Bool            bRet = sal_False;
     161          37 :     sal_Bool        bTopDown = sal_False;
     162             : 
     163          37 :     if( ImplReadDIBInfoHeader( rIStm, aHeader, bTopDown, bIsMSOFormat ) && aHeader.nWidth && aHeader.nHeight && aHeader.nBitCount )
     164             :     {
     165           6 :         const sal_uInt16 nBitCount( discretizeBitcount(aHeader.nBitCount) );
     166             : 
     167           6 :         const Size          aSizePixel( aHeader.nWidth, abs(aHeader.nHeight) );
     168           6 :         BitmapPalette       aDummyPal;
     169           6 :         Bitmap              aNewBmp( aSizePixel, nBitCount, &aDummyPal );
     170           6 :         BitmapWriteAccess*  pAcc = aNewBmp.AcquireWriteAccess();
     171             : 
     172           6 :         if( pAcc )
     173             :         {
     174             :             sal_uInt16          nColors;
     175             :             SvStream*       pIStm;
     176           5 :             SvMemoryStream* pMemStm = NULL;
     177           5 :             sal_uInt8*          pData = NULL;
     178             : 
     179           5 :             if( nBitCount <= 8 )
     180             :             {
     181           3 :                 if( aHeader.nColsUsed )
     182           3 :                     nColors = (sal_uInt16) aHeader.nColsUsed;
     183             :                 else
     184           0 :                     nColors = ( 1 << aHeader.nBitCount );
     185             :             }
     186             :             else
     187           2 :                 nColors = 0;
     188             : 
     189           5 :             if( ZCOMPRESS == aHeader.nCompression )
     190             :             {
     191           0 :                 ZCodec  aCodec;
     192             :                 sal_uInt32 nCodedSize, nUncodedSize;
     193             :                 sal_uLong   nCodedPos;
     194             : 
     195             :                 // read coding information
     196           0 :                 rIStm >> nCodedSize >> nUncodedSize >> aHeader.nCompression;
     197           0 :                 pData = (sal_uInt8*) rtl_allocateMemory( nUncodedSize );
     198             : 
     199             :                 // decode buffer
     200           0 :                 nCodedPos = rIStm.Tell();
     201           0 :                 aCodec.BeginCompression();
     202           0 :                 aCodec.Read( rIStm, pData, nUncodedSize );
     203           0 :                 aCodec.EndCompression();
     204             : 
     205             :                 // skip unread bytes from coded buffer
     206           0 :                 rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
     207             : 
     208             :                 // set decoded bytes to memory stream,
     209             :                 // from which we will read the bitmap data
     210           0 :                 pMemStm = new SvMemoryStream;
     211           0 :                 pIStm = pMemStm;
     212           0 :                 pMemStm->SetBuffer( (char*) pData, nUncodedSize, sal_False, nUncodedSize );
     213           0 :                 nOffset = 0;
     214             :             }
     215             :             else
     216           5 :                 pIStm = &rIStm;
     217             : 
     218             :             // read palette
     219           5 :             if( nColors )
     220             :             {
     221           3 :                 pAcc->SetPaletteEntryCount( nColors );
     222           3 :                 ImplReadDIBPalette( *pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE );
     223             :             }
     224             : 
     225             :             // read bits
     226           5 :             if( !pIStm->GetError() )
     227             :             {
     228           5 :                 if( nOffset )
     229           5 :                     pIStm->SeekRel( nOffset - ( pIStm->Tell() - nStmPos ) );
     230             : 
     231           5 :                 bRet = ImplReadDIBBits( *pIStm, aHeader, *pAcc, bTopDown );
     232             : 
     233           5 :                 if( bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter )
     234             :                 {
     235             :                     MapMode aMapMode( MAP_MM, Point(),
     236             :                                       Fraction( 1000, aHeader.nXPelsPerMeter ),
     237           2 :                                       Fraction( 1000, aHeader.nYPelsPerMeter ) );
     238             : 
     239           2 :                     aNewBmp.SetPrefMapMode( aMapMode );
     240           2 :                     aNewBmp.SetPrefSize( Size( aHeader.nWidth, abs(aHeader.nHeight) ) );
     241             :                 }
     242             :             }
     243             : 
     244           5 :             if( pData )
     245           0 :                 rtl_freeMemory( pData );
     246             : 
     247           5 :             delete pMemStm;
     248           5 :             aNewBmp.ReleaseAccess( pAcc );
     249             : 
     250           5 :             if( bRet )
     251           5 :                 rBmp = aNewBmp;
     252           6 :         }
     253             :     }
     254             : 
     255          37 :     return bRet;
     256             : }
     257             : 
     258             : // ------------------------------------------------------------------
     259             : 
     260        2326 : sal_Bool Bitmap::ImplReadDIBFileHeader( SvStream& rIStm, sal_uLong& rOffset )
     261             : {
     262             :     sal_uInt32  nTmp32;
     263        2326 :     sal_uInt16  nTmp16 = 0;
     264        2326 :     sal_Bool    bRet = sal_False;
     265             : 
     266        2326 :     rIStm >> nTmp16;
     267             : 
     268        2326 :     if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
     269             :     {
     270          74 :         if ( 0x4142 == nTmp16 )
     271             :         {
     272           0 :             rIStm.SeekRel( 12L );
     273           0 :             rIStm >> nTmp16;
     274           0 :             rIStm.SeekRel( 8L );
     275           0 :             rIStm >> nTmp32;
     276           0 :             rOffset = nTmp32 - 28UL;
     277           0 :             bRet = ( 0x4D42 == nTmp16 );
     278             :         }
     279             :         else
     280             :         {
     281          37 :             rIStm.SeekRel( 8L );
     282          37 :             rIStm >> nTmp32;
     283          37 :             rOffset = nTmp32 - 14UL;
     284          37 :             bRet = ( rIStm.GetError() == 0UL );
     285             :         }
     286             :     }
     287             :     else
     288        2289 :         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     289             : 
     290        2326 :     return bRet;
     291             : }
     292             : 
     293             : // ------------------------------------------------------------------
     294             : 
     295          37 : sal_Bool Bitmap::ImplReadDIBInfoHeader( SvStream& rIStm, DIBInfoHeader& rHeader, sal_Bool& bTopDown, sal_Bool bIsMSOFormat )
     296             : {
     297             :     // BITMAPINFOHEADER or BITMAPCOREHEADER
     298          37 :     rIStm >> rHeader.nSize;
     299             : 
     300             :     // BITMAPCOREHEADER
     301          37 :     sal_Int16 nTmp16 = 0;
     302          37 :     if ( rHeader.nSize == DIBCOREHEADERSIZE )
     303             :     {
     304             : 
     305           1 :         rIStm >> nTmp16; rHeader.nWidth = nTmp16;
     306           1 :         rIStm >> nTmp16; rHeader.nHeight = nTmp16;
     307           1 :         rIStm >> rHeader.nPlanes;
     308           1 :         rIStm >> rHeader.nBitCount;
     309             :     }
     310          36 :     else if ( bIsMSOFormat && ( rHeader.nSize == BITMAPINFOHEADER ) )
     311             :     {
     312           0 :         sal_uInt8 nTmp8 = 0;
     313           0 :         rIStm >> nTmp16; rHeader.nWidth = nTmp16;
     314           0 :         rIStm >> nTmp16; rHeader.nHeight = nTmp16;
     315           0 :         rIStm >> nTmp8; rHeader.nPlanes = nTmp8;
     316           0 :         rIStm >> nTmp8; rHeader.nBitCount = nTmp8;
     317           0 :         rIStm >> nTmp16; rHeader.nSizeImage = nTmp16;
     318           0 :         rIStm >> nTmp16; rHeader.nCompression = nTmp16;
     319           0 :         if ( !rHeader.nSizeImage ) // uncompressed?
     320           0 :             rHeader.nSizeImage = ((rHeader.nWidth * rHeader.nBitCount + 31) & ~31) / 8 * rHeader.nHeight;
     321           0 :         rIStm >> rHeader.nXPelsPerMeter;
     322           0 :         rIStm >> rHeader.nYPelsPerMeter;
     323           0 :         rIStm >> rHeader.nColsUsed;
     324           0 :         rIStm >> rHeader.nColsImportant;
     325             :     }
     326             :     else
     327             :     {
     328             :         // unknown Header
     329          36 :         if( rHeader.nSize < DIBINFOHEADERSIZE )
     330             :         {
     331          30 :             sal_uLong nUnknownSize = sizeof( rHeader.nSize );
     332             : 
     333          30 :             rIStm >> rHeader.nWidth; nUnknownSize += sizeof( rHeader.nWidth );
     334          30 :             rIStm >> rHeader.nHeight; nUnknownSize += sizeof( rHeader.nHeight );
     335          30 :             rIStm >> rHeader.nPlanes; nUnknownSize += sizeof( rHeader.nPlanes );
     336          30 :             rIStm >> rHeader.nBitCount; nUnknownSize += sizeof( rHeader.nBitCount );
     337             : 
     338          30 :             if( nUnknownSize < rHeader.nSize )
     339             :             {
     340           0 :                 rIStm >> rHeader.nCompression;
     341           0 :                 nUnknownSize += sizeof( rHeader.nCompression );
     342             : 
     343           0 :                 if( nUnknownSize < rHeader.nSize )
     344             :                 {
     345           0 :                     rIStm >> rHeader.nSizeImage;
     346           0 :                     nUnknownSize += sizeof( rHeader.nSizeImage );
     347             : 
     348           0 :                     if( nUnknownSize < rHeader.nSize )
     349             :                     {
     350           0 :                         rIStm >> rHeader.nXPelsPerMeter;
     351           0 :                         nUnknownSize += sizeof( rHeader.nXPelsPerMeter );
     352             : 
     353           0 :                         if( nUnknownSize < rHeader.nSize )
     354             :                         {
     355           0 :                             rIStm >> rHeader.nYPelsPerMeter;
     356           0 :                             nUnknownSize += sizeof( rHeader.nYPelsPerMeter );
     357             :                         }
     358             : 
     359           0 :                         if( nUnknownSize < rHeader.nSize )
     360             :                         {
     361           0 :                             rIStm >> rHeader.nColsUsed;
     362           0 :                             nUnknownSize += sizeof( rHeader.nColsUsed );
     363             : 
     364           0 :                             if( nUnknownSize < rHeader.nSize )
     365             :                             {
     366           0 :                                 rIStm >> rHeader.nColsImportant;
     367           0 :                                 nUnknownSize += sizeof( rHeader.nColsImportant );
     368             :                             }
     369             :                         }
     370             :                     }
     371             :                 }
     372             :             }
     373             :         }
     374             :         else
     375             :         {
     376           6 :             rIStm >> rHeader.nWidth;
     377           6 :             rIStm >> rHeader.nHeight; //rHeader.nHeight=abs(rHeader.nHeight);
     378           6 :             rIStm >> rHeader.nPlanes;
     379           6 :             rIStm >> rHeader.nBitCount;
     380           6 :             rIStm >> rHeader.nCompression;
     381           6 :             rIStm >> rHeader.nSizeImage;
     382           6 :             rIStm >> rHeader.nXPelsPerMeter;
     383           6 :             rIStm >> rHeader.nYPelsPerMeter;
     384           6 :             rIStm >> rHeader.nColsUsed;
     385           6 :             rIStm >> rHeader.nColsImportant;
     386             :         }
     387             : 
     388             :         // Eventuell bis zur Palette ueberlesen
     389          36 :         if ( rHeader.nSize > DIBINFOHEADERSIZE )
     390           0 :             rIStm.SeekRel( rHeader.nSize - DIBINFOHEADERSIZE );
     391             :     }
     392          37 :     if ( rHeader.nHeight < 0 )
     393             :     {
     394           0 :         bTopDown = sal_True;
     395           0 :         rHeader.nHeight *= -1;
     396             :     }
     397             :     else
     398          37 :         bTopDown = sal_False;
     399             : 
     400          37 :     if ( rHeader.nWidth < 0 )
     401           0 :         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     402             : 
     403             :     // #144105# protect a little against damaged files
     404          37 :     if( rHeader.nSizeImage > ( 16 * static_cast< sal_uInt32 >( rHeader.nWidth * rHeader.nHeight ) ) )
     405           1 :         rHeader.nSizeImage = 0;
     406             : 
     407          37 :     return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
     408             : }
     409             : 
     410             : // ------------------------------------------------------------------
     411             : 
     412           3 : sal_Bool Bitmap::ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, sal_Bool bQuad )
     413             : {
     414           3 :     const sal_uInt16    nColors = rAcc.GetPaletteEntryCount();
     415           3 :     const sal_uLong     nPalSize = nColors * ( bQuad ? 4UL : 3UL );
     416           3 :     BitmapColor     aPalColor;
     417             : 
     418           3 :     sal_uInt8* pEntries = new sal_uInt8[ nPalSize ];
     419           3 :     rIStm.Read( pEntries, nPalSize );
     420             : 
     421           3 :     sal_uInt8* pTmpEntry = pEntries;
     422       16725 :     for( sal_uInt16 i = 0; i < nColors; i++ )
     423             :     {
     424       16722 :         aPalColor.SetBlue( *pTmpEntry++ );
     425       16722 :         aPalColor.SetGreen( *pTmpEntry++ );
     426       16722 :         aPalColor.SetRed( *pTmpEntry++ );
     427             : 
     428       16722 :         if( bQuad )
     429       16722 :             pTmpEntry++;
     430             : 
     431       16722 :         rAcc.SetPaletteColor( i, aPalColor );
     432             :     }
     433             : 
     434           3 :     delete[] pEntries;
     435             : 
     436           3 :     return( rIStm.GetError() == 0UL );
     437             : }
     438             : 
     439             : // ------------------------------------------------------------------
     440             : 
     441           5 : sal_Bool Bitmap::ImplReadDIBBits( SvStream& rIStm, DIBInfoHeader& rHeader, BitmapWriteAccess& rAcc, sal_Bool bTopDown )
     442             : {
     443           5 :     const sal_uLong nAlignedWidth = AlignedWidth4Bytes( rHeader.nWidth * rHeader.nBitCount );
     444           5 :     sal_uInt32      nRMask = 0;
     445           5 :     sal_uInt32      nGMask = 0;
     446           5 :     sal_uInt32      nBMask = 0;
     447             :     sal_Bool        bNative;
     448           5 :     sal_Bool        bTCMask = ( rHeader.nBitCount == 16 ) || ( rHeader.nBitCount == 32 );
     449             :     sal_Bool        bRLE = ( RLE_8 == rHeader.nCompression && rHeader.nBitCount == 8 ) ||
     450           5 :                        ( RLE_4 == rHeader.nCompression && rHeader.nBitCount == 4 );
     451             : 
     452             :     // Is native format?
     453           5 :     switch( rAcc.GetScanlineFormat() )
     454             :     {
     455             :         case( BMP_FORMAT_1BIT_MSB_PAL ):
     456             :         case( BMP_FORMAT_4BIT_MSN_PAL ):
     457             :         case( BMP_FORMAT_8BIT_PAL ):
     458             :         case( BMP_FORMAT_24BIT_TC_BGR ):
     459           5 :             bNative = ( ( rAcc.IsBottomUp() != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
     460           5 :         break;
     461             : 
     462             :         default:
     463           0 :             bNative = sal_False;
     464           0 :         break;
     465             :     }
     466             :     // Read data
     467           5 :     if( bNative )
     468             :     {
     469             :         // true color DIB's can have a (optimization) palette
     470           2 :         if( rHeader.nColsUsed && rHeader.nBitCount > 8 )
     471           0 :             rIStm.SeekRel( rHeader.nColsUsed * ( ( rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3 ) );
     472             : 
     473           2 :         if ( rHeader.nHeight > 0 )
     474           2 :             rIStm.Read( rAcc.GetBuffer(), rHeader.nHeight * nAlignedWidth );
     475             :         else
     476             :         {
     477           0 :             for( int i = abs(rHeader.nHeight)-1; i >= 0; i-- )
     478           0 :                 rIStm.Read( ((char*)rAcc.GetBuffer()) + (nAlignedWidth*i), nAlignedWidth );
     479             :         }
     480             :     }
     481             :     else
     482             :     {
     483             :         // Read color mask
     484           3 :         if( bTCMask )
     485             :         {
     486           0 :             if( rHeader.nCompression == BITFIELDS )
     487             :             {
     488           0 :                 rIStm.SeekRel( -12L );
     489           0 :                 rIStm >> nRMask;
     490           0 :                 rIStm >> nGMask;
     491           0 :                 rIStm >> nBMask;
     492             :             }
     493             :             else
     494             :             {
     495           0 :                 nRMask = ( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL;
     496           0 :                 nGMask = ( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL;
     497           0 :                 nBMask = ( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL;
     498             :             }
     499             :         }
     500             : 
     501           3 :         if( bRLE )
     502             :         {
     503           2 :             if ( !rHeader.nSizeImage )
     504             :             {
     505           1 :                 const sal_uLong nOldPos = rIStm.Tell();
     506             : 
     507           1 :                 rIStm.Seek( STREAM_SEEK_TO_END );
     508           1 :                 rHeader.nSizeImage = rIStm.Tell() - nOldPos;
     509           1 :                 rIStm.Seek( nOldPos );
     510             :             }
     511             : 
     512           2 :             sal_uInt8* pBuffer = (sal_uInt8*) rtl_allocateMemory( rHeader.nSizeImage );
     513             : 
     514           2 :             rIStm.Read( (char*) pBuffer, rHeader.nSizeImage );
     515           2 :             ImplDecodeRLE( pBuffer, rHeader, rAcc, RLE_4 == rHeader.nCompression );
     516             : 
     517           2 :             rtl_freeMemory( pBuffer );
     518             :         }
     519             :         else
     520             :         {
     521           1 :             const long  nWidth = rHeader.nWidth;
     522           1 :             const long  nHeight = abs(rHeader.nHeight);
     523           1 :             sal_uInt8*      pBuf = new sal_uInt8[ nAlignedWidth ];
     524             : 
     525             :             // true color DIB's can have a (optimization) palette
     526           1 :             if( rHeader.nColsUsed && rHeader.nBitCount > 8 )
     527           0 :                 rIStm.SeekRel( rHeader.nColsUsed * ( ( rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3 ) );
     528             : 
     529           1 :             const long nI = bTopDown ? 1 : -1;
     530           1 :             long nY = bTopDown ? 0 : nHeight - 1;
     531           1 :             long nCount = nHeight;
     532             : 
     533           1 :             switch( rHeader.nBitCount )
     534             :             {
     535             :                 case( 1 ):
     536             :                 {
     537             :                     sal_uInt8*  pTmp;
     538             :                     sal_uInt8   cTmp;
     539             : 
     540           0 :                     for( ; nCount--; nY += nI )
     541             :                     {
     542           0 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     543           0 :                         cTmp = *pTmp++;
     544             : 
     545           0 :                         for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
     546             :                         {
     547           0 :                             if( !nShift )
     548             :                             {
     549             :                                 nShift = 8L,
     550           0 :                                 cTmp = *pTmp++;
     551             :                             }
     552             : 
     553           0 :                             rAcc.SetPixel( nY, nX, sal::static_int_cast<sal_uInt8>(( cTmp >> --nShift ) & 1) );
     554             :                         }
     555             :                     }
     556             :                 }
     557           0 :                 break;
     558             : 
     559             :                 case( 4 ):
     560             :                 {
     561             :                     sal_uInt8*  pTmp;
     562             :                     sal_uInt8   cTmp;
     563             : 
     564           0 :                     for( ; nCount--; nY += nI )
     565             :                     {
     566           0 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     567           0 :                         cTmp = *pTmp++;
     568             : 
     569           0 :                         for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
     570             :                         {
     571           0 :                             if( !nShift )
     572             :                             {
     573             :                                 nShift = 2UL,
     574           0 :                                 cTmp = *pTmp++;
     575             :                             }
     576             : 
     577           0 :                             rAcc.SetPixel( nY, nX, sal::static_int_cast<sal_uInt8>(( cTmp >> ( --nShift << 2UL ) ) & 0x0f) );
     578             :                         }
     579             :                     }
     580             :                 }
     581           0 :                 break;
     582             : 
     583             :                 case( 8 ):
     584             :                 {
     585             :                     sal_uInt8*  pTmp;
     586             : 
     587         439 :                     for( ; nCount--; nY += nI )
     588             :                     {
     589         438 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     590             : 
     591      223380 :                         for( long nX = 0L; nX < nWidth; nX++ )
     592      222942 :                             rAcc.SetPixel( nY, nX, *pTmp++ );
     593             :                     }
     594             :                 }
     595           1 :                 break;
     596             : 
     597             :                 case( 16 ):
     598             :                 {
     599           0 :                     ColorMask   aMask( nRMask, nGMask, nBMask );
     600           0 :                     BitmapColor aColor;
     601             :                     sal_uInt16*     pTmp16;
     602             : 
     603           0 :                     for( ; nCount--; nY += nI )
     604             :                     {
     605           0 :                         rIStm.Read( (char*)( pTmp16 = (sal_uInt16*) pBuf ), nAlignedWidth );
     606             : 
     607           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     608             :                         {
     609           0 :                             aMask.GetColorFor16BitLSB( aColor, (sal_uInt8*) pTmp16++ );
     610           0 :                             rAcc.SetPixel( nY, nX, aColor );
     611             :                         }
     612           0 :                     }
     613             :                 }
     614           0 :                 break;
     615             : 
     616             :                 case( 24 ):
     617             :                 {
     618           0 :                     BitmapColor aPixelColor;
     619             :                     sal_uInt8*      pTmp;
     620             : 
     621           0 :                     for( ; nCount--; nY += nI )
     622             :                     {
     623           0 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     624             : 
     625           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     626             :                         {
     627           0 :                             aPixelColor.SetBlue( *pTmp++ );
     628           0 :                             aPixelColor.SetGreen( *pTmp++ );
     629           0 :                             aPixelColor.SetRed( *pTmp++ );
     630           0 :                             rAcc.SetPixel( nY, nX, aPixelColor );
     631             :                         }
     632           0 :                     }
     633             :                 }
     634           0 :                 break;
     635             : 
     636             :                 case( 32 ):
     637             :                 {
     638           0 :                     ColorMask   aMask( nRMask, nGMask, nBMask );
     639           0 :                     BitmapColor aColor;
     640             :                     sal_uInt32*     pTmp32;
     641             : 
     642           0 :                     for( ; nCount--; nY += nI )
     643             :                     {
     644           0 :                         rIStm.Read( (char*)( pTmp32 = (sal_uInt32*) pBuf ), nAlignedWidth );
     645             : 
     646           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     647             :                         {
     648           0 :                             aMask.GetColorFor32Bit( aColor, (sal_uInt8*) pTmp32++ );
     649           0 :                             rAcc.SetPixel( nY, nX, aColor );
     650             :                         }
     651           0 :                     }
     652             :                 }
     653             :             }
     654             : 
     655           1 :             delete[] pBuf;
     656             :         }
     657             :     }
     658             : 
     659           5 :     return( rIStm.GetError() == 0UL );
     660             : }
     661             : 
     662             : // ------------------------------------------------------------------
     663             : 
     664           1 : sal_Bool Bitmap::Write( SvStream& rOStm, sal_Bool bCompressed, sal_Bool bFileHeader ) const
     665             : {
     666             :     DBG_ASSERT( mpImpBmp, "Empty Bitmaps can't be saved" );
     667             : 
     668           1 :     const Size  aSizePix( GetSizePixel() );
     669           1 :     sal_Bool        bRet = sal_False;
     670             : 
     671           1 :     if( mpImpBmp && aSizePix.Width() && aSizePix.Height() )
     672             :     {
     673           1 :         BitmapReadAccess*   pAcc = ( (Bitmap*) this)->AcquireReadAccess();
     674           1 :         const sal_uInt16        nOldFormat = rOStm.GetNumberFormatInt();
     675           1 :         const sal_uLong         nOldPos = rOStm.Tell();
     676             : 
     677           1 :         rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
     678             : 
     679           1 :         if( pAcc )
     680             :         {
     681           1 :             if( bFileHeader )
     682             :             {
     683           1 :                 if( ImplWriteDIBFileHeader( rOStm, *pAcc ) )
     684           1 :                     bRet = ImplWriteDIB( rOStm, *pAcc, bCompressed );
     685             :             }
     686             :             else
     687           0 :                 bRet = ImplWriteDIB( rOStm, *pAcc, bCompressed );
     688             : 
     689           1 :             ( (Bitmap*) this)->ReleaseAccess( pAcc );
     690             :         }
     691             : 
     692           1 :         if( !bRet )
     693             :         {
     694           0 :             rOStm.SetError( SVSTREAM_GENERALERROR );
     695           0 :             rOStm.Seek( nOldPos );
     696             :         }
     697             : 
     698           1 :         rOStm.SetNumberFormatInt( nOldFormat );
     699             :     }
     700             : 
     701           1 :     return bRet;
     702             : }
     703             : 
     704             : // ------------------------------------------------------------------
     705             : 
     706           1 : sal_Bool Bitmap::ImplWriteDIB( SvStream& rOStm, BitmapReadAccess& rAcc, sal_Bool bCompressed ) const
     707             : {
     708           1 :     const MapMode   aMapPixel( MAP_PIXEL );
     709           1 :     DIBInfoHeader   aHeader;
     710             :     sal_uLong           nImageSizePos;
     711             :     sal_uLong           nEndPos;
     712           1 :     sal_uInt32      nCompression = 0;
     713           1 :     sal_Bool            bRet = sal_False;
     714             : 
     715           1 :     aHeader.nSize = DIBINFOHEADERSIZE;
     716           1 :     aHeader.nWidth = rAcc.Width();
     717           1 :     aHeader.nHeight = rAcc.Height();
     718           1 :     aHeader.nPlanes = 1;
     719             : 
     720           1 :     if( isBitfieldCompression( rAcc.GetScanlineFormat() ) )
     721             :     {
     722           0 :         aHeader.nBitCount = ( rAcc.GetScanlineFormat() == BMP_FORMAT_16BIT_TC_LSB_MASK ) ? 16 : 32;
     723           0 :         aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
     724             : 
     725           0 :         nCompression = BITFIELDS;
     726             :     }
     727             :     else
     728             :     {
     729             :         // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are
     730             :         // not handled properly below (would have to set color
     731             :         // masks, and nCompression=BITFIELDS - but color mask is
     732             :         // not set for formats != *_TC_*). Note that this very
     733             :         // problem might cause trouble at other places - the
     734             :         // introduction of 32 bit RGBA bitmaps is relatively
     735             :         // recent.
     736             :         // #i59239# discretize bitcount to 1,4,8,24 (other cases
     737             :         // are not written below)
     738           1 :         const sal_uInt16 nBitCount( sal::static_int_cast<sal_uInt16>(rAcc.GetBitCount()) );
     739             : 
     740           1 :         aHeader.nBitCount = discretizeBitcount( nBitCount );
     741           1 :         aHeader.nSizeImage = rAcc.Height() *
     742           1 :             AlignedWidth4Bytes( rAcc.Width()*aHeader.nBitCount );
     743             : 
     744           1 :         if( bCompressed )
     745             :         {
     746           0 :             if( 4 == nBitCount )
     747           0 :                 nCompression = RLE_4;
     748           0 :             else if( 8 == nBitCount )
     749           0 :                 nCompression = RLE_8;
     750             :         }
     751             :         else
     752           1 :             nCompression = COMPRESS_NONE;
     753             :     }
     754             : 
     755           1 :     if( ( rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP ) &&
     756           0 :         ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40 ) )
     757             :     {
     758           0 :         aHeader.nCompression = ZCOMPRESS;
     759             :     }
     760             :     else
     761           1 :         aHeader.nCompression = nCompression;
     762             : 
     763           1 :     if( maPrefSize.Width() && maPrefSize.Height() && ( maPrefMapMode != aMapPixel ) )
     764             :     {
     765             :         // #i48108# Try to recover xpels/ypels as previously stored on
     766             :         // disk. The problem with just converting maPrefSize to 100th
     767             :         // mm and then relating that to the bitmap pixel size is that
     768             :         // MapMode is integer-based, and suffers from roundoffs,
     769             :         // especially if maPrefSize is small. Trying to circumvent
     770             :         // that by performing part of the math in floating point.
     771             :         const Size aScale100000(
     772             :             OutputDevice::LogicToLogic( Size(100000L,
     773             :                                              100000L),
     774             :                                         MAP_100TH_MM,
     775           0 :                                         maPrefMapMode ) );
     776           0 :         const double fBmpWidthM((double)maPrefSize.Width() / aScale100000.Width() );
     777           0 :         const double fBmpHeightM((double)maPrefSize.Height() / aScale100000.Height() );
     778           0 :         if( fabs(fBmpWidthM) > 0.000000001 &&
     779           0 :             fabs(fBmpHeightM) > 0.000000001 )
     780             :         {
     781           0 :             aHeader.nXPelsPerMeter = (sal_uInt32)(rAcc.Width() / fBmpWidthM + .5);
     782           0 :             aHeader.nYPelsPerMeter = (sal_uInt32)(rAcc.Height() / fBmpHeightM + .5);
     783             :         }
     784             :     }
     785             : 
     786           1 :     aHeader.nColsUsed = ( ( aHeader.nBitCount <= 8 ) ? rAcc.GetPaletteEntryCount() : 0 );
     787           1 :     aHeader.nColsImportant = 0;
     788             : 
     789           1 :     rOStm << aHeader.nSize;
     790           1 :     rOStm << aHeader.nWidth;
     791           1 :     rOStm << aHeader.nHeight;
     792           1 :     rOStm << aHeader.nPlanes;
     793           1 :     rOStm << aHeader.nBitCount;
     794           1 :     rOStm << aHeader.nCompression;
     795             : 
     796           1 :     nImageSizePos = rOStm.Tell();
     797           1 :     rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
     798             : 
     799           1 :     rOStm << aHeader.nXPelsPerMeter;
     800           1 :     rOStm << aHeader.nYPelsPerMeter;
     801           1 :     rOStm << aHeader.nColsUsed;
     802           1 :     rOStm << aHeader.nColsImportant;
     803             : 
     804           1 :     if( aHeader.nCompression == ZCOMPRESS )
     805             :     {
     806           0 :         ZCodec          aCodec;
     807           0 :         SvMemoryStream  aMemStm( aHeader.nSizeImage + 4096, 65535 );
     808           0 :         sal_uLong           nCodedPos = rOStm.Tell(), nLastPos;
     809             :         sal_uInt32      nCodedSize, nUncodedSize;
     810             : 
     811             :         // write uncoded data palette
     812           0 :         if( aHeader.nColsUsed )
     813           0 :             ImplWriteDIBPalette( aMemStm, rAcc );
     814             : 
     815             :         // write uncoded bits
     816           0 :         bRet = ImplWriteDIBBits( aMemStm, rAcc, nCompression, aHeader.nSizeImage );
     817             : 
     818             :         // get uncoded size
     819           0 :         nUncodedSize = aMemStm.Tell();
     820             : 
     821             :         // seek over compress info
     822           0 :         rOStm.SeekRel( 12 );
     823             : 
     824             :         // write compressed data
     825           0 :         aCodec.BeginCompression( 3 );
     826           0 :         aCodec.Write( rOStm, (sal_uInt8*) aMemStm.GetData(), nUncodedSize );
     827           0 :         aCodec.EndCompression();
     828             : 
     829             :         // update compress info ( coded size, uncoded size, uncoded compression )
     830           0 :         nCodedSize = ( nLastPos = rOStm.Tell() ) - nCodedPos - 12;
     831           0 :         rOStm.Seek( nCodedPos );
     832           0 :         rOStm << nCodedSize << nUncodedSize << nCompression;
     833           0 :         rOStm.Seek( nLastPos );
     834             : 
     835           0 :         if( bRet )
     836           0 :             bRet = ( rOStm.GetError() == ERRCODE_NONE );
     837             :     }
     838             :     else
     839             :     {
     840           1 :         if( aHeader.nColsUsed )
     841           1 :             ImplWriteDIBPalette( rOStm, rAcc );
     842             : 
     843           1 :         bRet = ImplWriteDIBBits( rOStm, rAcc, aHeader.nCompression, aHeader.nSizeImage );
     844             :     }
     845             : 
     846           1 :     nEndPos = rOStm.Tell();
     847           1 :     rOStm.Seek( nImageSizePos );
     848           1 :     rOStm << aHeader.nSizeImage;
     849           1 :     rOStm.Seek( nEndPos );
     850             : 
     851           1 :     return bRet;
     852             : }
     853             : 
     854             : // ------------------------------------------------------------------
     855             : 
     856           1 : sal_Bool Bitmap::ImplWriteDIBFileHeader( SvStream& rOStm, BitmapReadAccess& rAcc )
     857             : {
     858           2 :     sal_uInt32  nPalCount = ( rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() :
     859           2 :                           isBitfieldCompression( rAcc.GetScanlineFormat() ) ? 3UL : 0UL );
     860           1 :     sal_uInt32  nOffset = 14 + DIBINFOHEADERSIZE + nPalCount * 4UL;
     861             : 
     862           1 :     rOStm << (sal_uInt16) 0x4D42;
     863           1 :     rOStm << (sal_uInt32) ( nOffset + ( rAcc.Height() * rAcc.GetScanlineSize() ) );
     864           1 :     rOStm << (sal_uInt16) 0;
     865           1 :     rOStm << (sal_uInt16) 0;
     866           1 :     rOStm << nOffset;
     867             : 
     868           1 :     return( rOStm.GetError() == 0UL );
     869             : }
     870             : 
     871             : // ------------------------------------------------------------------
     872             : 
     873           1 : sal_Bool Bitmap::ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
     874             : {
     875           1 :     const sal_uInt16    nColors = rAcc.GetPaletteEntryCount();
     876           1 :     const sal_uLong     nPalSize = nColors * 4UL;
     877           1 :     sal_uInt8*          pEntries = new sal_uInt8[ nPalSize ];
     878           1 :     sal_uInt8*          pTmpEntry = pEntries;
     879           1 :     BitmapColor     aPalColor;
     880             : 
     881          17 :     for( sal_uInt16 i = 0; i < nColors; i++ )
     882             :     {
     883          16 :         const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
     884             : 
     885          16 :         *pTmpEntry++ = rPalColor.GetBlue();
     886          16 :         *pTmpEntry++ = rPalColor.GetGreen();
     887          16 :         *pTmpEntry++ = rPalColor.GetRed();
     888          16 :         *pTmpEntry++ = 0;
     889             :     }
     890             : 
     891           1 :     rOStm.Write( pEntries, nPalSize );
     892           1 :     delete[] pEntries;
     893             : 
     894           1 :     return( rOStm.GetError() == 0UL );
     895             : }
     896             : 
     897             : // ------------------------------------------------------------------
     898             : 
     899             : #if defined HAVE_VALGRIND_HEADERS
     900             : namespace
     901             : {
     902             :     void blankExtraSpace(sal_uInt8 *pBits, long nWidth, long nScanlineSize, int nBitCount)
     903             :     {
     904             :         size_t nExtraSpaceInScanLine = nScanlineSize - nWidth * nBitCount / 8;
     905             :         if (nExtraSpaceInScanLine)
     906             :             memset(pBits + (nScanlineSize - nExtraSpaceInScanLine), 0, nExtraSpaceInScanLine);
     907             :     }
     908             : }
     909             : #endif
     910             : 
     911           1 : sal_Bool Bitmap::ImplWriteDIBBits( SvStream& rOStm, BitmapReadAccess& rAcc,
     912             :                                sal_uLong nCompression, sal_uInt32& rImageSize )
     913             : {
     914           1 :     if( BITFIELDS == nCompression )
     915             :     {
     916           0 :         const ColorMask&    rMask = rAcc.GetColorMask();
     917             :         SVBT32              aVal32;
     918             : 
     919           0 :         UInt32ToSVBT32( rMask.GetRedMask(), aVal32 );
     920           0 :         rOStm.Write( (sal_uInt8*) aVal32, 4UL );
     921             : 
     922           0 :         UInt32ToSVBT32( rMask.GetGreenMask(), aVal32 );
     923           0 :         rOStm.Write( (sal_uInt8*) aVal32, 4UL );
     924             : 
     925           0 :         UInt32ToSVBT32( rMask.GetBlueMask(), aVal32 );
     926           0 :         rOStm.Write( (sal_uInt8*) aVal32, 4UL );
     927             : 
     928           0 :         rImageSize = rOStm.Tell();
     929             : 
     930           0 :         if( rAcc.IsBottomUp() )
     931           0 :             rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
     932             :         else
     933             :         {
     934           0 :             for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
     935           0 :                 rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
     936             :         }
     937             :     }
     938           1 :     else if( ( RLE_4 == nCompression ) || ( RLE_8 == nCompression ) )
     939             :     {
     940           0 :         rImageSize = rOStm.Tell();
     941           0 :         ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
     942             :     }
     943           1 :     else if( !nCompression )
     944             :     {
     945             :         // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are not
     946             :         // handled properly below (would have to set color masks, and
     947             :         // nCompression=BITFIELDS - but color mask is not set for
     948             :         // formats != *_TC_*). Note that this very problem might cause
     949             :         // trouble at other places - the introduction of 32 bit RGBA
     950             :         // bitmaps is relatively recent.
     951             :         // #i59239# discretize bitcount for aligned width to 1,4,8,24
     952             :         // (other cases are not written below)
     953           1 :         const sal_uInt16 nBitCount( sal::static_int_cast<sal_uInt16>(rAcc.GetBitCount()) );
     954           1 :         const sal_uLong  nAlignedWidth = AlignedWidth4Bytes( rAcc.Width() *
     955           1 :                                                          discretizeBitcount(nBitCount));
     956           1 :         sal_Bool         bNative = sal_False;
     957             : 
     958           1 :         switch( rAcc.GetScanlineFormat() )
     959             :         {
     960             :             case( BMP_FORMAT_1BIT_MSB_PAL ):
     961             :             case( BMP_FORMAT_4BIT_MSN_PAL ):
     962             :             case( BMP_FORMAT_8BIT_PAL ):
     963             :             case( BMP_FORMAT_24BIT_TC_BGR ):
     964             :             {
     965           1 :                 if( rAcc.IsBottomUp() && ( rAcc.GetScanlineSize() == nAlignedWidth ) )
     966           0 :                     bNative = sal_True;
     967             :             }
     968           1 :             break;
     969             : 
     970             :             default:
     971           0 :             break;
     972             :         }
     973             : 
     974           1 :         rImageSize = rOStm.Tell();
     975             : 
     976           1 :         if( bNative )
     977           0 :             rOStm.Write( rAcc.GetBuffer(), nAlignedWidth * rAcc.Height() );
     978             :         else
     979             :         {
     980           1 :             const long  nWidth = rAcc.Width();
     981           1 :             const long  nHeight = rAcc.Height();
     982           1 :             sal_uInt8*      pBuf = new sal_uInt8[ nAlignedWidth ];
     983             : #if defined HAVE_VALGRIND_HEADERS
     984             :             if (RUNNING_ON_VALGRIND)
     985             :                 blankExtraSpace(pBuf, nWidth, nAlignedWidth, discretizeBitcount(nBitCount));
     986             : #endif
     987             :             sal_uInt8*      pTmp;
     988             :             sal_uInt8       cTmp;
     989             : 
     990           1 :             switch( nBitCount )
     991             :             {
     992             :                 case( 1 ):
     993             :                 {
     994           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
     995             :                     {
     996           0 :                         pTmp = pBuf;
     997           0 :                         cTmp = 0;
     998             : 
     999           0 :                         for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
    1000             :                         {
    1001           0 :                             if( !nShift )
    1002             :                             {
    1003           0 :                                 nShift = 8L;
    1004           0 :                                 *pTmp++ = cTmp;
    1005           0 :                                 cTmp = 0;
    1006             :                             }
    1007             : 
    1008           0 :                             cTmp |= ( (sal_uInt8) rAcc.GetPixel( nY, nX ) << --nShift );
    1009             :                         }
    1010             : 
    1011           0 :                         *pTmp = cTmp;
    1012           0 :                         rOStm.Write( pBuf, nAlignedWidth );
    1013             :                     }
    1014             :                 }
    1015           0 :                 break;
    1016             : 
    1017             :                 case( 4 ):
    1018             :                 {
    1019          17 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1020             :                     {
    1021          16 :                         pTmp = pBuf;
    1022          16 :                         cTmp = 0;
    1023             : 
    1024         288 :                         for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
    1025             :                         {
    1026         272 :                             if( !nShift )
    1027             :                             {
    1028         128 :                                 nShift = 2L;
    1029         128 :                                 *pTmp++ = cTmp;
    1030         128 :                                 cTmp = 0;
    1031             :                             }
    1032             : 
    1033         272 :                             cTmp |= ( (sal_uInt8) rAcc.GetPixel( nY, nX ) << ( --nShift << 2L ) );
    1034             :                         }
    1035          16 :                         *pTmp = cTmp;
    1036          16 :                         rOStm.Write( pBuf, nAlignedWidth );
    1037             :                     }
    1038             :                 }
    1039           1 :                 break;
    1040             : 
    1041             :                 case( 8 ):
    1042             :                 {
    1043           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1044             :                     {
    1045           0 :                         pTmp = pBuf;
    1046             : 
    1047           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
    1048           0 :                             *pTmp++ = rAcc.GetPixel( nY, nX );
    1049             : 
    1050           0 :                         rOStm.Write( pBuf, nAlignedWidth );
    1051             :                     }
    1052             :                 }
    1053           0 :                 break;
    1054             : 
    1055             :                 // #i59239# fallback to 24 bit format, if bitcount is non-default
    1056             :                 default:
    1057             :                     // FALLTHROUGH intended
    1058             :                 case( 24 ):
    1059             :                 {
    1060           0 :                     BitmapColor aPixelColor;
    1061             : 
    1062           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1063             :                     {
    1064           0 :                         pTmp = pBuf;
    1065             : 
    1066           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
    1067             :                         {
    1068           0 :                             aPixelColor = rAcc.GetPixel( nY, nX );
    1069           0 :                             *pTmp++ = aPixelColor.GetBlue();
    1070           0 :                             *pTmp++ = aPixelColor.GetGreen();
    1071           0 :                             *pTmp++ = aPixelColor.GetRed();
    1072             :                         }
    1073             : 
    1074           0 :                         rOStm.Write( pBuf, nAlignedWidth );
    1075           0 :                     }
    1076             :                 }
    1077           0 :                 break;
    1078             :             }
    1079             : 
    1080           1 :             delete[] pBuf;
    1081             :         }
    1082             :     }
    1083             : 
    1084           1 :     rImageSize = rOStm.Tell() - rImageSize;
    1085             : 
    1086           1 :     return( rOStm.GetError() == 0UL );
    1087             : }
    1088             : 
    1089             : // ------------------------------------------------------------------
    1090             : 
    1091           2 : void Bitmap::ImplDecodeRLE( sal_uInt8* pBuffer, DIBInfoHeader& rHeader,
    1092             :                             BitmapWriteAccess& rAcc, sal_Bool bRLE4 )
    1093             : {
    1094           2 :     Scanline    pRLE = pBuffer;
    1095           2 :     long        nY = abs(rHeader.nHeight) - 1L;
    1096           2 :     const sal_uLong nWidth = rAcc.Width();
    1097             :     sal_uLong       nCountByte;
    1098             :     sal_uLong       nRunByte;
    1099           2 :     sal_uLong       nX = 0UL;
    1100             :     sal_uInt8       cTmp;
    1101           2 :     sal_Bool        bEndDecoding = sal_False;
    1102             : 
    1103        5053 :     do
    1104             :     {
    1105        5053 :         if( ( nCountByte = *pRLE++ ) == 0 )
    1106             :         {
    1107        2032 :             nRunByte = *pRLE++;
    1108             : 
    1109        2032 :             if( nRunByte > 2 )
    1110             :             {
    1111        1662 :                 if( bRLE4 )
    1112             :                 {
    1113        1662 :                     nCountByte = nRunByte >> 1;
    1114             : 
    1115        7607 :                     for( sal_uLong i = 0UL; i < nCountByte; i++ )
    1116             :                     {
    1117        5945 :                         cTmp = *pRLE++;
    1118             : 
    1119        5945 :                         if( nX < nWidth )
    1120        5500 :                             rAcc.SetPixel( nY, nX++, cTmp >> 4 );
    1121             : 
    1122        5945 :                         if( nX < nWidth )
    1123        5500 :                             rAcc.SetPixel( nY, nX++, cTmp & 0x0f );
    1124             :                     }
    1125             : 
    1126        1662 :                     if( nRunByte & 1 )
    1127             :                     {
    1128           1 :                         if( nX < nWidth )
    1129           0 :                             rAcc.SetPixel( nY, nX++, *pRLE >> 4 );
    1130             : 
    1131           1 :                         pRLE++;
    1132             :                     }
    1133             : 
    1134        1662 :                     if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
    1135         604 :                         pRLE++;
    1136             :                 }
    1137             :                 else
    1138             :                 {
    1139           0 :                     for( sal_uLong i = 0UL; i < nRunByte; i++ )
    1140             :                     {
    1141           0 :                         if( nX < nWidth )
    1142           0 :                             rAcc.SetPixel( nY, nX++, *pRLE );
    1143             : 
    1144           0 :                         pRLE++;
    1145             :                     }
    1146             : 
    1147           0 :                     if( nRunByte & 1 )
    1148           0 :                         pRLE++;
    1149             :                 }
    1150             :             }
    1151         370 :             else if( !nRunByte )
    1152             :             {
    1153         370 :                 nY--;
    1154         370 :                 nX = 0UL;
    1155             :             }
    1156           0 :             else if( nRunByte == 1 )
    1157           0 :                 bEndDecoding = sal_True;
    1158             :             else
    1159             :             {
    1160           0 :                 nX += *pRLE++;
    1161           0 :                 nY -= *pRLE++;
    1162             :             }
    1163             :         }
    1164             :         else
    1165             :         {
    1166        3021 :             cTmp = *pRLE++;
    1167             : 
    1168        3021 :             if( bRLE4 )
    1169             :             {
    1170        3012 :                 nRunByte = nCountByte >> 1;
    1171             : 
    1172       65423 :                 for( sal_uLong i = 0UL; i < nRunByte; i++ )
    1173             :                 {
    1174       62411 :                     if( nX < nWidth )
    1175       58372 :                         rAcc.SetPixel( nY, nX++, cTmp >> 4 );
    1176             : 
    1177       62411 :                     if( nX < nWidth )
    1178       58371 :                         rAcc.SetPixel( nY, nX++, cTmp & 0x0f );
    1179             :                 }
    1180             : 
    1181        3012 :                 if( ( nCountByte & 1 ) && ( nX < nWidth ) )
    1182           1 :                     rAcc.SetPixel( nY, nX++, cTmp >> 4 );
    1183             :             }
    1184             :             else
    1185             :             {
    1186          50 :                 for( sal_uLong i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
    1187          41 :                     rAcc.SetPixel( nY, nX++, cTmp );
    1188             :             }
    1189             :         }
    1190             :     }
    1191             :     while ( !bEndDecoding && ( nY >= 0L ) );
    1192           2 : }
    1193             : 
    1194             : // ------------------------------------------------------------------
    1195             : 
    1196           0 : sal_Bool Bitmap::ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, sal_Bool bRLE4 )
    1197             : {
    1198           0 :     const sal_uLong nWidth = rAcc.Width();
    1199           0 :     const sal_uLong nHeight = rAcc.Height();
    1200             :     sal_uLong       nX;
    1201             :     sal_uLong       nSaveIndex;
    1202             :     sal_uLong       nCount;
    1203             :     sal_uLong       nBufCount;
    1204           0 :     sal_uInt8*      pBuf = new sal_uInt8[ ( nWidth << 1 ) + 2 ];
    1205             :     sal_uInt8*      pTmp;
    1206             :     sal_uInt8       cPix;
    1207             :     sal_uInt8       cLast;
    1208             :     sal_Bool        bFound;
    1209             : 
    1210           0 :     for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
    1211             :     {
    1212           0 :         pTmp = pBuf;
    1213           0 :         nX = nBufCount = 0UL;
    1214             : 
    1215           0 :         while( nX < nWidth )
    1216             :         {
    1217           0 :             nCount = 1L;
    1218           0 :             cPix = rAcc.GetPixel( nY, nX++ );
    1219             : 
    1220           0 :             while( ( nX < nWidth ) && ( nCount < 255L ) && ( cPix == rAcc.GetPixel( nY, nX ) ) )
    1221             :             {
    1222           0 :                 nX++;
    1223           0 :                 nCount++;
    1224             :             }
    1225             : 
    1226           0 :             if ( nCount > 1 )
    1227             :             {
    1228           0 :                 *pTmp++ = (sal_uInt8) nCount;
    1229           0 :                 *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
    1230           0 :                 nBufCount += 2;
    1231             :             }
    1232             :             else
    1233             :             {
    1234           0 :                 cLast = cPix;
    1235           0 :                 nSaveIndex = nX - 1UL;
    1236           0 :                 bFound = sal_False;
    1237             : 
    1238           0 :                 while( ( nX < nWidth ) && ( nCount < 256L ) && ( cPix = rAcc.GetPixel( nY, nX ) ) != cLast )
    1239             :                 {
    1240           0 :                     nX++; nCount++;
    1241           0 :                     cLast = cPix;
    1242           0 :                     bFound = sal_True;
    1243             :                 }
    1244             : 
    1245           0 :                 if ( bFound )
    1246           0 :                     nX--;
    1247             : 
    1248           0 :                 if ( nCount > 3 )
    1249             :                 {
    1250           0 :                     *pTmp++ = 0;
    1251           0 :                     *pTmp++ = (sal_uInt8) --nCount;
    1252             : 
    1253           0 :                     if( bRLE4 )
    1254             :                     {
    1255           0 :                         for ( sal_uLong i = 0; i < nCount; i++, pTmp++ )
    1256             :                         {
    1257           0 :                             *pTmp = (sal_uInt8) rAcc.GetPixel( nY, nSaveIndex++ ) << 4;
    1258             : 
    1259           0 :                             if ( ++i < nCount )
    1260           0 :                                 *pTmp |= rAcc.GetPixel( nY, nSaveIndex++ );
    1261             :                         }
    1262             : 
    1263           0 :                         nCount = ( nCount + 1 ) >> 1;
    1264             :                     }
    1265             :                     else
    1266             :                     {
    1267           0 :                         for( sal_uLong i = 0UL; i < nCount; i++ )
    1268           0 :                             *pTmp++ = rAcc.GetPixel( nY, nSaveIndex++ );
    1269             :                     }
    1270             : 
    1271           0 :                     if ( nCount & 1 )
    1272             :                     {
    1273           0 :                         *pTmp++ = 0;
    1274           0 :                         nBufCount += ( nCount + 3 );
    1275             :                     }
    1276             :                     else
    1277           0 :                         nBufCount += ( nCount + 2 );
    1278             :                 }
    1279             :                 else
    1280             :                 {
    1281           0 :                     *pTmp++ = 1;
    1282           0 :                     *pTmp++ = (sal_uInt8) rAcc.GetPixel( nY, nSaveIndex ) << ( bRLE4 ? 4 : 0 );
    1283             : 
    1284           0 :                     if ( nCount == 3 )
    1285             :                     {
    1286           0 :                         *pTmp++ = 1;
    1287           0 :                         *pTmp++ = (sal_uInt8) rAcc.GetPixel( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
    1288           0 :                         nBufCount += 4;
    1289             :                     }
    1290             :                     else
    1291           0 :                         nBufCount += 2;
    1292             :                 }
    1293             :             }
    1294             :         }
    1295             : 
    1296           0 :         pBuf[ nBufCount++ ] = 0;
    1297           0 :         pBuf[ nBufCount++ ] = 0;
    1298             : 
    1299           0 :         rOStm.Write( pBuf, nBufCount );
    1300             :     }
    1301             : 
    1302           0 :     rOStm << (sal_uInt8) 0;
    1303           0 :     rOStm << (sal_uInt8) 1;
    1304             : 
    1305           0 :     delete[] pBuf;
    1306             : 
    1307           0 :     return( rOStm.GetError() == 0UL );
    1308             : }
    1309             : 
    1310             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10