LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/source/gdi - dibtools.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 520 695 74.8 %
Date: 2013-07-09 Functions: 29 31 93.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * This file is part of the LibreOffice project.
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * This file incorporates work covered by the following license notice:
       9             :  *
      10             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      11             :  *   contributor license agreements. See the NOTICE file distributed
      12             :  *   with this work for additional information regarding copyright
      13             :  *   ownership. The ASF licenses this file to you under the Apache
      14             :  *   License, Version 2.0 (the "License"); you may not use this file
      15             :  *   except in compliance with the License. You may obtain a copy of
      16             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      17             :  */
      18             : 
      19             : #include <vcl/salbtype.hxx>
      20             : #include <vcl/dibtools.hxx>
      21             : #include <tools/zcodec.hxx>
      22             : #include <tools/stream.hxx>
      23             : #include <vcl/bitmapex.hxx>
      24             : #include <vcl/bmpacc.hxx>
      25             : #include <vcl/outdev.hxx>
      26             : 
      27             : //////////////////////////////////////////////////////////////////////////////
      28             : // - Defines -
      29             : 
      30             : #define DIBCOREHEADERSIZE       ( 12UL )
      31             : #define DIBINFOHEADERSIZE       ( sizeof(DIBInfoHeader) )
      32             : #define DIBV5HEADERSIZE         ( sizeof(DIBV5Header) )
      33             : 
      34             : //////////////////////////////////////////////////////////////////////////////
      35             : // - Compression defines
      36             : 
      37             : #define COMPRESS_OWN                ('S'|('D'<<8UL))
      38             : #define COMPRESS_NONE               ( 0UL )
      39             : #define RLE_8                       ( 1UL )
      40             : #define RLE_4                       ( 2UL )
      41             : #define BITFIELDS                   ( 3UL )
      42             : #define ZCOMPRESS                   ( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
      43             : 
      44             : //////////////////////////////////////////////////////////////////////////////
      45             : // - DIBInfoHeader and DIBV5Header
      46             : 
      47             : typedef sal_Int32 FXPT2DOT30;
      48             : 
      49             : struct CIEXYZ
      50             : {
      51             :     FXPT2DOT30      aXyzX;
      52             :     FXPT2DOT30      aXyzY;
      53             :     FXPT2DOT30      aXyzZ;
      54             : 
      55        3957 :     CIEXYZ()
      56             :     :   aXyzX(0L),
      57             :         aXyzY(0L),
      58        3957 :         aXyzZ(0L)
      59        3957 :     {}
      60             : 
      61        3957 :     ~CIEXYZ()
      62        3957 :     {}
      63             : };
      64             : 
      65             : struct CIEXYZTriple
      66             : {
      67             :     CIEXYZ          aXyzRed;
      68             :     CIEXYZ          aXyzGreen;
      69             :     CIEXYZ          aXyzBlue;
      70             : 
      71        1319 :     CIEXYZTriple()
      72             :     :   aXyzRed(),
      73             :         aXyzGreen(),
      74        1319 :         aXyzBlue()
      75        1319 :     {}
      76             : 
      77        1319 :     ~CIEXYZTriple()
      78        1319 :     {}
      79             : };
      80             : 
      81             : struct DIBInfoHeader
      82             : {
      83             :     sal_uInt32      nSize;
      84             :     sal_Int32       nWidth;
      85             :     sal_Int32       nHeight;
      86             :     sal_uInt16      nPlanes;
      87             :     sal_uInt16      nBitCount;
      88             :     sal_uInt32      nCompression;
      89             :     sal_uInt32      nSizeImage;
      90             :     sal_Int32       nXPelsPerMeter;
      91             :     sal_Int32       nYPelsPerMeter;
      92             :     sal_uInt32      nColsUsed;
      93             :     sal_uInt32      nColsImportant;
      94             : 
      95        1319 :     DIBInfoHeader()
      96             :     :   nSize(0UL),
      97             :         nWidth(0UL),
      98             :         nHeight(0UL),
      99             :         nPlanes(0),
     100             :         nBitCount(0),
     101             :         nCompression(0),
     102             :         nSizeImage(0),
     103             :         nXPelsPerMeter(0UL),
     104             :         nYPelsPerMeter(0UL),
     105             :         nColsUsed(0UL),
     106        1319 :         nColsImportant(0UL)
     107        1319 :     {}
     108             : 
     109        1319 :     ~DIBInfoHeader()
     110        1319 :     {}
     111             : };
     112             : 
     113             : struct DIBV5Header : public DIBInfoHeader
     114             : {
     115             :     sal_uInt32      nV5RedMask;
     116             :     sal_uInt32      nV5GreenMask;
     117             :     sal_uInt32      nV5BlueMask;
     118             :     sal_uInt32      nV5AlphaMask;
     119             :     sal_uInt32      nV5CSType;
     120             :     CIEXYZTriple    aV5Endpoints;
     121             :     sal_uInt32      nV5GammaRed;
     122             :     sal_uInt32      nV5GammaGreen;
     123             :     sal_uInt32      nV5GammaBlue;
     124             :     sal_uInt32      nV5Intent;
     125             :     sal_uInt32      nV5ProfileData;
     126             :     sal_uInt32      nV5ProfileSize;
     127             :     sal_uInt32      nV5Reserved;
     128             : 
     129        1319 :     DIBV5Header()
     130             :     :   DIBInfoHeader(),
     131             :         nV5RedMask(0UL),
     132             :         nV5GreenMask(0UL),
     133             :         nV5BlueMask(0UL),
     134             :         nV5AlphaMask(0UL),
     135             :         nV5CSType(0UL),
     136             :         aV5Endpoints(),
     137             :         nV5GammaRed(0UL),
     138             :         nV5GammaGreen(0UL),
     139             :         nV5GammaBlue(0UL),
     140             :         nV5Intent(0UL),
     141             :         nV5ProfileData(0UL),
     142             :         nV5ProfileSize(0UL),
     143        1319 :         nV5Reserved(0UL)
     144        1319 :     {}
     145             : 
     146        1319 :     ~DIBV5Header()
     147        1319 :     {}
     148             : };
     149             : 
     150             : //////////////////////////////////////////////////////////////////////////////
     151             : 
     152             : namespace
     153             : {
     154        1042 :     inline sal_uInt16 discretizeBitcount( sal_uInt16 nInputCount )
     155             :     {
     156             :         return ( nInputCount <= 1 ) ? 1 :
     157             :                ( nInputCount <= 4 ) ? 4 :
     158        1042 :                ( nInputCount <= 8 ) ? 8 : 24;
     159             :     }
     160             : 
     161         980 :     inline bool isBitfieldCompression( sal_uLong nScanlineFormat )
     162             :     {
     163         980 :         return (BMP_FORMAT_16BIT_TC_LSB_MASK == nScanlineFormat) || (BMP_FORMAT_32BIT_TC_MASK == nScanlineFormat);
     164             :     }
     165             : }
     166             : 
     167             : //////////////////////////////////////////////////////////////////////////////
     168             : 
     169         341 : bool ImplReadDIBInfoHeader(SvStream& rIStm, DIBV5Header& rHeader, bool& bTopDown)
     170             : {
     171             :     // BITMAPINFOHEADER or BITMAPCOREHEADER or BITMAPV5HEADER
     172         341 :     const sal_Size aStartPos(rIStm.Tell());
     173         341 :     rIStm >> rHeader.nSize;
     174             : 
     175             :     // BITMAPCOREHEADER
     176         341 :     if ( rHeader.nSize == DIBCOREHEADERSIZE )
     177             :     {
     178             :         sal_Int16 nTmp16;
     179             : 
     180           1 :         rIStm >> nTmp16; rHeader.nWidth = nTmp16;
     181           1 :         rIStm >> nTmp16; rHeader.nHeight = nTmp16;
     182           1 :         rIStm >> rHeader.nPlanes;
     183           1 :         rIStm >> rHeader.nBitCount;
     184             :     }
     185             :     else
     186             :     {
     187             :         // BITMAPCOREHEADER, BITMAPV5HEADER or unknown. Read as far as possible
     188         340 :         sal_Size nUsed(sizeof(rHeader.nSize));
     189             : 
     190             :         // read DIBInfoHeader entries
     191         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nWidth; nUsed += sizeof(rHeader.nWidth); }
     192         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nHeight; nUsed += sizeof(rHeader.nHeight); }
     193         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nPlanes; nUsed += sizeof(rHeader.nPlanes); }
     194         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nBitCount;  nUsed += sizeof(rHeader.nBitCount); }
     195         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nCompression;  nUsed += sizeof(rHeader.nCompression); }
     196         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nSizeImage;  nUsed += sizeof(rHeader.nSizeImage); }
     197         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nXPelsPerMeter;  nUsed += sizeof(rHeader.nXPelsPerMeter); }
     198         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nYPelsPerMeter;  nUsed += sizeof(rHeader.nYPelsPerMeter); }
     199         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nColsUsed;  nUsed += sizeof(rHeader.nColsUsed); }
     200         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nColsImportant;  nUsed += sizeof(rHeader.nColsImportant); }
     201             : 
     202             :         // read DIBV5HEADER members
     203         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5RedMask; nUsed += sizeof(rHeader.nV5RedMask); }
     204         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GreenMask; nUsed += sizeof(rHeader.nV5GreenMask);  }
     205         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5BlueMask; nUsed += sizeof(rHeader.nV5BlueMask);  }
     206         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5AlphaMask; nUsed += sizeof(rHeader.nV5AlphaMask);  }
     207         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5CSType; nUsed += sizeof(rHeader.nV5CSType);  }
     208             : 
     209             :         // read contained CIEXYZTriple's
     210         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzRed.aXyzX; nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzX); }
     211         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzRed.aXyzY; nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzY); }
     212         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzRed.aXyzZ; nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzZ); }
     213         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzGreen.aXyzX; nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzX); }
     214         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzGreen.aXyzY; nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzY); }
     215         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzGreen.aXyzZ; nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzZ); }
     216         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzBlue.aXyzX; nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzX); }
     217         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzBlue.aXyzY; nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzY); }
     218         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzBlue.aXyzZ; nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzZ); }
     219             : 
     220         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GammaRed; nUsed += sizeof(rHeader.nV5GammaRed);  }
     221         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GammaGreen; nUsed += sizeof(rHeader.nV5GammaGreen);  }
     222         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GammaBlue; nUsed += sizeof(rHeader.nV5GammaBlue);  }
     223         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5Intent; nUsed += sizeof(rHeader.nV5Intent);  }
     224         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5ProfileData; nUsed += sizeof(rHeader.nV5ProfileData);  }
     225         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5ProfileSize; nUsed += sizeof(rHeader.nV5ProfileSize);  }
     226         340 :         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5Reserved; nUsed += sizeof(rHeader.nV5Reserved);  }
     227             : 
     228             :         // seek to EndPos
     229         340 :         rIStm.Seek(aStartPos + rHeader.nSize);
     230             :     }
     231             : 
     232         341 :     if ( rHeader.nHeight < 0 )
     233             :     {
     234           0 :         bTopDown = true;
     235           0 :         rHeader.nHeight *= -1;
     236             :     }
     237             :     else
     238             :     {
     239         341 :         bTopDown = false;
     240             :     }
     241             : 
     242         341 :     if ( rHeader.nWidth < 0 )
     243             :     {
     244           0 :         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     245             :     }
     246             : 
     247             :     // #144105# protect a little against damaged files
     248         341 :     if( rHeader.nSizeImage > ( 16 * static_cast< sal_uInt32 >( rHeader.nWidth * rHeader.nHeight ) ) )
     249             :     {
     250           1 :         rHeader.nSizeImage = 0;
     251             :     }
     252             : 
     253         341 :     return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
     254             : }
     255             : 
     256          11 : bool ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, bool bQuad )
     257             : {
     258          11 :     const sal_uInt16    nColors = rAcc.GetPaletteEntryCount();
     259          11 :     const sal_uLong     nPalSize = nColors * ( bQuad ? 4UL : 3UL );
     260          11 :     BitmapColor     aPalColor;
     261             : 
     262          11 :     sal_uInt8* pEntries = new sal_uInt8[ nPalSize ];
     263          11 :     rIStm.Read( pEntries, nPalSize );
     264             : 
     265          11 :     sal_uInt8* pTmpEntry = pEntries;
     266       16805 :     for( sal_uInt16 i = 0; i < nColors; i++ )
     267             :     {
     268       16794 :         aPalColor.SetBlue( *pTmpEntry++ );
     269       16794 :         aPalColor.SetGreen( *pTmpEntry++ );
     270       16794 :         aPalColor.SetRed( *pTmpEntry++ );
     271             : 
     272       16794 :         if( bQuad )
     273       16794 :             pTmpEntry++;
     274             : 
     275       16794 :         rAcc.SetPaletteColor( i, aPalColor );
     276             :     }
     277             : 
     278          11 :     delete[] pEntries;
     279             : 
     280          11 :     return( rIStm.GetError() == 0UL );
     281             : }
     282             : 
     283           2 : void ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, bool bRLE4 )
     284             : {
     285           2 :     Scanline    pRLE = pBuffer;
     286           2 :     long        nY = rHeader.nHeight - 1L;
     287           2 :     const sal_uLong nWidth = rAcc.Width();
     288             :     sal_uLong       nCountByte;
     289             :     sal_uLong       nRunByte;
     290           2 :     sal_uLong       nX = 0UL;
     291             :     sal_uInt8       cTmp;
     292           2 :     bool        bEndDecoding = false;
     293             : 
     294        5053 :     do
     295             :     {
     296        5053 :         if( ( nCountByte = *pRLE++ ) == 0 )
     297             :         {
     298        2032 :             nRunByte = *pRLE++;
     299             : 
     300        2032 :             if( nRunByte > 2 )
     301             :             {
     302        1662 :                 if( bRLE4 )
     303             :                 {
     304        1662 :                     nCountByte = nRunByte >> 1;
     305             : 
     306        7607 :                     for( sal_uLong i = 0UL; i < nCountByte; i++ )
     307             :                     {
     308        5945 :                         cTmp = *pRLE++;
     309             : 
     310        5945 :                         if( nX < nWidth )
     311        5500 :                             rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
     312             : 
     313        5945 :                         if( nX < nWidth )
     314        5500 :                             rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
     315             :                     }
     316             : 
     317        1662 :                     if( nRunByte & 1 )
     318             :                     {
     319           1 :                         if( nX < nWidth )
     320           0 :                             rAcc.SetPixelIndex( nY, nX++, *pRLE >> 4 );
     321             : 
     322           1 :                         pRLE++;
     323             :                     }
     324             : 
     325        1662 :                     if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
     326         604 :                         pRLE++;
     327             :                 }
     328             :                 else
     329             :                 {
     330           0 :                     for( sal_uLong i = 0UL; i < nRunByte; i++ )
     331             :                     {
     332           0 :                         if( nX < nWidth )
     333           0 :                             rAcc.SetPixelIndex( nY, nX++, *pRLE );
     334             : 
     335           0 :                         pRLE++;
     336             :                     }
     337             : 
     338           0 :                     if( nRunByte & 1 )
     339           0 :                         pRLE++;
     340             :                 }
     341             :             }
     342         370 :             else if( !nRunByte )
     343             :             {
     344         370 :                 nY--;
     345         370 :                 nX = 0UL;
     346             :             }
     347           0 :             else if( nRunByte == 1 )
     348           0 :                 bEndDecoding = true;
     349             :             else
     350             :             {
     351           0 :                 nX += *pRLE++;
     352           0 :                 nY -= *pRLE++;
     353             :             }
     354             :         }
     355             :         else
     356             :         {
     357        3021 :             cTmp = *pRLE++;
     358             : 
     359        3021 :             if( bRLE4 )
     360             :             {
     361        3012 :                 nRunByte = nCountByte >> 1;
     362             : 
     363       65423 :                 for( sal_uLong i = 0UL; i < nRunByte; i++ )
     364             :                 {
     365       62411 :                     if( nX < nWidth )
     366       58372 :                         rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
     367             : 
     368       62411 :                     if( nX < nWidth )
     369       58371 :                         rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
     370             :                 }
     371             : 
     372        3012 :                 if( ( nCountByte & 1 ) && ( nX < nWidth ) )
     373           1 :                     rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
     374             :             }
     375             :             else
     376             :             {
     377          50 :                 for( sal_uLong i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
     378          41 :                     rAcc.SetPixelIndex( nY, nX++, cTmp );
     379             :             }
     380             :         }
     381             :     }
     382       10106 :     while ( !bEndDecoding && ( nY >= 0L ) );
     383           2 : }
     384             : 
     385          19 : bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, BitmapWriteAccess* pAccAlpha, bool bTopDown)
     386             : {
     387          19 :     const sal_uLong nAlignedWidth = AlignedWidth4Bytes(rHeader.nWidth * rHeader.nBitCount);
     388          19 :     sal_uInt32 nRMask(0);
     389          19 :     sal_uInt32 nGMask(0);
     390          19 :     sal_uInt32 nBMask(0);
     391          19 :     bool bNative(false);
     392          19 :     bool bTCMask(!pAccAlpha && ((16 == rHeader.nBitCount) || (32 == rHeader.nBitCount)));
     393          19 :     bool bRLE((RLE_8 == rHeader.nCompression && 8 == rHeader.nBitCount) || (RLE_4 == rHeader.nCompression && 4 == rHeader.nBitCount));
     394             : 
     395             :     // Is native format?
     396          19 :     switch(rAcc.GetScanlineFormat())
     397             :     {
     398             :         case( BMP_FORMAT_1BIT_MSB_PAL ):
     399             :         case( BMP_FORMAT_4BIT_MSN_PAL ):
     400             :         case( BMP_FORMAT_8BIT_PAL ):
     401             :         case( BMP_FORMAT_24BIT_TC_BGR ):
     402             :         {
     403          19 :             bNative = ( ( static_cast< bool >(rAcc.IsBottomUp()) != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
     404          19 :             break;
     405             :         }
     406             : 
     407             :         default:
     408             :         {
     409           0 :             break;
     410             :         }
     411             :     }
     412             : 
     413             :     // Read data
     414          19 :     if(bNative)
     415             :     {
     416             :         // true color DIB's can have a (optimization) palette
     417          10 :         if(rHeader.nColsUsed && 8 < rHeader.nBitCount)
     418             :         {
     419           0 :             rIStm.SeekRel(rHeader.nColsUsed * ((rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3));
     420             :         }
     421             : 
     422          10 :         rIStm.Read(rAcc.GetBuffer(), rHeader.nHeight * nAlignedWidth);
     423             :     }
     424             :     else
     425             :     {
     426             :         // Read color mask
     427           9 :         if(bTCMask)
     428             :         {
     429           1 :             if(BITFIELDS == rHeader.nCompression)
     430             :             {
     431           1 :                 rIStm.SeekRel( -12L );
     432           1 :                 rIStm >> nRMask;
     433           1 :                 rIStm >> nGMask;
     434           1 :                 rIStm >> nBMask;
     435             :             }
     436             :             else
     437             :             {
     438           0 :                 nRMask = ( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL;
     439           0 :                 nGMask = ( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL;
     440           0 :                 nBMask = ( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL;
     441             :             }
     442             :         }
     443             : 
     444           9 :         if(bRLE)
     445             :         {
     446           2 :             if(!rHeader.nSizeImage)
     447             :             {
     448           1 :                 const sal_uLong nOldPos(rIStm.Tell());
     449             : 
     450           1 :                 rIStm.Seek(STREAM_SEEK_TO_END);
     451           1 :                 rHeader.nSizeImage = rIStm.Tell() - nOldPos;
     452           1 :                 rIStm.Seek(nOldPos);
     453             :             }
     454             : 
     455           2 :             sal_uInt8* pBuffer = (sal_uInt8*)rtl_allocateMemory(rHeader.nSizeImage);
     456           2 :             rIStm.Read((char*)pBuffer, rHeader.nSizeImage);
     457           2 :             ImplDecodeRLE(pBuffer, rHeader, rAcc, RLE_4 == rHeader.nCompression);
     458           2 :             rtl_freeMemory(pBuffer);
     459             :         }
     460             :         else
     461             :         {
     462           7 :             const long nWidth(rHeader.nWidth);
     463           7 :             const long nHeight(rHeader.nHeight);
     464           7 :             sal_uInt8* pBuf = new sal_uInt8[nAlignedWidth];
     465             : 
     466             :             // true color DIB's can have a (optimization) palette
     467           7 :             if(rHeader.nColsUsed && 8 < rHeader.nBitCount)
     468             :             {
     469           0 :                 rIStm.SeekRel(rHeader.nColsUsed * ((rHeader.nSize != DIBCOREHEADERSIZE ) ? 4 : 3));
     470             :             }
     471             : 
     472           7 :             const long nI(bTopDown ? 1 : -1);
     473           7 :             long nY(bTopDown ? 0 : nHeight - 1);
     474           7 :             long nCount(nHeight);
     475             : 
     476           7 :             switch(rHeader.nBitCount)
     477             :             {
     478             :                 case( 1 ):
     479             :                 {
     480             :                     sal_uInt8*  pTmp;
     481             :                     sal_uInt8   cTmp;
     482             : 
     483          14 :                     for( ; nCount--; nY += nI )
     484             :                     {
     485          13 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     486          13 :                         cTmp = *pTmp++;
     487             : 
     488         182 :                         for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
     489             :                         {
     490         169 :                             if( !nShift )
     491             :                             {
     492             :                                 nShift = 8L,
     493          13 :                                 cTmp = *pTmp++;
     494             :                             }
     495             : 
     496         169 :                             rAcc.SetPixelIndex( nY, nX, (cTmp >> --nShift) & 1);
     497             :                         }
     498             :                     }
     499             :                 }
     500           1 :                 break;
     501             : 
     502             :                 case( 4 ):
     503             :                 {
     504             :                     sal_uInt8*  pTmp;
     505             :                     sal_uInt8   cTmp;
     506             : 
     507          56 :                     for( ; nCount--; nY += nI )
     508             :                     {
     509          52 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     510          52 :                         cTmp = *pTmp++;
     511             : 
     512        5122 :                         for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
     513             :                         {
     514        5070 :                             if( !nShift )
     515             :                             {
     516             :                                 nShift = 2UL,
     517        2496 :                                 cTmp = *pTmp++;
     518             :                             }
     519             : 
     520        5070 :                             rAcc.SetPixelIndex( nY, nX, (cTmp >> ( --nShift << 2UL ) ) & 0x0f);
     521             :                         }
     522             :                     }
     523             :                 }
     524           4 :                 break;
     525             : 
     526             :                 case( 8 ):
     527             :                 {
     528             :                     sal_uInt8*  pTmp;
     529             : 
     530         439 :                     for( ; nCount--; nY += nI )
     531             :                     {
     532         438 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     533             : 
     534      223380 :                         for( long nX = 0L; nX < nWidth; nX++ )
     535      222942 :                             rAcc.SetPixelIndex( nY, nX, *pTmp++ );
     536             :                     }
     537             :                 }
     538           1 :                 break;
     539             : 
     540             :                 case( 16 ):
     541             :                 {
     542           0 :                     ColorMask   aMask( nRMask, nGMask, nBMask );
     543           0 :                     BitmapColor aColor;
     544             :                     sal_uInt16*     pTmp16;
     545             : 
     546           0 :                     for( ; nCount--; nY += nI )
     547             :                     {
     548           0 :                         rIStm.Read( (char*)( pTmp16 = (sal_uInt16*) pBuf ), nAlignedWidth );
     549             : 
     550           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     551             :                         {
     552           0 :                             aMask.GetColorFor16BitLSB( aColor, (sal_uInt8*) pTmp16++ );
     553           0 :                             rAcc.SetPixel( nY, nX, aColor );
     554             :                         }
     555           0 :                     }
     556             :                 }
     557           0 :                 break;
     558             : 
     559             :                 case( 24 ):
     560             :                 {
     561           0 :                     BitmapColor aPixelColor;
     562             :                     sal_uInt8*      pTmp;
     563             : 
     564           0 :                     for( ; nCount--; nY += nI )
     565             :                     {
     566           0 :                         rIStm.Read( pTmp = pBuf, nAlignedWidth );
     567             : 
     568           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     569             :                         {
     570           0 :                             aPixelColor.SetBlue( *pTmp++ );
     571           0 :                             aPixelColor.SetGreen( *pTmp++ );
     572           0 :                             aPixelColor.SetRed( *pTmp++ );
     573           0 :                             rAcc.SetPixel( nY, nX, aPixelColor );
     574             :                         }
     575           0 :                     }
     576             :                 }
     577           0 :                 break;
     578             : 
     579             :                 case( 32 ):
     580             :                 {
     581           1 :                     ColorMask aMask(nRMask, nGMask, nBMask);
     582           2 :                     BitmapColor aColor;
     583             :                     sal_uInt32* pTmp32;
     584             : 
     585           1 :                     if(pAccAlpha)
     586             :                     {
     587             :                         sal_uInt8 aAlpha;
     588             : 
     589           0 :                         for( ; nCount--; nY += nI )
     590             :                         {
     591           0 :                             rIStm.Read( (char*)( pTmp32 = (sal_uInt32*) pBuf ), nAlignedWidth );
     592             : 
     593           0 :                             for( long nX = 0L; nX < nWidth; nX++ )
     594             :                             {
     595           0 :                                 aMask.GetColorAndAlphaFor32Bit( aColor, aAlpha, (sal_uInt8*) pTmp32++ );
     596           0 :                                 rAcc.SetPixel( nY, nX, aColor );
     597           0 :                                 pAccAlpha->SetPixelIndex(nY, nX, sal_uInt8(0xff) - aAlpha);
     598             :                             }
     599             :                         }
     600             :                     }
     601             :                     else
     602             :                     {
     603          33 :                         for( ; nCount--; nY += nI )
     604             :                         {
     605          32 :                             rIStm.Read( (char*)( pTmp32 = (sal_uInt32*) pBuf ), nAlignedWidth );
     606             : 
     607        1056 :                             for( long nX = 0L; nX < nWidth; nX++ )
     608             :                             {
     609        1024 :                                 aMask.GetColorFor32Bit( aColor, (sal_uInt8*) pTmp32++ );
     610        1024 :                                 rAcc.SetPixel( nY, nX, aColor );
     611             :                             }
     612             :                         }
     613           1 :                     }
     614             :                 }
     615             :             }
     616             : 
     617           7 :             delete[] pBuf;
     618             :         }
     619             :     }
     620             : 
     621          19 :     return( rIStm.GetError() == 0UL );
     622             : }
     623             : 
     624         341 : bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLong nOffset )
     625             : {
     626         341 :     DIBV5Header aHeader;
     627         341 :     const sal_uLong nStmPos = rIStm.Tell();
     628         341 :     bool bRet(false);
     629         341 :     bool bTopDown(false);
     630             : 
     631         341 :     if(ImplReadDIBInfoHeader(rIStm, aHeader, bTopDown) && aHeader.nWidth && aHeader.nHeight && aHeader.nBitCount)
     632             :     {
     633          21 :         const sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount));
     634          21 :         const Size aSizePixel(aHeader.nWidth, aHeader.nHeight);
     635          21 :         BitmapPalette aDummyPal;
     636          42 :         Bitmap aNewBmp(aSizePixel, nBitCount, &aDummyPal);
     637          42 :         Bitmap aNewBmpAlpha;
     638          21 :         BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
     639          21 :         BitmapWriteAccess* pAccAlpha = 0;
     640          21 :         bool bAlphaPossible(pBmpAlpha && aHeader.nBitCount == 32);
     641             : 
     642          21 :         if(bAlphaPossible)
     643             :         {
     644           0 :             const bool bRedSet(0 != aHeader.nV5RedMask);
     645           0 :             const bool bGreenSet(0 != aHeader.nV5GreenMask);
     646           0 :             const bool bBlueSet(0 != aHeader.nV5BlueMask);
     647             : 
     648             :             // some clipboard entries have alpha mask on zero to say that there is
     649             :             // no alpha; do only use this when the other masks are set. The MS docu
     650             :             // says that that masks are only to be set when bV5Compression is set to
     651             :             // BI_BITFIELDS, but there seem to exist a wild variety of usages...
     652           0 :             if((bRedSet || bGreenSet || bBlueSet) && (0 == aHeader.nV5AlphaMask))
     653             :             {
     654           0 :                 bAlphaPossible = false;
     655             :             }
     656             :         }
     657             : 
     658          21 :         if(bAlphaPossible)
     659             :         {
     660           0 :             aNewBmpAlpha = Bitmap(aSizePixel, 8);
     661           0 :             pAccAlpha = aNewBmpAlpha.AcquireWriteAccess();
     662             :         }
     663             : 
     664          21 :         if(pAcc)
     665             :         {
     666          19 :             sal_uInt16 nColors(0);
     667             :             SvStream* pIStm;
     668          19 :             SvMemoryStream* pMemStm = NULL;
     669          19 :             sal_uInt8* pData = NULL;
     670             : 
     671          19 :             if(nBitCount <= 8)
     672             :             {
     673          11 :                 if(aHeader.nColsUsed)
     674             :                 {
     675           9 :                     nColors = (sal_uInt16)aHeader.nColsUsed;
     676             :                 }
     677             :                 else
     678             :                 {
     679           2 :                     nColors = ( 1 << aHeader.nBitCount );
     680             :                 }
     681             :             }
     682             : 
     683          19 :             if(ZCOMPRESS == aHeader.nCompression)
     684             :             {
     685           0 :                 ZCodec aCodec;
     686           0 :                 sal_uInt32 nCodedSize(0);
     687           0 :                 sal_uInt32  nUncodedSize(0);
     688           0 :                 sal_uLong nCodedPos(0);
     689             : 
     690             :                 // read coding information
     691           0 :                 rIStm >> nCodedSize >> nUncodedSize >> aHeader.nCompression;
     692           0 :                 pData = (sal_uInt8*) rtl_allocateMemory( nUncodedSize );
     693             : 
     694             :                 // decode buffer
     695           0 :                 nCodedPos = rIStm.Tell();
     696           0 :                 aCodec.BeginCompression();
     697           0 :                 aCodec.Read( rIStm, pData, nUncodedSize );
     698           0 :                 aCodec.EndCompression();
     699             : 
     700             :                 // skip unread bytes from coded buffer
     701           0 :                 rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
     702             : 
     703             :                 // set decoded bytes to memory stream,
     704             :                 // from which we will read the bitmap data
     705           0 :                 pIStm = pMemStm = new SvMemoryStream;
     706           0 :                 pMemStm->SetBuffer( (char*) pData, nUncodedSize, false, nUncodedSize );
     707           0 :                 nOffset = 0;
     708             :             }
     709             :             else
     710             :             {
     711          19 :                 pIStm = &rIStm;
     712             :             }
     713             : 
     714             :             // read palette
     715          19 :             if(nColors)
     716             :             {
     717          11 :                 pAcc->SetPaletteEntryCount(nColors);
     718          11 :                 ImplReadDIBPalette(*pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE);
     719             :             }
     720             : 
     721             :             // read bits
     722          19 :             if(!pIStm->GetError())
     723             :             {
     724          19 :                 if(nOffset)
     725             :                 {
     726          19 :                     pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
     727             :                 }
     728             : 
     729          19 :                 bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown);
     730             : 
     731          19 :                 if(bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter)
     732             :                 {
     733             :                     MapMode aMapMode(
     734             :                         MAP_MM,
     735             :                         Point(),
     736             :                         Fraction(1000, aHeader.nXPelsPerMeter),
     737           7 :                         Fraction(1000, aHeader.nYPelsPerMeter));
     738             : 
     739           7 :                     aNewBmp.SetPrefMapMode(aMapMode);
     740           7 :                     aNewBmp.SetPrefSize(Size(aHeader.nWidth, aHeader.nHeight));
     741             :                 }
     742             :             }
     743             : 
     744          19 :             if( pData )
     745             :             {
     746           0 :                 rtl_freeMemory(pData);
     747             :             }
     748             : 
     749          19 :             delete pMemStm;
     750          19 :             aNewBmp.ReleaseAccess(pAcc);
     751             : 
     752          19 :             if(bAlphaPossible)
     753             :             {
     754           0 :                 aNewBmpAlpha.ReleaseAccess(pAccAlpha);
     755             :             }
     756             : 
     757          19 :             if(bRet)
     758             :             {
     759          19 :                 rBmp = aNewBmp;
     760             : 
     761          19 :                 if(bAlphaPossible)
     762             :                 {
     763           0 :                     *pBmpAlpha = aNewBmpAlpha;
     764             :                 }
     765             :             }
     766          21 :         }
     767             :     }
     768             : 
     769         341 :     return bRet;
     770             : }
     771             : 
     772        3010 : bool ImplReadDIBFileHeader( SvStream& rIStm, sal_uLong& rOffset )
     773             : {
     774             :     sal_uInt32  nTmp32;
     775        3010 :     sal_uInt16  nTmp16 = 0;
     776        3010 :     bool    bRet = false;
     777             : 
     778        3010 :     rIStm >> nTmp16;
     779             : 
     780        3010 :     if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
     781             :     {
     782         682 :         if ( 0x4142 == nTmp16 )
     783             :         {
     784           0 :             rIStm.SeekRel( 12L );
     785           0 :             rIStm >> nTmp16;
     786           0 :             rIStm.SeekRel( 8L );
     787           0 :             rIStm >> nTmp32;
     788           0 :             rOffset = nTmp32 - 28UL;
     789           0 :             bRet = ( 0x4D42 == nTmp16 );
     790             :         }
     791             :         else // 0x4D42 == nTmp16, 'MB' from BITMAPFILEHEADER
     792             :         {
     793         341 :             rIStm.SeekRel( 8L );        // we are on bfSize member of BITMAPFILEHEADER, forward to bfOffBits
     794         341 :             rIStm >> nTmp32;            // read bfOffBits
     795         341 :             rOffset = nTmp32 - 14UL;    // adapt offset by sizeof(BITMAPFILEHEADER)
     796         341 :             bRet = ( rIStm.GetError() == 0UL );
     797             :         }
     798             :     }
     799             :     else
     800        2669 :         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     801             : 
     802        3010 :     return bRet;
     803             : }
     804             : 
     805         974 : bool ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
     806             : {
     807         974 :     const sal_uInt16    nColors = rAcc.GetPaletteEntryCount();
     808         974 :     const sal_uLong     nPalSize = nColors * 4UL;
     809         974 :     sal_uInt8*          pEntries = new sal_uInt8[ nPalSize ];
     810         974 :     sal_uInt8*          pTmpEntry = pEntries;
     811         974 :     BitmapColor     aPalColor;
     812             : 
     813      240426 :     for( sal_uInt16 i = 0; i < nColors; i++ )
     814             :     {
     815      239452 :         const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
     816             : 
     817      239452 :         *pTmpEntry++ = rPalColor.GetBlue();
     818      239452 :         *pTmpEntry++ = rPalColor.GetGreen();
     819      239452 :         *pTmpEntry++ = rPalColor.GetRed();
     820      239452 :         *pTmpEntry++ = 0;
     821             :     }
     822             : 
     823         974 :     rOStm.Write( pEntries, nPalSize );
     824         974 :     delete[] pEntries;
     825             : 
     826         974 :     return( rOStm.GetError() == 0UL );
     827             : }
     828             : 
     829         935 : bool ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, bool bRLE4 )
     830             : {
     831         935 :     const sal_uLong nWidth = rAcc.Width();
     832         935 :     const sal_uLong nHeight = rAcc.Height();
     833             :     sal_uLong       nX;
     834             :     sal_uLong       nSaveIndex;
     835             :     sal_uLong       nCount;
     836             :     sal_uLong       nBufCount;
     837         935 :     sal_uInt8*      pBuf = new sal_uInt8[ ( nWidth << 1 ) + 2 ];
     838             :     sal_uInt8*      pTmp;
     839             :     sal_uInt8       cPix;
     840             :     sal_uInt8       cLast;
     841             :     bool        bFound;
     842             : 
     843       64578 :     for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
     844             :     {
     845       63643 :         pTmp = pBuf;
     846       63643 :         nX = nBufCount = 0UL;
     847             : 
     848     1007160 :         while( nX < nWidth )
     849             :         {
     850      879874 :             nCount = 1L;
     851      879874 :             cPix = rAcc.GetPixelIndex( nY, nX++ );
     852             : 
     853     8286773 :             while( ( nX < nWidth ) && ( nCount < 255L )
     854     7406899 :                 && ( cPix == rAcc.GetPixelIndex( nY, nX ) ) )
     855             :             {
     856     2855397 :                 nX++;
     857     2855397 :                 nCount++;
     858             :             }
     859             : 
     860      879874 :             if ( nCount > 1 )
     861             :             {
     862      514859 :                 *pTmp++ = (sal_uInt8) nCount;
     863      514859 :                 *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
     864      514859 :                 nBufCount += 2;
     865             :             }
     866             :             else
     867             :             {
     868      365015 :                 cLast = cPix;
     869      365015 :                 nSaveIndex = nX - 1UL;
     870      365015 :                 bFound = false;
     871             : 
     872     3744954 :                 while( ( nX < nWidth ) && ( nCount < 256L )
     873     3379939 :                     && ( cPix = rAcc.GetPixelIndex( nY, nX ) ) != cLast )
     874             :                 {
     875     1340167 :                     nX++; nCount++;
     876     1340167 :                     cLast = cPix;
     877     1340167 :                     bFound = true;
     878             :                 }
     879             : 
     880      365015 :                 if ( bFound )
     881      346814 :                     nX--;
     882             : 
     883      365015 :                 if ( nCount > 3 )
     884             :                 {
     885      180452 :                     *pTmp++ = 0;
     886      180452 :                     *pTmp++ = (sal_uInt8) --nCount;
     887             : 
     888      180452 :                     if( bRLE4 )
     889             :                     {
     890           0 :                         for ( sal_uLong i = 0; i < nCount; i++, pTmp++ )
     891             :                         {
     892           0 :                             *pTmp = rAcc.GetPixelIndex( nY, nSaveIndex++ ) << 4;
     893             : 
     894           0 :                             if ( ++i < nCount )
     895           0 :                                 *pTmp |= rAcc.GetPixelIndex( nY, nSaveIndex++ );
     896             :                         }
     897             : 
     898           0 :                         nCount = ( nCount + 1 ) >> 1;
     899             :                     }
     900             :                     else
     901             :                     {
     902     1292372 :                         for( sal_uLong i = 0UL; i < nCount; i++ )
     903     1111920 :                             *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex++ );
     904             :                     }
     905             : 
     906      180452 :                     if ( nCount & 1 )
     907             :                     {
     908      104446 :                         *pTmp++ = 0;
     909      104446 :                         nBufCount += ( nCount + 3 );
     910             :                     }
     911             :                     else
     912       76006 :                         nBufCount += ( nCount + 2 );
     913             :                 }
     914             :                 else
     915             :                 {
     916      184563 :                     *pTmp++ = 1;
     917      184563 :                     *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex ) << (bRLE4 ? 4 : 0);
     918             : 
     919      184563 :                     if ( nCount == 3 )
     920             :                     {
     921       61885 :                         *pTmp++ = 1;
     922       61885 :                         *pTmp++ = rAcc.GetPixelIndex( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
     923       61885 :                         nBufCount += 4;
     924             :                     }
     925             :                     else
     926      122678 :                         nBufCount += 2;
     927             :                 }
     928             :             }
     929             :         }
     930             : 
     931       63643 :         pBuf[ nBufCount++ ] = 0;
     932       63643 :         pBuf[ nBufCount++ ] = 0;
     933             : 
     934       63643 :         rOStm.Write( pBuf, nBufCount );
     935             :     }
     936             : 
     937         935 :     rOStm << (sal_uInt8) 0;
     938         935 :     rOStm << (sal_uInt8) 1;
     939             : 
     940         935 :     delete[] pBuf;
     941             : 
     942         935 :     return( rOStm.GetError() == 0UL );
     943             : }
     944             : 
     945         978 : bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, sal_uLong nCompression, sal_uInt32& rImageSize)
     946             : {
     947         978 :     if(!pAccAlpha && BITFIELDS == nCompression)
     948             :     {
     949           0 :         const ColorMask&    rMask = rAcc.GetColorMask();
     950             :         SVBT32              aVal32;
     951             : 
     952           0 :         UInt32ToSVBT32( rMask.GetRedMask(), aVal32 );
     953           0 :         rOStm.Write( (sal_uInt8*) aVal32, 4UL );
     954             : 
     955           0 :         UInt32ToSVBT32( rMask.GetGreenMask(), aVal32 );
     956           0 :         rOStm.Write( (sal_uInt8*) aVal32, 4UL );
     957             : 
     958           0 :         UInt32ToSVBT32( rMask.GetBlueMask(), aVal32 );
     959           0 :         rOStm.Write( (sal_uInt8*) aVal32, 4UL );
     960             : 
     961           0 :         rImageSize = rOStm.Tell();
     962             : 
     963           0 :         if( rAcc.IsBottomUp() )
     964           0 :             rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
     965             :         else
     966             :         {
     967           0 :             for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
     968           0 :                 rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
     969           0 :         }
     970             :     }
     971         978 :     else if(!pAccAlpha && ((RLE_4 == nCompression) || (RLE_8 == nCompression)))
     972             :     {
     973         935 :         rImageSize = rOStm.Tell();
     974         935 :         ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
     975             :     }
     976          43 :     else if(!nCompression)
     977             :     {
     978             :         // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are not
     979             :         // handled properly below (would have to set color masks, and
     980             :         // nCompression=BITFIELDS - but color mask is not set for
     981             :         // formats != *_TC_*). Note that this very problem might cause
     982             :         // trouble at other places - the introduction of 32 bit RGBA
     983             :         // bitmaps is relatively recent.
     984             :         // #i59239# discretize bitcount for aligned width to 1,4,8,24
     985             :         // (other cases are not written below)
     986          43 :         const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
     987          43 :         const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * nBitCount));
     988          43 :         bool bNative(false);
     989             : 
     990          43 :         switch(rAcc.GetScanlineFormat())
     991             :         {
     992             :             case( BMP_FORMAT_1BIT_MSB_PAL ):
     993             :             case( BMP_FORMAT_4BIT_MSN_PAL ):
     994             :             case( BMP_FORMAT_8BIT_PAL ):
     995             :             case( BMP_FORMAT_24BIT_TC_BGR ):
     996             :             {
     997          43 :                 if(!pAccAlpha && rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth))
     998             :                 {
     999           6 :                     bNative = true;
    1000             :                 }
    1001             : 
    1002          43 :                 break;
    1003             :             }
    1004             : 
    1005             :             default:
    1006             :             {
    1007           0 :                 break;
    1008             :             }
    1009             :         }
    1010             : 
    1011          43 :         rImageSize = rOStm.Tell();
    1012             : 
    1013          43 :         if(bNative)
    1014             :         {
    1015           6 :             rOStm.Write(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height());
    1016             :         }
    1017             :         else
    1018             :         {
    1019          37 :             const long nWidth(rAcc.Width());
    1020          37 :             const long nHeight(rAcc.Height());
    1021          37 :             sal_uInt8* pBuf = new sal_uInt8[ nAlignedWidth ];
    1022          37 :             sal_uInt8* pTmp(0);
    1023          37 :             sal_uInt8 cTmp(0);
    1024             : 
    1025          37 :             switch( nBitCount )
    1026             :             {
    1027             :                 case( 1 ):
    1028             :                 {
    1029         106 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1030             :                     {
    1031          70 :                         pTmp = pBuf;
    1032          70 :                         cTmp = 0;
    1033             : 
    1034        2905 :                         for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
    1035             :                         {
    1036        2835 :                             if( !nShift )
    1037             :                             {
    1038         315 :                                 nShift = 8L;
    1039         315 :                                 *pTmp++ = cTmp;
    1040         315 :                                 cTmp = 0;
    1041             :                             }
    1042             : 
    1043        2835 :                             cTmp |= rAcc.GetPixelIndex( nY, nX ) << --nShift;
    1044             :                         }
    1045             : 
    1046          70 :                         *pTmp = cTmp;
    1047          70 :                         rOStm.Write( pBuf, nAlignedWidth );
    1048             :                     }
    1049             :                 }
    1050          36 :                 break;
    1051             : 
    1052             :                 case( 4 ):
    1053             :                 {
    1054          17 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1055             :                     {
    1056          16 :                         pTmp = pBuf;
    1057          16 :                         cTmp = 0;
    1058             : 
    1059         288 :                         for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
    1060             :                         {
    1061         272 :                             if( !nShift )
    1062             :                             {
    1063         128 :                                 nShift = 2L;
    1064         128 :                                 *pTmp++ = cTmp;
    1065         128 :                                 cTmp = 0;
    1066             :                             }
    1067             : 
    1068         272 :                             cTmp |= rAcc.GetPixelIndex( nY, nX ) << ( --nShift << 2L );
    1069             :                         }
    1070          16 :                         *pTmp = cTmp;
    1071          16 :                         rOStm.Write( pBuf, nAlignedWidth );
    1072             :                     }
    1073             :                 }
    1074           1 :                 break;
    1075             : 
    1076             :                 case( 8 ):
    1077             :                 {
    1078           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1079             :                     {
    1080           0 :                         pTmp = pBuf;
    1081             : 
    1082           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
    1083           0 :                             *pTmp++ = rAcc.GetPixelIndex( nY, nX );
    1084             : 
    1085           0 :                         rOStm.Write( pBuf, nAlignedWidth );
    1086             :                     }
    1087             :                 }
    1088           0 :                 break;
    1089             : 
    1090             :                 // #i59239# fallback to 24 bit format, if bitcount is non-default
    1091             :                 default:
    1092             :                     // FALLTHROUGH intended
    1093             :                 case( 24 ):
    1094             :                 {
    1095           0 :                     BitmapColor aPixelColor;
    1096           0 :                     const bool bWriteAlpha(32 == nBitCount && pAccAlpha);
    1097             : 
    1098           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1099             :                     {
    1100           0 :                         pTmp = pBuf;
    1101             : 
    1102           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
    1103             :                         {
    1104             :                             // when alpha is used, this may be non-24bit main bitmap, so use GetColor
    1105             :                             // instead of GetPixel to ensure RGB value
    1106           0 :                             aPixelColor = rAcc.GetColor( nY, nX );
    1107             : 
    1108           0 :                             *pTmp++ = aPixelColor.GetBlue();
    1109           0 :                             *pTmp++ = aPixelColor.GetGreen();
    1110           0 :                             *pTmp++ = aPixelColor.GetRed();
    1111             : 
    1112           0 :                             if(bWriteAlpha)
    1113             :                             {
    1114           0 :                                 *pTmp++ = (sal_uInt8)0xff - (sal_uInt8)pAccAlpha->GetPixelIndex( nY, nX );
    1115             :                             }
    1116             :                         }
    1117             : 
    1118           0 :                         rOStm.Write( pBuf, nAlignedWidth );
    1119           0 :                     }
    1120             :                 }
    1121           0 :                 break;
    1122             :             }
    1123             : 
    1124          37 :             delete[] pBuf;
    1125             :         }
    1126             :     }
    1127             : 
    1128         978 :     rImageSize = rOStm.Tell() - rImageSize;
    1129             : 
    1130         978 :     return (!rOStm.GetError());
    1131             : }
    1132             : 
    1133         978 : bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, bool bCompressed)
    1134             : {
    1135         978 :     const MapMode aMapPixel(MAP_PIXEL);
    1136        1956 :     DIBV5Header aHeader;
    1137         978 :     sal_uLong nImageSizePos(0);
    1138         978 :     sal_uLong nEndPos(0);
    1139         978 :     sal_uInt32 nCompression(COMPRESS_NONE);
    1140         978 :     bool bRet(false);
    1141             : 
    1142         978 :     aHeader.nSize = pAccAlpha ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE; // size dependent on CF_DIB type to use
    1143         978 :     aHeader.nWidth = rAcc.Width();
    1144         978 :     aHeader.nHeight = rAcc.Height();
    1145         978 :     aHeader.nPlanes = 1;
    1146             : 
    1147         978 :     if(!pAccAlpha && isBitfieldCompression(rAcc.GetScanlineFormat()))
    1148             :     {
    1149           0 :         aHeader.nBitCount = (BMP_FORMAT_16BIT_TC_LSB_MASK == rAcc.GetScanlineFormat()) ? 16 : 32;
    1150           0 :         aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
    1151           0 :         nCompression = BITFIELDS;
    1152             :     }
    1153             :     else
    1154             :     {
    1155             :         // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are
    1156             :         // not handled properly below (would have to set color
    1157             :         // masks, and nCompression=BITFIELDS - but color mask is
    1158             :         // not set for formats != *_TC_*). Note that this very
    1159             :         // problem might cause trouble at other places - the
    1160             :         // introduction of 32 bit RGBA bitmaps is relatively
    1161             :         // recent.
    1162             :         // #i59239# discretize bitcount to 1,4,8,24 (other cases
    1163             :         // are not written below)
    1164         978 :         const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
    1165         978 :         aHeader.nBitCount = nBitCount;
    1166         978 :         aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount);
    1167             : 
    1168         978 :         if(bCompressed)
    1169             :         {
    1170         976 :             if(4 == nBitCount)
    1171             :             {
    1172           0 :                 nCompression = RLE_4;
    1173             :             }
    1174         976 :             else if(8 == nBitCount)
    1175             :             {
    1176         935 :                 nCompression = RLE_8;
    1177             :             }
    1178             :         }
    1179             :     }
    1180             : 
    1181         978 :     if((rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP) && (rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40))
    1182             :     {
    1183         971 :         aHeader.nCompression = ZCOMPRESS;
    1184             :     }
    1185             :     else
    1186             :     {
    1187           7 :         aHeader.nCompression = nCompression;
    1188             :     }
    1189             : 
    1190         978 :     if(rBitmap.GetPrefSize().Width() && rBitmap.GetPrefSize().Height() && (rBitmap.GetPrefMapMode() != aMapPixel))
    1191             :     {
    1192             :         // #i48108# Try to recover xpels/ypels as previously stored on
    1193             :         // disk. The problem with just converting maPrefSize to 100th
    1194             :         // mm and then relating that to the bitmap pixel size is that
    1195             :         // MapMode is integer-based, and suffers from roundoffs,
    1196             :         // especially if maPrefSize is small. Trying to circumvent
    1197             :         // that by performing part of the math in floating point.
    1198          12 :         const Size aScale100000(OutputDevice::LogicToLogic(Size(100000L, 100000L), MAP_100TH_MM, rBitmap.GetPrefMapMode()));
    1199          12 :         const double fBmpWidthM((double)rBitmap.GetPrefSize().Width() / aScale100000.Width());
    1200          12 :         const double fBmpHeightM((double)rBitmap.GetPrefSize().Height() / aScale100000.Height());
    1201             : 
    1202          12 :         if(!basegfx::fTools::equalZero(fBmpWidthM) && !basegfx::fTools::equalZero(fBmpHeightM))
    1203             :         {
    1204          12 :             aHeader.nXPelsPerMeter = basegfx::fround(rAcc.Width() / fabs(fBmpWidthM));
    1205          12 :             aHeader.nYPelsPerMeter = basegfx::fround(rAcc.Height() / fabs(fBmpHeightM));
    1206             :         }
    1207             :     }
    1208             : 
    1209         978 :     aHeader.nColsUsed = ((!pAccAlpha && aHeader.nBitCount <= 8) ? rAcc.GetPaletteEntryCount() : 0);
    1210         978 :     aHeader.nColsImportant = 0;
    1211             : 
    1212         978 :     rOStm << aHeader.nSize;
    1213         978 :     rOStm << aHeader.nWidth;
    1214         978 :     rOStm << aHeader.nHeight;
    1215         978 :     rOStm << aHeader.nPlanes;
    1216         978 :     rOStm << aHeader.nBitCount;
    1217         978 :     rOStm << aHeader.nCompression;
    1218             : 
    1219         978 :     nImageSizePos = rOStm.Tell();
    1220         978 :     rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
    1221             : 
    1222         978 :     rOStm << aHeader.nXPelsPerMeter;
    1223         978 :     rOStm << aHeader.nYPelsPerMeter;
    1224         978 :     rOStm << aHeader.nColsUsed;
    1225         978 :     rOStm << aHeader.nColsImportant;
    1226             : 
    1227         978 :     if(pAccAlpha) // only write DIBV5 when asked to do so
    1228             :     {
    1229           0 :         aHeader.nV5CSType = 0x57696E20; // LCS_WINDOWS_COLOR_SPACE
    1230           0 :         aHeader.nV5Intent = 0x00000008; // LCS_GM_ABS_COLORIMETRIC
    1231             : 
    1232           0 :         rOStm << aHeader.nV5RedMask;
    1233           0 :         rOStm << aHeader.nV5GreenMask;
    1234           0 :         rOStm << aHeader.nV5BlueMask;
    1235           0 :         rOStm << aHeader.nV5AlphaMask;
    1236           0 :         rOStm << aHeader.nV5CSType;
    1237             : 
    1238           0 :         rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzX;
    1239           0 :         rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzY;
    1240           0 :         rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzZ;
    1241           0 :         rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzX;
    1242           0 :         rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzY;
    1243           0 :         rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzZ;
    1244           0 :         rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzX;
    1245           0 :         rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzY;
    1246           0 :         rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzZ;
    1247             : 
    1248           0 :         rOStm << aHeader.nV5GammaRed;
    1249           0 :         rOStm << aHeader.nV5GammaGreen;
    1250           0 :         rOStm << aHeader.nV5GammaBlue;
    1251           0 :         rOStm << aHeader.nV5Intent;
    1252           0 :         rOStm << aHeader.nV5ProfileData;
    1253           0 :         rOStm << aHeader.nV5ProfileSize;
    1254           0 :         rOStm << aHeader.nV5Reserved;
    1255             :     }
    1256             : 
    1257         978 :     if(ZCOMPRESS == aHeader.nCompression)
    1258             :     {
    1259         971 :         ZCodec aCodec;
    1260        1942 :         SvMemoryStream aMemStm(aHeader.nSizeImage + 4096, 65535);
    1261         971 :         sal_uLong nCodedPos(rOStm.Tell());
    1262         971 :         sal_uLong nLastPos(0);
    1263         971 :         sal_uInt32 nCodedSize(0);
    1264         971 :         sal_uInt32 nUncodedSize(0);
    1265             : 
    1266             :         // write uncoded data palette
    1267         971 :         if(aHeader.nColsUsed)
    1268             :         {
    1269         971 :             ImplWriteDIBPalette(aMemStm, rAcc);
    1270             :         }
    1271             : 
    1272             :         // write uncoded bits
    1273         971 :         bRet = ImplWriteDIBBits(aMemStm, rAcc, pAccAlpha, nCompression, aHeader.nSizeImage);
    1274             : 
    1275             :         // get uncoded size
    1276         971 :         nUncodedSize = aMemStm.Tell();
    1277             : 
    1278             :         // seek over compress info
    1279         971 :         rOStm.SeekRel(12);
    1280             : 
    1281             :         // write compressed data
    1282         971 :         aCodec.BeginCompression(3);
    1283         971 :         aCodec.Write(rOStm, (sal_uInt8*)aMemStm.GetData(), nUncodedSize);
    1284         971 :         aCodec.EndCompression();
    1285             : 
    1286             :         // update compress info ( coded size, uncoded size, uncoded compression )
    1287         971 :         nLastPos = rOStm.Tell();
    1288         971 :         nCodedSize = nLastPos - nCodedPos - 12;
    1289         971 :         rOStm.Seek(nCodedPos);
    1290         971 :         rOStm << nCodedSize << nUncodedSize << nCompression;
    1291         971 :         rOStm.Seek(nLastPos);
    1292             : 
    1293         971 :         if(bRet)
    1294             :         {
    1295         971 :             bRet = (ERRCODE_NONE == rOStm.GetError());
    1296         971 :         }
    1297             :     }
    1298             :     else
    1299             :     {
    1300           7 :         if(aHeader.nColsUsed)
    1301             :         {
    1302           3 :             ImplWriteDIBPalette(rOStm, rAcc);
    1303             :         }
    1304             : 
    1305           7 :         bRet = ImplWriteDIBBits(rOStm, rAcc, pAccAlpha, aHeader.nCompression, aHeader.nSizeImage);
    1306             :     }
    1307             : 
    1308         978 :     nEndPos = rOStm.Tell();
    1309         978 :     rOStm.Seek(nImageSizePos);
    1310         978 :     rOStm << aHeader.nSizeImage;
    1311         978 :     rOStm.Seek(nEndPos);
    1312             : 
    1313        1956 :     return bRet;
    1314             : }
    1315             : 
    1316         974 : bool ImplWriteDIBFileHeader(SvStream& rOStm, BitmapReadAccess& rAcc, bool bUseDIBV5)
    1317             : {
    1318         974 :     const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : isBitfieldCompression(rAcc.GetScanlineFormat()) ? 3UL : 0UL));
    1319         974 :     const sal_uInt32 nOffset(14 + (bUseDIBV5 ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE) + nPalCount * 4UL);
    1320             : 
    1321         974 :     rOStm << (sal_uInt16)0x4D42; // 'MB' from BITMAPFILEHEADER
    1322         974 :     rOStm << (sal_uInt32)(nOffset + (rAcc.Height() * rAcc.GetScanlineSize()));
    1323         974 :     rOStm << (sal_uInt16)0;
    1324         974 :     rOStm << (sal_uInt16)0;
    1325         974 :     rOStm << nOffset;
    1326             : 
    1327         974 :     return( rOStm.GetError() == 0UL );
    1328             : }
    1329             : 
    1330             : //////////////////////////////////////////////////////////////////////////////
    1331             : 
    1332        3010 : bool ImplReadDIB(
    1333             :     Bitmap& rTarget, Bitmap*
    1334             :     pTargetAlpha,
    1335             :     SvStream& rIStm,
    1336             :     bool bFileHeader)
    1337             : {
    1338        3010 :     const sal_uInt16 nOldFormat(rIStm.GetNumberFormatInt());
    1339        3010 :     const sal_uLong nOldPos(rIStm.Tell());
    1340        3010 :     sal_uLong nOffset(0UL);
    1341        3010 :     bool bRet(false);
    1342             : 
    1343        3010 :     rIStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
    1344             : 
    1345        3010 :     if(bFileHeader)
    1346             :     {
    1347        3010 :         if(ImplReadDIBFileHeader(rIStm, nOffset))
    1348             :         {
    1349         341 :             bRet = ImplReadDIBBody(rIStm, rTarget, nOffset >= DIBV5HEADERSIZE ? pTargetAlpha : 0, nOffset);
    1350             :         }
    1351             :     }
    1352             :     else
    1353             :     {
    1354           0 :         bRet = ImplReadDIBBody(rIStm, rTarget, 0, nOffset);
    1355             :     }
    1356             : 
    1357        3010 :     if(!bRet)
    1358             :     {
    1359        2991 :         if(!rIStm.GetError())
    1360             :         {
    1361         322 :             rIStm.SetError(SVSTREAM_GENERALERROR);
    1362             :         }
    1363             : 
    1364        2991 :         rIStm.Seek(nOldPos);
    1365             :     }
    1366             : 
    1367        3010 :     rIStm.SetNumberFormatInt(nOldFormat);
    1368             : 
    1369        3010 :     return bRet;
    1370             : }
    1371             : 
    1372         978 : bool ImplWriteDIB(
    1373             :     const Bitmap& rSource,
    1374             :     const Bitmap* pSourceAlpha,
    1375             :     SvStream& rOStm,
    1376             :     bool bCompressed,
    1377             :     bool bFileHeader)
    1378             : {
    1379         978 :     const Size aSizePix(rSource.GetSizePixel());
    1380         978 :     bool bRet(false);
    1381             : 
    1382         978 :     if(aSizePix.Width() && aSizePix.Height())
    1383             :     {
    1384         978 :         BitmapReadAccess* pAcc = const_cast< Bitmap& >(rSource).AcquireReadAccess();
    1385         978 :         BitmapReadAccess* pAccAlpha = 0;
    1386         978 :         const sal_uInt16 nOldFormat(rOStm.GetNumberFormatInt());
    1387         978 :         const sal_uLong nOldPos(rOStm.Tell());
    1388             : 
    1389         978 :         if(pSourceAlpha)
    1390             :         {
    1391           0 :             const Size aSizePixAlpha(pSourceAlpha->GetSizePixel());
    1392             : 
    1393           0 :             if(aSizePixAlpha == aSizePix)
    1394             :             {
    1395           0 :                 pAccAlpha = const_cast< Bitmap* >(pSourceAlpha)->AcquireReadAccess();
    1396             :             }
    1397             :             else
    1398             :             {
    1399             :                 OSL_ENSURE(false, "WriteDIB got an alpha channel, but it's pixel size differs from the base bitmap (!)");
    1400             :             }
    1401             :         }
    1402             : 
    1403         978 :         rOStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
    1404             : 
    1405         978 :         if(pAcc)
    1406             :         {
    1407         978 :             if(bFileHeader)
    1408             :             {
    1409         974 :                 if(ImplWriteDIBFileHeader(rOStm, *pAcc, 0 != pSourceAlpha))
    1410             :                 {
    1411         974 :                     bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
    1412             :                 }
    1413             :             }
    1414             :             else
    1415             :             {
    1416           4 :                 bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
    1417             :             }
    1418             : 
    1419         978 :             const_cast< Bitmap& >(rSource).ReleaseAccess(pAcc);
    1420             : 
    1421         978 :             if(pAccAlpha)
    1422             :             {
    1423           0 :                 const_cast< Bitmap* >(pSourceAlpha)->ReleaseAccess(pAccAlpha);
    1424             :             }
    1425             :         }
    1426             : 
    1427         978 :         if(!bRet)
    1428             :         {
    1429           0 :             rOStm.SetError(SVSTREAM_GENERALERROR);
    1430           0 :             rOStm.Seek(nOldPos);
    1431             :         }
    1432             : 
    1433         978 :         rOStm.SetNumberFormatInt(nOldFormat);
    1434             :     }
    1435             : 
    1436         978 :     return bRet;
    1437             : }
    1438             : 
    1439             : //////////////////////////////////////////////////////////////////////////////
    1440             : 
    1441         329 : bool ReadDIB(
    1442             :     Bitmap& rTarget,
    1443             :     SvStream& rIStm,
    1444             :     bool bFileHeader)
    1445             : {
    1446         329 :     return ImplReadDIB(rTarget, 0, rIStm, bFileHeader);
    1447             : }
    1448             : 
    1449        2681 : bool ReadDIBBitmapEx(
    1450             :     BitmapEx& rTarget,
    1451             :     SvStream& rIStm)
    1452             : {
    1453        2681 :     Bitmap aBmp;
    1454        2681 :     bool bRetval(ImplReadDIB(aBmp, 0, rIStm, true) && !rIStm.GetError());
    1455             : 
    1456        2681 :     if(bRetval)
    1457             :     {
    1458             :         // base bitmap was read, set as return value and try to read alpha extra-data
    1459          10 :         const sal_uLong nStmPos(rIStm.Tell());
    1460          10 :         sal_uInt32 nMagic1(0);
    1461          10 :         sal_uInt32 nMagic2(0);
    1462             : 
    1463          10 :         rTarget = BitmapEx(aBmp);
    1464          10 :         rIStm >> nMagic1 >> nMagic2;
    1465          10 :         bRetval = (0x25091962 == nMagic1) && (0xACB20201 == nMagic2) && !rIStm.GetError();
    1466             : 
    1467          10 :         if(bRetval)
    1468             :         {
    1469           0 :             sal_uInt8 bTransparent(false);
    1470             : 
    1471           0 :             rIStm >> bTransparent;
    1472           0 :             bRetval = !rIStm.GetError();
    1473             : 
    1474           0 :             if(bRetval)
    1475             :             {
    1476           0 :                 if((sal_uInt8)TRANSPARENT_BITMAP == bTransparent)
    1477             :                 {
    1478           0 :                     Bitmap aMask;
    1479             : 
    1480           0 :                     bRetval = ImplReadDIB(aMask, 0, rIStm, true);
    1481             : 
    1482           0 :                     if(bRetval)
    1483             :                     {
    1484           0 :                         if(!!aMask)
    1485             :                         {
    1486             :                             // do we have an alpha mask?
    1487           0 :                             if((8 == aMask.GetBitCount()) && aMask.HasGreyPalette())
    1488             :                             {
    1489           0 :                                 AlphaMask aAlpha;
    1490             : 
    1491             :                                 // create alpha mask quickly (without greyscale conversion)
    1492           0 :                                 aAlpha.ImplSetBitmap(aMask);
    1493           0 :                                 rTarget = BitmapEx(aBmp, aAlpha);
    1494             :                             }
    1495             :                             else
    1496             :                             {
    1497           0 :                                 rTarget = BitmapEx(aBmp, aMask);
    1498             :                             }
    1499             :                         }
    1500           0 :                     }
    1501             :                 }
    1502           0 :                 else if((sal_uInt8)TRANSPARENT_COLOR == bTransparent)
    1503             :                 {
    1504           0 :                     Color aTransparentColor;
    1505             : 
    1506           0 :                     rIStm >> aTransparentColor;
    1507           0 :                     bRetval = !rIStm.GetError();
    1508             : 
    1509           0 :                     if(bRetval)
    1510             :                     {
    1511           0 :                         rTarget = BitmapEx(aBmp, aTransparentColor);
    1512             :                     }
    1513             :                 }
    1514             :             }
    1515             :         }
    1516             : 
    1517          10 :         if(!bRetval)
    1518             :         {
    1519             :             // alpha extra data could not be read; reset, but use base bitmap as result
    1520          10 :             rIStm.ResetError();
    1521          10 :             rIStm.Seek(nStmPos);
    1522          10 :             bRetval = true;
    1523             :         }
    1524             :     }
    1525             : 
    1526        2681 :     return bRetval;
    1527             : }
    1528             : 
    1529           0 : bool ReadDIBV5(
    1530             :     Bitmap& rTarget,
    1531             :     Bitmap& rTargetAlpha,
    1532             :     SvStream& rIStm)
    1533             : {
    1534           0 :     return ImplReadDIB(rTarget, &rTargetAlpha, rIStm, true);
    1535             : }
    1536             : 
    1537             : //////////////////////////////////////////////////////////////////////////////
    1538             : 
    1539           7 : bool WriteDIB(
    1540             :     const Bitmap& rSource,
    1541             :     SvStream& rOStm,
    1542             :     bool bCompressed,
    1543             :     bool bFileHeader)
    1544             : {
    1545           7 :     return ImplWriteDIB(rSource, 0, rOStm, bCompressed, bFileHeader);
    1546             : }
    1547             : 
    1548         503 : bool WriteDIBBitmapEx(
    1549             :     const BitmapEx& rSource,
    1550             :     SvStream& rOStm)
    1551             : {
    1552         503 :     if(ImplWriteDIB(rSource.GetBitmap(), 0, rOStm, true, true))
    1553             :     {
    1554         503 :         rOStm << (sal_uInt32)0x25091962;
    1555         503 :         rOStm << (sal_uInt32)0xACB20201;
    1556         503 :         rOStm << (sal_uInt8)rSource.eTransparent;
    1557             : 
    1558         503 :         if(TRANSPARENT_BITMAP == rSource.eTransparent)
    1559             :         {
    1560         468 :             return ImplWriteDIB(rSource.aMask, 0, rOStm, true, true);
    1561             :         }
    1562          35 :         else if(TRANSPARENT_COLOR == rSource.eTransparent)
    1563             :         {
    1564           0 :             rOStm << rSource.aTransparentColor;
    1565           0 :             return true;
    1566             :         }
    1567             :     }
    1568             : 
    1569          35 :     return false;
    1570             : }
    1571             : 
    1572           0 : bool WriteDIBV5(
    1573             :     const Bitmap& rSource,
    1574             :     const Bitmap& rSourceAlpha,
    1575             :     SvStream& rOStm)
    1576             : {
    1577           0 :     return ImplWriteDIB(rSource, &rSourceAlpha, rOStm, false, true);
    1578         465 : }
    1579             : 
    1580             : //////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.10