LCOV - code coverage report
Current view: top level - vcl/source/gdi - dibtools.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 618 757 81.6 %
Date: 2015-06-13 12:38:46 Functions: 27 29 93.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11