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