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
CIEXYZCIEXYZ6145fd3b9aSArmin Le Grand CIEXYZ()
6245fd3b9aSArmin Le Grand : aXyzX(0L),
6345fd3b9aSArmin Le Grand aXyzY(0L),
6445fd3b9aSArmin Le Grand aXyzZ(0L)
6545fd3b9aSArmin Le Grand {}
6645fd3b9aSArmin Le Grand
~CIEXYZCIEXYZ6745fd3b9aSArmin 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
CIEXYZTripleCIEXYZTriple7745fd3b9aSArmin Le Grand CIEXYZTriple()
7845fd3b9aSArmin Le Grand : aXyzRed(),
7945fd3b9aSArmin Le Grand aXyzGreen(),
8045fd3b9aSArmin Le Grand aXyzBlue()
8145fd3b9aSArmin Le Grand {}
8245fd3b9aSArmin Le Grand
~CIEXYZTripleCIEXYZTriple8345fd3b9aSArmin 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
DIBInfoHeaderDIBInfoHeader10145fd3b9aSArmin 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
~DIBInfoHeaderDIBInfoHeader11545fd3b9aSArmin 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
DIBV5HeaderDIBV5Header13545fd3b9aSArmin 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
~DIBV5HeaderDIBV5Header15245fd3b9aSArmin 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 {
discretizeBitcount(sal_uInt16 nInputCount)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
isBitfieldCompression(sal_uLong nScanlineFormat)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
ImplReadDIBInfoHeader(SvStream & rIStm,DIBV5Header & rHeader,bool & bTopDown)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
ImplReadDIBPalette(SvStream & rIStm,BitmapWriteAccess & rAcc,bool bQuad)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
ImplDecodeRLE(sal_uInt8 * pBuffer,DIBV5Header & rHeader,BitmapWriteAccess & rAcc,bool bRLE4)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
ImplReadDIBBits(SvStream & rIStm,DIBV5Header & rHeader,BitmapWriteAccess & rAcc,BitmapWriteAccess * pAccAlpha,bool bTopDown,bool & rAlphaUsed)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
ImplReadDIBBody(SvStream & rIStm,Bitmap & rBmp,Bitmap * pBmpAlpha,sal_uLong nOffset)61445fd3b9aSArmin Le Grand bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLong nOffset )
61545fd3b9aSArmin Le Grand {
616*4b444595SOliver-Rainer Wittmann DIBV5Header aHeader;
617*4b444595SOliver-Rainer Wittmann const sal_uLong nStmPos = rIStm.Tell();
618*4b444595SOliver-Rainer Wittmann bool bRet( false );
619*4b444595SOliver-Rainer Wittmann bool bTopDown( false );
620*4b444595SOliver-Rainer Wittmann
621*4b444595SOliver-Rainer Wittmann if ( ImplReadDIBInfoHeader( rIStm, aHeader, bTopDown )
622*4b444595SOliver-Rainer Wittmann && aHeader.nWidth != 0
623*4b444595SOliver-Rainer Wittmann && aHeader.nHeight != 0
624*4b444595SOliver-Rainer Wittmann && aHeader.nBitCount != 0 )
625*4b444595SOliver-Rainer Wittmann {
626*4b444595SOliver-Rainer Wittmann if ( nOffset > 0 && aHeader.nSize > nOffset )
6273aedac3eSJürgen Schmidt {
6283aedac3eSJürgen Schmidt // Header size claims to extend into the image data.
6293aedac3eSJürgen Schmidt // Looks like an error.
6303aedac3eSJürgen Schmidt return false;
6313aedac3eSJürgen Schmidt }
6323aedac3eSJürgen Schmidt
63345fd3b9aSArmin Le Grand const sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount));
63445fd3b9aSArmin Le Grand const Size aSizePixel(aHeader.nWidth, aHeader.nHeight);
63545fd3b9aSArmin Le Grand BitmapPalette aDummyPal;
63645fd3b9aSArmin Le Grand Bitmap aNewBmp(aSizePixel, nBitCount, &aDummyPal);
63745fd3b9aSArmin Le Grand Bitmap aNewBmpAlpha;
63845fd3b9aSArmin Le Grand BitmapWriteAccess* pAcc = aNewBmp.AcquireWriteAccess();
63945fd3b9aSArmin Le Grand BitmapWriteAccess* pAccAlpha = 0;
64045fd3b9aSArmin Le Grand bool bAlphaPossible(pBmpAlpha && aHeader.nBitCount == 32);
64145fd3b9aSArmin Le Grand
64245fd3b9aSArmin Le Grand if(bAlphaPossible)
64345fd3b9aSArmin Le Grand {
64445fd3b9aSArmin Le Grand const bool bRedSet(0 != aHeader.nV5RedMask);
64545fd3b9aSArmin Le Grand const bool bGreenSet(0 != aHeader.nV5GreenMask);
64645fd3b9aSArmin Le Grand const bool bBlueSet(0 != aHeader.nV5BlueMask);
64745fd3b9aSArmin Le Grand
64845fd3b9aSArmin Le Grand // some clipboard entries have alpha mask on zero to say that there is
64945fd3b9aSArmin Le Grand // no alpha; do only use this when the other masks are set. The MS docu
65045fd3b9aSArmin Le Grand // says that that masks are only to be set when bV5Compression is set to
65145fd3b9aSArmin Le Grand // BI_BITFIELDS, but there seem to exist a wild variety of usages...
65245fd3b9aSArmin Le Grand if((bRedSet || bGreenSet || bBlueSet) && (0 == aHeader.nV5AlphaMask))
65345fd3b9aSArmin Le Grand {
65445fd3b9aSArmin Le Grand bAlphaPossible = false;
65545fd3b9aSArmin Le Grand }
65645fd3b9aSArmin Le Grand }
65745fd3b9aSArmin Le Grand
65845fd3b9aSArmin Le Grand if(bAlphaPossible)
65945fd3b9aSArmin Le Grand {
66045fd3b9aSArmin Le Grand aNewBmpAlpha = Bitmap(aSizePixel, 8);
66145fd3b9aSArmin Le Grand pAccAlpha = aNewBmpAlpha.AcquireWriteAccess();
66245fd3b9aSArmin Le Grand }
66345fd3b9aSArmin Le Grand
66445fd3b9aSArmin Le Grand if(pAcc)
66545fd3b9aSArmin Le Grand {
66645fd3b9aSArmin Le Grand sal_uInt16 nColors(0);
66745fd3b9aSArmin Le Grand SvStream* pIStm;
66845fd3b9aSArmin Le Grand SvMemoryStream* pMemStm = NULL;
66945fd3b9aSArmin Le Grand sal_uInt8* pData = NULL;
67045fd3b9aSArmin Le Grand
67145fd3b9aSArmin Le Grand if(nBitCount <= 8)
67245fd3b9aSArmin Le Grand {
67345fd3b9aSArmin Le Grand if(aHeader.nColsUsed)
67445fd3b9aSArmin Le Grand {
67545fd3b9aSArmin Le Grand nColors = (sal_uInt16)aHeader.nColsUsed;
67645fd3b9aSArmin Le Grand }
67745fd3b9aSArmin Le Grand else
67845fd3b9aSArmin Le Grand {
67945fd3b9aSArmin Le Grand nColors = ( 1 << aHeader.nBitCount );
68045fd3b9aSArmin Le Grand }
68145fd3b9aSArmin Le Grand }
68245fd3b9aSArmin Le Grand
68345fd3b9aSArmin Le Grand if(ZCOMPRESS == aHeader.nCompression)
68445fd3b9aSArmin Le Grand {
68545fd3b9aSArmin Le Grand ZCodec aCodec;
68645fd3b9aSArmin Le Grand sal_uInt32 nCodedSize(0);
68745fd3b9aSArmin Le Grand sal_uInt32 nUncodedSize(0);
68845fd3b9aSArmin Le Grand sal_uLong nCodedPos(0);
68945fd3b9aSArmin Le Grand
69045fd3b9aSArmin Le Grand // read coding information
69145fd3b9aSArmin Le Grand rIStm >> nCodedSize >> nUncodedSize >> aHeader.nCompression;
69245fd3b9aSArmin Le Grand pData = (sal_uInt8*) rtl_allocateMemory( nUncodedSize );
69345fd3b9aSArmin Le Grand
69445fd3b9aSArmin Le Grand // decode buffer
69545fd3b9aSArmin Le Grand nCodedPos = rIStm.Tell();
69645fd3b9aSArmin Le Grand aCodec.BeginCompression();
69745fd3b9aSArmin Le Grand aCodec.Read( rIStm, pData, nUncodedSize );
69845fd3b9aSArmin Le Grand aCodec.EndCompression();
69945fd3b9aSArmin Le Grand
70045fd3b9aSArmin Le Grand // skip unread bytes from coded buffer
70145fd3b9aSArmin Le Grand rIStm.SeekRel( nCodedSize - ( rIStm.Tell() - nCodedPos ) );
70245fd3b9aSArmin Le Grand
70345fd3b9aSArmin Le Grand // set decoded bytes to memory stream,
70445fd3b9aSArmin Le Grand // from which we will read the bitmap data
70545fd3b9aSArmin Le Grand pIStm = pMemStm = new SvMemoryStream;
70645fd3b9aSArmin Le Grand pMemStm->SetBuffer( (char*) pData, nUncodedSize, false, nUncodedSize );
70745fd3b9aSArmin Le Grand nOffset = 0;
70845fd3b9aSArmin Le Grand }
70945fd3b9aSArmin Le Grand else
71045fd3b9aSArmin Le Grand {
71145fd3b9aSArmin Le Grand pIStm = &rIStm;
71245fd3b9aSArmin Le Grand }
71345fd3b9aSArmin Le Grand
71445fd3b9aSArmin Le Grand // read palette
71545fd3b9aSArmin Le Grand if(nColors)
71645fd3b9aSArmin Le Grand {
71745fd3b9aSArmin Le Grand pAcc->SetPaletteEntryCount(nColors);
71845fd3b9aSArmin Le Grand ImplReadDIBPalette(*pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE);
71945fd3b9aSArmin Le Grand }
72045fd3b9aSArmin Le Grand
72145fd3b9aSArmin Le Grand // read bits
722c7a371deSArmin Le Grand bool bAlphaUsed(false);
723c7a371deSArmin Le Grand
72445fd3b9aSArmin Le Grand if(!pIStm->GetError())
72545fd3b9aSArmin Le Grand {
72645fd3b9aSArmin Le Grand if(nOffset)
72745fd3b9aSArmin Le Grand {
72845fd3b9aSArmin Le Grand pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
72945fd3b9aSArmin Le Grand }
73045fd3b9aSArmin Le Grand
731c7a371deSArmin Le Grand bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown, bAlphaUsed);
73245fd3b9aSArmin Le Grand
73345fd3b9aSArmin Le Grand if(bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter)
73445fd3b9aSArmin Le Grand {
73545fd3b9aSArmin Le Grand MapMode aMapMode(
73645fd3b9aSArmin Le Grand MAP_MM,
73745fd3b9aSArmin Le Grand Point(),
73845fd3b9aSArmin Le Grand Fraction(1000, aHeader.nXPelsPerMeter),
73945fd3b9aSArmin Le Grand Fraction(1000, aHeader.nYPelsPerMeter));
74045fd3b9aSArmin Le Grand
74145fd3b9aSArmin Le Grand aNewBmp.SetPrefMapMode(aMapMode);
74245fd3b9aSArmin Le Grand aNewBmp.SetPrefSize(Size(aHeader.nWidth, aHeader.nHeight));
74345fd3b9aSArmin Le Grand }
74445fd3b9aSArmin Le Grand }
74545fd3b9aSArmin Le Grand
74645fd3b9aSArmin Le Grand if( pData )
74745fd3b9aSArmin Le Grand {
74845fd3b9aSArmin Le Grand rtl_freeMemory(pData);
74945fd3b9aSArmin Le Grand }
75045fd3b9aSArmin Le Grand
75145fd3b9aSArmin Le Grand delete pMemStm;
75245fd3b9aSArmin Le Grand aNewBmp.ReleaseAccess(pAcc);
75345fd3b9aSArmin Le Grand
75445fd3b9aSArmin Le Grand if(bAlphaPossible)
75545fd3b9aSArmin Le Grand {
75645fd3b9aSArmin Le Grand aNewBmpAlpha.ReleaseAccess(pAccAlpha);
757c7a371deSArmin Le Grand
758c7a371deSArmin Le Grand if(!bAlphaUsed)
759c7a371deSArmin Le Grand {
760c7a371deSArmin Le Grand bAlphaPossible = false;
761c7a371deSArmin Le Grand }
76245fd3b9aSArmin Le Grand }
76345fd3b9aSArmin Le Grand
76445fd3b9aSArmin Le Grand if(bRet)
76545fd3b9aSArmin Le Grand {
76645fd3b9aSArmin Le Grand rBmp = aNewBmp;
76745fd3b9aSArmin Le Grand
76845fd3b9aSArmin Le Grand if(bAlphaPossible)
76945fd3b9aSArmin Le Grand {
77045fd3b9aSArmin Le Grand *pBmpAlpha = aNewBmpAlpha;
77145fd3b9aSArmin Le Grand }
77245fd3b9aSArmin Le Grand }
77345fd3b9aSArmin Le Grand }
77445fd3b9aSArmin Le Grand }
77545fd3b9aSArmin Le Grand
77645fd3b9aSArmin Le Grand return bRet;
77745fd3b9aSArmin Le Grand }
77845fd3b9aSArmin Le Grand
ImplReadDIBFileHeader(SvStream & rIStm,sal_uLong & rOffset)77945fd3b9aSArmin Le Grand bool ImplReadDIBFileHeader( SvStream& rIStm, sal_uLong& rOffset )
78045fd3b9aSArmin Le Grand {
7814e95292aSOliver-Rainer Wittmann bool bRet = false;
78245fd3b9aSArmin Le Grand
7834e95292aSOliver-Rainer Wittmann const sal_Int64 nSavedStreamPos( rIStm.Tell() );
7844e95292aSOliver-Rainer Wittmann const sal_Int64 nStreamLength( rIStm.Seek( STREAM_SEEK_TO_END ) );
7854e95292aSOliver-Rainer Wittmann rIStm.Seek( nSavedStreamPos );
7863aedac3eSJürgen Schmidt
7874e95292aSOliver-Rainer Wittmann sal_uInt16 nTmp16 = 0;
7884e95292aSOliver-Rainer Wittmann rIStm >> nTmp16;
78945fd3b9aSArmin Le Grand
7904e95292aSOliver-Rainer Wittmann if ( ( 0x4D42 == nTmp16 ) || ( 0x4142 == nTmp16 ) )
7914e95292aSOliver-Rainer Wittmann {
7924e95292aSOliver-Rainer Wittmann sal_uInt32 nTmp32;
7934e95292aSOliver-Rainer Wittmann if ( 0x4142 == nTmp16 )
7944e95292aSOliver-Rainer Wittmann {
7954e95292aSOliver-Rainer Wittmann rIStm.SeekRel( 12L );
7964e95292aSOliver-Rainer Wittmann rIStm >> nTmp16;
7974e95292aSOliver-Rainer Wittmann rIStm.SeekRel( 8L );
7984e95292aSOliver-Rainer Wittmann rIStm >> nTmp32;
7994e95292aSOliver-Rainer Wittmann rOffset = nTmp32 - 28UL;
8004e95292aSOliver-Rainer Wittmann bRet = ( 0x4D42 == nTmp16 );
8014e95292aSOliver-Rainer Wittmann }
8024e95292aSOliver-Rainer Wittmann else // 0x4D42 == nTmp16, 'MB' from BITMAPFILEHEADER
8034e95292aSOliver-Rainer Wittmann {
8044e95292aSOliver-Rainer Wittmann rIStm.SeekRel( 8L ); // we are on bfSize member of BITMAPFILEHEADER, forward to bfOffBits
8054e95292aSOliver-Rainer Wittmann rIStm >> nTmp32; // read bfOffBits
8064e95292aSOliver-Rainer Wittmann rOffset = nTmp32 - 14UL; // adapt offset by sizeof(BITMAPFILEHEADER)
8074e95292aSOliver-Rainer Wittmann bRet = ( rIStm.GetError() == 0UL );
8084e95292aSOliver-Rainer Wittmann }
8093aedac3eSJürgen Schmidt
8104e95292aSOliver-Rainer Wittmann if ( rOffset >= nStreamLength )
8113aedac3eSJürgen Schmidt {
8123aedac3eSJürgen Schmidt // Offset claims that image starts past the end of the
8133aedac3eSJürgen Schmidt // stream. Unlikely.
8143aedac3eSJürgen Schmidt rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
8153aedac3eSJürgen Schmidt bRet = false;
8163aedac3eSJürgen Schmidt }
8174e95292aSOliver-Rainer Wittmann }
8184e95292aSOliver-Rainer Wittmann else
8194e95292aSOliver-Rainer Wittmann rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
82045fd3b9aSArmin Le Grand
8214e95292aSOliver-Rainer Wittmann return bRet;
82245fd3b9aSArmin Le Grand }
82345fd3b9aSArmin Le Grand
ImplWriteDIBPalette(SvStream & rOStm,BitmapReadAccess & rAcc)82445fd3b9aSArmin Le Grand bool ImplWriteDIBPalette( SvStream& rOStm, BitmapReadAccess& rAcc )
82545fd3b9aSArmin Le Grand {
82645fd3b9aSArmin Le Grand const sal_uInt16 nColors = rAcc.GetPaletteEntryCount();
82745fd3b9aSArmin Le Grand const sal_uLong nPalSize = nColors * 4UL;
82845fd3b9aSArmin Le Grand sal_uInt8* pEntries = new sal_uInt8[ nPalSize ];
82945fd3b9aSArmin Le Grand sal_uInt8* pTmpEntry = pEntries;
83045fd3b9aSArmin Le Grand BitmapColor aPalColor;
83145fd3b9aSArmin Le Grand
83245fd3b9aSArmin Le Grand for( sal_uInt16 i = 0; i < nColors; i++ )
83345fd3b9aSArmin Le Grand {
83445fd3b9aSArmin Le Grand const BitmapColor& rPalColor = rAcc.GetPaletteColor( i );
83545fd3b9aSArmin Le Grand
83645fd3b9aSArmin Le Grand *pTmpEntry++ = rPalColor.GetBlue();
83745fd3b9aSArmin Le Grand *pTmpEntry++ = rPalColor.GetGreen();
83845fd3b9aSArmin Le Grand *pTmpEntry++ = rPalColor.GetRed();
83945fd3b9aSArmin Le Grand *pTmpEntry++ = 0;
84045fd3b9aSArmin Le Grand }
84145fd3b9aSArmin Le Grand
84245fd3b9aSArmin Le Grand rOStm.Write( pEntries, nPalSize );
84345fd3b9aSArmin Le Grand delete[] pEntries;
84445fd3b9aSArmin Le Grand
84545fd3b9aSArmin Le Grand return( rOStm.GetError() == 0UL );
84645fd3b9aSArmin Le Grand }
84745fd3b9aSArmin Le Grand
ImplWriteRLE(SvStream & rOStm,BitmapReadAccess & rAcc,bool bRLE4)84845fd3b9aSArmin Le Grand bool ImplWriteRLE( SvStream& rOStm, BitmapReadAccess& rAcc, bool bRLE4 )
84945fd3b9aSArmin Le Grand {
85045fd3b9aSArmin Le Grand const sal_uLong nWidth = rAcc.Width();
85145fd3b9aSArmin Le Grand const sal_uLong nHeight = rAcc.Height();
85245fd3b9aSArmin Le Grand sal_uLong nX;
85345fd3b9aSArmin Le Grand sal_uLong nSaveIndex;
85445fd3b9aSArmin Le Grand sal_uLong nCount;
85545fd3b9aSArmin Le Grand sal_uLong nBufCount;
85645fd3b9aSArmin Le Grand sal_uInt8* pBuf = new sal_uInt8[ ( nWidth << 1 ) + 2 ];
85745fd3b9aSArmin Le Grand sal_uInt8* pTmp;
85845fd3b9aSArmin Le Grand sal_uInt8 cPix;
85945fd3b9aSArmin Le Grand sal_uInt8 cLast;
86045fd3b9aSArmin Le Grand bool bFound;
86145fd3b9aSArmin Le Grand
86245fd3b9aSArmin Le Grand for ( long nY = nHeight - 1L; nY >= 0L; nY-- )
86345fd3b9aSArmin Le Grand {
86445fd3b9aSArmin Le Grand pTmp = pBuf;
86545fd3b9aSArmin Le Grand nX = nBufCount = 0UL;
86645fd3b9aSArmin Le Grand
86745fd3b9aSArmin Le Grand while( nX < nWidth )
86845fd3b9aSArmin Le Grand {
86945fd3b9aSArmin Le Grand nCount = 1L;
87045fd3b9aSArmin Le Grand cPix = rAcc.GetPixelIndex( nY, nX++ );
87145fd3b9aSArmin Le Grand
87245fd3b9aSArmin Le Grand while( ( nX < nWidth ) && ( nCount < 255L )
87345fd3b9aSArmin Le Grand && ( cPix == rAcc.GetPixelIndex( nY, nX ) ) )
87445fd3b9aSArmin Le Grand {
87545fd3b9aSArmin Le Grand nX++;
87645fd3b9aSArmin Le Grand nCount++;
87745fd3b9aSArmin Le Grand }
87845fd3b9aSArmin Le Grand
87945fd3b9aSArmin Le Grand if ( nCount > 1 )
88045fd3b9aSArmin Le Grand {
88145fd3b9aSArmin Le Grand *pTmp++ = (sal_uInt8) nCount;
88245fd3b9aSArmin Le Grand *pTmp++ = ( bRLE4 ? ( ( cPix << 4 ) | cPix ) : cPix );
88345fd3b9aSArmin Le Grand nBufCount += 2;
88445fd3b9aSArmin Le Grand }
88545fd3b9aSArmin Le Grand else
88645fd3b9aSArmin Le Grand {
88745fd3b9aSArmin Le Grand cLast = cPix;
88845fd3b9aSArmin Le Grand nSaveIndex = nX - 1UL;
88945fd3b9aSArmin Le Grand bFound = false;
89045fd3b9aSArmin Le Grand
89145fd3b9aSArmin Le Grand while( ( nX < nWidth ) && ( nCount < 256L )
89245fd3b9aSArmin Le Grand && ( cPix = rAcc.GetPixelIndex( nY, nX ) ) != cLast )
89345fd3b9aSArmin Le Grand {
89445fd3b9aSArmin Le Grand nX++; nCount++;
89545fd3b9aSArmin Le Grand cLast = cPix;
89645fd3b9aSArmin Le Grand bFound = true;
89745fd3b9aSArmin Le Grand }
89845fd3b9aSArmin Le Grand
89945fd3b9aSArmin Le Grand if ( bFound )
90045fd3b9aSArmin Le Grand nX--;
90145fd3b9aSArmin Le Grand
90245fd3b9aSArmin Le Grand if ( nCount > 3 )
90345fd3b9aSArmin Le Grand {
90445fd3b9aSArmin Le Grand *pTmp++ = 0;
90545fd3b9aSArmin Le Grand *pTmp++ = (sal_uInt8) --nCount;
90645fd3b9aSArmin Le Grand
90745fd3b9aSArmin Le Grand if( bRLE4 )
90845fd3b9aSArmin Le Grand {
90945fd3b9aSArmin Le Grand for ( sal_uLong i = 0; i < nCount; i++, pTmp++ )
91045fd3b9aSArmin Le Grand {
91145fd3b9aSArmin Le Grand *pTmp = rAcc.GetPixelIndex( nY, nSaveIndex++ ) << 4;
91245fd3b9aSArmin Le Grand
91345fd3b9aSArmin Le Grand if ( ++i < nCount )
91445fd3b9aSArmin Le Grand *pTmp |= rAcc.GetPixelIndex( nY, nSaveIndex++ );
91545fd3b9aSArmin Le Grand }
91645fd3b9aSArmin Le Grand
91745fd3b9aSArmin Le Grand nCount = ( nCount + 1 ) >> 1;
91845fd3b9aSArmin Le Grand }
91945fd3b9aSArmin Le Grand else
92045fd3b9aSArmin Le Grand {
92145fd3b9aSArmin Le Grand for( sal_uLong i = 0UL; i < nCount; i++ )
92245fd3b9aSArmin Le Grand *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex++ );
92345fd3b9aSArmin Le Grand }
92445fd3b9aSArmin Le Grand
92545fd3b9aSArmin Le Grand if ( nCount & 1 )
92645fd3b9aSArmin Le Grand {
92745fd3b9aSArmin Le Grand *pTmp++ = 0;
92845fd3b9aSArmin Le Grand nBufCount += ( nCount + 3 );
92945fd3b9aSArmin Le Grand }
93045fd3b9aSArmin Le Grand else
93145fd3b9aSArmin Le Grand nBufCount += ( nCount + 2 );
93245fd3b9aSArmin Le Grand }
93345fd3b9aSArmin Le Grand else
93445fd3b9aSArmin Le Grand {
93545fd3b9aSArmin Le Grand *pTmp++ = 1;
93645fd3b9aSArmin Le Grand *pTmp++ = rAcc.GetPixelIndex( nY, nSaveIndex ) << (bRLE4 ? 4 : 0);
93745fd3b9aSArmin Le Grand
93845fd3b9aSArmin Le Grand if ( nCount == 3 )
93945fd3b9aSArmin Le Grand {
94045fd3b9aSArmin Le Grand *pTmp++ = 1;
94145fd3b9aSArmin Le Grand *pTmp++ = rAcc.GetPixelIndex( nY, ++nSaveIndex ) << ( bRLE4 ? 4 : 0 );
94245fd3b9aSArmin Le Grand nBufCount += 4;
94345fd3b9aSArmin Le Grand }
94445fd3b9aSArmin Le Grand else
94545fd3b9aSArmin Le Grand nBufCount += 2;
94645fd3b9aSArmin Le Grand }
94745fd3b9aSArmin Le Grand }
94845fd3b9aSArmin Le Grand }
94945fd3b9aSArmin Le Grand
95045fd3b9aSArmin Le Grand pBuf[ nBufCount++ ] = 0;
95145fd3b9aSArmin Le Grand pBuf[ nBufCount++ ] = 0;
95245fd3b9aSArmin Le Grand
95345fd3b9aSArmin Le Grand rOStm.Write( pBuf, nBufCount );
95445fd3b9aSArmin Le Grand }
95545fd3b9aSArmin Le Grand
95645fd3b9aSArmin Le Grand rOStm << (sal_uInt8) 0;
95745fd3b9aSArmin Le Grand rOStm << (sal_uInt8) 1;
95845fd3b9aSArmin Le Grand
95945fd3b9aSArmin Le Grand delete[] pBuf;
96045fd3b9aSArmin Le Grand
96145fd3b9aSArmin Le Grand return( rOStm.GetError() == 0UL );
96245fd3b9aSArmin Le Grand }
96345fd3b9aSArmin Le Grand
ImplWriteDIBBits(SvStream & rOStm,BitmapReadAccess & rAcc,BitmapReadAccess * pAccAlpha,sal_uLong nCompression,sal_uInt32 & rImageSize)96445fd3b9aSArmin Le Grand bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, sal_uLong nCompression, sal_uInt32& rImageSize)
96545fd3b9aSArmin Le Grand {
96645fd3b9aSArmin Le Grand if(!pAccAlpha && BITFIELDS == nCompression)
96745fd3b9aSArmin Le Grand {
96845fd3b9aSArmin Le Grand const ColorMask& rMask = rAcc.GetColorMask();
96945fd3b9aSArmin Le Grand SVBT32 aVal32;
97045fd3b9aSArmin Le Grand
97145fd3b9aSArmin Le Grand UInt32ToSVBT32( rMask.GetRedMask(), aVal32 );
97245fd3b9aSArmin Le Grand rOStm.Write( (sal_uInt8*) aVal32, 4UL );
97345fd3b9aSArmin Le Grand
97445fd3b9aSArmin Le Grand UInt32ToSVBT32( rMask.GetGreenMask(), aVal32 );
97545fd3b9aSArmin Le Grand rOStm.Write( (sal_uInt8*) aVal32, 4UL );
97645fd3b9aSArmin Le Grand
97745fd3b9aSArmin Le Grand UInt32ToSVBT32( rMask.GetBlueMask(), aVal32 );
97845fd3b9aSArmin Le Grand rOStm.Write( (sal_uInt8*) aVal32, 4UL );
97945fd3b9aSArmin Le Grand
98045fd3b9aSArmin Le Grand rImageSize = rOStm.Tell();
98145fd3b9aSArmin Le Grand
98245fd3b9aSArmin Le Grand if( rAcc.IsBottomUp() )
98345fd3b9aSArmin Le Grand rOStm.Write( rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize() );
98445fd3b9aSArmin Le Grand else
98545fd3b9aSArmin Le Grand {
98645fd3b9aSArmin Le Grand for( long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0L; nY-- )
98745fd3b9aSArmin Le Grand rOStm.Write( rAcc.GetScanline( nY ), nScanlineSize );
98845fd3b9aSArmin Le Grand }
98945fd3b9aSArmin Le Grand }
99045fd3b9aSArmin Le Grand else if(!pAccAlpha && ((RLE_4 == nCompression) || (RLE_8 == nCompression)))
99145fd3b9aSArmin Le Grand {
99245fd3b9aSArmin Le Grand rImageSize = rOStm.Tell();
99345fd3b9aSArmin Le Grand ImplWriteRLE( rOStm, rAcc, RLE_4 == nCompression );
99445fd3b9aSArmin Le Grand }
99545fd3b9aSArmin Le Grand else if(!nCompression)
99645fd3b9aSArmin Le Grand {
99745fd3b9aSArmin Le Grand // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are not
99845fd3b9aSArmin Le Grand // handled properly below (would have to set color masks, and
99945fd3b9aSArmin Le Grand // nCompression=BITFIELDS - but color mask is not set for
100045fd3b9aSArmin Le Grand // formats != *_TC_*). Note that this very problem might cause
100145fd3b9aSArmin Le Grand // trouble at other places - the introduction of 32 bit RGBA
100245fd3b9aSArmin Le Grand // bitmaps is relatively recent.
100345fd3b9aSArmin Le Grand // #i59239# discretize bitcount for aligned width to 1,4,8,24
100445fd3b9aSArmin Le Grand // (other cases are not written below)
100545fd3b9aSArmin Le Grand const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
100645fd3b9aSArmin Le Grand const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * nBitCount));
100745fd3b9aSArmin Le Grand bool bNative(false);
100845fd3b9aSArmin Le Grand
100945fd3b9aSArmin Le Grand switch(rAcc.GetScanlineFormat())
101045fd3b9aSArmin Le Grand {
101145fd3b9aSArmin Le Grand case( BMP_FORMAT_1BIT_MSB_PAL ):
101245fd3b9aSArmin Le Grand case( BMP_FORMAT_4BIT_MSN_PAL ):
101345fd3b9aSArmin Le Grand case( BMP_FORMAT_8BIT_PAL ):
101445fd3b9aSArmin Le Grand case( BMP_FORMAT_24BIT_TC_BGR ):
101545fd3b9aSArmin Le Grand {
101645fd3b9aSArmin Le Grand if(!pAccAlpha && rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth))
101745fd3b9aSArmin Le Grand {
101845fd3b9aSArmin Le Grand bNative = true;
101945fd3b9aSArmin Le Grand }
102045fd3b9aSArmin Le Grand
102145fd3b9aSArmin Le Grand break;
102245fd3b9aSArmin Le Grand }
102345fd3b9aSArmin Le Grand
102445fd3b9aSArmin Le Grand default:
102545fd3b9aSArmin Le Grand {
102645fd3b9aSArmin Le Grand break;
102745fd3b9aSArmin Le Grand }
102845fd3b9aSArmin Le Grand }
102945fd3b9aSArmin Le Grand
103045fd3b9aSArmin Le Grand rImageSize = rOStm.Tell();
103145fd3b9aSArmin Le Grand
103245fd3b9aSArmin Le Grand if(bNative)
103345fd3b9aSArmin Le Grand {
103445fd3b9aSArmin Le Grand rOStm.Write(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height());
103545fd3b9aSArmin Le Grand }
103645fd3b9aSArmin Le Grand else
103745fd3b9aSArmin Le Grand {
103845fd3b9aSArmin Le Grand const long nWidth(rAcc.Width());
103945fd3b9aSArmin Le Grand const long nHeight(rAcc.Height());
104045fd3b9aSArmin Le Grand sal_uInt8* pBuf = new sal_uInt8[ nAlignedWidth ];
104145fd3b9aSArmin Le Grand sal_uInt8* pTmp(0);
104245fd3b9aSArmin Le Grand sal_uInt8 cTmp(0);
104345fd3b9aSArmin Le Grand
104445fd3b9aSArmin Le Grand switch( nBitCount )
104545fd3b9aSArmin Le Grand {
104645fd3b9aSArmin Le Grand case( 1 ):
104745fd3b9aSArmin Le Grand {
104845fd3b9aSArmin Le Grand for( long nY = nHeight - 1; nY >= 0L; nY-- )
104945fd3b9aSArmin Le Grand {
105045fd3b9aSArmin Le Grand pTmp = pBuf;
105145fd3b9aSArmin Le Grand cTmp = 0;
105245fd3b9aSArmin Le Grand
105345fd3b9aSArmin Le Grand for( long nX = 0L, nShift = 8L; nX < nWidth; nX++ )
105445fd3b9aSArmin Le Grand {
105545fd3b9aSArmin Le Grand if( !nShift )
105645fd3b9aSArmin Le Grand {
105745fd3b9aSArmin Le Grand nShift = 8L;
105845fd3b9aSArmin Le Grand *pTmp++ = cTmp;
105945fd3b9aSArmin Le Grand cTmp = 0;
106045fd3b9aSArmin Le Grand }
106145fd3b9aSArmin Le Grand
106245fd3b9aSArmin Le Grand cTmp |= rAcc.GetPixelIndex( nY, nX ) << --nShift;
106345fd3b9aSArmin Le Grand }
106445fd3b9aSArmin Le Grand
106545fd3b9aSArmin Le Grand *pTmp = cTmp;
106645fd3b9aSArmin Le Grand rOStm.Write( pBuf, nAlignedWidth );
106745fd3b9aSArmin Le Grand }
106845fd3b9aSArmin Le Grand }
106945fd3b9aSArmin Le Grand break;
107045fd3b9aSArmin Le Grand
107145fd3b9aSArmin Le Grand case( 4 ):
107245fd3b9aSArmin Le Grand {
107345fd3b9aSArmin Le Grand for( long nY = nHeight - 1; nY >= 0L; nY-- )
107445fd3b9aSArmin Le Grand {
107545fd3b9aSArmin Le Grand pTmp = pBuf;
107645fd3b9aSArmin Le Grand cTmp = 0;
107745fd3b9aSArmin Le Grand
107845fd3b9aSArmin Le Grand for( long nX = 0L, nShift = 2L; nX < nWidth; nX++ )
107945fd3b9aSArmin Le Grand {
108045fd3b9aSArmin Le Grand if( !nShift )
108145fd3b9aSArmin Le Grand {
108245fd3b9aSArmin Le Grand nShift = 2L;
108345fd3b9aSArmin Le Grand *pTmp++ = cTmp;
108445fd3b9aSArmin Le Grand cTmp = 0;
108545fd3b9aSArmin Le Grand }
108645fd3b9aSArmin Le Grand
108745fd3b9aSArmin Le Grand cTmp |= rAcc.GetPixelIndex( nY, nX ) << ( --nShift << 2L );
108845fd3b9aSArmin Le Grand }
108945fd3b9aSArmin Le Grand *pTmp = cTmp;
109045fd3b9aSArmin Le Grand rOStm.Write( pBuf, nAlignedWidth );
109145fd3b9aSArmin Le Grand }
109245fd3b9aSArmin Le Grand }
109345fd3b9aSArmin Le Grand break;
109445fd3b9aSArmin Le Grand
109545fd3b9aSArmin Le Grand case( 8 ):
109645fd3b9aSArmin Le Grand {
109745fd3b9aSArmin Le Grand for( long nY = nHeight - 1; nY >= 0L; nY-- )
109845fd3b9aSArmin Le Grand {
109945fd3b9aSArmin Le Grand pTmp = pBuf;
110045fd3b9aSArmin Le Grand
110145fd3b9aSArmin Le Grand for( long nX = 0L; nX < nWidth; nX++ )
110245fd3b9aSArmin Le Grand *pTmp++ = rAcc.GetPixelIndex( nY, nX );
110345fd3b9aSArmin Le Grand
110445fd3b9aSArmin Le Grand rOStm.Write( pBuf, nAlignedWidth );
110545fd3b9aSArmin Le Grand }
110645fd3b9aSArmin Le Grand }
110745fd3b9aSArmin Le Grand break;
110845fd3b9aSArmin Le Grand
110945fd3b9aSArmin Le Grand // #i59239# fallback to 24 bit format, if bitcount is non-default
111045fd3b9aSArmin Le Grand default:
111145fd3b9aSArmin Le Grand // FALLTHROUGH intended
111245fd3b9aSArmin Le Grand case( 24 ):
111345fd3b9aSArmin Le Grand {
111445fd3b9aSArmin Le Grand BitmapColor aPixelColor;
111545fd3b9aSArmin Le Grand const bool bWriteAlpha(32 == nBitCount && pAccAlpha);
111645fd3b9aSArmin Le Grand
111745fd3b9aSArmin Le Grand for( long nY = nHeight - 1; nY >= 0L; nY-- )
111845fd3b9aSArmin Le Grand {
111945fd3b9aSArmin Le Grand pTmp = pBuf;
112045fd3b9aSArmin Le Grand
112145fd3b9aSArmin Le Grand for( long nX = 0L; nX < nWidth; nX++ )
112245fd3b9aSArmin Le Grand {
112345fd3b9aSArmin Le Grand // when alpha is used, this may be non-24bit main bitmap, so use GetColor
112445fd3b9aSArmin Le Grand // instead of GetPixel to ensure RGB value
112545fd3b9aSArmin Le Grand aPixelColor = rAcc.GetColor( nY, nX );
112645fd3b9aSArmin Le Grand
112745fd3b9aSArmin Le Grand *pTmp++ = aPixelColor.GetBlue();
112845fd3b9aSArmin Le Grand *pTmp++ = aPixelColor.GetGreen();
112945fd3b9aSArmin Le Grand *pTmp++ = aPixelColor.GetRed();
113045fd3b9aSArmin Le Grand
113145fd3b9aSArmin Le Grand if(bWriteAlpha)
113245fd3b9aSArmin Le Grand {
113345fd3b9aSArmin Le Grand if(pAccAlpha)
113445fd3b9aSArmin Le Grand {
113545fd3b9aSArmin Le Grand *pTmp++ = (sal_uInt8)0xff - (sal_uInt8)pAccAlpha->GetPixelIndex( nY, nX );
113645fd3b9aSArmin Le Grand }
113745fd3b9aSArmin Le Grand else
113845fd3b9aSArmin Le Grand {
113945fd3b9aSArmin Le Grand *pTmp++ = (sal_uInt8)0xff;
114045fd3b9aSArmin Le Grand }
114145fd3b9aSArmin Le Grand }
114245fd3b9aSArmin Le Grand }
114345fd3b9aSArmin Le Grand
114445fd3b9aSArmin Le Grand rOStm.Write( pBuf, nAlignedWidth );
114545fd3b9aSArmin Le Grand }
114645fd3b9aSArmin Le Grand }
114745fd3b9aSArmin Le Grand break;
114845fd3b9aSArmin Le Grand }
114945fd3b9aSArmin Le Grand
115045fd3b9aSArmin Le Grand delete[] pBuf;
115145fd3b9aSArmin Le Grand }
115245fd3b9aSArmin Le Grand }
115345fd3b9aSArmin Le Grand
115445fd3b9aSArmin Le Grand rImageSize = rOStm.Tell() - rImageSize;
115545fd3b9aSArmin Le Grand
115645fd3b9aSArmin Le Grand return (!rOStm.GetError());
115745fd3b9aSArmin Le Grand }
115845fd3b9aSArmin Le Grand
ImplWriteDIBBody(const Bitmap & rBitmap,SvStream & rOStm,BitmapReadAccess & rAcc,BitmapReadAccess * pAccAlpha,bool bCompressed)115945fd3b9aSArmin Le Grand bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess& rAcc, BitmapReadAccess* pAccAlpha, bool bCompressed)
116045fd3b9aSArmin Le Grand {
116145fd3b9aSArmin Le Grand const MapMode aMapPixel(MAP_PIXEL);
116245fd3b9aSArmin Le Grand DIBV5Header aHeader;
116345fd3b9aSArmin Le Grand sal_uLong nImageSizePos(0);
116445fd3b9aSArmin Le Grand sal_uLong nEndPos(0);
116545fd3b9aSArmin Le Grand sal_uInt32 nCompression(COMPRESS_NONE);
116645fd3b9aSArmin Le Grand bool bRet(false);
116745fd3b9aSArmin Le Grand
116845fd3b9aSArmin Le Grand aHeader.nSize = pAccAlpha ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE; // size dependent on CF_DIB type to use
116945fd3b9aSArmin Le Grand aHeader.nWidth = rAcc.Width();
117045fd3b9aSArmin Le Grand aHeader.nHeight = rAcc.Height();
117145fd3b9aSArmin Le Grand aHeader.nPlanes = 1;
117245fd3b9aSArmin Le Grand
117345fd3b9aSArmin Le Grand if(!pAccAlpha && isBitfieldCompression(rAcc.GetScanlineFormat()))
117445fd3b9aSArmin Le Grand {
117545fd3b9aSArmin Le Grand aHeader.nBitCount = (BMP_FORMAT_16BIT_TC_LSB_MASK == rAcc.GetScanlineFormat()) ? 16 : 32;
117645fd3b9aSArmin Le Grand aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize();
117745fd3b9aSArmin Le Grand nCompression = BITFIELDS;
117845fd3b9aSArmin Le Grand }
117945fd3b9aSArmin Le Grand else
118045fd3b9aSArmin Le Grand {
118145fd3b9aSArmin Le Grand // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are
118245fd3b9aSArmin Le Grand // not handled properly below (would have to set color
118345fd3b9aSArmin Le Grand // masks, and nCompression=BITFIELDS - but color mask is
118445fd3b9aSArmin Le Grand // not set for formats != *_TC_*). Note that this very
118545fd3b9aSArmin Le Grand // problem might cause trouble at other places - the
118645fd3b9aSArmin Le Grand // introduction of 32 bit RGBA bitmaps is relatively
118745fd3b9aSArmin Le Grand // recent.
118845fd3b9aSArmin Le Grand // #i59239# discretize bitcount to 1,4,8,24 (other cases
118945fd3b9aSArmin Le Grand // are not written below)
119045fd3b9aSArmin Le Grand const sal_uInt16 nBitCount(pAccAlpha ? 32 : discretizeBitcount(static_cast< sal_uInt16 >(rAcc.GetBitCount())));
119145fd3b9aSArmin Le Grand aHeader.nBitCount = nBitCount;
119245fd3b9aSArmin Le Grand aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount);
119345fd3b9aSArmin Le Grand
119445fd3b9aSArmin Le Grand if(bCompressed)
119545fd3b9aSArmin Le Grand {
119645fd3b9aSArmin Le Grand if(4 == nBitCount)
119745fd3b9aSArmin Le Grand {
119845fd3b9aSArmin Le Grand nCompression = RLE_4;
119945fd3b9aSArmin Le Grand }
120045fd3b9aSArmin Le Grand else if(8 == nBitCount)
120145fd3b9aSArmin Le Grand {
120245fd3b9aSArmin Le Grand nCompression = RLE_8;
120345fd3b9aSArmin Le Grand }
120445fd3b9aSArmin Le Grand }
120545fd3b9aSArmin Le Grand }
120645fd3b9aSArmin Le Grand
120745fd3b9aSArmin Le Grand if((rOStm.GetCompressMode() & COMPRESSMODE_ZBITMAP) && (rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40))
120845fd3b9aSArmin Le Grand {
120945fd3b9aSArmin Le Grand aHeader.nCompression = ZCOMPRESS;
121045fd3b9aSArmin Le Grand }
121145fd3b9aSArmin Le Grand else
121245fd3b9aSArmin Le Grand {
121345fd3b9aSArmin Le Grand aHeader.nCompression = nCompression;
121445fd3b9aSArmin Le Grand }
121545fd3b9aSArmin Le Grand
121645fd3b9aSArmin Le Grand if(rBitmap.GetPrefSize().Width() && rBitmap.GetPrefSize().Height() && (rBitmap.GetPrefMapMode() != aMapPixel))
121745fd3b9aSArmin Le Grand {
121845fd3b9aSArmin Le Grand // #i48108# Try to recover xpels/ypels as previously stored on
121945fd3b9aSArmin Le Grand // disk. The problem with just converting maPrefSize to 100th
122045fd3b9aSArmin Le Grand // mm and then relating that to the bitmap pixel size is that
122145fd3b9aSArmin Le Grand // MapMode is integer-based, and suffers from roundoffs,
122245fd3b9aSArmin Le Grand // especially if maPrefSize is small. Trying to circumvent
122345fd3b9aSArmin Le Grand // that by performing part of the math in floating point.
122445fd3b9aSArmin Le Grand const Size aScale100000(OutputDevice::LogicToLogic(Size(100000L, 100000L), MAP_100TH_MM, rBitmap.GetPrefMapMode()));
122545fd3b9aSArmin Le Grand const double fBmpWidthM((double)rBitmap.GetPrefSize().Width() / aScale100000.Width());
122645fd3b9aSArmin Le Grand const double fBmpHeightM((double)rBitmap.GetPrefSize().Height() / aScale100000.Height());
122745fd3b9aSArmin Le Grand
122845fd3b9aSArmin Le Grand if(!basegfx::fTools::equalZero(fBmpWidthM) && !basegfx::fTools::equalZero(fBmpHeightM))
122945fd3b9aSArmin Le Grand {
123045fd3b9aSArmin Le Grand aHeader.nXPelsPerMeter = basegfx::fround(rAcc.Width() / fabs(fBmpWidthM));
123145fd3b9aSArmin Le Grand aHeader.nYPelsPerMeter = basegfx::fround(rAcc.Height() / fabs(fBmpHeightM));
123245fd3b9aSArmin Le Grand }
123345fd3b9aSArmin Le Grand }
123445fd3b9aSArmin Le Grand
123545fd3b9aSArmin Le Grand aHeader.nColsUsed = ((!pAccAlpha && aHeader.nBitCount <= 8) ? rAcc.GetPaletteEntryCount() : 0);
123645fd3b9aSArmin Le Grand aHeader.nColsImportant = 0;
123745fd3b9aSArmin Le Grand
123845fd3b9aSArmin Le Grand rOStm << aHeader.nSize;
123945fd3b9aSArmin Le Grand rOStm << aHeader.nWidth;
124045fd3b9aSArmin Le Grand rOStm << aHeader.nHeight;
124145fd3b9aSArmin Le Grand rOStm << aHeader.nPlanes;
124245fd3b9aSArmin Le Grand rOStm << aHeader.nBitCount;
124345fd3b9aSArmin Le Grand rOStm << aHeader.nCompression;
124445fd3b9aSArmin Le Grand
124545fd3b9aSArmin Le Grand nImageSizePos = rOStm.Tell();
124645fd3b9aSArmin Le Grand rOStm.SeekRel( sizeof( aHeader.nSizeImage ) );
124745fd3b9aSArmin Le Grand
124845fd3b9aSArmin Le Grand rOStm << aHeader.nXPelsPerMeter;
124945fd3b9aSArmin Le Grand rOStm << aHeader.nYPelsPerMeter;
125045fd3b9aSArmin Le Grand rOStm << aHeader.nColsUsed;
125145fd3b9aSArmin Le Grand rOStm << aHeader.nColsImportant;
125245fd3b9aSArmin Le Grand
125345fd3b9aSArmin Le Grand if(pAccAlpha) // only write DIBV5 when asked to do so
125445fd3b9aSArmin Le Grand {
125545fd3b9aSArmin Le Grand aHeader.nV5CSType = 0x57696E20; // LCS_WINDOWS_COLOR_SPACE
1256c7a371deSArmin Le Grand aHeader.nV5Intent = 0x00000004; // LCS_GM_IMAGES
125745fd3b9aSArmin Le Grand
125845fd3b9aSArmin Le Grand rOStm << aHeader.nV5RedMask;
125945fd3b9aSArmin Le Grand rOStm << aHeader.nV5GreenMask;
126045fd3b9aSArmin Le Grand rOStm << aHeader.nV5BlueMask;
126145fd3b9aSArmin Le Grand rOStm << aHeader.nV5AlphaMask;
126245fd3b9aSArmin Le Grand rOStm << aHeader.nV5CSType;
126345fd3b9aSArmin Le Grand
126445fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzX;
126545fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzY;
126645fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzRed.aXyzZ;
126745fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzX;
126845fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzY;
126945fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzGreen.aXyzZ;
127045fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzX;
127145fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzY;
127245fd3b9aSArmin Le Grand rOStm << aHeader.aV5Endpoints.aXyzBlue.aXyzZ;
127345fd3b9aSArmin Le Grand
127445fd3b9aSArmin Le Grand rOStm << aHeader.nV5GammaRed;
127545fd3b9aSArmin Le Grand rOStm << aHeader.nV5GammaGreen;
127645fd3b9aSArmin Le Grand rOStm << aHeader.nV5GammaBlue;
127745fd3b9aSArmin Le Grand rOStm << aHeader.nV5Intent;
127845fd3b9aSArmin Le Grand rOStm << aHeader.nV5ProfileData;
127945fd3b9aSArmin Le Grand rOStm << aHeader.nV5ProfileSize;
128045fd3b9aSArmin Le Grand rOStm << aHeader.nV5Reserved;
128145fd3b9aSArmin Le Grand }
128245fd3b9aSArmin Le Grand
128345fd3b9aSArmin Le Grand if(ZCOMPRESS == aHeader.nCompression)
128445fd3b9aSArmin Le Grand {
128545fd3b9aSArmin Le Grand ZCodec aCodec;
128645fd3b9aSArmin Le Grand SvMemoryStream aMemStm(aHeader.nSizeImage + 4096, 65535);
128745fd3b9aSArmin Le Grand sal_uLong nCodedPos(rOStm.Tell());
128845fd3b9aSArmin Le Grand sal_uLong nLastPos(0);
128945fd3b9aSArmin Le Grand sal_uInt32 nCodedSize(0);
129045fd3b9aSArmin Le Grand sal_uInt32 nUncodedSize(0);
129145fd3b9aSArmin Le Grand
129245fd3b9aSArmin Le Grand // write uncoded data palette
129345fd3b9aSArmin Le Grand if(aHeader.nColsUsed)
129445fd3b9aSArmin Le Grand {
129545fd3b9aSArmin Le Grand ImplWriteDIBPalette(aMemStm, rAcc);
129645fd3b9aSArmin Le Grand }
129745fd3b9aSArmin Le Grand
129845fd3b9aSArmin Le Grand // write uncoded bits
129945fd3b9aSArmin Le Grand bRet = ImplWriteDIBBits(aMemStm, rAcc, pAccAlpha, nCompression, aHeader.nSizeImage);
130045fd3b9aSArmin Le Grand
130145fd3b9aSArmin Le Grand // get uncoded size
130245fd3b9aSArmin Le Grand nUncodedSize = aMemStm.Tell();
130345fd3b9aSArmin Le Grand
130445fd3b9aSArmin Le Grand // seek over compress info
130545fd3b9aSArmin Le Grand rOStm.SeekRel(12);
130645fd3b9aSArmin Le Grand
130745fd3b9aSArmin Le Grand // write compressed data
130845fd3b9aSArmin Le Grand aCodec.BeginCompression(3);
130945fd3b9aSArmin Le Grand aCodec.Write(rOStm, (sal_uInt8*)aMemStm.GetData(), nUncodedSize);
131045fd3b9aSArmin Le Grand aCodec.EndCompression();
131145fd3b9aSArmin Le Grand
131245fd3b9aSArmin Le Grand // update compress info ( coded size, uncoded size, uncoded compression )
131345fd3b9aSArmin Le Grand nLastPos = rOStm.Tell();
131445fd3b9aSArmin Le Grand nCodedSize = nLastPos - nCodedPos - 12;
131545fd3b9aSArmin Le Grand rOStm.Seek(nCodedPos);
131645fd3b9aSArmin Le Grand rOStm << nCodedSize << nUncodedSize << nCompression;
131745fd3b9aSArmin Le Grand rOStm.Seek(nLastPos);
131845fd3b9aSArmin Le Grand
131945fd3b9aSArmin Le Grand if(bRet)
132045fd3b9aSArmin Le Grand {
132145fd3b9aSArmin Le Grand bRet = (ERRCODE_NONE == rOStm.GetError());
132245fd3b9aSArmin Le Grand }
132345fd3b9aSArmin Le Grand }
132445fd3b9aSArmin Le Grand else
132545fd3b9aSArmin Le Grand {
132645fd3b9aSArmin Le Grand if(aHeader.nColsUsed)
132745fd3b9aSArmin Le Grand {
132845fd3b9aSArmin Le Grand ImplWriteDIBPalette(rOStm, rAcc);
132945fd3b9aSArmin Le Grand }
133045fd3b9aSArmin Le Grand
133145fd3b9aSArmin Le Grand bRet = ImplWriteDIBBits(rOStm, rAcc, pAccAlpha, aHeader.nCompression, aHeader.nSizeImage);
133245fd3b9aSArmin Le Grand }
133345fd3b9aSArmin Le Grand
133445fd3b9aSArmin Le Grand nEndPos = rOStm.Tell();
133545fd3b9aSArmin Le Grand rOStm.Seek(nImageSizePos);
133645fd3b9aSArmin Le Grand rOStm << aHeader.nSizeImage;
133745fd3b9aSArmin Le Grand rOStm.Seek(nEndPos);
133845fd3b9aSArmin Le Grand
133945fd3b9aSArmin Le Grand return bRet;
134045fd3b9aSArmin Le Grand }
134145fd3b9aSArmin Le Grand
ImplWriteDIBFileHeader(SvStream & rOStm,BitmapReadAccess & rAcc,bool bUseDIBV5)134245fd3b9aSArmin Le Grand bool ImplWriteDIBFileHeader(SvStream& rOStm, BitmapReadAccess& rAcc, bool bUseDIBV5)
134345fd3b9aSArmin Le Grand {
134445fd3b9aSArmin Le Grand const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : isBitfieldCompression(rAcc.GetScanlineFormat()) ? 3UL : 0UL));
134545fd3b9aSArmin Le Grand const sal_uInt32 nOffset(14 + (bUseDIBV5 ? DIBV5HEADERSIZE : DIBINFOHEADERSIZE) + nPalCount * 4UL);
134645fd3b9aSArmin Le Grand
134745fd3b9aSArmin Le Grand rOStm << (sal_uInt16)0x4D42; // 'MB' from BITMAPFILEHEADER
134845fd3b9aSArmin Le Grand rOStm << (sal_uInt32)(nOffset + (rAcc.Height() * rAcc.GetScanlineSize()));
134945fd3b9aSArmin Le Grand rOStm << (sal_uInt16)0;
135045fd3b9aSArmin Le Grand rOStm << (sal_uInt16)0;
135145fd3b9aSArmin Le Grand rOStm << nOffset;
135245fd3b9aSArmin Le Grand
135345fd3b9aSArmin Le Grand return( rOStm.GetError() == 0UL );
135445fd3b9aSArmin Le Grand }
135545fd3b9aSArmin Le Grand
135645fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
135745fd3b9aSArmin Le Grand
ImplReadDIB(Bitmap & rTarget,Bitmap * pTargetAlpha,SvStream & rIStm,bool bFileHeader)135845fd3b9aSArmin Le Grand bool ImplReadDIB(
135945fd3b9aSArmin Le Grand Bitmap& rTarget, Bitmap*
136045fd3b9aSArmin Le Grand pTargetAlpha,
136145fd3b9aSArmin Le Grand SvStream& rIStm,
136245fd3b9aSArmin Le Grand bool bFileHeader)
136345fd3b9aSArmin Le Grand {
136445fd3b9aSArmin Le Grand const sal_uInt16 nOldFormat(rIStm.GetNumberFormatInt());
136545fd3b9aSArmin Le Grand const sal_uLong nOldPos(rIStm.Tell());
136645fd3b9aSArmin Le Grand sal_uLong nOffset(0UL);
136745fd3b9aSArmin Le Grand bool bRet(false);
136845fd3b9aSArmin Le Grand
136945fd3b9aSArmin Le Grand rIStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
137045fd3b9aSArmin Le Grand
137145fd3b9aSArmin Le Grand if(bFileHeader)
137245fd3b9aSArmin Le Grand {
137345fd3b9aSArmin Le Grand if(ImplReadDIBFileHeader(rIStm, nOffset))
137445fd3b9aSArmin Le Grand {
137545fd3b9aSArmin Le Grand bRet = ImplReadDIBBody(rIStm, rTarget, nOffset >= DIBV5HEADERSIZE ? pTargetAlpha : 0, nOffset);
137645fd3b9aSArmin Le Grand }
137745fd3b9aSArmin Le Grand }
137845fd3b9aSArmin Le Grand else
137945fd3b9aSArmin Le Grand {
138045fd3b9aSArmin Le Grand bRet = ImplReadDIBBody(rIStm, rTarget, 0, nOffset);
138145fd3b9aSArmin Le Grand }
138245fd3b9aSArmin Le Grand
138345fd3b9aSArmin Le Grand if(!bRet)
138445fd3b9aSArmin Le Grand {
138545fd3b9aSArmin Le Grand if(!rIStm.GetError())
138645fd3b9aSArmin Le Grand {
138745fd3b9aSArmin Le Grand rIStm.SetError(SVSTREAM_GENERALERROR);
138845fd3b9aSArmin Le Grand }
138945fd3b9aSArmin Le Grand
139045fd3b9aSArmin Le Grand rIStm.Seek(nOldPos);
139145fd3b9aSArmin Le Grand }
139245fd3b9aSArmin Le Grand
139345fd3b9aSArmin Le Grand rIStm.SetNumberFormatInt(nOldFormat);
139445fd3b9aSArmin Le Grand
139545fd3b9aSArmin Le Grand return bRet;
139645fd3b9aSArmin Le Grand }
139745fd3b9aSArmin Le Grand
ImplWriteDIB(const Bitmap & rSource,const Bitmap * pSourceAlpha,SvStream & rOStm,bool bCompressed,bool bFileHeader)139845fd3b9aSArmin Le Grand bool ImplWriteDIB(
139945fd3b9aSArmin Le Grand const Bitmap& rSource,
140045fd3b9aSArmin Le Grand const Bitmap* pSourceAlpha,
140145fd3b9aSArmin Le Grand SvStream& rOStm,
140245fd3b9aSArmin Le Grand bool bCompressed,
140345fd3b9aSArmin Le Grand bool bFileHeader)
140445fd3b9aSArmin Le Grand {
140545fd3b9aSArmin Le Grand const Size aSizePix(rSource.GetSizePixel());
140645fd3b9aSArmin Le Grand bool bRet(false);
140745fd3b9aSArmin Le Grand
140845fd3b9aSArmin Le Grand if(aSizePix.Width() && aSizePix.Height())
140945fd3b9aSArmin Le Grand {
141045fd3b9aSArmin Le Grand BitmapReadAccess* pAcc = const_cast< Bitmap& >(rSource).AcquireReadAccess();
141145fd3b9aSArmin Le Grand BitmapReadAccess* pAccAlpha = 0;
141245fd3b9aSArmin Le Grand const sal_uInt16 nOldFormat(rOStm.GetNumberFormatInt());
141345fd3b9aSArmin Le Grand const sal_uLong nOldPos(rOStm.Tell());
141445fd3b9aSArmin Le Grand
141545fd3b9aSArmin Le Grand if(pSourceAlpha)
141645fd3b9aSArmin Le Grand {
141745fd3b9aSArmin Le Grand const Size aSizePixAlpha(pSourceAlpha->GetSizePixel());
141845fd3b9aSArmin Le Grand
141945fd3b9aSArmin Le Grand if(aSizePixAlpha == aSizePix)
142045fd3b9aSArmin Le Grand {
142145fd3b9aSArmin Le Grand pAccAlpha = const_cast< Bitmap* >(pSourceAlpha)->AcquireReadAccess();
142245fd3b9aSArmin Le Grand }
142345fd3b9aSArmin Le Grand else
142445fd3b9aSArmin Le Grand {
142545fd3b9aSArmin Le Grand OSL_ENSURE(false, "WriteDIB got an alpha channel, but it's pixel size differs from the base bitmap (!)");
142645fd3b9aSArmin Le Grand }
142745fd3b9aSArmin Le Grand }
142845fd3b9aSArmin Le Grand
142945fd3b9aSArmin Le Grand rOStm.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
143045fd3b9aSArmin Le Grand
143145fd3b9aSArmin Le Grand if(pAcc)
143245fd3b9aSArmin Le Grand {
143345fd3b9aSArmin Le Grand if(bFileHeader)
143445fd3b9aSArmin Le Grand {
143545fd3b9aSArmin Le Grand if(ImplWriteDIBFileHeader(rOStm, *pAcc, 0 != pSourceAlpha))
143645fd3b9aSArmin Le Grand {
143745fd3b9aSArmin Le Grand bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
143845fd3b9aSArmin Le Grand }
143945fd3b9aSArmin Le Grand }
144045fd3b9aSArmin Le Grand else
144145fd3b9aSArmin Le Grand {
144245fd3b9aSArmin Le Grand bRet = ImplWriteDIBBody(rSource, rOStm, *pAcc, pAccAlpha, bCompressed);
144345fd3b9aSArmin Le Grand }
144445fd3b9aSArmin Le Grand
144545fd3b9aSArmin Le Grand const_cast< Bitmap& >(rSource).ReleaseAccess(pAcc);
144645fd3b9aSArmin Le Grand
144745fd3b9aSArmin Le Grand if(pAccAlpha)
144845fd3b9aSArmin Le Grand {
144945fd3b9aSArmin Le Grand const_cast< Bitmap* >(pSourceAlpha)->ReleaseAccess(pAccAlpha);
145045fd3b9aSArmin Le Grand }
145145fd3b9aSArmin Le Grand }
145245fd3b9aSArmin Le Grand
145345fd3b9aSArmin Le Grand if(!bRet)
145445fd3b9aSArmin Le Grand {
145545fd3b9aSArmin Le Grand rOStm.SetError(SVSTREAM_GENERALERROR);
145645fd3b9aSArmin Le Grand rOStm.Seek(nOldPos);
145745fd3b9aSArmin Le Grand }
145845fd3b9aSArmin Le Grand
145945fd3b9aSArmin Le Grand rOStm.SetNumberFormatInt(nOldFormat);
146045fd3b9aSArmin Le Grand }
146145fd3b9aSArmin Le Grand
146245fd3b9aSArmin Le Grand return bRet;
146345fd3b9aSArmin Le Grand }
146445fd3b9aSArmin Le Grand
146545fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
146645fd3b9aSArmin Le Grand
ReadDIB(Bitmap & rTarget,SvStream & rIStm,bool bFileHeader)146745fd3b9aSArmin Le Grand bool ReadDIB(
146845fd3b9aSArmin Le Grand Bitmap& rTarget,
146945fd3b9aSArmin Le Grand SvStream& rIStm,
147045fd3b9aSArmin Le Grand bool bFileHeader)
147145fd3b9aSArmin Le Grand {
147245fd3b9aSArmin Le Grand return ImplReadDIB(rTarget, 0, rIStm, bFileHeader);
147345fd3b9aSArmin Le Grand }
147445fd3b9aSArmin Le Grand
ReadDIBBitmapEx(BitmapEx & rTarget,SvStream & rIStm)147545fd3b9aSArmin Le Grand bool ReadDIBBitmapEx(
147645fd3b9aSArmin Le Grand BitmapEx& rTarget,
147745fd3b9aSArmin Le Grand SvStream& rIStm)
147845fd3b9aSArmin Le Grand {
147945fd3b9aSArmin Le Grand Bitmap aBmp;
148045fd3b9aSArmin Le Grand bool bRetval(ImplReadDIB(aBmp, 0, rIStm, true) && !rIStm.GetError());
148145fd3b9aSArmin Le Grand
148245fd3b9aSArmin Le Grand if(bRetval)
148345fd3b9aSArmin Le Grand {
148445fd3b9aSArmin Le Grand // base bitmap was read, set as return value and try to read alpha extra-data
148545fd3b9aSArmin Le Grand const sal_uLong nStmPos(rIStm.Tell());
148645fd3b9aSArmin Le Grand sal_uInt32 nMagic1(0);
148745fd3b9aSArmin Le Grand sal_uInt32 nMagic2(0);
148845fd3b9aSArmin Le Grand
148945fd3b9aSArmin Le Grand rTarget = BitmapEx(aBmp);
149045fd3b9aSArmin Le Grand rIStm >> nMagic1 >> nMagic2;
149145fd3b9aSArmin Le Grand bRetval = (0x25091962 == nMagic1) && (0xACB20201 == nMagic2) && !rIStm.GetError();
149245fd3b9aSArmin Le Grand
149345fd3b9aSArmin Le Grand if(bRetval)
149445fd3b9aSArmin Le Grand {
149545fd3b9aSArmin Le Grand sal_uInt8 bTransparent(false);
149645fd3b9aSArmin Le Grand
149745fd3b9aSArmin Le Grand rIStm >> bTransparent;
149845fd3b9aSArmin Le Grand bRetval = !rIStm.GetError();
149945fd3b9aSArmin Le Grand
150045fd3b9aSArmin Le Grand if(bRetval)
150145fd3b9aSArmin Le Grand {
150245fd3b9aSArmin Le Grand if((sal_uInt8)TRANSPARENT_BITMAP == bTransparent)
150345fd3b9aSArmin Le Grand {
150445fd3b9aSArmin Le Grand Bitmap aMask;
150545fd3b9aSArmin Le Grand
150645fd3b9aSArmin Le Grand bRetval = ImplReadDIB(aMask, 0, rIStm, true);
150745fd3b9aSArmin Le Grand
150845fd3b9aSArmin Le Grand if(bRetval)
150945fd3b9aSArmin Le Grand {
151045fd3b9aSArmin Le Grand if(!!aMask)
151145fd3b9aSArmin Le Grand {
151245fd3b9aSArmin Le Grand // do we have an alpha mask?
151345fd3b9aSArmin Le Grand if((8 == aMask.GetBitCount()) && aMask.HasGreyPalette())
151445fd3b9aSArmin Le Grand {
151545fd3b9aSArmin Le Grand AlphaMask aAlpha;
151645fd3b9aSArmin Le Grand
151745fd3b9aSArmin Le Grand // create alpha mask quickly (without greyscale conversion)
151845fd3b9aSArmin Le Grand aAlpha.ImplSetBitmap(aMask);
151945fd3b9aSArmin Le Grand rTarget = BitmapEx(aBmp, aAlpha);
152045fd3b9aSArmin Le Grand }
152145fd3b9aSArmin Le Grand else
152245fd3b9aSArmin Le Grand {
152345fd3b9aSArmin Le Grand rTarget = BitmapEx(aBmp, aMask);
152445fd3b9aSArmin Le Grand }
152545fd3b9aSArmin Le Grand }
152645fd3b9aSArmin Le Grand }
152745fd3b9aSArmin Le Grand }
152845fd3b9aSArmin Le Grand else if((sal_uInt8)TRANSPARENT_COLOR == bTransparent)
152945fd3b9aSArmin Le Grand {
153045fd3b9aSArmin Le Grand Color aTransparentColor;
153145fd3b9aSArmin Le Grand
153245fd3b9aSArmin Le Grand rIStm >> aTransparentColor;
153345fd3b9aSArmin Le Grand bRetval = !rIStm.GetError();
153445fd3b9aSArmin Le Grand
153545fd3b9aSArmin Le Grand if(bRetval)
153645fd3b9aSArmin Le Grand {
153745fd3b9aSArmin Le Grand rTarget = BitmapEx(aBmp, aTransparentColor);
153845fd3b9aSArmin Le Grand }
153945fd3b9aSArmin Le Grand }
154045fd3b9aSArmin Le Grand }
154145fd3b9aSArmin Le Grand }
154245fd3b9aSArmin Le Grand
154345fd3b9aSArmin Le Grand if(!bRetval)
154445fd3b9aSArmin Le Grand {
154545fd3b9aSArmin Le Grand // alpha extra data could not be read; reset, but use base bitmap as result
154645fd3b9aSArmin Le Grand rIStm.ResetError();
154745fd3b9aSArmin Le Grand rIStm.Seek(nStmPos);
154845fd3b9aSArmin Le Grand bRetval = true;
154945fd3b9aSArmin Le Grand }
155045fd3b9aSArmin Le Grand }
155145fd3b9aSArmin Le Grand
155245fd3b9aSArmin Le Grand return bRetval;
155345fd3b9aSArmin Le Grand }
155445fd3b9aSArmin Le Grand
ReadDIBV5(Bitmap & rTarget,Bitmap & rTargetAlpha,SvStream & rIStm)155545fd3b9aSArmin Le Grand bool ReadDIBV5(
155645fd3b9aSArmin Le Grand Bitmap& rTarget,
155745fd3b9aSArmin Le Grand Bitmap& rTargetAlpha,
155845fd3b9aSArmin Le Grand SvStream& rIStm)
155945fd3b9aSArmin Le Grand {
156045fd3b9aSArmin Le Grand return ImplReadDIB(rTarget, &rTargetAlpha, rIStm, true);
156145fd3b9aSArmin Le Grand }
156245fd3b9aSArmin Le Grand
156345fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
156445fd3b9aSArmin Le Grand
WriteDIB(const Bitmap & rSource,SvStream & rOStm,bool bCompressed,bool bFileHeader)156545fd3b9aSArmin Le Grand bool WriteDIB(
156645fd3b9aSArmin Le Grand const Bitmap& rSource,
156745fd3b9aSArmin Le Grand SvStream& rOStm,
156845fd3b9aSArmin Le Grand bool bCompressed,
156945fd3b9aSArmin Le Grand bool bFileHeader)
157045fd3b9aSArmin Le Grand {
157145fd3b9aSArmin Le Grand return ImplWriteDIB(rSource, 0, rOStm, bCompressed, bFileHeader);
157245fd3b9aSArmin Le Grand }
157345fd3b9aSArmin Le Grand
WriteDIBBitmapEx(const BitmapEx & rSource,SvStream & rOStm)157445fd3b9aSArmin Le Grand bool WriteDIBBitmapEx(
157545fd3b9aSArmin Le Grand const BitmapEx& rSource,
157645fd3b9aSArmin Le Grand SvStream& rOStm)
157745fd3b9aSArmin Le Grand {
157845fd3b9aSArmin Le Grand if(ImplWriteDIB(rSource.GetBitmap(), 0, rOStm, true, true))
157945fd3b9aSArmin Le Grand {
158045fd3b9aSArmin Le Grand rOStm << (sal_uInt32)0x25091962;
158145fd3b9aSArmin Le Grand rOStm << (sal_uInt32)0xACB20201;
158245fd3b9aSArmin Le Grand rOStm << (sal_uInt8)rSource.eTransparent;
158345fd3b9aSArmin Le Grand
158445fd3b9aSArmin Le Grand if(TRANSPARENT_BITMAP == rSource.eTransparent)
158545fd3b9aSArmin Le Grand {
158645fd3b9aSArmin Le Grand return ImplWriteDIB(rSource.aMask, 0, rOStm, true, true);
158745fd3b9aSArmin Le Grand }
158845fd3b9aSArmin Le Grand else if(TRANSPARENT_COLOR == rSource.eTransparent)
158945fd3b9aSArmin Le Grand {
159045fd3b9aSArmin Le Grand rOStm << rSource.aTransparentColor;
159145fd3b9aSArmin Le Grand return true;
159245fd3b9aSArmin Le Grand }
159345fd3b9aSArmin Le Grand }
159445fd3b9aSArmin Le Grand
159545fd3b9aSArmin Le Grand return false;
159645fd3b9aSArmin Le Grand }
159745fd3b9aSArmin Le Grand
WriteDIBV5(const Bitmap & rSource,const Bitmap & rSourceAlpha,SvStream & rOStm)159845fd3b9aSArmin Le Grand bool WriteDIBV5(
159945fd3b9aSArmin Le Grand const Bitmap& rSource,
160045fd3b9aSArmin Le Grand const Bitmap& rSourceAlpha,
160145fd3b9aSArmin Le Grand SvStream& rOStm)
160245fd3b9aSArmin Le Grand {
160345fd3b9aSArmin Le Grand return ImplWriteDIB(rSource, &rSourceAlpha, rOStm, false, true);
160445fd3b9aSArmin Le Grand }
160545fd3b9aSArmin Le Grand
160645fd3b9aSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
160745fd3b9aSArmin Le Grand // eof
1608