xref: /aoo41x/main/vcl/source/gdi/dibtools.cxx (revision 4e95292a)
145fd3b9aSArmin Le Grand /**************************************************************
245fd3b9aSArmin Le Grand  *
345fd3b9aSArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
445fd3b9aSArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
545fd3b9aSArmin Le Grand  * distributed with this work for additional information
645fd3b9aSArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
745fd3b9aSArmin Le Grand  * to you under the Apache License, Version 2.0 (the
845fd3b9aSArmin Le Grand  * "License"); you may not use this file except in compliance
945fd3b9aSArmin Le Grand  * with the License.  You may obtain a copy of the License at
1045fd3b9aSArmin Le Grand  *
1145fd3b9aSArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
1245fd3b9aSArmin Le Grand  *
1345fd3b9aSArmin Le Grand  * Unless required by applicable law or agreed to in writing,
1445fd3b9aSArmin Le Grand  * software distributed under the License is distributed on an
1545fd3b9aSArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1645fd3b9aSArmin Le Grand  * KIND, either express or implied.  See the License for the
1745fd3b9aSArmin Le Grand  * specific language governing permissions and limitations
1845fd3b9aSArmin Le Grand  * under the License.
1945fd3b9aSArmin Le Grand  *
2045fd3b9aSArmin Le Grand  *************************************************************/
2145fd3b9aSArmin Le Grand 
2245fd3b9aSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
2345fd3b9aSArmin Le Grand #include "precompiled_vcl.hxx"
2445fd3b9aSArmin Le Grand 
2545fd3b9aSArmin Le Grand #include <vcl/salbtype.hxx>
2645fd3b9aSArmin Le Grand #include <vcl/dibtools.hxx>
2745fd3b9aSArmin Le Grand #include <tools/zcodec.hxx>
2845fd3b9aSArmin Le Grand #include <tools/stream.hxx>
2945fd3b9aSArmin Le Grand #include <vcl/bitmapex.hxx>
3045fd3b9aSArmin Le Grand #include <vcl/bmpacc.hxx>
3145fd3b9aSArmin Le Grand #include <vcl/outdev.hxx>
3245fd3b9aSArmin Le Grand 
3345fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
3445fd3b9aSArmin Le Grand // - Defines -
3545fd3b9aSArmin Le Grand 
3645fd3b9aSArmin Le Grand #define DIBCOREHEADERSIZE		( 12UL )
3745fd3b9aSArmin Le Grand #define DIBINFOHEADERSIZE		( sizeof(DIBInfoHeader) )
3845fd3b9aSArmin Le Grand #define DIBV5HEADERSIZE		    ( sizeof(DIBV5Header) )
3945fd3b9aSArmin Le Grand 
4045fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
4145fd3b9aSArmin Le Grand // - Compression defines
4245fd3b9aSArmin Le Grand 
4345fd3b9aSArmin Le Grand #define COMPRESS_OWN				('S'|('D'<<8UL))
4445fd3b9aSArmin Le Grand #define COMPRESS_NONE				( 0UL )
4545fd3b9aSArmin Le Grand #define RLE_8						( 1UL )
4645fd3b9aSArmin Le Grand #define RLE_4						( 2UL )
4745fd3b9aSArmin Le Grand #define BITFIELDS					( 3UL )
4845fd3b9aSArmin Le Grand #define ZCOMPRESS					( COMPRESS_OWN | 0x01000000UL ) /* == 'SD01' (binary) */
4945fd3b9aSArmin Le Grand 
5045fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
5145fd3b9aSArmin Le Grand // - DIBInfoHeader and DIBV5Header
5245fd3b9aSArmin Le Grand 
5345fd3b9aSArmin Le Grand typedef sal_Int32 FXPT2DOT30;
5445fd3b9aSArmin Le Grand 
5545fd3b9aSArmin Le Grand struct CIEXYZ
5645fd3b9aSArmin Le Grand {
5745fd3b9aSArmin Le Grand     FXPT2DOT30      aXyzX;
5845fd3b9aSArmin Le Grand     FXPT2DOT30      aXyzY;
5945fd3b9aSArmin Le Grand     FXPT2DOT30      aXyzZ;
6045fd3b9aSArmin Le Grand 
6145fd3b9aSArmin Le Grand     CIEXYZ()
6245fd3b9aSArmin Le Grand     :   aXyzX(0L),
6345fd3b9aSArmin Le Grand         aXyzY(0L),
6445fd3b9aSArmin Le Grand         aXyzZ(0L)
6545fd3b9aSArmin Le Grand     {}
6645fd3b9aSArmin Le Grand 
6745fd3b9aSArmin Le Grand     ~CIEXYZ()
6845fd3b9aSArmin Le Grand     {}
6945fd3b9aSArmin Le Grand };
7045fd3b9aSArmin Le Grand 
7145fd3b9aSArmin Le Grand struct CIEXYZTriple
7245fd3b9aSArmin Le Grand {
7345fd3b9aSArmin Le Grand     CIEXYZ          aXyzRed;
7445fd3b9aSArmin Le Grand     CIEXYZ          aXyzGreen;
7545fd3b9aSArmin Le Grand     CIEXYZ          aXyzBlue;
7645fd3b9aSArmin Le Grand 
7745fd3b9aSArmin Le Grand     CIEXYZTriple()
7845fd3b9aSArmin Le Grand     :   aXyzRed(),
7945fd3b9aSArmin Le Grand         aXyzGreen(),
8045fd3b9aSArmin Le Grand         aXyzBlue()
8145fd3b9aSArmin Le Grand     {}
8245fd3b9aSArmin Le Grand 
8345fd3b9aSArmin Le Grand     ~CIEXYZTriple()
8445fd3b9aSArmin Le Grand     {}
8545fd3b9aSArmin Le Grand };
8645fd3b9aSArmin Le Grand 
8745fd3b9aSArmin Le Grand struct DIBInfoHeader
8845fd3b9aSArmin Le Grand {
8945fd3b9aSArmin Le Grand     sal_uInt32      nSize;
9045fd3b9aSArmin Le Grand     sal_Int32       nWidth;
9145fd3b9aSArmin Le Grand     sal_Int32       nHeight;
9245fd3b9aSArmin Le Grand     sal_uInt16      nPlanes;
9345fd3b9aSArmin Le Grand     sal_uInt16      nBitCount;
9445fd3b9aSArmin Le Grand     sal_uInt32      nCompression;
9545fd3b9aSArmin Le Grand     sal_uInt32      nSizeImage;
9645fd3b9aSArmin Le Grand     sal_Int32       nXPelsPerMeter;
9745fd3b9aSArmin Le Grand     sal_Int32       nYPelsPerMeter;
9845fd3b9aSArmin Le Grand     sal_uInt32      nColsUsed;
9945fd3b9aSArmin Le Grand     sal_uInt32      nColsImportant;
10045fd3b9aSArmin Le Grand 
10145fd3b9aSArmin Le Grand     DIBInfoHeader()
10245fd3b9aSArmin Le Grand     :   nSize(0UL),
10345fd3b9aSArmin Le Grand         nWidth(0UL),
10445fd3b9aSArmin Le Grand         nHeight(0UL),
10545fd3b9aSArmin Le Grand         nPlanes(0),
10645fd3b9aSArmin Le Grand         nBitCount(0),
10745fd3b9aSArmin Le Grand         nCompression(0),
10845fd3b9aSArmin Le Grand         nSizeImage(0),
10945fd3b9aSArmin Le Grand         nXPelsPerMeter(0UL),
11045fd3b9aSArmin Le Grand         nYPelsPerMeter(0UL),
11145fd3b9aSArmin Le Grand         nColsUsed(0UL),
11245fd3b9aSArmin Le Grand         nColsImportant(0UL)
11345fd3b9aSArmin Le Grand     {}
11445fd3b9aSArmin Le Grand 
11545fd3b9aSArmin Le Grand     ~DIBInfoHeader()
11645fd3b9aSArmin Le Grand     {}
11745fd3b9aSArmin Le Grand };
11845fd3b9aSArmin Le Grand 
11945fd3b9aSArmin Le Grand struct DIBV5Header : public DIBInfoHeader
12045fd3b9aSArmin Le Grand {
12145fd3b9aSArmin Le Grand     sal_uInt32      nV5RedMask;
12245fd3b9aSArmin Le Grand     sal_uInt32      nV5GreenMask;
12345fd3b9aSArmin Le Grand     sal_uInt32      nV5BlueMask;
12445fd3b9aSArmin Le Grand     sal_uInt32      nV5AlphaMask;
12545fd3b9aSArmin Le Grand     sal_uInt32      nV5CSType;
12645fd3b9aSArmin Le Grand     CIEXYZTriple    aV5Endpoints;
12745fd3b9aSArmin Le Grand     sal_uInt32      nV5GammaRed;
12845fd3b9aSArmin Le Grand     sal_uInt32      nV5GammaGreen;
12945fd3b9aSArmin Le Grand     sal_uInt32      nV5GammaBlue;
13045fd3b9aSArmin Le Grand     sal_uInt32      nV5Intent;
13145fd3b9aSArmin Le Grand     sal_uInt32      nV5ProfileData;
13245fd3b9aSArmin Le Grand     sal_uInt32      nV5ProfileSize;
13345fd3b9aSArmin Le Grand     sal_uInt32      nV5Reserved;
13445fd3b9aSArmin Le Grand 
13545fd3b9aSArmin Le Grand     DIBV5Header()
13645fd3b9aSArmin Le Grand     :   DIBInfoHeader(),
13745fd3b9aSArmin Le Grand         nV5RedMask(0UL),
13845fd3b9aSArmin Le Grand         nV5GreenMask(0UL),
13945fd3b9aSArmin Le Grand         nV5BlueMask(0UL),
14045fd3b9aSArmin Le Grand         nV5AlphaMask(0UL),
14145fd3b9aSArmin Le Grand         nV5CSType(0UL),
14245fd3b9aSArmin Le Grand         aV5Endpoints(),
14345fd3b9aSArmin Le Grand         nV5GammaRed(0UL),
14445fd3b9aSArmin Le Grand         nV5GammaGreen(0UL),
14545fd3b9aSArmin Le Grand         nV5GammaBlue(0UL),
14645fd3b9aSArmin Le Grand         nV5Intent(0UL),
14745fd3b9aSArmin Le Grand         nV5ProfileData(0UL),
14845fd3b9aSArmin Le Grand         nV5ProfileSize(0UL),
14945fd3b9aSArmin Le Grand         nV5Reserved(0UL)
15045fd3b9aSArmin Le Grand     {}
15145fd3b9aSArmin Le Grand 
15245fd3b9aSArmin Le Grand     ~DIBV5Header()
15345fd3b9aSArmin Le Grand     {}
15445fd3b9aSArmin Le Grand };
15545fd3b9aSArmin Le Grand 
15645fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
15745fd3b9aSArmin Le Grand 
15845fd3b9aSArmin Le Grand namespace
15945fd3b9aSArmin Le Grand {
16045fd3b9aSArmin Le Grand     inline sal_uInt16 discretizeBitcount( sal_uInt16 nInputCount )
16145fd3b9aSArmin Le Grand     {
16245fd3b9aSArmin Le Grand         return ( nInputCount <= 1 ) ? 1 :
16345fd3b9aSArmin Le Grand                ( nInputCount <= 4 ) ? 4 :
16445fd3b9aSArmin Le Grand                ( nInputCount <= 8 ) ? 8 : 24;
16545fd3b9aSArmin Le Grand     }
16645fd3b9aSArmin Le Grand 
16745fd3b9aSArmin Le Grand     inline bool isBitfieldCompression( sal_uLong nScanlineFormat )
16845fd3b9aSArmin Le Grand     {
16945fd3b9aSArmin Le Grand         return (BMP_FORMAT_16BIT_TC_LSB_MASK == nScanlineFormat) || (BMP_FORMAT_32BIT_TC_MASK == nScanlineFormat);
17045fd3b9aSArmin Le Grand     }
17145fd3b9aSArmin Le Grand }
17245fd3b9aSArmin Le Grand 
17345fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
17445fd3b9aSArmin Le Grand 
17545fd3b9aSArmin Le Grand bool ImplReadDIBInfoHeader(SvStream& rIStm, DIBV5Header& rHeader, bool& bTopDown)
17645fd3b9aSArmin Le Grand {
17745fd3b9aSArmin Le Grand 	// BITMAPINFOHEADER or BITMAPCOREHEADER or BITMAPV5HEADER
17845fd3b9aSArmin Le Grand     const sal_Size aStartPos(rIStm.Tell());
17945fd3b9aSArmin Le Grand 	rIStm >> rHeader.nSize;
18045fd3b9aSArmin Le Grand 
18145fd3b9aSArmin Le Grand 	// BITMAPCOREHEADER
18245fd3b9aSArmin Le Grand 	if ( rHeader.nSize == DIBCOREHEADERSIZE )
18345fd3b9aSArmin Le Grand 	{
18445fd3b9aSArmin Le Grand 		sal_Int16 nTmp16;
18545fd3b9aSArmin Le Grand 
18645fd3b9aSArmin Le Grand 		rIStm >> nTmp16; rHeader.nWidth = nTmp16;
18745fd3b9aSArmin Le Grand 		rIStm >> nTmp16; rHeader.nHeight = nTmp16;
18845fd3b9aSArmin Le Grand 		rIStm >> rHeader.nPlanes;
18945fd3b9aSArmin Le Grand 		rIStm >> rHeader.nBitCount;
19045fd3b9aSArmin Le Grand 	}
19145fd3b9aSArmin Le Grand 	else
19245fd3b9aSArmin Le Grand 	{
19345fd3b9aSArmin Le Grand         // BITMAPCOREHEADER, BITMAPV5HEADER or unknown. Read as far as possible
19445fd3b9aSArmin Le Grand         sal_Size nUsed(sizeof(rHeader.nSize));
19545fd3b9aSArmin Le Grand 
19645fd3b9aSArmin Le Grand         // read DIBInfoHeader entries
19745fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nWidth; nUsed += sizeof(rHeader.nWidth); }
19845fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nHeight; nUsed += sizeof(rHeader.nHeight); }
19945fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nPlanes; nUsed += sizeof(rHeader.nPlanes); }
20045fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nBitCount;  nUsed += sizeof(rHeader.nBitCount); }
20145fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nCompression;  nUsed += sizeof(rHeader.nCompression); }
20245fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nSizeImage;  nUsed += sizeof(rHeader.nSizeImage); }
20345fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nXPelsPerMeter;  nUsed += sizeof(rHeader.nXPelsPerMeter); }
20445fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nYPelsPerMeter;  nUsed += sizeof(rHeader.nYPelsPerMeter); }
20545fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nColsUsed;  nUsed += sizeof(rHeader.nColsUsed); }
20645fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nColsImportant;  nUsed += sizeof(rHeader.nColsImportant); }
20745fd3b9aSArmin Le Grand 
20845fd3b9aSArmin Le Grand         // read DIBV5HEADER members
20945fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5RedMask; nUsed += sizeof(rHeader.nV5RedMask); }
21045fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GreenMask; nUsed += sizeof(rHeader.nV5GreenMask);  }
21145fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5BlueMask; nUsed += sizeof(rHeader.nV5BlueMask);  }
21245fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5AlphaMask; nUsed += sizeof(rHeader.nV5AlphaMask);  }
21345fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5CSType; nUsed += sizeof(rHeader.nV5CSType);  }
21445fd3b9aSArmin Le Grand 
21545fd3b9aSArmin Le Grand         // read contained CIEXYZTriple's
21645fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzRed.aXyzX; nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzX); }
21745fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzRed.aXyzY; nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzY); }
21845fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzRed.aXyzZ; nUsed += sizeof(rHeader.aV5Endpoints.aXyzRed.aXyzZ); }
21945fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzGreen.aXyzX; nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzX); }
22045fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzGreen.aXyzY; nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzY); }
22145fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzGreen.aXyzZ; nUsed += sizeof(rHeader.aV5Endpoints.aXyzGreen.aXyzZ); }
22245fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzBlue.aXyzX; nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzX); }
22345fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzBlue.aXyzY; nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzY); }
22445fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.aV5Endpoints.aXyzBlue.aXyzZ; nUsed += sizeof(rHeader.aV5Endpoints.aXyzBlue.aXyzZ); }
22545fd3b9aSArmin Le Grand 
22645fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GammaRed; nUsed += sizeof(rHeader.nV5GammaRed);  }
22745fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GammaGreen; nUsed += sizeof(rHeader.nV5GammaGreen);  }
22845fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5GammaBlue; nUsed += sizeof(rHeader.nV5GammaBlue);  }
22945fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5Intent; nUsed += sizeof(rHeader.nV5Intent);  }
23045fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5ProfileData; nUsed += sizeof(rHeader.nV5ProfileData);  }
23145fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5ProfileSize; nUsed += sizeof(rHeader.nV5ProfileSize);  }
23245fd3b9aSArmin Le Grand         if(nUsed < rHeader.nSize) { rIStm >> rHeader.nV5Reserved; nUsed += sizeof(rHeader.nV5Reserved);  }
23345fd3b9aSArmin Le Grand 
23445fd3b9aSArmin Le Grand         // seek to EndPos
23545fd3b9aSArmin Le Grand         rIStm.Seek(aStartPos + rHeader.nSize);
23645fd3b9aSArmin Le Grand     }
23745fd3b9aSArmin Le Grand 
23845fd3b9aSArmin Le Grand     if ( rHeader.nHeight < 0 )
23945fd3b9aSArmin Le Grand 	{
24045fd3b9aSArmin Le Grand 		bTopDown = true;
24145fd3b9aSArmin Le Grand 		rHeader.nHeight *= -1;
24245fd3b9aSArmin Le Grand 	}
24345fd3b9aSArmin Le Grand 	else
24445fd3b9aSArmin Le Grand     {
24545fd3b9aSArmin Le Grand 		bTopDown = false;
24645fd3b9aSArmin Le Grand     }
24745fd3b9aSArmin Le Grand 
24845fd3b9aSArmin Le Grand 	if ( rHeader.nWidth < 0 )
24945fd3b9aSArmin Le Grand     {
25045fd3b9aSArmin Le Grand 		rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
25145fd3b9aSArmin Le Grand     }
25245fd3b9aSArmin Le Grand 
25345fd3b9aSArmin Le Grand     // #144105# protect a little against damaged files
25445fd3b9aSArmin Le Grand     if( rHeader.nSizeImage > ( 16 * static_cast< sal_uInt32 >( rHeader.nWidth * rHeader.nHeight ) ) )
25545fd3b9aSArmin Le Grand     {
25645fd3b9aSArmin Le Grand         rHeader.nSizeImage = 0;
25745fd3b9aSArmin Le Grand     }
25845fd3b9aSArmin Le Grand 
25945fd3b9aSArmin Le Grand 	return( ( rHeader.nPlanes == 1 ) && ( rIStm.GetError() == 0UL ) );
26045fd3b9aSArmin Le Grand }
26145fd3b9aSArmin Le Grand 
26245fd3b9aSArmin Le Grand bool ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, bool bQuad )
26345fd3b9aSArmin Le Grand {
26445fd3b9aSArmin Le Grand 	const sal_uInt16	nColors = rAcc.GetPaletteEntryCount();
26545fd3b9aSArmin Le Grand 	const sal_uLong 	nPalSize = nColors * ( bQuad ? 4UL : 3UL );
26645fd3b9aSArmin Le Grand 	BitmapColor 	aPalColor;
26745fd3b9aSArmin Le Grand 
26845fd3b9aSArmin Le Grand 	sal_uInt8* pEntries = new sal_uInt8[ nPalSize ];
26945fd3b9aSArmin Le Grand 	rIStm.Read( pEntries, nPalSize );
27045fd3b9aSArmin Le Grand 
27145fd3b9aSArmin Le Grand 	sal_uInt8* pTmpEntry = pEntries;
27245fd3b9aSArmin Le Grand 	for( sal_uInt16 i = 0; i < nColors; i++ )
27345fd3b9aSArmin Le Grand 	{
27445fd3b9aSArmin Le Grand 		aPalColor.SetBlue( *pTmpEntry++ );
27545fd3b9aSArmin Le Grand 		aPalColor.SetGreen( *pTmpEntry++ );
27645fd3b9aSArmin Le Grand 		aPalColor.SetRed( *pTmpEntry++ );
27745fd3b9aSArmin Le Grand 
27845fd3b9aSArmin Le Grand 		if( bQuad )
27945fd3b9aSArmin Le Grand 			pTmpEntry++;
28045fd3b9aSArmin Le Grand 
28145fd3b9aSArmin Le Grand 		rAcc.SetPaletteColor( i, aPalColor );
28245fd3b9aSArmin Le Grand 	}
28345fd3b9aSArmin Le Grand 
28445fd3b9aSArmin Le Grand 	delete[] pEntries;
28545fd3b9aSArmin Le Grand 
28645fd3b9aSArmin Le Grand 	return( rIStm.GetError() == 0UL );
28745fd3b9aSArmin Le Grand }
28845fd3b9aSArmin Le Grand 
28945fd3b9aSArmin Le Grand void ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, bool bRLE4 )
29045fd3b9aSArmin Le Grand {
29145fd3b9aSArmin Le Grand 	Scanline	pRLE = pBuffer;
29245fd3b9aSArmin Le Grand 	long		nY = rHeader.nHeight - 1L;
29345fd3b9aSArmin Le Grand 	const sal_uLong	nWidth = rAcc.Width();
29445fd3b9aSArmin Le Grand 	sal_uLong		nCountByte;
29545fd3b9aSArmin Le Grand 	sal_uLong		nRunByte;
29645fd3b9aSArmin Le Grand 	sal_uLong		nX = 0UL;
29745fd3b9aSArmin Le Grand 	sal_uInt8		cTmp;
29845fd3b9aSArmin Le Grand 	bool		bEndDecoding = false;
29945fd3b9aSArmin Le Grand 
30045fd3b9aSArmin Le Grand 	do
30145fd3b9aSArmin Le Grand 	{
30245fd3b9aSArmin Le Grand 		if( ( nCountByte = *pRLE++ ) == 0 )
30345fd3b9aSArmin Le Grand 		{
30445fd3b9aSArmin Le Grand 			nRunByte = *pRLE++;
30545fd3b9aSArmin Le Grand 
30645fd3b9aSArmin Le Grand 			if( nRunByte > 2 )
30745fd3b9aSArmin Le Grand 			{
30845fd3b9aSArmin Le Grand 				if( bRLE4 )
30945fd3b9aSArmin Le Grand 				{
31045fd3b9aSArmin Le Grand 					nCountByte = nRunByte >> 1;
31145fd3b9aSArmin Le Grand 
31245fd3b9aSArmin Le Grand 					for( sal_uLong i = 0UL; i < nCountByte; i++ )
31345fd3b9aSArmin Le Grand 					{
31445fd3b9aSArmin Le Grand 						cTmp = *pRLE++;
31545fd3b9aSArmin Le Grand 
31645fd3b9aSArmin Le Grand 						if( nX < nWidth )
31745fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
31845fd3b9aSArmin Le Grand 
31945fd3b9aSArmin Le Grand 						if( nX < nWidth )
32045fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
32145fd3b9aSArmin Le Grand 					}
32245fd3b9aSArmin Le Grand 
32345fd3b9aSArmin Le Grand 					if( nRunByte & 1 )
32445fd3b9aSArmin Le Grand 					{
32545fd3b9aSArmin Le Grand 						if( nX < nWidth )
32645fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX++, *pRLE >> 4 );
32745fd3b9aSArmin Le Grand 
32845fd3b9aSArmin Le Grand 						pRLE++;
32945fd3b9aSArmin Le Grand 					}
33045fd3b9aSArmin Le Grand 
33145fd3b9aSArmin Le Grand 					if( ( ( nRunByte + 1 ) >> 1 ) & 1 )
33245fd3b9aSArmin Le Grand 						pRLE++;
33345fd3b9aSArmin Le Grand 				}
33445fd3b9aSArmin Le Grand 				else
33545fd3b9aSArmin Le Grand 				{
33645fd3b9aSArmin Le Grand 					for( sal_uLong i = 0UL; i < nRunByte; i++ )
33745fd3b9aSArmin Le Grand 					{
33845fd3b9aSArmin Le Grand 						if( nX < nWidth )
33945fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX++, *pRLE );
34045fd3b9aSArmin Le Grand 
34145fd3b9aSArmin Le Grand 						pRLE++;
34245fd3b9aSArmin Le Grand 					}
34345fd3b9aSArmin Le Grand 
34445fd3b9aSArmin Le Grand 					if( nRunByte & 1 )
34545fd3b9aSArmin Le Grand 						pRLE++;
34645fd3b9aSArmin Le Grand 				}
34745fd3b9aSArmin Le Grand 			}
34845fd3b9aSArmin Le Grand 			else if( !nRunByte )
34945fd3b9aSArmin Le Grand 			{
35045fd3b9aSArmin Le Grand 				nY--;
35145fd3b9aSArmin Le Grand 				nX = 0UL;
35245fd3b9aSArmin Le Grand 			}
35345fd3b9aSArmin Le Grand 			else if( nRunByte == 1 )
35445fd3b9aSArmin Le Grand 				bEndDecoding = true;
35545fd3b9aSArmin Le Grand 			else
35645fd3b9aSArmin Le Grand 			{
35745fd3b9aSArmin Le Grand 				nX += *pRLE++;
35845fd3b9aSArmin Le Grand 				nY -= *pRLE++;
35945fd3b9aSArmin Le Grand 			}
36045fd3b9aSArmin Le Grand 		}
36145fd3b9aSArmin Le Grand 		else
36245fd3b9aSArmin Le Grand 		{
36345fd3b9aSArmin Le Grand 			cTmp = *pRLE++;
36445fd3b9aSArmin Le Grand 
36545fd3b9aSArmin Le Grand 			if( bRLE4 )
36645fd3b9aSArmin Le Grand 			{
36745fd3b9aSArmin Le Grand 				nRunByte = nCountByte >> 1;
36845fd3b9aSArmin Le Grand 
36945fd3b9aSArmin Le Grand 				for( sal_uLong i = 0UL; i < nRunByte; i++ )
37045fd3b9aSArmin Le Grand 				{
37145fd3b9aSArmin Le Grand 					if( nX < nWidth )
37245fd3b9aSArmin Le Grand 						rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
37345fd3b9aSArmin Le Grand 
37445fd3b9aSArmin Le Grand 					if( nX < nWidth )
37545fd3b9aSArmin Le Grand 						rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
37645fd3b9aSArmin Le Grand 				}
37745fd3b9aSArmin Le Grand 
37845fd3b9aSArmin Le Grand 				if( ( nCountByte & 1 ) && ( nX < nWidth ) )
37945fd3b9aSArmin Le Grand 					rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
38045fd3b9aSArmin Le Grand 			}
38145fd3b9aSArmin Le Grand 			else
38245fd3b9aSArmin Le Grand 			{
38345fd3b9aSArmin Le Grand 				for( sal_uLong i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
38445fd3b9aSArmin Le Grand 					rAcc.SetPixelIndex( nY, nX++, cTmp );
38545fd3b9aSArmin Le Grand 			}
38645fd3b9aSArmin Le Grand 		}
38745fd3b9aSArmin Le Grand 	}
38845fd3b9aSArmin Le Grand 	while ( !bEndDecoding && ( nY >= 0L ) );
38945fd3b9aSArmin Le Grand }
39045fd3b9aSArmin Le Grand 
391c7a371deSArmin Le Grand bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, BitmapWriteAccess* pAccAlpha, bool bTopDown, bool& rAlphaUsed)
39245fd3b9aSArmin Le Grand {
3933aedac3eSJürgen Schmidt     const sal_Int64 nBitsPerLine (static_cast<sal_Int64>(rHeader.nWidth) * static_cast<sal_Int64>(rHeader.nBitCount));
3943aedac3eSJürgen Schmidt     if (nBitsPerLine > SAL_MAX_UINT32)
3953aedac3eSJürgen Schmidt         return false;
3963aedac3eSJürgen Schmidt 
3973aedac3eSJürgen Schmidt 	const sal_uLong nAlignedWidth = AlignedWidth4Bytes(static_cast<sal_uLong>(nBitsPerLine));
398c7a371deSArmin Le Grand 	sal_uInt32 nRMask(( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL);
399c7a371deSArmin Le Grand 	sal_uInt32 nGMask(( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL);
400c7a371deSArmin Le Grand 	sal_uInt32 nBMask(( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL);
40145fd3b9aSArmin Le Grand 	bool bNative(false);
40245fd3b9aSArmin Le Grand 	bool bTCMask(!pAccAlpha && ((16 == rHeader.nBitCount) || (32 == rHeader.nBitCount)));
40345fd3b9aSArmin Le Grand 	bool bRLE((RLE_8 == rHeader.nCompression && 8 == rHeader.nBitCount) || (RLE_4 == rHeader.nCompression && 4 == rHeader.nBitCount));
40445fd3b9aSArmin Le Grand 
40545fd3b9aSArmin Le Grand 	// Is native format?
40645fd3b9aSArmin Le Grand 	switch(rAcc.GetScanlineFormat())
40745fd3b9aSArmin Le Grand 	{
40845fd3b9aSArmin Le Grand 		case( BMP_FORMAT_1BIT_MSB_PAL ):
40945fd3b9aSArmin Le Grand 		case( BMP_FORMAT_4BIT_MSN_PAL ):
41045fd3b9aSArmin Le Grand 		case( BMP_FORMAT_8BIT_PAL ):
41145fd3b9aSArmin Le Grand 		case( BMP_FORMAT_24BIT_TC_BGR ):
41245fd3b9aSArmin Le Grand         {
41345fd3b9aSArmin Le Grand 			bNative = ( ( static_cast< bool >(rAcc.IsBottomUp()) != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
41445fd3b9aSArmin Le Grand 		    break;
41545fd3b9aSArmin Le Grand         }
41645fd3b9aSArmin Le Grand 
41745fd3b9aSArmin Le Grand 		default:
41845fd3b9aSArmin Le Grand         {
41945fd3b9aSArmin Le Grand     		break;
42045fd3b9aSArmin Le Grand         }
42145fd3b9aSArmin Le Grand 	}
42245fd3b9aSArmin Le Grand 
42345fd3b9aSArmin Le Grand     // Read data
42445fd3b9aSArmin Le Grand 	if(bNative)
42545fd3b9aSArmin Le Grand 	{
42645fd3b9aSArmin Le Grand 		rIStm.Read(rAcc.GetBuffer(), rHeader.nHeight * nAlignedWidth);
42745fd3b9aSArmin Le Grand 	}
42845fd3b9aSArmin Le Grand 	else
42945fd3b9aSArmin Le Grand 	{
43045fd3b9aSArmin Le Grand 		// Read color mask
431c7a371deSArmin Le Grand         if(bTCMask && BITFIELDS == rHeader.nCompression)
432c7a371deSArmin Le Grand         {
433c7a371deSArmin Le Grand             rIStm.SeekRel( -12L );
434c7a371deSArmin Le Grand             rIStm >> nRMask;
435c7a371deSArmin Le Grand             rIStm >> nGMask;
436c7a371deSArmin Le Grand             rIStm >> nBMask;
437c7a371deSArmin Le Grand         }
43845fd3b9aSArmin Le Grand 
43945fd3b9aSArmin Le Grand 		if(bRLE)
44045fd3b9aSArmin Le Grand 		{
44145fd3b9aSArmin Le Grand 			if(!rHeader.nSizeImage)
44245fd3b9aSArmin Le Grand 			{
44345fd3b9aSArmin Le Grand 				const sal_uLong nOldPos(rIStm.Tell());
44445fd3b9aSArmin Le Grand 
44545fd3b9aSArmin Le Grand 				rIStm.Seek(STREAM_SEEK_TO_END);
44645fd3b9aSArmin Le Grand 				rHeader.nSizeImage = rIStm.Tell() - nOldPos;
44745fd3b9aSArmin Le Grand 				rIStm.Seek(nOldPos);
44845fd3b9aSArmin Le Grand 			}
44945fd3b9aSArmin Le Grand 
45045fd3b9aSArmin Le Grand 			sal_uInt8* pBuffer = (sal_uInt8*)rtl_allocateMemory(rHeader.nSizeImage);
45145fd3b9aSArmin Le Grand 			rIStm.Read((char*)pBuffer, rHeader.nSizeImage);
45245fd3b9aSArmin Le Grand 			ImplDecodeRLE(pBuffer, rHeader, rAcc, RLE_4 == rHeader.nCompression);
45345fd3b9aSArmin Le Grand 			rtl_freeMemory(pBuffer);
45445fd3b9aSArmin Le Grand 		}
45545fd3b9aSArmin Le Grand 		else
45645fd3b9aSArmin Le Grand 		{
45745fd3b9aSArmin Le Grand 			const long nWidth(rHeader.nWidth);
45845fd3b9aSArmin Le Grand 			const long nHeight(rHeader.nHeight);
45945fd3b9aSArmin Le Grand 			sal_uInt8* pBuf = new sal_uInt8[nAlignedWidth];
46045fd3b9aSArmin Le Grand 
46145fd3b9aSArmin Le Grand 			const long nI(bTopDown ? 1 : -1);
46245fd3b9aSArmin Le Grand 			long nY(bTopDown ? 0 : nHeight - 1);
46345fd3b9aSArmin Le Grand 			long nCount(nHeight);
46445fd3b9aSArmin Le Grand 
46545fd3b9aSArmin Le Grand 			switch(rHeader.nBitCount)
46645fd3b9aSArmin Le Grand 			{
46745fd3b9aSArmin Le Grand 				case( 1 ):
46845fd3b9aSArmin Le Grand 				{
46945fd3b9aSArmin Le Grand 					sal_uInt8*	pTmp;
47045fd3b9aSArmin Le Grand 					sal_uInt8	cTmp;
47145fd3b9aSArmin Le Grand 
47245fd3b9aSArmin Le Grand 					for( ; nCount--; nY += nI )
47345fd3b9aSArmin Le Grand 					{
47445fd3b9aSArmin Le Grand 						rIStm.Read( pTmp = pBuf, nAlignedWidth );
47545fd3b9aSArmin Le Grand 						cTmp = *pTmp++;
47645fd3b9aSArmin Le Grand 
47745fd3b9aSArmin Le Grand 						for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
47845fd3b9aSArmin Le Grand 						{
47945fd3b9aSArmin Le Grand 							if( !nShift )
48045fd3b9aSArmin Le Grand 							{
48145fd3b9aSArmin Le Grand 								nShift = 8L,
48245fd3b9aSArmin Le Grand 								cTmp = *pTmp++;
48345fd3b9aSArmin Le Grand 							}
48445fd3b9aSArmin Le Grand 
48545fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX, (cTmp >> --nShift) & 1);
48645fd3b9aSArmin Le Grand 						}
48745fd3b9aSArmin Le Grand 					}
48845fd3b9aSArmin Le Grand 				}
48945fd3b9aSArmin Le Grand 				break;
49045fd3b9aSArmin Le Grand 
49145fd3b9aSArmin Le Grand 				case( 4 ):
49245fd3b9aSArmin Le Grand 				{
49345fd3b9aSArmin Le Grand 					sal_uInt8*	pTmp;
49445fd3b9aSArmin Le Grand 					sal_uInt8	cTmp;
49545fd3b9aSArmin Le Grand 
49645fd3b9aSArmin Le Grand 					for( ; nCount--; nY += nI )
49745fd3b9aSArmin Le Grand 					{
49845fd3b9aSArmin Le Grand 						rIStm.Read( pTmp = pBuf, nAlignedWidth );
49945fd3b9aSArmin Le Grand 						cTmp = *pTmp++;
50045fd3b9aSArmin Le Grand 
50145fd3b9aSArmin Le Grand 						for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
50245fd3b9aSArmin Le Grand 						{
50345fd3b9aSArmin Le Grand 							if( !nShift )
50445fd3b9aSArmin Le Grand 							{
50545fd3b9aSArmin Le Grand 								nShift = 2UL,
50645fd3b9aSArmin Le Grand 								cTmp = *pTmp++;
50745fd3b9aSArmin Le Grand 							}
50845fd3b9aSArmin Le Grand 
50945fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX, (cTmp >> ( --nShift << 2UL ) ) & 0x0f);
51045fd3b9aSArmin Le Grand 						}
51145fd3b9aSArmin Le Grand 					}
51245fd3b9aSArmin Le Grand 				}
51345fd3b9aSArmin Le Grand 				break;
51445fd3b9aSArmin Le Grand 
51545fd3b9aSArmin Le Grand 				case( 8 ):
51645fd3b9aSArmin Le Grand 				{
51745fd3b9aSArmin Le Grand 					sal_uInt8*	pTmp;
51845fd3b9aSArmin Le Grand 
51945fd3b9aSArmin Le Grand 					for( ; nCount--; nY += nI )
52045fd3b9aSArmin Le Grand 					{
52145fd3b9aSArmin Le Grand 						rIStm.Read( pTmp = pBuf, nAlignedWidth );
52245fd3b9aSArmin Le Grand 
52345fd3b9aSArmin Le Grand 						for( long nX = 0L; nX < nWidth; nX++ )
52445fd3b9aSArmin Le Grand 							rAcc.SetPixelIndex( nY, nX, *pTmp++ );
52545fd3b9aSArmin Le Grand 					}
52645fd3b9aSArmin Le Grand 				}
52745fd3b9aSArmin Le Grand 				break;
52845fd3b9aSArmin Le Grand 
52945fd3b9aSArmin Le Grand 				case( 16 ):
53045fd3b9aSArmin Le Grand 				{
53145fd3b9aSArmin Le Grand 					ColorMask	aMask( nRMask, nGMask, nBMask );
53245fd3b9aSArmin Le Grand 					BitmapColor aColor;
53345fd3b9aSArmin Le Grand 					sal_uInt16* 	pTmp16;
53445fd3b9aSArmin Le Grand 
53545fd3b9aSArmin Le Grand 					for( ; nCount--; nY += nI )
53645fd3b9aSArmin Le Grand 					{
53745fd3b9aSArmin Le Grand 						rIStm.Read( (char*)( pTmp16 = (sal_uInt16*) pBuf ), nAlignedWidth );
53845fd3b9aSArmin Le Grand 
53945fd3b9aSArmin Le Grand 						for( long nX = 0L; nX < nWidth; nX++ )
54045fd3b9aSArmin Le Grand 						{
54145fd3b9aSArmin Le Grand 							aMask.GetColorFor16BitLSB( aColor, (sal_uInt8*) pTmp16++ );
54245fd3b9aSArmin Le Grand 							rAcc.SetPixel( nY, nX, aColor );
54345fd3b9aSArmin Le Grand 						}
54445fd3b9aSArmin Le Grand 					}
54545fd3b9aSArmin Le Grand 				}
54645fd3b9aSArmin Le Grand 				break;
54745fd3b9aSArmin Le Grand 
54845fd3b9aSArmin Le Grand 				case( 24 ):
54945fd3b9aSArmin Le Grand 				{
55045fd3b9aSArmin Le Grand 					BitmapColor aPixelColor;
55145fd3b9aSArmin Le Grand 					sal_uInt8*		pTmp;
55245fd3b9aSArmin Le Grand 
55345fd3b9aSArmin Le Grand 					for( ; nCount--; nY += nI )
55445fd3b9aSArmin Le Grand 					{
55545fd3b9aSArmin Le Grand 						rIStm.Read( pTmp = pBuf, nAlignedWidth );
55645fd3b9aSArmin Le Grand 
55745fd3b9aSArmin Le Grand 						for( long nX = 0L; nX < nWidth; nX++ )
55845fd3b9aSArmin Le Grand 						{
55945fd3b9aSArmin Le Grand 							aPixelColor.SetBlue( *pTmp++ );
56045fd3b9aSArmin Le Grand 							aPixelColor.SetGreen( *pTmp++ );
56145fd3b9aSArmin Le Grand 							aPixelColor.SetRed( *pTmp++ );
56245fd3b9aSArmin Le Grand 							rAcc.SetPixel( nY, nX, aPixelColor );
56345fd3b9aSArmin Le Grand 						}
56445fd3b9aSArmin Le Grand 					}
56545fd3b9aSArmin Le Grand 				}
56645fd3b9aSArmin Le Grand 				break;
56745fd3b9aSArmin Le Grand 
56845fd3b9aSArmin Le Grand 				case( 32 ):
56945fd3b9aSArmin Le Grand 				{
57045fd3b9aSArmin Le Grand 					ColorMask aMask(nRMask, nGMask, nBMask);
57145fd3b9aSArmin Le Grand 					BitmapColor aColor;
57245fd3b9aSArmin Le Grand 					sal_uInt32* pTmp32;
57345fd3b9aSArmin Le Grand 
57445fd3b9aSArmin Le Grand                     if(pAccAlpha)
57545fd3b9aSArmin Le Grand                     {
57645fd3b9aSArmin Le Grand                         sal_uInt8 aAlpha;
57745fd3b9aSArmin Le Grand 
57845fd3b9aSArmin Le Grand                         for( ; nCount--; nY += nI )
57945fd3b9aSArmin Le Grand                         {
58045fd3b9aSArmin Le Grand                             rIStm.Read( (char*)( pTmp32 = (sal_uInt32*) pBuf ), nAlignedWidth );
58145fd3b9aSArmin Le Grand 
58245fd3b9aSArmin Le Grand                             for( long nX = 0L; nX < nWidth; nX++ )
58345fd3b9aSArmin Le Grand                             {
58445fd3b9aSArmin Le Grand                                 aMask.GetColorAndAlphaFor32Bit( aColor, aAlpha, (sal_uInt8*) pTmp32++ );
58545fd3b9aSArmin Le Grand                                 rAcc.SetPixel( nY, nX, aColor );
58645fd3b9aSArmin Le Grand                                 pAccAlpha->SetPixelIndex(nY, nX, sal_uInt8(0xff) - aAlpha);
587c7a371deSArmin Le Grand                                 rAlphaUsed |= bool(0xff != aAlpha);
58845fd3b9aSArmin Le Grand                             }
58945fd3b9aSArmin Le Grand                         }
59045fd3b9aSArmin Le Grand                     }
59145fd3b9aSArmin Le Grand                     else
59245fd3b9aSArmin Le Grand                     {
59345fd3b9aSArmin Le Grand                         for( ; nCount--; nY += nI )
59445fd3b9aSArmin Le Grand                         {
59545fd3b9aSArmin Le Grand                             rIStm.Read( (char*)( pTmp32 = (sal_uInt32*) pBuf ), nAlignedWidth );
59645fd3b9aSArmin Le Grand 
59745fd3b9aSArmin Le Grand                             for( long nX = 0L; nX < nWidth; nX++ )
59845fd3b9aSArmin Le Grand                             {
59945fd3b9aSArmin Le Grand                                 aMask.GetColorFor32Bit( aColor, (sal_uInt8*) pTmp32++ );
60045fd3b9aSArmin Le Grand                                 rAcc.SetPixel( nY, nX, aColor );
60145fd3b9aSArmin Le Grand                             }
60245fd3b9aSArmin Le Grand                         }
60345fd3b9aSArmin Le Grand                     }
60445fd3b9aSArmin Le Grand 				}
60545fd3b9aSArmin Le Grand 			}
60645fd3b9aSArmin Le Grand 
60745fd3b9aSArmin Le Grand 			delete[] pBuf;
60845fd3b9aSArmin Le Grand 		}
60945fd3b9aSArmin Le Grand 	}
61045fd3b9aSArmin Le Grand 
61145fd3b9aSArmin Le Grand 	return( rIStm.GetError() == 0UL );
61245fd3b9aSArmin Le Grand }
61345fd3b9aSArmin Le Grand 
61445fd3b9aSArmin Le Grand bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLong nOffset )
61545fd3b9aSArmin Le Grand {
61645fd3b9aSArmin Le Grand 	DIBV5Header aHeader;
61745fd3b9aSArmin Le Grand 	const sal_uLong nStmPos = rIStm.Tell();
61845fd3b9aSArmin Le Grand 	bool bRet(false);
61945fd3b9aSArmin Le Grand 	bool bTopDown(false);
62045fd3b9aSArmin Le Grand 
62145fd3b9aSArmin Le Grand 	if(ImplReadDIBInfoHeader(rIStm, aHeader, bTopDown) && aHeader.nWidth && aHeader.nHeight && aHeader.nBitCount)
62245fd3b9aSArmin Le Grand 	{
6233aedac3eSJürgen Schmidt         if (aHeader.nSize > nOffset)
6243aedac3eSJürgen Schmidt         {
6253aedac3eSJürgen Schmidt             // Header size claims to extend into the image data.
6263aedac3eSJürgen Schmidt             // Looks like an error.
6273aedac3eSJürgen Schmidt             return false;
6283aedac3eSJürgen Schmidt         }
6293aedac3eSJürgen Schmidt 
63045fd3b9aSArmin Le Grand 		const sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount));
63145fd3b9aSArmin Le Grand 		const Size aSizePixel(aHeader.nWidth, aHeader.nHeight);
63245fd3b9aSArmin Le Grand 		BitmapPalette aDummyPal;
63345fd3b9aSArmin Le Grand 		Bitmap aNewBmp(aSizePixel, nBitCount, &aDummyPal);
63445fd3b9aSArmin Le Grand 		Bitmap aNewBmpAlpha;
63545fd3b9aSArmin Le Grand 		BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
63645fd3b9aSArmin Le Grand         BitmapWriteAccess* pAccAlpha = 0;
63745fd3b9aSArmin Le Grand         bool bAlphaPossible(pBmpAlpha && aHeader.nBitCount == 32);
63845fd3b9aSArmin Le Grand 
63945fd3b9aSArmin Le Grand         if(bAlphaPossible)
64045fd3b9aSArmin Le Grand         {
64145fd3b9aSArmin Le Grand             const bool bRedSet(0 != aHeader.nV5RedMask);
64245fd3b9aSArmin Le Grand             const bool bGreenSet(0 != aHeader.nV5GreenMask);
64345fd3b9aSArmin Le Grand             const bool bBlueSet(0 != aHeader.nV5BlueMask);
64445fd3b9aSArmin Le Grand 
64545fd3b9aSArmin Le Grand             // some clipboard entries have alpha mask on zero to say that there is
64645fd3b9aSArmin Le Grand             // no alpha; do only use this when the other masks are set. The MS docu
64745fd3b9aSArmin Le Grand             // says that that masks are only to be set when bV5Compression is set to
64845fd3b9aSArmin Le Grand             // BI_BITFIELDS, but there seem to exist a wild variety of usages...
64945fd3b9aSArmin Le Grand             if((bRedSet || bGreenSet || bBlueSet) && (0 == aHeader.nV5AlphaMask))
65045fd3b9aSArmin Le Grand             {
65145fd3b9aSArmin Le Grand                 bAlphaPossible = false;
65245fd3b9aSArmin Le Grand             }
65345fd3b9aSArmin Le Grand         }
65445fd3b9aSArmin Le Grand 
65545fd3b9aSArmin Le Grand         if(bAlphaPossible)
65645fd3b9aSArmin Le Grand         {
65745fd3b9aSArmin Le Grand             aNewBmpAlpha = Bitmap(aSizePixel, 8);
65845fd3b9aSArmin Le Grand             pAccAlpha = aNewBmpAlpha.AcquireWriteAccess();
65945fd3b9aSArmin Le Grand         }
66045fd3b9aSArmin Le Grand 
66145fd3b9aSArmin Le Grand 		if(pAcc)
66245fd3b9aSArmin Le Grand 		{
66345fd3b9aSArmin Le Grand 			sal_uInt16 nColors(0);
66445fd3b9aSArmin Le Grand 			SvStream* pIStm;
66545fd3b9aSArmin Le Grand 			SvMemoryStream* pMemStm = NULL;
66645fd3b9aSArmin Le Grand 			sal_uInt8* pData = NULL;
66745fd3b9aSArmin Le Grand 
66845fd3b9aSArmin Le Grand 			if(nBitCount <= 8)
66945fd3b9aSArmin Le Grand 			{
67045fd3b9aSArmin Le Grand 				if(aHeader.nColsUsed)
67145fd3b9aSArmin Le Grand                 {
67245fd3b9aSArmin Le Grand 					nColors = (sal_uInt16)aHeader.nColsUsed;
67345fd3b9aSArmin Le Grand                 }
67445fd3b9aSArmin Le Grand 				else
67545fd3b9aSArmin Le Grand                 {
67645fd3b9aSArmin Le Grand 					nColors = ( 1 << aHeader.nBitCount );
67745fd3b9aSArmin Le Grand                 }
67845fd3b9aSArmin Le Grand 			}
67945fd3b9aSArmin Le Grand 
68045fd3b9aSArmin Le Grand 			if(ZCOMPRESS == aHeader.nCompression)
68145fd3b9aSArmin Le Grand 			{
68245fd3b9aSArmin Le Grand 				ZCodec aCodec;
68345fd3b9aSArmin Le Grand 				sal_uInt32 nCodedSize(0);
68445fd3b9aSArmin Le Grand                 sal_uInt32  nUncodedSize(0);
68545fd3b9aSArmin Le Grand 				sal_uLong nCodedPos(0);
68645fd3b9aSArmin Le Grand 
68745fd3b9aSArmin Le Grand 				// read coding information
68845fd3b9aSArmin Le Grand 				rIStm >> nCodedSize >> nUncodedSize >> aHeader.nCompression;
68945fd3b9aSArmin Le Grand 				pData = (sal_uInt8*) rtl_allocateMemory( nUncodedSize );
69045fd3b9aSArmin Le Grand 
69145fd3b9aSArmin Le Grand 				// decode buffer
69245fd3b9aSArmin Le Grand 				nCodedPos = rIStm.Tell();
69345fd3b9aSArmin Le Grand 				aCodec.BeginCompression();
69445fd3b9aSArmin Le Grand 				aCodec.Read( rIStm, pData, nUncodedSize );
69545fd3b9aSArmin Le Grand 				aCodec.EndCompression();
69645fd3b9aSArmin Le Grand 
69745fd3b9aSArmin Le Grand 				// skip unread bytes from coded buffer
69845fd3b9aSArmin Le Grand 				rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
69945fd3b9aSArmin Le Grand 
70045fd3b9aSArmin Le Grand 				// set decoded bytes to memory stream,
70145fd3b9aSArmin Le Grand 				// from which we will read the bitmap data
70245fd3b9aSArmin Le Grand 				pIStm = pMemStm = new SvMemoryStream;
70345fd3b9aSArmin Le Grand 				pMemStm->SetBuffer( (char*) pData, nUncodedSize, false, nUncodedSize );
70445fd3b9aSArmin Le Grand 				nOffset = 0;
70545fd3b9aSArmin Le Grand 			}
70645fd3b9aSArmin Le Grand 			else
70745fd3b9aSArmin Le Grand             {
70845fd3b9aSArmin Le Grand 				pIStm = &rIStm;
70945fd3b9aSArmin Le Grand             }
71045fd3b9aSArmin Le Grand 
71145fd3b9aSArmin Le Grand 			// read palette
71245fd3b9aSArmin Le Grand 			if(nColors)
71345fd3b9aSArmin Le Grand 			{
71445fd3b9aSArmin Le Grand 				pAcc->SetPaletteEntryCount(nColors);
71545fd3b9aSArmin Le Grand 				ImplReadDIBPalette(*pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE);
71645fd3b9aSArmin Le Grand 			}
71745fd3b9aSArmin Le Grand 
71845fd3b9aSArmin Le Grand 			// read bits
719c7a371deSArmin Le Grand             bool bAlphaUsed(false);
720c7a371deSArmin Le Grand 
72145fd3b9aSArmin Le Grand 			if(!pIStm->GetError())
72245fd3b9aSArmin Le Grand 			{
72345fd3b9aSArmin Le Grand 				if(nOffset)
72445fd3b9aSArmin Le Grand                 {
72545fd3b9aSArmin Le Grand 					pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
72645fd3b9aSArmin Le Grand                 }
72745fd3b9aSArmin Le Grand 
728c7a371deSArmin Le Grand 				bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown, bAlphaUsed);
72945fd3b9aSArmin Le Grand 
73045fd3b9aSArmin Le Grand 				if(bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter)
73145fd3b9aSArmin Le Grand 				{
73245fd3b9aSArmin Le Grand 					MapMode aMapMode(
73345fd3b9aSArmin Le Grand                         MAP_MM,
73445fd3b9aSArmin Le Grand                         Point(),
73545fd3b9aSArmin Le Grand 						Fraction(1000, aHeader.nXPelsPerMeter),
73645fd3b9aSArmin Le Grand 						Fraction(1000, aHeader.nYPelsPerMeter));
73745fd3b9aSArmin Le Grand 
73845fd3b9aSArmin Le Grand 					aNewBmp.SetPrefMapMode(aMapMode);
73945fd3b9aSArmin Le Grand 					aNewBmp.SetPrefSize(Size(aHeader.nWidth, aHeader.nHeight));
74045fd3b9aSArmin Le Grand 				}
74145fd3b9aSArmin Le Grand 			}
74245fd3b9aSArmin Le Grand 
74345fd3b9aSArmin Le Grand 			if( pData )
74445fd3b9aSArmin Le Grand             {
74545fd3b9aSArmin Le Grand 				rtl_freeMemory(pData);
74645fd3b9aSArmin Le Grand             }
74745fd3b9aSArmin Le Grand 
74845fd3b9aSArmin Le Grand 			delete pMemStm;
74945fd3b9aSArmin Le Grand 			aNewBmp.ReleaseAccess(pAcc);
75045fd3b9aSArmin Le Grand 
75145fd3b9aSArmin Le Grand             if(bAlphaPossible)
75245fd3b9aSArmin Le Grand             {
75345fd3b9aSArmin Le Grand                 aNewBmpAlpha.ReleaseAccess(pAccAlpha);
754c7a371deSArmin Le Grand 
755c7a371deSArmin Le Grand                 if(!bAlphaUsed)
756c7a371deSArmin Le Grand                 {
757c7a371deSArmin Le Grand                     bAlphaPossible = false;
758c7a371deSArmin Le Grand                 }
75945fd3b9aSArmin Le Grand             }
76045fd3b9aSArmin Le Grand 
76145fd3b9aSArmin Le Grand 			if(bRet)
76245fd3b9aSArmin Le Grand             {
76345fd3b9aSArmin Le Grand                 rBmp = aNewBmp;
76445fd3b9aSArmin Le Grand 
76545fd3b9aSArmin Le Grand                 if(bAlphaPossible)
76645fd3b9aSArmin Le Grand                 {
76745fd3b9aSArmin Le Grand                     *pBmpAlpha = aNewBmpAlpha;
76845fd3b9aSArmin Le Grand                 }
76945fd3b9aSArmin Le Grand             }
77045fd3b9aSArmin Le Grand 		}
77145fd3b9aSArmin Le Grand 	}
77245fd3b9aSArmin Le Grand 
77345fd3b9aSArmin Le Grand 	return bRet;
77445fd3b9aSArmin Le Grand }
77545fd3b9aSArmin Le Grand 
77645fd3b9aSArmin Le Grand bool ImplReadDIBFileHeader( SvStream& rIStm, sal_uLong& rOffset )
77745fd3b9aSArmin Le Grand {
778*4e95292aSOliver-Rainer Wittmann     bool bRet = false;
77945fd3b9aSArmin Le Grand 
780*4e95292aSOliver-Rainer Wittmann     const sal_Int64 nSavedStreamPos( rIStm.Tell() );
781*4e95292aSOliver-Rainer Wittmann     const sal_Int64 nStreamLength( rIStm.Seek( STREAM_SEEK_TO_END ) );
782*4e95292aSOliver-Rainer Wittmann     rIStm.Seek( nSavedStreamPos );
7833aedac3eSJürgen Schmidt 
784*4e95292aSOliver-Rainer Wittmann     sal_uInt16 nTmp16 = 0;
785*4e95292aSOliver-Rainer Wittmann     rIStm >> nTmp16;
78645fd3b9aSArmin Le Grand 
787*4e95292aSOliver-Rainer Wittmann     if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
788*4e95292aSOliver-Rainer Wittmann     {
789*4e95292aSOliver-Rainer Wittmann         sal_uInt32 nTmp32;
790*4e95292aSOliver-Rainer Wittmann         if ( 0x4142 == nTmp16 )
791*4e95292aSOliver-Rainer Wittmann         {
792*4e95292aSOliver-Rainer Wittmann             rIStm.SeekRel( 12L );
793*4e95292aSOliver-Rainer Wittmann             rIStm >> nTmp16;
794*4e95292aSOliver-Rainer Wittmann             rIStm.SeekRel( 8L );
795*4e95292aSOliver-Rainer Wittmann             rIStm >> nTmp32;
796*4e95292aSOliver-Rainer Wittmann             rOffset = nTmp32 - 28UL;
797*4e95292aSOliver-Rainer Wittmann             bRet = ( 0x4D42 == nTmp16 );
798*4e95292aSOliver-Rainer Wittmann         }
799*4e95292aSOliver-Rainer Wittmann         else // 0x4D42 == nTmp16, 'MB' from BITMAPFILEHEADER
800*4e95292aSOliver-Rainer Wittmann         {
801*4e95292aSOliver-Rainer Wittmann             rIStm.SeekRel( 8L );        // we are on bfSize member of BITMAPFILEHEADER, forward to bfOffBits
802*4e95292aSOliver-Rainer Wittmann             rIStm >> nTmp32;            // read bfOffBits
803*4e95292aSOliver-Rainer Wittmann             rOffset = nTmp32 - 14UL;    // adapt offset by sizeof(BITMAPFILEHEADER)
804*4e95292aSOliver-Rainer Wittmann             bRet = ( rIStm.GetError() == 0UL );
805*4e95292aSOliver-Rainer Wittmann         }
8063aedac3eSJürgen Schmidt 
807*4e95292aSOliver-Rainer Wittmann         if ( rOffset >= nStreamLength )
8083aedac3eSJürgen Schmidt         {
8093aedac3eSJürgen Schmidt             // Offset claims that image starts past the end of the
8103aedac3eSJürgen Schmidt             // stream.  Unlikely.
8113aedac3eSJürgen Schmidt             rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
8123aedac3eSJürgen Schmidt             bRet = false;
8133aedac3eSJürgen Schmidt         }
814*4e95292aSOliver-Rainer Wittmann     }
815*4e95292aSOliver-Rainer Wittmann     else
816*4e95292aSOliver-Rainer Wittmann         rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
81745fd3b9aSArmin Le Grand 
818*4e95292aSOliver-Rainer Wittmann     return bRet;
81945fd3b9aSArmin Le Grand }
82045fd3b9aSArmin Le Grand 
82145fd3b9aSArmin Le Grand bool ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
82245fd3b9aSArmin Le Grand {
82345fd3b9aSArmin Le Grand 	const sal_uInt16	nColors = rAcc.GetPaletteEntryCount();
82445fd3b9aSArmin Le Grand 	const sal_uLong 	nPalSize = nColors * 4UL;
82545fd3b9aSArmin Le Grand 	sal_uInt8*			pEntries = new sal_uInt8[ nPalSize ];
82645fd3b9aSArmin Le Grand 	sal_uInt8*			pTmpEntry = pEntries;
82745fd3b9aSArmin Le Grand 	BitmapColor 	aPalColor;
82845fd3b9aSArmin Le Grand 
82945fd3b9aSArmin Le Grand 	for( sal_uInt16 i = 0; i < nColors; i++ )
83045fd3b9aSArmin Le Grand 	{
83145fd3b9aSArmin Le Grand 		const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
83245fd3b9aSArmin Le Grand 
83345fd3b9aSArmin Le Grand 		*pTmpEntry++ = rPalColor.GetBlue();
83445fd3b9aSArmin Le Grand 		*pTmpEntry++ = rPalColor.GetGreen();
83545fd3b9aSArmin Le Grand 		*pTmpEntry++ = rPalColor.GetRed();
83645fd3b9aSArmin Le Grand 		*pTmpEntry++ = 0;
83745fd3b9aSArmin Le Grand 	}
83845fd3b9aSArmin Le Grand 
83945fd3b9aSArmin Le Grand 	rOStm.Write( pEntries, nPalSize );
84045fd3b9aSArmin Le Grand 	delete[] pEntries;
84145fd3b9aSArmin Le Grand 
84245fd3b9aSArmin Le Grand 	return( rOStm.GetError() == 0UL );
84345fd3b9aSArmin Le Grand }
84445fd3b9aSArmin Le Grand 
84545fd3b9aSArmin Le Grand bool ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, bool bRLE4 )
84645fd3b9aSArmin Le Grand {
84745fd3b9aSArmin Le Grand 	const sal_uLong nWidth = rAcc.Width();
84845fd3b9aSArmin Le Grand 	const sal_uLong nHeight = rAcc.Height();
84945fd3b9aSArmin Le Grand 	sal_uLong		nX;
85045fd3b9aSArmin Le Grand 	sal_uLong		nSaveIndex;
85145fd3b9aSArmin Le Grand 	sal_uLong		nCount;
85245fd3b9aSArmin Le Grand 	sal_uLong		nBufCount;
85345fd3b9aSArmin Le Grand 	sal_uInt8*		pBuf = new sal_uInt8[ ( nWidth << 1 ) + 2 ];
85445fd3b9aSArmin Le Grand 	sal_uInt8*		pTmp;
85545fd3b9aSArmin Le Grand 	sal_uInt8		cPix;
85645fd3b9aSArmin Le Grand 	sal_uInt8		cLast;
85745fd3b9aSArmin Le Grand 	bool		bFound;
85845fd3b9aSArmin Le Grand 
85945fd3b9aSArmin Le Grand 	for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
86045fd3b9aSArmin Le Grand 	{
86145fd3b9aSArmin Le Grand 		pTmp = pBuf;
86245fd3b9aSArmin Le Grand 		nX = nBufCount = 0UL;
86345fd3b9aSArmin Le Grand 
86445fd3b9aSArmin Le Grand 		while( nX < nWidth )
86545fd3b9aSArmin Le Grand 		{
86645fd3b9aSArmin Le Grand 			nCount = 1L;
86745fd3b9aSArmin Le Grand 			cPix = rAcc.GetPixelIndex( nY, nX++ );
86845fd3b9aSArmin Le Grand 
86945fd3b9aSArmin Le Grand 			while( ( nX < nWidth ) && ( nCount < 255L )
87045fd3b9aSArmin Le Grand 				&& ( cPix == rAcc.GetPixelIndex( nY, nX ) ) )
87145fd3b9aSArmin Le Grand 			{
87245fd3b9aSArmin Le Grand 				nX++;
87345fd3b9aSArmin Le Grand 				nCount++;
87445fd3b9aSArmin Le Grand 			}
87545fd3b9aSArmin Le Grand 
87645fd3b9aSArmin Le Grand 			if ( nCount > 1 )
87745fd3b9aSArmin Le Grand 			{
87845fd3b9aSArmin Le Grand 				*pTmp++ = (sal_uInt8) nCount;
87945fd3b9aSArmin Le Grand 				*pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
88045fd3b9aSArmin Le Grand 				nBufCount += 2;
88145fd3b9aSArmin Le Grand 			}
88245fd3b9aSArmin Le Grand 			else
88345fd3b9aSArmin Le Grand 			{
88445fd3b9aSArmin Le Grand 				cLast = cPix;
88545fd3b9aSArmin Le Grand 				nSaveIndex = nX - 1UL;
88645fd3b9aSArmin Le Grand 				bFound = false;
88745fd3b9aSArmin Le Grand 
88845fd3b9aSArmin Le Grand 				while( ( nX < nWidth ) && ( nCount < 256L )
88945fd3b9aSArmin Le Grand 					&& ( cPix = rAcc.GetPixelIndex( nY, nX ) ) != cLast )
89045fd3b9aSArmin Le Grand 				{
89145fd3b9aSArmin Le Grand 					nX++; nCount++;
89245fd3b9aSArmin Le Grand 					cLast = cPix;
89345fd3b9aSArmin Le Grand 					bFound = true;
89445fd3b9aSArmin Le Grand 				}
89545fd3b9aSArmin Le Grand 
89645fd3b9aSArmin Le Grand 				if ( bFound )
89745fd3b9aSArmin Le Grand 					nX--;
89845fd3b9aSArmin Le Grand 
89945fd3b9aSArmin Le Grand 				if ( nCount > 3 )
90045fd3b9aSArmin Le Grand 				{
90145fd3b9aSArmin Le Grand 					*pTmp++ = 0;
90245fd3b9aSArmin Le Grand 					*pTmp++ = (sal_uInt8) --nCount;
90345fd3b9aSArmin Le Grand 
90445fd3b9aSArmin Le Grand 					if( bRLE4 )
90545fd3b9aSArmin Le Grand 					{
90645fd3b9aSArmin Le Grand 						for ( sal_uLong i = 0; i < nCount; i++, pTmp++ )
90745fd3b9aSArmin Le Grand 						{
90845fd3b9aSArmin Le Grand 							*pTmp = rAcc.GetPixelIndex( nY, nSaveIndex++ ) << 4;
90945fd3b9aSArmin Le Grand 
91045fd3b9aSArmin Le Grand 							if ( ++i < nCount )
91145fd3b9aSArmin Le Grand 								*pTmp |= rAcc.GetPixelIndex( nY, nSaveIndex++ );
91245fd3b9aSArmin Le Grand 						}
91345fd3b9aSArmin Le Grand 
91445fd3b9aSArmin Le Grand 						nCount = ( nCount + 1 ) >> 1;
91545fd3b9aSArmin Le Grand 					}
91645fd3b9aSArmin Le Grand 					else
91745fd3b9aSArmin Le Grand 					{
91845fd3b9aSArmin Le Grand 						for( sal_uLong i = 0UL; i < nCount; i++ )
91945fd3b9aSArmin Le Grand 							*pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex++ );
92045fd3b9aSArmin Le Grand 					}
92145fd3b9aSArmin Le Grand 
92245fd3b9aSArmin Le Grand 					if ( nCount & 1 )
92345fd3b9aSArmin Le Grand 					{
92445fd3b9aSArmin Le Grand 						*pTmp++ = 0;
92545fd3b9aSArmin Le Grand 						nBufCount += ( nCount + 3 );
92645fd3b9aSArmin Le Grand 					}
92745fd3b9aSArmin Le Grand 					else
92845fd3b9aSArmin Le Grand 						nBufCount += ( nCount + 2 );
92945fd3b9aSArmin Le Grand 				}
93045fd3b9aSArmin Le Grand 				else
93145fd3b9aSArmin Le Grand 				{
93245fd3b9aSArmin Le Grand 					*pTmp++ = 1;
93345fd3b9aSArmin Le Grand 					*pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex ) << (bRLE4 ? 4 : 0);
93445fd3b9aSArmin Le Grand 
93545fd3b9aSArmin Le Grand 					if ( nCount == 3 )
93645fd3b9aSArmin Le Grand 					{
93745fd3b9aSArmin Le Grand 						*pTmp++ = 1;
93845fd3b9aSArmin Le Grand 						*pTmp++ = rAcc.GetPixelIndex( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
93945fd3b9aSArmin Le Grand 						nBufCount += 4;
94045fd3b9aSArmin Le Grand 					}
94145fd3b9aSArmin Le Grand 					else
94245fd3b9aSArmin Le Grand 						nBufCount += 2;
94345fd3b9aSArmin Le Grand 				}
94445fd3b9aSArmin Le Grand 			}
94545fd3b9aSArmin Le Grand 		}
94645fd3b9aSArmin Le Grand 
94745fd3b9aSArmin Le Grand 		pBuf[ nBufCount++ ] = 0;
94845fd3b9aSArmin Le Grand 		pBuf[ nBufCount++ ] = 0;
94945fd3b9aSArmin Le Grand 
95045fd3b9aSArmin Le Grand 		rOStm.Write( pBuf, nBufCount );
95145fd3b9aSArmin Le Grand 	}
95245fd3b9aSArmin Le Grand 
95345fd3b9aSArmin Le Grand 	rOStm << (sal_uInt8) 0;
95445fd3b9aSArmin Le Grand 	rOStm << (sal_uInt8) 1;
95545fd3b9aSArmin Le Grand 
95645fd3b9aSArmin Le Grand 	delete[] pBuf;
95745fd3b9aSArmin Le Grand 
95845fd3b9aSArmin Le Grand 	return( rOStm.GetError() == 0UL );
95945fd3b9aSArmin Le Grand }
96045fd3b9aSArmin Le Grand 
96145fd3b9aSArmin Le Grand bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, sal_uLong nCompression, sal_uInt32& rImageSize)
96245fd3b9aSArmin Le Grand {
96345fd3b9aSArmin Le Grand 	if(!pAccAlpha && BITFIELDS == nCompression)
96445fd3b9aSArmin Le Grand 	{
96545fd3b9aSArmin Le Grand 		const ColorMask&	rMask = rAcc.GetColorMask();
96645fd3b9aSArmin Le Grand 		SVBT32				aVal32;
96745fd3b9aSArmin Le Grand 
96845fd3b9aSArmin Le Grand 		UInt32ToSVBT32( rMask.GetRedMask(), aVal32 );
96945fd3b9aSArmin Le Grand 		rOStm.Write( (sal_uInt8*) aVal32, 4UL );
97045fd3b9aSArmin Le Grand 
97145fd3b9aSArmin Le Grand 		UInt32ToSVBT32( rMask.GetGreenMask(), aVal32 );
97245fd3b9aSArmin Le Grand 		rOStm.Write( (sal_uInt8*) aVal32, 4UL );
97345fd3b9aSArmin Le Grand 
97445fd3b9aSArmin Le Grand 		UInt32ToSVBT32( rMask.GetBlueMask(), aVal32 );
97545fd3b9aSArmin Le Grand 		rOStm.Write( (sal_uInt8*) aVal32, 4UL );
97645fd3b9aSArmin Le Grand 
97745fd3b9aSArmin Le Grand 		rImageSize = rOStm.Tell();
97845fd3b9aSArmin Le Grand 
97945fd3b9aSArmin Le Grand 		if( rAcc.IsBottomUp() )
98045fd3b9aSArmin Le Grand 			rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
98145fd3b9aSArmin Le Grand 		else
98245fd3b9aSArmin Le Grand 		{
98345fd3b9aSArmin Le Grand 			for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
98445fd3b9aSArmin Le Grand 				rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
98545fd3b9aSArmin Le Grand 		}
98645fd3b9aSArmin Le Grand 	}
98745fd3b9aSArmin Le Grand 	else if(!pAccAlpha && ((RLE_4 == nCompression) || (RLE_8 == nCompression)))
98845fd3b9aSArmin Le Grand 	{
98945fd3b9aSArmin Le Grand 		rImageSize = rOStm.Tell();
99045fd3b9aSArmin Le Grand 		ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
99145fd3b9aSArmin Le Grand 	}
99245fd3b9aSArmin Le Grand 	else if(!nCompression)
99345fd3b9aSArmin Le Grand 	{
99445fd3b9aSArmin Le Grand         // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are not
99545fd3b9aSArmin Le Grand         // handled properly below (would have to set color masks, and
99645fd3b9aSArmin Le Grand         // nCompression=BITFIELDS - but color mask is not set for
99745fd3b9aSArmin Le Grand         // formats != *_TC_*). Note that this very problem might cause
99845fd3b9aSArmin Le Grand         // trouble at other places - the introduction of 32 bit RGBA
99945fd3b9aSArmin Le Grand         // bitmaps is relatively recent.
100045fd3b9aSArmin Le Grand         // #i59239# discretize bitcount for aligned width to 1,4,8,24
100145fd3b9aSArmin Le Grand         // (other cases are not written below)
100245fd3b9aSArmin Le Grand         const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
100345fd3b9aSArmin Le Grand         const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * nBitCount));
100445fd3b9aSArmin Le Grand 		bool bNative(false);
100545fd3b9aSArmin Le Grand 
100645fd3b9aSArmin Le Grand 		switch(rAcc.GetScanlineFormat())
100745fd3b9aSArmin Le Grand 		{
100845fd3b9aSArmin Le Grand 			case( BMP_FORMAT_1BIT_MSB_PAL ):
100945fd3b9aSArmin Le Grand 			case( BMP_FORMAT_4BIT_MSN_PAL ):
101045fd3b9aSArmin Le Grand 			case( BMP_FORMAT_8BIT_PAL ):
101145fd3b9aSArmin Le Grand 			case( BMP_FORMAT_24BIT_TC_BGR ):
101245fd3b9aSArmin Le Grand 			{
101345fd3b9aSArmin Le Grand 				if(!pAccAlpha && rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth))
101445fd3b9aSArmin Le Grand                 {
101545fd3b9aSArmin Le Grand 					bNative = true;
101645fd3b9aSArmin Le Grand                 }
101745fd3b9aSArmin Le Grand 
101845fd3b9aSArmin Le Grand                 break;
101945fd3b9aSArmin Le Grand 			}
102045fd3b9aSArmin Le Grand 
102145fd3b9aSArmin Le Grand 			default:
102245fd3b9aSArmin Le Grand             {
102345fd3b9aSArmin Le Grand                 break;
102445fd3b9aSArmin Le Grand             }
102545fd3b9aSArmin Le Grand 		}
102645fd3b9aSArmin Le Grand 
102745fd3b9aSArmin Le Grand 		rImageSize = rOStm.Tell();
102845fd3b9aSArmin Le Grand 
102945fd3b9aSArmin Le Grand 		if(bNative)
103045fd3b9aSArmin Le Grand         {
103145fd3b9aSArmin Le Grand 			rOStm.Write(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height());
103245fd3b9aSArmin Le Grand         }
103345fd3b9aSArmin Le Grand 		else
103445fd3b9aSArmin Le Grand 		{
103545fd3b9aSArmin Le Grand 			const long nWidth(rAcc.Width());
103645fd3b9aSArmin Le Grand 			const long nHeight(rAcc.Height());
103745fd3b9aSArmin Le Grand 			sal_uInt8* pBuf = new sal_uInt8[ nAlignedWidth ];
103845fd3b9aSArmin Le Grand 			sal_uInt8* pTmp(0);
103945fd3b9aSArmin Le Grand 			sal_uInt8 cTmp(0);
104045fd3b9aSArmin Le Grand 
104145fd3b9aSArmin Le Grand 			switch( nBitCount )
104245fd3b9aSArmin Le Grand 			{
104345fd3b9aSArmin Le Grand 				case( 1 ):
104445fd3b9aSArmin Le Grand 				{
104545fd3b9aSArmin Le Grand 					for( long nY = nHeight - 1; nY >= 0L; nY-- )
104645fd3b9aSArmin Le Grand 					{
104745fd3b9aSArmin Le Grand 						pTmp = pBuf;
104845fd3b9aSArmin Le Grand 						cTmp = 0;
104945fd3b9aSArmin Le Grand 
105045fd3b9aSArmin Le Grand 						for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
105145fd3b9aSArmin Le Grand 						{
105245fd3b9aSArmin Le Grand 							if( !nShift )
105345fd3b9aSArmin Le Grand 							{
105445fd3b9aSArmin Le Grand 								nShift = 8L;
105545fd3b9aSArmin Le Grand 								*pTmp++ = cTmp;
105645fd3b9aSArmin Le Grand 								cTmp = 0;
105745fd3b9aSArmin Le Grand 							}
105845fd3b9aSArmin Le Grand 
105945fd3b9aSArmin Le Grand 							cTmp |= rAcc.GetPixelIndex( nY, nX ) << --nShift;
106045fd3b9aSArmin Le Grand 						}
106145fd3b9aSArmin Le Grand 
106245fd3b9aSArmin Le Grand 						*pTmp = cTmp;
106345fd3b9aSArmin Le Grand 						rOStm.Write( pBuf, nAlignedWidth );
106445fd3b9aSArmin Le Grand 					}
106545fd3b9aSArmin Le Grand 				}
106645fd3b9aSArmin Le Grand 				break;
106745fd3b9aSArmin Le Grand 
106845fd3b9aSArmin Le Grand 				case( 4 ):
106945fd3b9aSArmin Le Grand 				{
107045fd3b9aSArmin Le Grand 					for( long nY = nHeight - 1; nY >= 0L; nY-- )
107145fd3b9aSArmin Le Grand 					{
107245fd3b9aSArmin Le Grand 						pTmp = pBuf;
107345fd3b9aSArmin Le Grand 						cTmp = 0;
107445fd3b9aSArmin Le Grand 
107545fd3b9aSArmin Le Grand 						for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
107645fd3b9aSArmin Le Grand 						{
107745fd3b9aSArmin Le Grand 							if( !nShift )
107845fd3b9aSArmin Le Grand 							{
107945fd3b9aSArmin Le Grand 								nShift = 2L;
108045fd3b9aSArmin Le Grand 								*pTmp++ = cTmp;
108145fd3b9aSArmin Le Grand 								cTmp = 0;
108245fd3b9aSArmin Le Grand 							}
108345fd3b9aSArmin Le Grand 
108445fd3b9aSArmin Le Grand 							cTmp |= rAcc.GetPixelIndex( nY, nX ) << ( --nShift << 2L );
108545fd3b9aSArmin Le Grand 						}
108645fd3b9aSArmin Le Grand 						*pTmp = cTmp;
108745fd3b9aSArmin Le Grand 						rOStm.Write( pBuf, nAlignedWidth );
108845fd3b9aSArmin Le Grand 					}
108945fd3b9aSArmin Le Grand 				}
109045fd3b9aSArmin Le Grand 				break;
109145fd3b9aSArmin Le Grand 
109245fd3b9aSArmin Le Grand 				case( 8 ):
109345fd3b9aSArmin Le Grand 				{
109445fd3b9aSArmin Le Grand 					for( long nY = nHeight - 1; nY >= 0L; nY-- )
109545fd3b9aSArmin Le Grand 					{
109645fd3b9aSArmin Le Grand 						pTmp = pBuf;
109745fd3b9aSArmin Le Grand 
109845fd3b9aSArmin Le Grand 						for( long nX = 0L; nX < nWidth; nX++ )
109945fd3b9aSArmin Le Grand 							*pTmp++ = rAcc.GetPixelIndex( nY, nX );
110045fd3b9aSArmin Le Grand 
110145fd3b9aSArmin Le Grand 						rOStm.Write( pBuf, nAlignedWidth );
110245fd3b9aSArmin Le Grand 					}
110345fd3b9aSArmin Le Grand 				}
110445fd3b9aSArmin Le Grand 				break;
110545fd3b9aSArmin Le Grand 
110645fd3b9aSArmin Le Grand                 // #i59239# fallback to 24 bit format, if bitcount is non-default
110745fd3b9aSArmin Le Grand                 default:
110845fd3b9aSArmin Le Grand                     // FALLTHROUGH intended
110945fd3b9aSArmin Le Grand 				case( 24 ):
111045fd3b9aSArmin Le Grand 				{
111145fd3b9aSArmin Le Grand 					BitmapColor aPixelColor;
111245fd3b9aSArmin Le Grand                     const bool bWriteAlpha(32 == nBitCount && pAccAlpha);
111345fd3b9aSArmin Le Grand 
111445fd3b9aSArmin Le Grand 					for( long nY = nHeight - 1; nY >= 0L; nY-- )
111545fd3b9aSArmin Le Grand 					{
111645fd3b9aSArmin Le Grand 						pTmp = pBuf;
111745fd3b9aSArmin Le Grand 
111845fd3b9aSArmin Le Grand 						for( long nX = 0L; nX < nWidth; nX++ )
111945fd3b9aSArmin Le Grand 						{
112045fd3b9aSArmin Le Grand                             // when alpha is used, this may be non-24bit main bitmap, so use GetColor
112145fd3b9aSArmin Le Grand                             // instead of GetPixel to ensure RGB value
112245fd3b9aSArmin Le Grand                             aPixelColor = rAcc.GetColor( nY, nX );
112345fd3b9aSArmin Le Grand 
112445fd3b9aSArmin Le Grand 							*pTmp++ = aPixelColor.GetBlue();
112545fd3b9aSArmin Le Grand 							*pTmp++ = aPixelColor.GetGreen();
112645fd3b9aSArmin Le Grand 							*pTmp++ = aPixelColor.GetRed();
112745fd3b9aSArmin Le Grand 
112845fd3b9aSArmin Le Grand                             if(bWriteAlpha)
112945fd3b9aSArmin Le Grand                             {
113045fd3b9aSArmin Le Grand                                 if(pAccAlpha)
113145fd3b9aSArmin Le Grand                                 {
113245fd3b9aSArmin Le Grand                                     *pTmp++ = (sal_uInt8)0xff - (sal_uInt8)pAccAlpha->GetPixelIndex( nY, nX );
113345fd3b9aSArmin Le Grand                                 }
113445fd3b9aSArmin Le Grand                                 else
113545fd3b9aSArmin Le Grand                                 {
113645fd3b9aSArmin Le Grand                                     *pTmp++ = (sal_uInt8)0xff;
113745fd3b9aSArmin Le Grand                                 }
113845fd3b9aSArmin Le Grand                             }
113945fd3b9aSArmin Le Grand 						}
114045fd3b9aSArmin Le Grand 
114145fd3b9aSArmin Le Grand 						rOStm.Write( pBuf, nAlignedWidth );
114245fd3b9aSArmin Le Grand 					}
114345fd3b9aSArmin Le Grand 				}
114445fd3b9aSArmin Le Grand 				break;
114545fd3b9aSArmin Le Grand 			}
114645fd3b9aSArmin Le Grand 
114745fd3b9aSArmin Le Grand 			delete[] pBuf;
114845fd3b9aSArmin Le Grand 		}
114945fd3b9aSArmin Le Grand 	}
115045fd3b9aSArmin Le Grand 
115145fd3b9aSArmin Le Grand 	rImageSize = rOStm.Tell() - rImageSize;
115245fd3b9aSArmin Le Grand 
115345fd3b9aSArmin Le Grand 	return (!rOStm.GetError());
115445fd3b9aSArmin Le Grand }
115545fd3b9aSArmin Le Grand 
115645fd3b9aSArmin Le Grand bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, bool bCompressed)
115745fd3b9aSArmin Le Grand {
115845fd3b9aSArmin Le Grand 	const MapMode aMapPixel(MAP_PIXEL);
115945fd3b9aSArmin Le Grand 	DIBV5Header aHeader;
116045fd3b9aSArmin Le Grand 	sal_uLong nImageSizePos(0);
116145fd3b9aSArmin Le Grand 	sal_uLong nEndPos(0);
116245fd3b9aSArmin Le Grand 	sal_uInt32 nCompression(COMPRESS_NONE);
116345fd3b9aSArmin Le Grand 	bool bRet(false);
116445fd3b9aSArmin Le Grand 
116545fd3b9aSArmin Le Grand 	aHeader.nSize = pAccAlpha ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE; // size dependent on CF_DIB type to use
116645fd3b9aSArmin Le Grand 	aHeader.nWidth = rAcc.Width();
116745fd3b9aSArmin Le Grand 	aHeader.nHeight = rAcc.Height();
116845fd3b9aSArmin Le Grand 	aHeader.nPlanes = 1;
116945fd3b9aSArmin Le Grand 
117045fd3b9aSArmin Le Grand     if(!pAccAlpha && isBitfieldCompression(rAcc.GetScanlineFormat()))
117145fd3b9aSArmin Le Grand 	{
117245fd3b9aSArmin Le Grand         aHeader.nBitCount = (BMP_FORMAT_16BIT_TC_LSB_MASK == rAcc.GetScanlineFormat()) ? 16 : 32;
117345fd3b9aSArmin Le Grand         aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
117445fd3b9aSArmin Le Grand         nCompression = BITFIELDS;
117545fd3b9aSArmin Le Grand     }
117645fd3b9aSArmin Le Grand     else
117745fd3b9aSArmin Le Grand     {
117845fd3b9aSArmin Le Grand         // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are
117945fd3b9aSArmin Le Grand         // not handled properly below (would have to set color
118045fd3b9aSArmin Le Grand         // masks, and nCompression=BITFIELDS - but color mask is
118145fd3b9aSArmin Le Grand         // not set for formats != *_TC_*). Note that this very
118245fd3b9aSArmin Le Grand         // problem might cause trouble at other places - the
118345fd3b9aSArmin Le Grand         // introduction of 32 bit RGBA bitmaps is relatively
118445fd3b9aSArmin Le Grand         // recent.
118545fd3b9aSArmin Le Grand         // #i59239# discretize bitcount to 1,4,8,24 (other cases
118645fd3b9aSArmin Le Grand         // are not written below)
118745fd3b9aSArmin Le Grand         const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
118845fd3b9aSArmin Le Grand         aHeader.nBitCount = nBitCount;
118945fd3b9aSArmin Le Grand         aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount);
119045fd3b9aSArmin Le Grand 
119145fd3b9aSArmin Le Grand         if(bCompressed)
119245fd3b9aSArmin Le Grand         {
119345fd3b9aSArmin Le Grand             if(4 == nBitCount)
119445fd3b9aSArmin Le Grand             {
119545fd3b9aSArmin Le Grand                 nCompression = RLE_4;
119645fd3b9aSArmin Le Grand             }
119745fd3b9aSArmin Le Grand             else if(8 == nBitCount)
119845fd3b9aSArmin Le Grand             {
119945fd3b9aSArmin Le Grand                 nCompression = RLE_8;
120045fd3b9aSArmin Le Grand             }
120145fd3b9aSArmin Le Grand         }
120245fd3b9aSArmin Le Grand 	}
120345fd3b9aSArmin Le Grand 
120445fd3b9aSArmin Le Grand 	if((rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP) && (rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40))
120545fd3b9aSArmin Le Grand 	{
120645fd3b9aSArmin Le Grand 		aHeader.nCompression = ZCOMPRESS;
120745fd3b9aSArmin Le Grand 	}
120845fd3b9aSArmin Le Grand 	else
120945fd3b9aSArmin Le Grand     {
121045fd3b9aSArmin Le Grand 		aHeader.nCompression = nCompression;
121145fd3b9aSArmin Le Grand     }
121245fd3b9aSArmin Le Grand 
121345fd3b9aSArmin Le Grand 	if(rBitmap.GetPrefSize().Width() && rBitmap.GetPrefSize().Height() && (rBitmap.GetPrefMapMode() != aMapPixel))
121445fd3b9aSArmin Le Grand 	{
121545fd3b9aSArmin Le Grand         // #i48108# Try to recover xpels/ypels as previously stored on
121645fd3b9aSArmin Le Grand         // disk. The problem with just converting maPrefSize to 100th
121745fd3b9aSArmin Le Grand         // mm and then relating that to the bitmap pixel size is that
121845fd3b9aSArmin Le Grand         // MapMode is integer-based, and suffers from roundoffs,
121945fd3b9aSArmin Le Grand         // especially if maPrefSize is small. Trying to circumvent
122045fd3b9aSArmin Le Grand         // that by performing part of the math in floating point.
122145fd3b9aSArmin Le Grand         const Size aScale100000(OutputDevice::LogicToLogic(Size(100000L, 100000L), MAP_100TH_MM, rBitmap.GetPrefMapMode()));
122245fd3b9aSArmin Le Grand         const double fBmpWidthM((double)rBitmap.GetPrefSize().Width() / aScale100000.Width());
122345fd3b9aSArmin Le Grand         const double fBmpHeightM((double)rBitmap.GetPrefSize().Height() / aScale100000.Height());
122445fd3b9aSArmin Le Grand 
122545fd3b9aSArmin Le Grand         if(!basegfx::fTools::equalZero(fBmpWidthM) && !basegfx::fTools::equalZero(fBmpHeightM))
122645fd3b9aSArmin Le Grand         {
122745fd3b9aSArmin Le Grand             aHeader.nXPelsPerMeter = basegfx::fround(rAcc.Width() / fabs(fBmpWidthM));
122845fd3b9aSArmin Le Grand             aHeader.nYPelsPerMeter = basegfx::fround(rAcc.Height() / fabs(fBmpHeightM));
122945fd3b9aSArmin Le Grand         }
123045fd3b9aSArmin Le Grand 	}
123145fd3b9aSArmin Le Grand 
123245fd3b9aSArmin Le Grand 	aHeader.nColsUsed = ((!pAccAlpha && aHeader.nBitCount <= 8) ? rAcc.GetPaletteEntryCount() : 0);
123345fd3b9aSArmin Le Grand 	aHeader.nColsImportant = 0;
123445fd3b9aSArmin Le Grand 
123545fd3b9aSArmin Le Grand 	rOStm << aHeader.nSize;
123645fd3b9aSArmin Le Grand 	rOStm << aHeader.nWidth;
123745fd3b9aSArmin Le Grand 	rOStm << aHeader.nHeight;
123845fd3b9aSArmin Le Grand 	rOStm << aHeader.nPlanes;
123945fd3b9aSArmin Le Grand 	rOStm << aHeader.nBitCount;
124045fd3b9aSArmin Le Grand 	rOStm << aHeader.nCompression;
124145fd3b9aSArmin Le Grand 
124245fd3b9aSArmin Le Grand     nImageSizePos = rOStm.Tell();
124345fd3b9aSArmin Le Grand 	rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
124445fd3b9aSArmin Le Grand 
124545fd3b9aSArmin Le Grand     rOStm << aHeader.nXPelsPerMeter;
124645fd3b9aSArmin Le Grand 	rOStm << aHeader.nYPelsPerMeter;
124745fd3b9aSArmin Le Grand 	rOStm << aHeader.nColsUsed;
124845fd3b9aSArmin Le Grand 	rOStm << aHeader.nColsImportant;
124945fd3b9aSArmin Le Grand 
125045fd3b9aSArmin Le Grand     if(pAccAlpha) // only write DIBV5 when asked to do so
125145fd3b9aSArmin Le Grand     {
125245fd3b9aSArmin Le Grand         aHeader.nV5CSType = 0x57696E20; // LCS_WINDOWS_COLOR_SPACE
1253c7a371deSArmin Le Grand         aHeader.nV5Intent = 0x00000004; // LCS_GM_IMAGES
125445fd3b9aSArmin Le Grand 
125545fd3b9aSArmin Le Grand         rOStm << aHeader.nV5RedMask;
125645fd3b9aSArmin Le Grand         rOStm << aHeader.nV5GreenMask;
125745fd3b9aSArmin Le Grand         rOStm << aHeader.nV5BlueMask;
125845fd3b9aSArmin Le Grand         rOStm << aHeader.nV5AlphaMask;
125945fd3b9aSArmin Le Grand         rOStm << aHeader.nV5CSType;
126045fd3b9aSArmin Le Grand 
126145fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzX;
126245fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzY;
126345fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzZ;
126445fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzX;
126545fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzY;
126645fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzZ;
126745fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzX;
126845fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzY;
126945fd3b9aSArmin Le Grand         rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzZ;
127045fd3b9aSArmin Le Grand 
127145fd3b9aSArmin Le Grand         rOStm << aHeader.nV5GammaRed;
127245fd3b9aSArmin Le Grand         rOStm << aHeader.nV5GammaGreen;
127345fd3b9aSArmin Le Grand         rOStm << aHeader.nV5GammaBlue;
127445fd3b9aSArmin Le Grand         rOStm << aHeader.nV5Intent;
127545fd3b9aSArmin Le Grand         rOStm << aHeader.nV5ProfileData;
127645fd3b9aSArmin Le Grand         rOStm << aHeader.nV5ProfileSize;
127745fd3b9aSArmin Le Grand         rOStm << aHeader.nV5Reserved;
127845fd3b9aSArmin Le Grand     }
127945fd3b9aSArmin Le Grand 
128045fd3b9aSArmin Le Grand 	if(ZCOMPRESS == aHeader.nCompression)
128145fd3b9aSArmin Le Grand 	{
128245fd3b9aSArmin Le Grand 		ZCodec aCodec;
128345fd3b9aSArmin Le Grand 		SvMemoryStream aMemStm(aHeader.nSizeImage + 4096, 65535);
128445fd3b9aSArmin Le Grand 		sal_uLong nCodedPos(rOStm.Tell());
128545fd3b9aSArmin Le Grand         sal_uLong nLastPos(0);
128645fd3b9aSArmin Le Grand 		sal_uInt32 nCodedSize(0);
128745fd3b9aSArmin Le Grand         sal_uInt32 nUncodedSize(0);
128845fd3b9aSArmin Le Grand 
128945fd3b9aSArmin Le Grand 		// write uncoded data palette
129045fd3b9aSArmin Le Grand 		if(aHeader.nColsUsed)
129145fd3b9aSArmin Le Grand         {
129245fd3b9aSArmin Le Grand 			ImplWriteDIBPalette(aMemStm, rAcc);
129345fd3b9aSArmin Le Grand         }
129445fd3b9aSArmin Le Grand 
129545fd3b9aSArmin Le Grand 		// write uncoded bits
129645fd3b9aSArmin Le Grand 		bRet = ImplWriteDIBBits(aMemStm, rAcc, pAccAlpha, nCompression, aHeader.nSizeImage);
129745fd3b9aSArmin Le Grand 
129845fd3b9aSArmin Le Grand 		// get uncoded size
129945fd3b9aSArmin Le Grand 		nUncodedSize = aMemStm.Tell();
130045fd3b9aSArmin Le Grand 
130145fd3b9aSArmin Le Grand 		// seek over compress info
130245fd3b9aSArmin Le Grand 		rOStm.SeekRel(12);
130345fd3b9aSArmin Le Grand 
130445fd3b9aSArmin Le Grand 		// write compressed data
130545fd3b9aSArmin Le Grand 		aCodec.BeginCompression(3);
130645fd3b9aSArmin Le Grand 		aCodec.Write(rOStm, (sal_uInt8*)aMemStm.GetData(), nUncodedSize);
130745fd3b9aSArmin Le Grand 		aCodec.EndCompression();
130845fd3b9aSArmin Le Grand 
130945fd3b9aSArmin Le Grand 		// update compress info ( coded size, uncoded size, uncoded compression )
131045fd3b9aSArmin Le Grand         nLastPos = rOStm.Tell();
131145fd3b9aSArmin Le Grand 		nCodedSize = nLastPos - nCodedPos - 12;
131245fd3b9aSArmin Le Grand 		rOStm.Seek(nCodedPos);
131345fd3b9aSArmin Le Grand 		rOStm << nCodedSize << nUncodedSize << nCompression;
131445fd3b9aSArmin Le Grand 		rOStm.Seek(nLastPos);
131545fd3b9aSArmin Le Grand 
131645fd3b9aSArmin Le Grand 		if(bRet)
131745fd3b9aSArmin Le Grand         {
131845fd3b9aSArmin Le Grand 			bRet = (ERRCODE_NONE == rOStm.GetError());
131945fd3b9aSArmin Le Grand         }
132045fd3b9aSArmin Le Grand 	}
132145fd3b9aSArmin Le Grand 	else
132245fd3b9aSArmin Le Grand 	{
132345fd3b9aSArmin Le Grand 		if(aHeader.nColsUsed)
132445fd3b9aSArmin Le Grand         {
132545fd3b9aSArmin Le Grand 			ImplWriteDIBPalette(rOStm, rAcc);
132645fd3b9aSArmin Le Grand         }
132745fd3b9aSArmin Le Grand 
132845fd3b9aSArmin Le Grand 		bRet = ImplWriteDIBBits(rOStm, rAcc, pAccAlpha, aHeader.nCompression, aHeader.nSizeImage);
132945fd3b9aSArmin Le Grand 	}
133045fd3b9aSArmin Le Grand 
133145fd3b9aSArmin Le Grand 	nEndPos = rOStm.Tell();
133245fd3b9aSArmin Le Grand 	rOStm.Seek(nImageSizePos);
133345fd3b9aSArmin Le Grand 	rOStm << aHeader.nSizeImage;
133445fd3b9aSArmin Le Grand 	rOStm.Seek(nEndPos);
133545fd3b9aSArmin Le Grand 
133645fd3b9aSArmin Le Grand 	return bRet;
133745fd3b9aSArmin Le Grand }
133845fd3b9aSArmin Le Grand 
133945fd3b9aSArmin Le Grand bool ImplWriteDIBFileHeader(SvStream& rOStm, BitmapReadAccess& rAcc, bool bUseDIBV5)
134045fd3b9aSArmin Le Grand {
134145fd3b9aSArmin Le Grand 	const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : isBitfieldCompression(rAcc.GetScanlineFormat()) ? 3UL : 0UL));
134245fd3b9aSArmin Le Grand 	const sal_uInt32 nOffset(14 + (bUseDIBV5 ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE) + nPalCount * 4UL);
134345fd3b9aSArmin Le Grand 
134445fd3b9aSArmin Le Grand 	rOStm << (sal_uInt16)0x4D42; // 'MB' from BITMAPFILEHEADER
134545fd3b9aSArmin Le Grand 	rOStm << (sal_uInt32)(nOffset + (rAcc.Height() * rAcc.GetScanlineSize()));
134645fd3b9aSArmin Le Grand 	rOStm << (sal_uInt16)0;
134745fd3b9aSArmin Le Grand 	rOStm << (sal_uInt16)0;
134845fd3b9aSArmin Le Grand 	rOStm << nOffset;
134945fd3b9aSArmin Le Grand 
135045fd3b9aSArmin Le Grand 	return( rOStm.GetError() == 0UL );
135145fd3b9aSArmin Le Grand }
135245fd3b9aSArmin Le Grand 
135345fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
135445fd3b9aSArmin Le Grand 
135545fd3b9aSArmin Le Grand bool ImplReadDIB(
135645fd3b9aSArmin Le Grand     Bitmap& rTarget, Bitmap*
135745fd3b9aSArmin Le Grand     pTargetAlpha,
135845fd3b9aSArmin Le Grand     SvStream& rIStm,
135945fd3b9aSArmin Le Grand     bool bFileHeader)
136045fd3b9aSArmin Le Grand {
136145fd3b9aSArmin Le Grand     const sal_uInt16 nOldFormat(rIStm.GetNumberFormatInt());
136245fd3b9aSArmin Le Grand     const sal_uLong nOldPos(rIStm.Tell());
136345fd3b9aSArmin Le Grand     sal_uLong nOffset(0UL);
136445fd3b9aSArmin Le Grand     bool bRet(false);
136545fd3b9aSArmin Le Grand 
136645fd3b9aSArmin Le Grand     rIStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
136745fd3b9aSArmin Le Grand 
136845fd3b9aSArmin Le Grand     if(bFileHeader)
136945fd3b9aSArmin Le Grand     {
137045fd3b9aSArmin Le Grand         if(ImplReadDIBFileHeader(rIStm, nOffset))
137145fd3b9aSArmin Le Grand         {
137245fd3b9aSArmin Le Grand             bRet = ImplReadDIBBody(rIStm, rTarget, nOffset >= DIBV5HEADERSIZE ? pTargetAlpha : 0, nOffset);
137345fd3b9aSArmin Le Grand         }
137445fd3b9aSArmin Le Grand     }
137545fd3b9aSArmin Le Grand     else
137645fd3b9aSArmin Le Grand     {
137745fd3b9aSArmin Le Grand         bRet = ImplReadDIBBody(rIStm, rTarget, 0, nOffset);
137845fd3b9aSArmin Le Grand     }
137945fd3b9aSArmin Le Grand 
138045fd3b9aSArmin Le Grand     if(!bRet)
138145fd3b9aSArmin Le Grand     {
138245fd3b9aSArmin Le Grand         if(!rIStm.GetError())
138345fd3b9aSArmin Le Grand         {
138445fd3b9aSArmin Le Grand             rIStm.SetError(SVSTREAM_GENERALERROR);
138545fd3b9aSArmin Le Grand         }
138645fd3b9aSArmin Le Grand 
138745fd3b9aSArmin Le Grand         rIStm.Seek(nOldPos);
138845fd3b9aSArmin Le Grand     }
138945fd3b9aSArmin Le Grand 
139045fd3b9aSArmin Le Grand     rIStm.SetNumberFormatInt(nOldFormat);
139145fd3b9aSArmin Le Grand 
139245fd3b9aSArmin Le Grand     return bRet;
139345fd3b9aSArmin Le Grand }
139445fd3b9aSArmin Le Grand 
139545fd3b9aSArmin Le Grand bool ImplWriteDIB(
139645fd3b9aSArmin Le Grand     const Bitmap& rSource,
139745fd3b9aSArmin Le Grand     const Bitmap* pSourceAlpha,
139845fd3b9aSArmin Le Grand     SvStream& rOStm,
139945fd3b9aSArmin Le Grand     bool bCompressed,
140045fd3b9aSArmin Le Grand     bool bFileHeader)
140145fd3b9aSArmin Le Grand {
140245fd3b9aSArmin Le Grand     const Size aSizePix(rSource.GetSizePixel());
140345fd3b9aSArmin Le Grand     bool bRet(false);
140445fd3b9aSArmin Le Grand 
140545fd3b9aSArmin Le Grand     if(aSizePix.Width() && aSizePix.Height())
140645fd3b9aSArmin Le Grand     {
140745fd3b9aSArmin Le Grand         BitmapReadAccess* pAcc = const_cast< Bitmap& >(rSource).AcquireReadAccess();
140845fd3b9aSArmin Le Grand         BitmapReadAccess* pAccAlpha = 0;
140945fd3b9aSArmin Le Grand         const sal_uInt16 nOldFormat(rOStm.GetNumberFormatInt());
141045fd3b9aSArmin Le Grand         const sal_uLong nOldPos(rOStm.Tell());
141145fd3b9aSArmin Le Grand 
141245fd3b9aSArmin Le Grand         if(pSourceAlpha)
141345fd3b9aSArmin Le Grand         {
141445fd3b9aSArmin Le Grand             const Size aSizePixAlpha(pSourceAlpha->GetSizePixel());
141545fd3b9aSArmin Le Grand 
141645fd3b9aSArmin Le Grand             if(aSizePixAlpha == aSizePix)
141745fd3b9aSArmin Le Grand             {
141845fd3b9aSArmin Le Grand                 pAccAlpha = const_cast< Bitmap* >(pSourceAlpha)->AcquireReadAccess();
141945fd3b9aSArmin Le Grand             }
142045fd3b9aSArmin Le Grand             else
142145fd3b9aSArmin Le Grand             {
142245fd3b9aSArmin Le Grand                 OSL_ENSURE(false, "WriteDIB got an alpha channel, but it's pixel size differs from the base bitmap (!)");
142345fd3b9aSArmin Le Grand             }
142445fd3b9aSArmin Le Grand         }
142545fd3b9aSArmin Le Grand 
142645fd3b9aSArmin Le Grand         rOStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
142745fd3b9aSArmin Le Grand 
142845fd3b9aSArmin Le Grand         if(pAcc)
142945fd3b9aSArmin Le Grand         {
143045fd3b9aSArmin Le Grand             if(bFileHeader)
143145fd3b9aSArmin Le Grand             {
143245fd3b9aSArmin Le Grand                 if(ImplWriteDIBFileHeader(rOStm, *pAcc, 0 != pSourceAlpha))
143345fd3b9aSArmin Le Grand                 {
143445fd3b9aSArmin Le Grand                     bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
143545fd3b9aSArmin Le Grand                 }
143645fd3b9aSArmin Le Grand             }
143745fd3b9aSArmin Le Grand             else
143845fd3b9aSArmin Le Grand             {
143945fd3b9aSArmin Le Grand                 bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
144045fd3b9aSArmin Le Grand             }
144145fd3b9aSArmin Le Grand 
144245fd3b9aSArmin Le Grand             const_cast< Bitmap& >(rSource).ReleaseAccess(pAcc);
144345fd3b9aSArmin Le Grand 
144445fd3b9aSArmin Le Grand             if(pAccAlpha)
144545fd3b9aSArmin Le Grand             {
144645fd3b9aSArmin Le Grand                 const_cast< Bitmap* >(pSourceAlpha)->ReleaseAccess(pAccAlpha);
144745fd3b9aSArmin Le Grand             }
144845fd3b9aSArmin Le Grand         }
144945fd3b9aSArmin Le Grand 
145045fd3b9aSArmin Le Grand         if(!bRet)
145145fd3b9aSArmin Le Grand         {
145245fd3b9aSArmin Le Grand             rOStm.SetError(SVSTREAM_GENERALERROR);
145345fd3b9aSArmin Le Grand             rOStm.Seek(nOldPos);
145445fd3b9aSArmin Le Grand         }
145545fd3b9aSArmin Le Grand 
145645fd3b9aSArmin Le Grand         rOStm.SetNumberFormatInt(nOldFormat);
145745fd3b9aSArmin Le Grand     }
145845fd3b9aSArmin Le Grand 
145945fd3b9aSArmin Le Grand     return bRet;
146045fd3b9aSArmin Le Grand }
146145fd3b9aSArmin Le Grand 
146245fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
146345fd3b9aSArmin Le Grand 
146445fd3b9aSArmin Le Grand bool ReadDIB(
146545fd3b9aSArmin Le Grand     Bitmap& rTarget,
146645fd3b9aSArmin Le Grand     SvStream& rIStm,
146745fd3b9aSArmin Le Grand     bool bFileHeader)
146845fd3b9aSArmin Le Grand {
146945fd3b9aSArmin Le Grand     return ImplReadDIB(rTarget, 0, rIStm, bFileHeader);
147045fd3b9aSArmin Le Grand }
147145fd3b9aSArmin Le Grand 
147245fd3b9aSArmin Le Grand bool ReadDIBBitmapEx(
147345fd3b9aSArmin Le Grand     BitmapEx& rTarget,
147445fd3b9aSArmin Le Grand     SvStream& rIStm)
147545fd3b9aSArmin Le Grand {
147645fd3b9aSArmin Le Grand     Bitmap aBmp;
147745fd3b9aSArmin Le Grand     bool bRetval(ImplReadDIB(aBmp, 0, rIStm, true) && !rIStm.GetError());
147845fd3b9aSArmin Le Grand 
147945fd3b9aSArmin Le Grand     if(bRetval)
148045fd3b9aSArmin Le Grand     {
148145fd3b9aSArmin Le Grand         // base bitmap was read, set as return value and try to read alpha extra-data
148245fd3b9aSArmin Le Grand         const sal_uLong nStmPos(rIStm.Tell());
148345fd3b9aSArmin Le Grand         sal_uInt32 nMagic1(0);
148445fd3b9aSArmin Le Grand         sal_uInt32 nMagic2(0);
148545fd3b9aSArmin Le Grand 
148645fd3b9aSArmin Le Grand         rTarget = BitmapEx(aBmp);
148745fd3b9aSArmin Le Grand         rIStm >> nMagic1 >> nMagic2;
148845fd3b9aSArmin Le Grand         bRetval = (0x25091962 == nMagic1) && (0xACB20201 == nMagic2) && !rIStm.GetError();
148945fd3b9aSArmin Le Grand 
149045fd3b9aSArmin Le Grand         if(bRetval)
149145fd3b9aSArmin Le Grand         {
149245fd3b9aSArmin Le Grand             sal_uInt8 bTransparent(false);
149345fd3b9aSArmin Le Grand 
149445fd3b9aSArmin Le Grand             rIStm >> bTransparent;
149545fd3b9aSArmin Le Grand             bRetval = !rIStm.GetError();
149645fd3b9aSArmin Le Grand 
149745fd3b9aSArmin Le Grand             if(bRetval)
149845fd3b9aSArmin Le Grand             {
149945fd3b9aSArmin Le Grand                 if((sal_uInt8)TRANSPARENT_BITMAP == bTransparent)
150045fd3b9aSArmin Le Grand                 {
150145fd3b9aSArmin Le Grand                     Bitmap aMask;
150245fd3b9aSArmin Le Grand 
150345fd3b9aSArmin Le Grand                     bRetval = ImplReadDIB(aMask, 0, rIStm, true);
150445fd3b9aSArmin Le Grand 
150545fd3b9aSArmin Le Grand                     if(bRetval)
150645fd3b9aSArmin Le Grand                     {
150745fd3b9aSArmin Le Grand                         if(!!aMask)
150845fd3b9aSArmin Le Grand                         {
150945fd3b9aSArmin Le Grand                             // do we have an alpha mask?
151045fd3b9aSArmin Le Grand                             if((8 == aMask.GetBitCount()) && aMask.HasGreyPalette())
151145fd3b9aSArmin Le Grand                             {
151245fd3b9aSArmin Le Grand                                 AlphaMask aAlpha;
151345fd3b9aSArmin Le Grand 
151445fd3b9aSArmin Le Grand                                 // create alpha mask quickly (without greyscale conversion)
151545fd3b9aSArmin Le Grand                                 aAlpha.ImplSetBitmap(aMask);
151645fd3b9aSArmin Le Grand                                 rTarget = BitmapEx(aBmp, aAlpha);
151745fd3b9aSArmin Le Grand                             }
151845fd3b9aSArmin Le Grand                             else
151945fd3b9aSArmin Le Grand                             {
152045fd3b9aSArmin Le Grand                                 rTarget = BitmapEx(aBmp, aMask);
152145fd3b9aSArmin Le Grand                             }
152245fd3b9aSArmin Le Grand                         }
152345fd3b9aSArmin Le Grand                     }
152445fd3b9aSArmin Le Grand                 }
152545fd3b9aSArmin Le Grand                 else if((sal_uInt8)TRANSPARENT_COLOR == bTransparent)
152645fd3b9aSArmin Le Grand                 {
152745fd3b9aSArmin Le Grand                     Color aTransparentColor;
152845fd3b9aSArmin Le Grand 
152945fd3b9aSArmin Le Grand                     rIStm >> aTransparentColor;
153045fd3b9aSArmin Le Grand                     bRetval = !rIStm.GetError();
153145fd3b9aSArmin Le Grand 
153245fd3b9aSArmin Le Grand                     if(bRetval)
153345fd3b9aSArmin Le Grand                     {
153445fd3b9aSArmin Le Grand                         rTarget = BitmapEx(aBmp, aTransparentColor);
153545fd3b9aSArmin Le Grand                     }
153645fd3b9aSArmin Le Grand                 }
153745fd3b9aSArmin Le Grand             }
153845fd3b9aSArmin Le Grand         }
153945fd3b9aSArmin Le Grand 
154045fd3b9aSArmin Le Grand         if(!bRetval)
154145fd3b9aSArmin Le Grand         {
154245fd3b9aSArmin Le Grand             // alpha extra data could not be read; reset, but use base bitmap as result
154345fd3b9aSArmin Le Grand             rIStm.ResetError();
154445fd3b9aSArmin Le Grand             rIStm.Seek(nStmPos);
154545fd3b9aSArmin Le Grand             bRetval = true;
154645fd3b9aSArmin Le Grand         }
154745fd3b9aSArmin Le Grand     }
154845fd3b9aSArmin Le Grand 
154945fd3b9aSArmin Le Grand     return bRetval;
155045fd3b9aSArmin Le Grand }
155145fd3b9aSArmin Le Grand 
155245fd3b9aSArmin Le Grand bool ReadDIBV5(
155345fd3b9aSArmin Le Grand     Bitmap& rTarget,
155445fd3b9aSArmin Le Grand     Bitmap& rTargetAlpha,
155545fd3b9aSArmin Le Grand     SvStream& rIStm)
155645fd3b9aSArmin Le Grand {
155745fd3b9aSArmin Le Grand     return ImplReadDIB(rTarget, &rTargetAlpha, rIStm, true);
155845fd3b9aSArmin Le Grand }
155945fd3b9aSArmin Le Grand 
156045fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
156145fd3b9aSArmin Le Grand 
156245fd3b9aSArmin Le Grand bool WriteDIB(
156345fd3b9aSArmin Le Grand     const Bitmap& rSource,
156445fd3b9aSArmin Le Grand     SvStream& rOStm,
156545fd3b9aSArmin Le Grand     bool bCompressed,
156645fd3b9aSArmin Le Grand     bool bFileHeader)
156745fd3b9aSArmin Le Grand {
156845fd3b9aSArmin Le Grand     return ImplWriteDIB(rSource, 0, rOStm, bCompressed, bFileHeader);
156945fd3b9aSArmin Le Grand }
157045fd3b9aSArmin Le Grand 
157145fd3b9aSArmin Le Grand bool WriteDIBBitmapEx(
157245fd3b9aSArmin Le Grand     const BitmapEx& rSource,
157345fd3b9aSArmin Le Grand     SvStream& rOStm)
157445fd3b9aSArmin Le Grand {
157545fd3b9aSArmin Le Grand     if(ImplWriteDIB(rSource.GetBitmap(), 0, rOStm, true, true))
157645fd3b9aSArmin Le Grand     {
157745fd3b9aSArmin Le Grand         rOStm << (sal_uInt32)0x25091962;
157845fd3b9aSArmin Le Grand         rOStm << (sal_uInt32)0xACB20201;
157945fd3b9aSArmin Le Grand         rOStm << (sal_uInt8)rSource.eTransparent;
158045fd3b9aSArmin Le Grand 
158145fd3b9aSArmin Le Grand         if(TRANSPARENT_BITMAP == rSource.eTransparent)
158245fd3b9aSArmin Le Grand         {
158345fd3b9aSArmin Le Grand             return ImplWriteDIB(rSource.aMask, 0, rOStm, true, true);
158445fd3b9aSArmin Le Grand         }
158545fd3b9aSArmin Le Grand         else if(TRANSPARENT_COLOR == rSource.eTransparent)
158645fd3b9aSArmin Le Grand         {
158745fd3b9aSArmin Le Grand             rOStm << rSource.aTransparentColor;
158845fd3b9aSArmin Le Grand             return true;
158945fd3b9aSArmin Le Grand         }
159045fd3b9aSArmin Le Grand     }
159145fd3b9aSArmin Le Grand 
159245fd3b9aSArmin Le Grand     return false;
159345fd3b9aSArmin Le Grand }
159445fd3b9aSArmin Le Grand 
159545fd3b9aSArmin Le Grand bool WriteDIBV5(
159645fd3b9aSArmin Le Grand     const Bitmap& rSource,
159745fd3b9aSArmin Le Grand     const Bitmap& rSourceAlpha,
159845fd3b9aSArmin Le Grand     SvStream& rOStm)
159945fd3b9aSArmin Le Grand {
160045fd3b9aSArmin Le Grand     return ImplWriteDIB(rSource, &rSourceAlpha, rOStm, false, true);
160145fd3b9aSArmin Le Grand }
160245fd3b9aSArmin Le Grand 
160345fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
160445fd3b9aSArmin Le Grand // eof
1605