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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <vcl/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           0 :     CIEXYZ()
      55             :     :   aXyzX(0L),
      56             :         aXyzY(0L),
      57           0 :         aXyzZ(0L)
      58           0 :     {}
      59             : 
      60           0 :     ~CIEXYZ()
      61           0 :     {}
      62             : };
      63             : 
      64             : struct CIEXYZTriple
      65             : {
      66             :     CIEXYZ          aXyzRed;
      67             :     CIEXYZ          aXyzGreen;
      68             :     CIEXYZ          aXyzBlue;
      69             : 
      70           0 :     CIEXYZTriple()
      71             :     :   aXyzRed(),
      72             :         aXyzGreen(),
      73           0 :         aXyzBlue()
      74           0 :     {}
      75             : 
      76           0 :     ~CIEXYZTriple()
      77           0 :     {}
      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           0 :     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           0 :         nColsImportant(0UL)
     106           0 :     {}
     107             : 
     108           0 :     ~DIBInfoHeader()
     109           0 :     {}
     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           0 :     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           0 :         nV5Reserved(0UL)
     143           0 :     {}
     144             : 
     145           0 :     ~DIBV5Header()
     146           0 :     {}
     147             : };
     148             : 
     149             : namespace
     150             : {
     151           0 :     inline sal_uInt16 discretizeBitcount( sal_uInt16 nInputCount )
     152             :     {
     153             :         return ( nInputCount <= 1 ) ? 1 :
     154             :                ( nInputCount <= 4 ) ? 4 :
     155           0 :                ( nInputCount <= 8 ) ? 8 : 24;
     156             :     }
     157             : 
     158           0 :     inline bool isBitfieldCompression( sal_uLong nScanlineFormat )
     159             :     {
     160           0 :         return (BMP_FORMAT_16BIT_TC_LSB_MASK == nScanlineFormat) || (BMP_FORMAT_32BIT_TC_MASK == nScanlineFormat);
     161             :     }
     162             : }
     163             : 
     164           0 : bool ImplReadDIBInfoHeader(SvStream& rIStm, DIBV5Header& rHeader, bool& bTopDown)
     165             : {
     166             :     // BITMAPINFOHEADER or BITMAPCOREHEADER or BITMAPV5HEADER
     167           0 :     const sal_Size aStartPos(rIStm.Tell());
     168           0 :     rIStm.ReadUInt32( rHeader.nSize );
     169             : 
     170             :     // BITMAPCOREHEADER
     171           0 :     if ( rHeader.nSize == DIBCOREHEADERSIZE )
     172             :     {
     173             :         sal_Int16 nTmp16;
     174             : 
     175           0 :         rIStm.ReadInt16( nTmp16 ); rHeader.nWidth = nTmp16;
     176           0 :         rIStm.ReadInt16( nTmp16 ); rHeader.nHeight = nTmp16;
     177           0 :         rIStm.ReadUInt16( rHeader.nPlanes );
     178           0 :         rIStm.ReadUInt16( rHeader.nBitCount );
     179             :     }
     180             :     else
     181             :     {
     182             :         // BITMAPCOREHEADER, BITMAPV5HEADER or unknown. Read as far as possible
     183           0 :         sal_Size nUsed(sizeof(rHeader.nSize));
     184             : 
     185             :         // read DIBInfoHeader entries
     186           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nWidth ); nUsed += sizeof(rHeader.nWidth); }
     187           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nHeight ); nUsed += sizeof(rHeader.nHeight); }
     188           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt16( rHeader.nPlanes ); nUsed += sizeof(rHeader.nPlanes); }
     189           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt16( rHeader.nBitCount );  nUsed += sizeof(rHeader.nBitCount); }
     190           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nCompression );  nUsed += sizeof(rHeader.nCompression); }
     191           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nSizeImage );  nUsed += sizeof(rHeader.nSizeImage); }
     192           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nXPelsPerMeter );  nUsed += sizeof(rHeader.nXPelsPerMeter); }
     193           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.nYPelsPerMeter );  nUsed += sizeof(rHeader.nYPelsPerMeter); }
     194           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nColsUsed );  nUsed += sizeof(rHeader.nColsUsed); }
     195           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nColsImportant );  nUsed += sizeof(rHeader.nColsImportant); }
     196             : 
     197             :         // read DIBV5HEADER members
     198           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5RedMask ); nUsed += sizeof(rHeader.nV5RedMask); }
     199           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GreenMask ); nUsed += sizeof(rHeader.nV5GreenMask);  }
     200           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5BlueMask ); nUsed += sizeof(rHeader.nV5BlueMask);  }
     201           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5AlphaMask ); nUsed += sizeof(rHeader.nV5AlphaMask);  }
     202           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5CSType ); nUsed += sizeof(rHeader.nV5CSType);  }
     203             : 
     204             :         // read contained CIEXYZTriple's
     205           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzRed.aXyzX ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzX); }
     206           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzRed.aXyzY ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzY); }
     207           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzRed.aXyzZ ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzZ); }
     208           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzGreen.aXyzX ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzX); }
     209           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzGreen.aXyzY ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzY); }
     210           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzGreen.aXyzZ ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzZ); }
     211           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzBlue.aXyzX ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzX); }
     212           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzBlue.aXyzY ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzY); }
     213           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadInt32( rHeader.aV5Endpoints.aXyzBlue.aXyzZ ); nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzZ); }
     214             : 
     215           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GammaRed ); nUsed += sizeof(rHeader.nV5GammaRed);  }
     216           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GammaGreen ); nUsed += sizeof(rHeader.nV5GammaGreen);  }
     217           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5GammaBlue ); nUsed += sizeof(rHeader.nV5GammaBlue);  }
     218           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5Intent ); nUsed += sizeof(rHeader.nV5Intent);  }
     219           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5ProfileData ); nUsed += sizeof(rHeader.nV5ProfileData);  }
     220           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5ProfileSize ); nUsed += sizeof(rHeader.nV5ProfileSize);  }
     221           0 :         if(nUsed < rHeader.nSize) { rIStm.ReadUInt32( rHeader.nV5Reserved ); nUsed += sizeof(rHeader.nV5Reserved);  }
     222             : 
     223             :         // seek to EndPos
     224           0 :         rIStm.Seek(aStartPos + rHeader.nSize);
     225             :     }
     226             : 
     227           0 :     if ( rHeader.nHeight < 0 )
     228             :     {
     229           0 :         bTopDown = true;
     230           0 :         rHeader.nHeight *= -1;
     231             :     }
     232             :     else
     233             :     {
     234           0 :         bTopDown = false;
     235             :     }
     236             : 
     237           0 :     if ( rHeader.nWidth < 0 )
     238             :     {
     239           0 :         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     240             :     }
     241             : 
     242             :     // #144105# protect a little against damaged files
     243           0 :     if( rHeader.nSizeImage > ( 16 * static_cast< sal_uInt32 >( rHeader.nWidth * rHeader.nHeight ) ) )
     244             :     {
     245           0 :         rHeader.nSizeImage = 0;
     246             :     }
     247             : 
     248           0 :     return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
     249             : }
     250             : 
     251           0 : bool ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, bool bQuad )
     252             : {
     253           0 :     const sal_uInt16    nColors = rAcc.GetPaletteEntryCount();
     254           0 :     const sal_uLong     nPalSize = nColors * ( bQuad ? 4UL : 3UL );
     255           0 :     BitmapColor     aPalColor;
     256             : 
     257           0 :     boost::scoped_array<sal_uInt8> pEntries(new sal_uInt8[ nPalSize ]);
     258           0 :     rIStm.Read( pEntries.get(), nPalSize );
     259             : 
     260           0 :     sal_uInt8* pTmpEntry = pEntries.get();
     261           0 :     for( sal_uInt16 i = 0; i < nColors; i++ )
     262             :     {
     263           0 :         aPalColor.SetBlue( *pTmpEntry++ );
     264           0 :         aPalColor.SetGreen( *pTmpEntry++ );
     265           0 :         aPalColor.SetRed( *pTmpEntry++ );
     266             : 
     267           0 :         if( bQuad )
     268           0 :             pTmpEntry++;
     269             : 
     270           0 :         rAcc.SetPaletteColor( i, aPalColor );
     271             :     }
     272             : 
     273           0 :     return( rIStm.GetError() == 0UL );
     274             : }
     275             : 
     276           0 : void ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, bool bRLE4 )
     277             : {
     278           0 :     Scanline    pRLE = pBuffer;
     279           0 :     long        nY = rHeader.nHeight - 1L;
     280           0 :     const sal_uLong nWidth = rAcc.Width();
     281             :     sal_uLong       nCountByte;
     282             :     sal_uLong       nRunByte;
     283           0 :     sal_uLong       nX = 0UL;
     284             :     sal_uInt8       cTmp;
     285           0 :     bool        bEndDecoding = false;
     286             : 
     287           0 :     do
     288             :     {
     289           0 :         if( ( nCountByte = *pRLE++ ) == 0 )
     290             :         {
     291           0 :             nRunByte = *pRLE++;
     292             : 
     293           0 :             if( nRunByte > 2 )
     294             :             {
     295           0 :                 if( bRLE4 )
     296             :                 {
     297           0 :                     nCountByte = nRunByte >> 1;
     298             : 
     299           0 :                     for( sal_uLong i = 0UL; i < nCountByte; i++ )
     300             :                     {
     301           0 :                         cTmp = *pRLE++;
     302             : 
     303           0 :                         if( nX < nWidth )
     304           0 :                             rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
     305             : 
     306           0 :                         if( nX < nWidth )
     307           0 :                             rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
     308             :                     }
     309             : 
     310           0 :                     if( nRunByte & 1 )
     311             :                     {
     312           0 :                         if( nX < nWidth )
     313           0 :                             rAcc.SetPixelIndex( nY, nX++, *pRLE >> 4 );
     314             : 
     315           0 :                         pRLE++;
     316             :                     }
     317             : 
     318           0 :                     if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
     319           0 :                         pRLE++;
     320             :                 }
     321             :                 else
     322             :                 {
     323           0 :                     for( sal_uLong i = 0UL; i < nRunByte; i++ )
     324             :                     {
     325           0 :                         if( nX < nWidth )
     326           0 :                             rAcc.SetPixelIndex( nY, nX++, *pRLE );
     327             : 
     328           0 :                         pRLE++;
     329             :                     }
     330             : 
     331           0 :                     if( nRunByte & 1 )
     332           0 :                         pRLE++;
     333             :                 }
     334             :             }
     335           0 :             else if( !nRunByte )
     336             :             {
     337           0 :                 nY--;
     338           0 :                 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           0 :             cTmp = *pRLE++;
     351             : 
     352           0 :             if( bRLE4 )
     353             :             {
     354           0 :                 nRunByte = nCountByte >> 1;
     355             : 
     356           0 :                 for( sal_uLong i = 0UL; i < nRunByte; i++ )
     357             :                 {
     358           0 :                     if( nX < nWidth )
     359           0 :                         rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
     360             : 
     361           0 :                     if( nX < nWidth )
     362           0 :                         rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
     363             :                 }
     364             : 
     365           0 :                 if( ( nCountByte & 1 ) && ( nX < nWidth ) )
     366           0 :                     rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
     367             :             }
     368             :             else
     369             :             {
     370           0 :                 for( sal_uLong i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
     371           0 :                     rAcc.SetPixelIndex( nY, nX++, cTmp );
     372             :             }
     373             :         }
     374             :     }
     375           0 :     while ( !bEndDecoding && ( nY >= 0L ) );
     376           0 : }
     377             : 
     378           0 : bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, BitmapWriteAccess* pAccAlpha, bool bTopDown, bool& rAlphaUsed)
     379             : {
     380           0 :     const sal_Int64 nBitsPerLine (static_cast<sal_Int64>(rHeader.nWidth) * static_cast<sal_Int64>(rHeader.nBitCount));
     381           0 :     if (nBitsPerLine > SAL_MAX_UINT32)
     382           0 :         return false;
     383             : 
     384           0 :     const sal_uLong nAlignedWidth = AlignedWidth4Bytes(static_cast<sal_uLong>(nBitsPerLine));
     385           0 :     sal_uInt32 nRMask(( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL);
     386           0 :     sal_uInt32 nGMask(( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL);
     387           0 :     sal_uInt32 nBMask(( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL);
     388           0 :     bool bNative(false);
     389           0 :     bool bTCMask(!pAccAlpha && ((16 == rHeader.nBitCount) || (32 == rHeader.nBitCount)));
     390           0 :     bool bRLE((RLE_8 == rHeader.nCompression && 8 == rHeader.nBitCount) || (RLE_4 == rHeader.nCompression && 4 == rHeader.nBitCount));
     391             : 
     392             :     // Is native format?
     393           0 :     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           0 :             bNative = ( ( static_cast< bool >(rAcc.IsBottomUp()) != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
     401           0 :             break;
     402             :         }
     403             : 
     404             :         default:
     405             :         {
     406           0 :             break;
     407             :         }
     408             :     }
     409             : 
     410             :     // Read data
     411           0 :     if(bNative)
     412             :     {
     413           0 :         rIStm.Read(rAcc.GetBuffer(), rHeader.nHeight * nAlignedWidth);
     414             :     }
     415             :     else
     416             :     {
     417             :         // Read color mask
     418           0 :         if(bTCMask && BITFIELDS == rHeader.nCompression)
     419             :         {
     420           0 :             rIStm.SeekRel( -12L );
     421           0 :             rIStm.ReadUInt32( nRMask );
     422           0 :             rIStm.ReadUInt32( nGMask );
     423           0 :             rIStm.ReadUInt32( nBMask );
     424             :         }
     425             : 
     426           0 :         if(bRLE)
     427             :         {
     428           0 :             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           0 :             sal_uInt8* pBuffer = (sal_uInt8*)rtl_allocateMemory(rHeader.nSizeImage);
     438           0 :             rIStm.Read((char*)pBuffer, rHeader.nSizeImage);
     439           0 :             ImplDecodeRLE(pBuffer, rHeader, rAcc, RLE_4 == rHeader.nCompression);
     440           0 :             rtl_freeMemory(pBuffer);
     441             :         }
     442             :         else
     443             :         {
     444           0 :             const long nWidth(rHeader.nWidth);
     445           0 :             const long nHeight(rHeader.nHeight);
     446           0 :             boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[nAlignedWidth]);
     447             : 
     448           0 :             const long nI(bTopDown ? 1 : -1);
     449           0 :             long nY(bTopDown ? 0 : nHeight - 1);
     450           0 :             long nCount(nHeight);
     451             : 
     452           0 :             switch(rHeader.nBitCount)
     453             :             {
     454             :                 case( 1 ):
     455             :                 {
     456             :                     sal_uInt8*  pTmp;
     457             :                     sal_uInt8   cTmp;
     458             : 
     459           0 :                     for( ; nCount--; nY += nI )
     460             :                     {
     461           0 :                         rIStm.Read( pTmp = pBuf.get(), nAlignedWidth );
     462           0 :                         cTmp = *pTmp++;
     463             : 
     464           0 :                         for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
     465             :                         {
     466           0 :                             if( !nShift )
     467             :                             {
     468             :                                 nShift = 8L,
     469           0 :                                 cTmp = *pTmp++;
     470             :                             }
     471             : 
     472           0 :                             rAcc.SetPixelIndex( nY, nX, (cTmp >> --nShift) & 1);
     473             :                         }
     474             :                     }
     475             :                 }
     476           0 :                 break;
     477             : 
     478             :                 case( 4 ):
     479             :                 {
     480             :                     sal_uInt8*  pTmp;
     481             :                     sal_uInt8   cTmp;
     482             : 
     483           0 :                     for( ; nCount--; nY += nI )
     484             :                     {
     485           0 :                         rIStm.Read( pTmp = pBuf.get(), nAlignedWidth );
     486           0 :                         cTmp = *pTmp++;
     487             : 
     488           0 :                         for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
     489             :                         {
     490           0 :                             if( !nShift )
     491             :                             {
     492             :                                 nShift = 2UL,
     493           0 :                                 cTmp = *pTmp++;
     494             :                             }
     495             : 
     496           0 :                             rAcc.SetPixelIndex( nY, nX, (cTmp >> ( --nShift << 2UL ) ) & 0x0f);
     497             :                         }
     498             :                     }
     499             :                 }
     500           0 :                 break;
     501             : 
     502             :                 case( 8 ):
     503             :                 {
     504             :                     sal_uInt8*  pTmp;
     505             : 
     506           0 :                     for( ; nCount--; nY += nI )
     507             :                     {
     508           0 :                         rIStm.Read( pTmp = pBuf.get(), nAlignedWidth );
     509             : 
     510           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
     511           0 :                             rAcc.SetPixelIndex( nY, nX, *pTmp++ );
     512             :                     }
     513             :                 }
     514           0 :                 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           0 :                     ColorMask aMask(nRMask, nGMask, nBMask);
     558           0 :                     BitmapColor aColor;
     559             :                     sal_uInt32* pTmp32;
     560             : 
     561           0 :                     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           0 :                         for( ; nCount--; nY += nI )
     581             :                         {
     582           0 :                             rIStm.Read( (char*)( pTmp32 = (sal_uInt32*) pBuf.get() ), nAlignedWidth );
     583             : 
     584           0 :                             for( long nX = 0L; nX < nWidth; nX++ )
     585             :                             {
     586           0 :                                 aMask.GetColorFor32Bit( aColor, (sal_uInt8*) pTmp32++ );
     587           0 :                                 rAcc.SetPixel( nY, nX, aColor );
     588             :                             }
     589             :                         }
     590           0 :                     }
     591             :                 }
     592           0 :             }
     593             :         }
     594             :     }
     595             : 
     596           0 :     return( rIStm.GetError() == 0UL );
     597             : }
     598             : 
     599           0 : bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLong nOffset )
     600             : {
     601           0 :     DIBV5Header aHeader;
     602           0 :     const sal_uLong nStmPos = rIStm.Tell();
     603           0 :     bool bRet(false);
     604           0 :     bool bTopDown(false);
     605             : 
     606           0 :     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           0 :         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           0 :         const sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount));
     618           0 :         const Size aSizePixel(aHeader.nWidth, aHeader.nHeight);
     619           0 :         BitmapPalette aDummyPal;
     620           0 :         Bitmap aNewBmp(aSizePixel, nBitCount, &aDummyPal);
     621           0 :         Bitmap aNewBmpAlpha;
     622           0 :         BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
     623           0 :         BitmapWriteAccess* pAccAlpha = 0;
     624           0 :         bool bAlphaPossible(pBmpAlpha && aHeader.nBitCount == 32);
     625             : 
     626           0 :         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           0 :         if(bAlphaPossible)
     643             :         {
     644           0 :             aNewBmpAlpha = Bitmap(aSizePixel, 8);
     645           0 :             pAccAlpha = aNewBmpAlpha.AcquireWriteAccess();
     646             :         }
     647             : 
     648           0 :         if(pAcc)
     649             :         {
     650           0 :             sal_uInt16 nColors(0);
     651             :             SvStream* pIStm;
     652           0 :             SvMemoryStream* pMemStm = NULL;
     653           0 :             sal_uInt8* pData = NULL;
     654             : 
     655           0 :             if(nBitCount <= 8)
     656             :             {
     657           0 :                 if(aHeader.nColsUsed)
     658             :                 {
     659           0 :                     nColors = (sal_uInt16)aHeader.nColsUsed;
     660             :                 }
     661             :                 else
     662             :                 {
     663           0 :                     nColors = ( 1 << aHeader.nBitCount );
     664             :                 }
     665             :             }
     666             : 
     667           0 :             if(ZCOMPRESS == aHeader.nCompression)
     668             :             {
     669           0 :                 ZCodec aCodec;
     670           0 :                 sal_uInt32 nCodedSize(0);
     671           0 :                 sal_uInt32  nUncodedSize(0);
     672           0 :                 sal_uLong nCodedPos(0);
     673             : 
     674             :                 // read coding information
     675           0 :                 rIStm.ReadUInt32( nCodedSize ).ReadUInt32( nUncodedSize ).ReadUInt32( aHeader.nCompression );
     676           0 :                 pData = (sal_uInt8*) rtl_allocateMemory( nUncodedSize );
     677             : 
     678             :                 // decode buffer
     679           0 :                 nCodedPos = rIStm.Tell();
     680           0 :                 aCodec.BeginCompression();
     681           0 :                 aCodec.Read( rIStm, pData, nUncodedSize );
     682           0 :                 aCodec.EndCompression();
     683             : 
     684             :                 // skip unread bytes from coded buffer
     685           0 :                 rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
     686             : 
     687             :                 // set decoded bytes to memory stream,
     688             :                 // from which we will read the bitmap data
     689           0 :                 pIStm = pMemStm = new SvMemoryStream;
     690           0 :                 pMemStm->SetBuffer( (char*) pData, nUncodedSize, false, nUncodedSize );
     691           0 :                 nOffset = 0;
     692             :             }
     693             :             else
     694             :             {
     695           0 :                 pIStm = &rIStm;
     696             :             }
     697             : 
     698             :             // read palette
     699           0 :             if(nColors)
     700             :             {
     701           0 :                 pAcc->SetPaletteEntryCount(nColors);
     702           0 :                 ImplReadDIBPalette(*pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE);
     703             :             }
     704             : 
     705             :             // read bits
     706           0 :             bool bAlphaUsed(false);
     707             : 
     708           0 :             if(!pIStm->GetError())
     709             :             {
     710           0 :                 if(nOffset)
     711             :                 {
     712           0 :                     pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
     713             :                 }
     714             : 
     715           0 :                 bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown, bAlphaUsed);
     716             : 
     717           0 :                 if(bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter)
     718             :                 {
     719             :                     MapMode aMapMode(
     720             :                         MAP_MM,
     721             :                         Point(),
     722             :                         Fraction(1000, aHeader.nXPelsPerMeter),
     723           0 :                         Fraction(1000, aHeader.nYPelsPerMeter));
     724             : 
     725           0 :                     aNewBmp.SetPrefMapMode(aMapMode);
     726           0 :                     aNewBmp.SetPrefSize(Size(aHeader.nWidth, aHeader.nHeight));
     727             :                 }
     728             :             }
     729             : 
     730           0 :             if( pData )
     731             :             {
     732           0 :                 rtl_freeMemory(pData);
     733             :             }
     734             : 
     735           0 :             delete pMemStm;
     736           0 :             aNewBmp.ReleaseAccess(pAcc);
     737             : 
     738           0 :             if(bAlphaPossible)
     739             :             {
     740           0 :                 aNewBmpAlpha.ReleaseAccess(pAccAlpha);
     741             : 
     742           0 :                 if(!bAlphaUsed)
     743             :                 {
     744           0 :                     bAlphaPossible = false;
     745             :                 }
     746             :             }
     747             : 
     748           0 :             if(bRet)
     749             :             {
     750           0 :                 rBmp = aNewBmp;
     751             : 
     752           0 :                 if(bAlphaPossible)
     753             :                 {
     754           0 :                     *pBmpAlpha = aNewBmpAlpha;
     755             :                 }
     756             :             }
     757           0 :         }
     758             :     }
     759             : 
     760           0 :     return bRet;
     761             : }
     762             : 
     763           0 : bool ImplReadDIBFileHeader( SvStream& rIStm, sal_uLong& rOffset )
     764             : {
     765           0 :     bool bRet = false;
     766             : 
     767           0 :     const sal_uInt64 nSavedStreamPos( rIStm.Tell() );
     768           0 :     const sal_uInt64 nStreamLength( rIStm.Seek( STREAM_SEEK_TO_END ) );
     769           0 :     rIStm.Seek( nSavedStreamPos );
     770             : 
     771           0 :     sal_uInt16 nTmp16 = 0;
     772           0 :     rIStm.ReadUInt16( nTmp16 );
     773             : 
     774           0 :     if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
     775             :     {
     776           0 :         sal_uInt32 nTmp32(0);
     777           0 :         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           0 :             rIStm.SeekRel( 8L );        // we are on bfSize member of BITMAPFILEHEADER, forward to bfOffBits
     789           0 :             rIStm.ReadUInt32( nTmp32 );            // read bfOffBits
     790           0 :             rOffset = nTmp32 - 14UL;    // adapt offset by sizeof(BITMAPFILEHEADER)
     791           0 :             bRet = ( rIStm.GetError() == 0UL );
     792             :         }
     793             : 
     794           0 :         if ( rOffset >= nStreamLength )
     795             :         {
     796             :             // Offset claims that image starts past the end of the
     797             :             // stream.  Unlikely.
     798           0 :             rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     799           0 :             bRet = false;
     800           0 :         }
     801             :     }
     802             :     else
     803           0 :         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
     804             : 
     805           0 :     return bRet;
     806             : }
     807             : 
     808           0 : bool ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
     809             : {
     810           0 :     const sal_uInt16    nColors = rAcc.GetPaletteEntryCount();
     811           0 :     const sal_uLong     nPalSize = nColors * 4UL;
     812           0 :     boost::scoped_array<sal_uInt8> pEntries(new sal_uInt8[ nPalSize ]);
     813           0 :     sal_uInt8*          pTmpEntry = pEntries.get();
     814           0 :     BitmapColor     aPalColor;
     815             : 
     816           0 :     for( sal_uInt16 i = 0; i < nColors; i++ )
     817             :     {
     818           0 :         const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
     819             : 
     820           0 :         *pTmpEntry++ = rPalColor.GetBlue();
     821           0 :         *pTmpEntry++ = rPalColor.GetGreen();
     822           0 :         *pTmpEntry++ = rPalColor.GetRed();
     823           0 :         *pTmpEntry++ = 0;
     824             :     }
     825             : 
     826           0 :     rOStm.Write( pEntries.get(), nPalSize );
     827             : 
     828           0 :     return( rOStm.GetError() == 0UL );
     829             : }
     830             : 
     831           0 : bool ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, bool bRLE4 )
     832             : {
     833           0 :     const sal_uLong nWidth = rAcc.Width();
     834           0 :     const sal_uLong nHeight = rAcc.Height();
     835             :     sal_uLong       nX;
     836             :     sal_uLong       nSaveIndex;
     837             :     sal_uLong       nCount;
     838             :     sal_uLong       nBufCount;
     839           0 :     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           0 :     for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
     846             :     {
     847           0 :         pTmp = pBuf.get();
     848           0 :         nX = nBufCount = 0UL;
     849             : 
     850           0 :         while( nX < nWidth )
     851             :         {
     852           0 :             nCount = 1L;
     853           0 :             cPix = rAcc.GetPixelIndex( nY, nX++ );
     854             : 
     855           0 :             while( ( nX < nWidth ) && ( nCount < 255L )
     856           0 :                 && ( cPix == rAcc.GetPixelIndex( nY, nX ) ) )
     857             :             {
     858           0 :                 nX++;
     859           0 :                 nCount++;
     860             :             }
     861             : 
     862           0 :             if ( nCount > 1 )
     863             :             {
     864           0 :                 *pTmp++ = (sal_uInt8) nCount;
     865           0 :                 *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
     866           0 :                 nBufCount += 2;
     867             :             }
     868             :             else
     869             :             {
     870           0 :                 cLast = cPix;
     871           0 :                 nSaveIndex = nX - 1UL;
     872           0 :                 bFound = false;
     873             : 
     874           0 :                 while( ( nX < nWidth ) && ( nCount < 256L )
     875           0 :                     && ( cPix = rAcc.GetPixelIndex( nY, nX ) ) != cLast )
     876             :                 {
     877           0 :                     nX++; nCount++;
     878           0 :                     cLast = cPix;
     879           0 :                     bFound = true;
     880             :                 }
     881             : 
     882           0 :                 if ( bFound )
     883           0 :                     nX--;
     884             : 
     885           0 :                 if ( nCount > 3 )
     886             :                 {
     887           0 :                     *pTmp++ = 0;
     888           0 :                     *pTmp++ = (sal_uInt8) --nCount;
     889             : 
     890           0 :                     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           0 :                         for( sal_uLong i = 0UL; i < nCount; i++ )
     905           0 :                             *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex++ );
     906             :                     }
     907             : 
     908           0 :                     if ( nCount & 1 )
     909             :                     {
     910           0 :                         *pTmp++ = 0;
     911           0 :                         nBufCount += ( nCount + 3 );
     912             :                     }
     913             :                     else
     914           0 :                         nBufCount += ( nCount + 2 );
     915             :                 }
     916             :                 else
     917             :                 {
     918           0 :                     *pTmp++ = 1;
     919           0 :                     *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex ) << (bRLE4 ? 4 : 0);
     920             : 
     921           0 :                     if ( nCount == 3 )
     922             :                     {
     923           0 :                         *pTmp++ = 1;
     924           0 :                         *pTmp++ = rAcc.GetPixelIndex( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
     925           0 :                         nBufCount += 4;
     926             :                     }
     927             :                     else
     928           0 :                         nBufCount += 2;
     929             :                 }
     930             :             }
     931             :         }
     932             : 
     933           0 :         pBuf[ nBufCount++ ] = 0;
     934           0 :         pBuf[ nBufCount++ ] = 0;
     935             : 
     936           0 :         rOStm.Write( pBuf.get(), nBufCount );
     937             :     }
     938             : 
     939           0 :     rOStm.WriteUChar( (sal_uInt8) 0 );
     940           0 :     rOStm.WriteUChar( (sal_uInt8) 1 );
     941             : 
     942           0 :     return( rOStm.GetError() == 0UL );
     943             : }
     944             : 
     945           0 : bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, sal_uLong nCompression, sal_uInt32& rImageSize)
     946             : {
     947           0 :     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           0 :     else if(!pAccAlpha && ((RLE_4 == nCompression) || (RLE_8 == nCompression)))
     972             :     {
     973           0 :         rImageSize = rOStm.Tell();
     974           0 :         ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
     975             :     }
     976           0 :     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           0 :         const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
     987           0 :         const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * nBitCount));
     988           0 :         bool bNative(false);
     989             : 
     990           0 :         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           0 :                 if(!pAccAlpha && rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth))
     998             :                 {
     999           0 :                     bNative = true;
    1000             :                 }
    1001             : 
    1002           0 :                 break;
    1003             :             }
    1004             : 
    1005             :             default:
    1006             :             {
    1007           0 :                 break;
    1008             :             }
    1009             :         }
    1010             : 
    1011           0 :         rImageSize = rOStm.Tell();
    1012             : 
    1013           0 :         if(bNative)
    1014             :         {
    1015           0 :             rOStm.Write(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height());
    1016             :         }
    1017             :         else
    1018             :         {
    1019           0 :             const long nWidth(rAcc.Width());
    1020           0 :             const long nHeight(rAcc.Height());
    1021           0 :             boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[ nAlignedWidth ]);
    1022           0 :             sal_uInt8* pTmp(0);
    1023           0 :             sal_uInt8 cTmp(0);
    1024             : 
    1025           0 :             switch( nBitCount )
    1026             :             {
    1027             :                 case( 1 ):
    1028             :                 {
    1029           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1030             :                     {
    1031           0 :                         pTmp = pBuf.get();
    1032           0 :                         cTmp = 0;
    1033             : 
    1034           0 :                         for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
    1035             :                         {
    1036           0 :                             if( !nShift )
    1037             :                             {
    1038           0 :                                 nShift = 8L;
    1039           0 :                                 *pTmp++ = cTmp;
    1040           0 :                                 cTmp = 0;
    1041             :                             }
    1042             : 
    1043           0 :                             cTmp |= rAcc.GetPixelIndex( nY, nX ) << --nShift;
    1044             :                         }
    1045             : 
    1046           0 :                         *pTmp = cTmp;
    1047           0 :                         rOStm.Write( pBuf.get(), nAlignedWidth );
    1048             :                     }
    1049             :                 }
    1050           0 :                 break;
    1051             : 
    1052             :                 case( 4 ):
    1053             :                 {
    1054           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1055             :                     {
    1056           0 :                         pTmp = pBuf.get();
    1057           0 :                         cTmp = 0;
    1058             : 
    1059           0 :                         for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
    1060             :                         {
    1061           0 :                             if( !nShift )
    1062             :                             {
    1063           0 :                                 nShift = 2L;
    1064           0 :                                 *pTmp++ = cTmp;
    1065           0 :                                 cTmp = 0;
    1066             :                             }
    1067             : 
    1068           0 :                             cTmp |= rAcc.GetPixelIndex( nY, nX ) << ( --nShift << 2L );
    1069             :                         }
    1070           0 :                         *pTmp = cTmp;
    1071           0 :                         rOStm.Write( pBuf.get(), nAlignedWidth );
    1072             :                     }
    1073             :                 }
    1074           0 :                 break;
    1075             : 
    1076             :                 case( 8 ):
    1077             :                 {
    1078           0 :                     for( long nY = nHeight - 1; nY >= 0L; nY-- )
    1079             :                     {
    1080           0 :                         pTmp = pBuf.get();
    1081             : 
    1082           0 :                         for( long nX = 0L; nX < nWidth; nX++ )
    1083           0 :                             *pTmp++ = rAcc.GetPixelIndex( nY, nX );
    1084             : 
    1085           0 :                         rOStm.Write( pBuf.get(), 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.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           0 :             }
    1123             :         }
    1124             :     }
    1125             : 
    1126           0 :     rImageSize = rOStm.Tell() - rImageSize;
    1127             : 
    1128           0 :     return (!rOStm.GetError());
    1129             : }
    1130             : 
    1131           0 : bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, bool bCompressed)
    1132             : {
    1133           0 :     const MapMode aMapPixel(MAP_PIXEL);
    1134           0 :     DIBV5Header aHeader;
    1135           0 :     sal_uLong nImageSizePos(0);
    1136           0 :     sal_uLong nEndPos(0);
    1137           0 :     sal_uInt32 nCompression(COMPRESS_NONE);
    1138           0 :     bool bRet(false);
    1139             : 
    1140           0 :     aHeader.nSize = pAccAlpha ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE; // size dependent on CF_DIB type to use
    1141           0 :     aHeader.nWidth = rAcc.Width();
    1142           0 :     aHeader.nHeight = rAcc.Height();
    1143           0 :     aHeader.nPlanes = 1;
    1144             : 
    1145           0 :     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           0 :         const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
    1163           0 :         aHeader.nBitCount = nBitCount;
    1164           0 :         aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount);
    1165             : 
    1166           0 :         if(bCompressed)
    1167             :         {
    1168           0 :             if(4 == nBitCount)
    1169             :             {
    1170           0 :                 nCompression = RLE_4;
    1171             :             }
    1172           0 :             else if(8 == nBitCount)
    1173             :             {
    1174           0 :                 nCompression = RLE_8;
    1175             :             }
    1176             :         }
    1177             :     }
    1178             : 
    1179           0 :     if((rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP) && (rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40))
    1180             :     {
    1181           0 :         aHeader.nCompression = ZCOMPRESS;
    1182             :     }
    1183             :     else
    1184             :     {
    1185           0 :         aHeader.nCompression = nCompression;
    1186             :     }
    1187             : 
    1188           0 :     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           0 :         const Size aScale100000(OutputDevice::LogicToLogic(Size(100000L, 100000L), MAP_100TH_MM, rBitmap.GetPrefMapMode()));
    1197           0 :         const double fBmpWidthM((double)rBitmap.GetPrefSize().Width() / aScale100000.Width());
    1198           0 :         const double fBmpHeightM((double)rBitmap.GetPrefSize().Height() / aScale100000.Height());
    1199             : 
    1200           0 :         if(!basegfx::fTools::equalZero(fBmpWidthM) && !basegfx::fTools::equalZero(fBmpHeightM))
    1201             :         {
    1202           0 :             aHeader.nXPelsPerMeter = basegfx::fround(rAcc.Width() / fabs(fBmpWidthM));
    1203           0 :             aHeader.nYPelsPerMeter = basegfx::fround(rAcc.Height() / fabs(fBmpHeightM));
    1204             :         }
    1205             :     }
    1206             : 
    1207           0 :     aHeader.nColsUsed = ((!pAccAlpha && aHeader.nBitCount <= 8) ? rAcc.GetPaletteEntryCount() : 0);
    1208           0 :     aHeader.nColsImportant = 0;
    1209             : 
    1210           0 :     rOStm.WriteUInt32( aHeader.nSize );
    1211           0 :     rOStm.WriteInt32( aHeader.nWidth );
    1212           0 :     rOStm.WriteInt32( aHeader.nHeight );
    1213           0 :     rOStm.WriteUInt16( aHeader.nPlanes );
    1214           0 :     rOStm.WriteUInt16( aHeader.nBitCount );
    1215           0 :     rOStm.WriteUInt32( aHeader.nCompression );
    1216             : 
    1217           0 :     nImageSizePos = rOStm.Tell();
    1218           0 :     rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
    1219             : 
    1220           0 :     rOStm.WriteInt32( aHeader.nXPelsPerMeter );
    1221           0 :     rOStm.WriteInt32( aHeader.nYPelsPerMeter );
    1222           0 :     rOStm.WriteUInt32( aHeader.nColsUsed );
    1223           0 :     rOStm.WriteUInt32( aHeader.nColsImportant );
    1224             : 
    1225           0 :     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           0 :     if(ZCOMPRESS == aHeader.nCompression)
    1256             :     {
    1257           0 :         ZCodec aCodec;
    1258           0 :         SvMemoryStream aMemStm(aHeader.nSizeImage + 4096, 65535);
    1259           0 :         sal_uLong nCodedPos(rOStm.Tell());
    1260           0 :         sal_uLong nLastPos(0);
    1261           0 :         sal_uInt32 nCodedSize(0);
    1262           0 :         sal_uInt32 nUncodedSize(0);
    1263             : 
    1264             :         // write uncoded data palette
    1265           0 :         if(aHeader.nColsUsed)
    1266             :         {
    1267           0 :             ImplWriteDIBPalette(aMemStm, rAcc);
    1268             :         }
    1269             : 
    1270             :         // write uncoded bits
    1271           0 :         bRet = ImplWriteDIBBits(aMemStm, rAcc, pAccAlpha, nCompression, aHeader.nSizeImage);
    1272             : 
    1273             :         // get uncoded size
    1274           0 :         nUncodedSize = aMemStm.Tell();
    1275             : 
    1276             :         // seek over compress info
    1277           0 :         rOStm.SeekRel(12);
    1278             : 
    1279             :         // write compressed data
    1280           0 :         aCodec.BeginCompression(3);
    1281           0 :         aCodec.Write(rOStm, (sal_uInt8*)aMemStm.GetData(), nUncodedSize);
    1282           0 :         aCodec.EndCompression();
    1283             : 
    1284             :         // update compress info ( coded size, uncoded size, uncoded compression )
    1285           0 :         nLastPos = rOStm.Tell();
    1286           0 :         nCodedSize = nLastPos - nCodedPos - 12;
    1287           0 :         rOStm.Seek(nCodedPos);
    1288           0 :         rOStm.WriteUInt32( nCodedSize ).WriteUInt32( nUncodedSize ).WriteUInt32( nCompression );
    1289           0 :         rOStm.Seek(nLastPos);
    1290             : 
    1291           0 :         if(bRet)
    1292             :         {
    1293           0 :             bRet = (ERRCODE_NONE == rOStm.GetError());
    1294           0 :         }
    1295             :     }
    1296             :     else
    1297             :     {
    1298           0 :         if(aHeader.nColsUsed)
    1299             :         {
    1300           0 :             ImplWriteDIBPalette(rOStm, rAcc);
    1301             :         }
    1302             : 
    1303           0 :         bRet = ImplWriteDIBBits(rOStm, rAcc, pAccAlpha, aHeader.nCompression, aHeader.nSizeImage);
    1304             :     }
    1305             : 
    1306           0 :     nEndPos = rOStm.Tell();
    1307           0 :     rOStm.Seek(nImageSizePos);
    1308           0 :     rOStm.WriteUInt32( aHeader.nSizeImage );
    1309           0 :     rOStm.Seek(nEndPos);
    1310             : 
    1311           0 :     return bRet;
    1312             : }
    1313             : 
    1314           0 : bool ImplWriteDIBFileHeader(SvStream& rOStm, BitmapReadAccess& rAcc, bool bUseDIBV5)
    1315             : {
    1316           0 :     const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : isBitfieldCompression(rAcc.GetScanlineFormat()) ? 3UL : 0UL));
    1317           0 :     const sal_uInt32 nOffset(14 + (bUseDIBV5 ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE) + nPalCount * 4UL);
    1318             : 
    1319           0 :     rOStm.WriteUInt16( (sal_uInt16)0x4D42 ); // 'MB' from BITMAPFILEHEADER
    1320           0 :     rOStm.WriteUInt32( (sal_uInt32)(nOffset + (rAcc.Height() * rAcc.GetScanlineSize())) );
    1321           0 :     rOStm.WriteUInt16( (sal_uInt16)0 );
    1322           0 :     rOStm.WriteUInt16( (sal_uInt16)0 );
    1323           0 :     rOStm.WriteUInt32( nOffset );
    1324             : 
    1325           0 :     return( rOStm.GetError() == 0UL );
    1326             : }
    1327             : 
    1328           0 : bool ImplReadDIB(
    1329             :     Bitmap& rTarget, Bitmap*
    1330             :     pTargetAlpha,
    1331             :     SvStream& rIStm,
    1332             :     bool bFileHeader)
    1333             : {
    1334           0 :     const sal_uInt16 nOldFormat(rIStm.GetNumberFormatInt());
    1335           0 :     const sal_uLong nOldPos(rIStm.Tell());
    1336           0 :     sal_uLong nOffset(0UL);
    1337           0 :     bool bRet(false);
    1338             : 
    1339           0 :     rIStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
    1340             : 
    1341           0 :     if(bFileHeader)
    1342             :     {
    1343           0 :         if(ImplReadDIBFileHeader(rIStm, nOffset))
    1344             :         {
    1345           0 :             bRet = ImplReadDIBBody(rIStm, rTarget, nOffset >= DIBV5HEADERSIZE ? pTargetAlpha : 0, nOffset);
    1346             :         }
    1347             :     }
    1348             :     else
    1349             :     {
    1350           0 :         bRet = ImplReadDIBBody(rIStm, rTarget, 0, nOffset);
    1351             :     }
    1352             : 
    1353           0 :     if(!bRet)
    1354             :     {
    1355           0 :         if(!rIStm.GetError())
    1356             :         {
    1357           0 :             rIStm.SetError(SVSTREAM_GENERALERROR);
    1358             :         }
    1359             : 
    1360           0 :         rIStm.Seek(nOldPos);
    1361             :     }
    1362             : 
    1363           0 :     rIStm.SetNumberFormatInt(nOldFormat);
    1364             : 
    1365           0 :     return bRet;
    1366             : }
    1367             : 
    1368           0 : bool ImplWriteDIB(
    1369             :     const Bitmap& rSource,
    1370             :     const Bitmap* pSourceAlpha,
    1371             :     SvStream& rOStm,
    1372             :     bool bCompressed,
    1373             :     bool bFileHeader)
    1374             : {
    1375           0 :     const Size aSizePix(rSource.GetSizePixel());
    1376           0 :     bool bRet(false);
    1377             : 
    1378           0 :     if(aSizePix.Width() && aSizePix.Height())
    1379             :     {
    1380           0 :         BitmapReadAccess* pAcc = const_cast< Bitmap& >(rSource).AcquireReadAccess();
    1381           0 :         BitmapReadAccess* pAccAlpha = 0;
    1382           0 :         const sal_uInt16 nOldFormat(rOStm.GetNumberFormatInt());
    1383           0 :         const sal_uLong nOldPos(rOStm.Tell());
    1384             : 
    1385           0 :         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           0 :         rOStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
    1400             : 
    1401           0 :         if(pAcc)
    1402             :         {
    1403           0 :             if(bFileHeader)
    1404             :             {
    1405           0 :                 if(ImplWriteDIBFileHeader(rOStm, *pAcc, 0 != pSourceAlpha))
    1406             :                 {
    1407           0 :                     bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
    1408             :                 }
    1409             :             }
    1410             :             else
    1411             :             {
    1412           0 :                 bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
    1413             :             }
    1414             : 
    1415           0 :             const_cast< Bitmap& >(rSource).ReleaseAccess(pAcc);
    1416             : 
    1417           0 :             if(pAccAlpha)
    1418             :             {
    1419           0 :                 const_cast< Bitmap* >(pSourceAlpha)->ReleaseAccess(pAccAlpha);
    1420             :             }
    1421             :         }
    1422             : 
    1423           0 :         if(!bRet)
    1424             :         {
    1425           0 :             rOStm.SetError(SVSTREAM_GENERALERROR);
    1426           0 :             rOStm.Seek(nOldPos);
    1427             :         }
    1428             : 
    1429           0 :         rOStm.SetNumberFormatInt(nOldFormat);
    1430             :     }
    1431             : 
    1432           0 :     return bRet;
    1433             : }
    1434             : 
    1435           0 : bool ReadDIB(
    1436             :     Bitmap& rTarget,
    1437             :     SvStream& rIStm,
    1438             :     bool bFileHeader)
    1439             : {
    1440           0 :     return ImplReadDIB(rTarget, 0, rIStm, bFileHeader);
    1441             : }
    1442             : 
    1443           0 : bool ReadDIBBitmapEx(
    1444             :     BitmapEx& rTarget,
    1445             :     SvStream& rIStm)
    1446             : {
    1447           0 :     Bitmap aBmp;
    1448           0 :     bool bRetval(ImplReadDIB(aBmp, 0, rIStm, true) && !rIStm.GetError());
    1449             : 
    1450           0 :     if(bRetval)
    1451             :     {
    1452             :         // base bitmap was read, set as return value and try to read alpha extra-data
    1453           0 :         const sal_uLong nStmPos(rIStm.Tell());
    1454           0 :         sal_uInt32 nMagic1(0);
    1455           0 :         sal_uInt32 nMagic2(0);
    1456             : 
    1457           0 :         rTarget = BitmapEx(aBmp);
    1458           0 :         rIStm.ReadUInt32( nMagic1 ).ReadUInt32( nMagic2 );
    1459           0 :         bRetval = (0x25091962 == nMagic1) && (0xACB20201 == nMagic2) && !rIStm.GetError();
    1460             : 
    1461           0 :         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           0 :         if(!bRetval)
    1512             :         {
    1513             :             // alpha extra data could not be read; reset, but use base bitmap as result
    1514           0 :             rIStm.ResetError();
    1515           0 :             rIStm.Seek(nStmPos);
    1516           0 :             bRetval = true;
    1517             :         }
    1518             :     }
    1519             : 
    1520           0 :     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           0 : bool WriteDIB(
    1532             :     const Bitmap& rSource,
    1533             :     SvStream& rOStm,
    1534             :     bool bCompressed,
    1535             :     bool bFileHeader)
    1536             : {
    1537           0 :     return ImplWriteDIB(rSource, 0, rOStm, bCompressed, bFileHeader);
    1538             : }
    1539             : 
    1540           0 : bool WriteDIBBitmapEx(
    1541             :     const BitmapEx& rSource,
    1542             :     SvStream& rOStm)
    1543             : {
    1544           0 :     if(ImplWriteDIB(rSource.GetBitmap(), 0, rOStm, true, true))
    1545             :     {
    1546           0 :         rOStm.WriteUInt32( (sal_uInt32)0x25091962 );
    1547           0 :         rOStm.WriteUInt32( (sal_uInt32)0xACB20201 );
    1548           0 :         rOStm.WriteUChar( (sal_uInt8)rSource.eTransparent );
    1549             : 
    1550           0 :         if(TRANSPARENT_BITMAP == rSource.eTransparent)
    1551             :         {
    1552           0 :             return ImplWriteDIB(rSource.aMask, 0, rOStm, true, true);
    1553             :         }
    1554           0 :         else if(TRANSPARENT_COLOR == rSource.eTransparent)
    1555             :         {
    1556           0 :             WriteColor( rOStm, rSource.aTransparentColor );
    1557           0 :             return true;
    1558             :         }
    1559             :     }
    1560             : 
    1561           0 :     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