LCOV - code coverage report
Current view: top level - vcl/source/gdi - dibtools.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 549 700 78.4 %
Date: 2014-04-11 Functions: 27 29 93.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10