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

Generated by: LCOV version 1.10