diff options
Diffstat (limited to 'filter/source/graphicfilter/itga/itga.cxx')
-rw-r--r-- | filter/source/graphicfilter/itga/itga.cxx | 758 |
1 files changed, 758 insertions, 0 deletions
diff --git a/filter/source/graphicfilter/itga/itga.cxx b/filter/source/graphicfilter/itga/itga.cxx new file mode 100644 index 000000000000..5dcb5f82ccab --- /dev/null +++ b/filter/source/graphicfilter/itga/itga.cxx @@ -0,0 +1,758 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include <vcl/graph.hxx> +#include <vcl/bmpacc.hxx> +#include <svtools/fltcall.hxx> + +//============================ TGAReader ================================== + +struct TGAFileHeader +{ + BYTE nImageIDLength; + BYTE nColorMapType; + BYTE nImageType; + UINT16 nColorMapFirstEntryIndex; + UINT16 nColorMapLength; + BYTE nColorMapEntrySize; + UINT16 nColorMapXOrigin; + UINT16 nColorMapYOrigin; + UINT16 nImageWidth; + UINT16 nImageHeight; + BYTE nPixelDepth; + BYTE nImageDescriptor; +}; + +#define SizeOfTGAFileFooter 26 + +struct TGAFileFooter +{ + UINT32 nExtensionFileOffset; + UINT32 nDeveloperDirectoryOffset; + UINT32 nSignature[4]; + BYTE nPadByte; + BYTE nStringTerminator; +}; + +#define SizeOfTGAExtension 495 + +struct TGAExtension +{ + UINT16 nExtensionSize; + char sAuthorName[41]; + char sAuthorComment[324]; + char sDateTimeStamp[12]; + char sJobNameID[41]; + UINT16 nJobTime[3]; + char sSoftwareID[41]; + UINT16 nSoftwareVersionNumber; + BYTE nSoftwareVersionLetter; + UINT32 nKeyColor; + UINT16 nPixelAspectRatioNumerator; + UINT16 nPixelAspectRatioDeNumerator; + UINT16 nGammaValueNumerator; + UINT16 nGammaValueDeNumerator; + UINT32 nColorCorrectionOffset; + UINT32 nPostageStampOffset; + UINT32 nScanLineOffset; + BYTE nAttributesType; +}; + +class TGAReader { + +private: + + SvStream* mpTGA; + + BitmapWriteAccess* mpAcc; + TGAFileHeader* mpFileHeader; + TGAFileFooter* mpFileFooter; + TGAExtension* mpExtension; + UINT32* mpColorMap; + + BOOL mbStatus; + + ULONG mnTGAVersion; // Enhanced TGA is defined as Version 2.0 + UINT16 mnDestBitDepth; + BOOL mbIndexing; // TRUE if source contains indexing color values + BOOL mbEncoding; // TRUE if source is compressed + + BOOL ImplReadHeader(); + BOOL ImplReadPalette(); + BOOL ImplReadBody(); + +public: + TGAReader(); + ~TGAReader(); + BOOL ReadTGA( SvStream & rTGA, Graphic & rGraphic ); +}; + +//=================== Methoden von TGAReader ============================== + +TGAReader::TGAReader() : + mpAcc ( NULL ), + mpFileHeader ( NULL ), + mpFileFooter ( NULL ), + mpExtension ( NULL ), + mpColorMap ( NULL ), + mbStatus ( TRUE ), + mnTGAVersion ( 1 ), + mbIndexing ( FALSE ), + mbEncoding ( FALSE ) +{ +} + +TGAReader::~TGAReader() +{ + delete[] mpColorMap; + delete mpFileHeader; + delete mpExtension; + delete mpFileFooter; +} + +// ------------------------------------------------------------------------------------------- + +BOOL TGAReader::ReadTGA( SvStream & rTGA, Graphic & rGraphic ) +{ + if ( rTGA.GetError() ) + return FALSE; + + mpTGA = &rTGA; + mpTGA->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + + // Kopf einlesen: + + if ( !mpTGA->GetError() ) + { + mbStatus = ImplReadHeader(); + if ( mbStatus ) + { + Bitmap aBitmap; + + aBitmap = Bitmap( Size( mpFileHeader->nImageWidth, mpFileHeader->nImageHeight ), mnDestBitDepth ); + mpAcc = aBitmap.AcquireWriteAccess(); + if ( mpAcc ) + { + if ( mbIndexing ) + mbStatus = ImplReadPalette(); + if ( mbStatus ) + mbStatus = ImplReadBody(); + } + else + mbStatus = FALSE; + + if ( mpAcc ) + aBitmap.ReleaseAccess ( mpAcc), mpAcc = NULL; + + if ( mbStatus ) + rGraphic = aBitmap; + } + } + return mbStatus; +} + +// ------------------------------------------------------------------------------------------- + +BOOL TGAReader::ImplReadHeader() +{ + mpFileHeader = new TGAFileHeader; + if ( mpFileHeader == NULL ) + return FALSE; + + *mpTGA >> mpFileHeader->nImageIDLength >> mpFileHeader->nColorMapType >> mpFileHeader->nImageType >> + mpFileHeader->nColorMapFirstEntryIndex >> mpFileHeader->nColorMapLength >> mpFileHeader->nColorMapEntrySize >> + mpFileHeader->nColorMapXOrigin >> mpFileHeader->nColorMapYOrigin >> mpFileHeader->nImageWidth >> + mpFileHeader->nImageHeight >> mpFileHeader->nPixelDepth >> mpFileHeader->nImageDescriptor; + + if ( mpFileHeader->nColorMapType > 1 ) + return FALSE; + if ( mpFileHeader->nColorMapType == 1 ) + mbIndexing = TRUE; + + // first we want to get the version + mpFileFooter = new TGAFileFooter; // read the TGA-File-Footer to determine whether + if ( mpFileFooter ) // we got an old TGA format or the new one + { + ULONG nCurStreamPos = mpTGA->Tell(); + mpTGA->Seek( STREAM_SEEK_TO_END ); + ULONG nTemp = mpTGA->Tell(); + mpTGA->Seek( nTemp - SizeOfTGAFileFooter ); + + *mpTGA >> mpFileFooter->nExtensionFileOffset >> mpFileFooter->nDeveloperDirectoryOffset >> + mpFileFooter->nSignature[0] >> mpFileFooter->nSignature[1] >> mpFileFooter->nSignature[2] >> + mpFileFooter->nSignature[3] >> mpFileFooter->nPadByte >> mpFileFooter->nStringTerminator; + + // check for TRUE, VISI, ON-X, FILE in the signatures + if ( mpFileFooter->nSignature[ 0 ] == (('T'<<24)|('R'<<16)|('U'<<8)|'E') && + mpFileFooter->nSignature[ 1 ] == (('V'<<24)|('I'<<16)|('S'<<8)|'I') && + mpFileFooter->nSignature[ 2 ] == (('O'<<24)|('N'<<16)|('-'<<8)|'X') && + mpFileFooter->nSignature[ 3 ] == (('F'<<24)|('I'<<16)|('L'<<8)|'E') ) + { + mpExtension = new TGAExtension; + if ( mpExtension ) + { + mpTGA->Seek( mpFileFooter->nExtensionFileOffset ); + *mpTGA >> mpExtension->nExtensionSize; + if ( mpExtension->nExtensionSize >= SizeOfTGAExtension ) + { + mnTGAVersion = 2; + + mpTGA->Read( mpExtension->sAuthorName, 41 ); + mpTGA->Read( mpExtension->sAuthorComment, 324 ); + mpTGA->Read( mpExtension->sDateTimeStamp, 12 ); + mpTGA->Read( mpExtension->sJobNameID, 12 ); + *mpTGA >> mpExtension->sJobNameID[ 0 ] >> mpExtension->sJobNameID[ 1 ] >> mpExtension->sJobNameID[ 2 ]; + mpTGA->Read( mpExtension->sSoftwareID, 41 ); + *mpTGA >> mpExtension->nSoftwareVersionNumber >> mpExtension->nSoftwareVersionLetter + >> mpExtension->nKeyColor >> mpExtension->nPixelAspectRatioNumerator + >> mpExtension->nPixelAspectRatioDeNumerator >> mpExtension->nGammaValueNumerator + >> mpExtension->nGammaValueDeNumerator >> mpExtension->nColorCorrectionOffset + >> mpExtension->nPostageStampOffset >> mpExtension->nScanLineOffset + >> mpExtension->nAttributesType; + + } + } + } + mpTGA->Seek( nCurStreamPos ); + } + + // using the TGA file specification this was the correct form but adobe photoshop sets nImageDescriptor + // equal to nPixelDepth + // mnDestBitDepth = mpFileHeader->nPixelDepth - ( mpFileHeader->nImageDescriptor & 0xf ); + mnDestBitDepth = mpFileHeader->nPixelDepth; + + if ( mnDestBitDepth == 8 ) // this is a patch for grayscale pictures not including a palette + mbIndexing = TRUE; + + if ( mnDestBitDepth > 32 ) // maybe the pixeldepth is invalid + return FALSE; + else if ( mnDestBitDepth > 8 ) + mnDestBitDepth = 24; + else if ( mnDestBitDepth > 4 ) + mnDestBitDepth = 8; + else if ( mnDestBitDepth > 2 ) + mnDestBitDepth = 4; + + if ( !mbIndexing && ( mnDestBitDepth < 15 ) ) + return FALSE; + + switch ( mpFileHeader->nImageType ) + { + case 9 : // encoding for colortype 9, 10, 11 + case 10 : + case 11 : + mbEncoding = TRUE; + break; + }; + + if ( mpFileHeader->nImageIDLength ) // skip the Image ID + mpTGA->SeekRel( mpFileHeader->nImageIDLength ); + + return mbStatus; +} + +// ------------------------------------------------------------------------------------------- + +BOOL TGAReader::ImplReadBody() +{ + + USHORT nXCount, nYCount, nRGB16; + BYTE nRed, nGreen, nBlue, nRunCount, nDummy, nDepth; + + // this four variables match the image direction + long nY, nYAdd, nX, nXAdd, nXStart; + + nX = nXStart = nY = 0; + nXCount = nYCount = 0; + nYAdd = nXAdd = 1; + + if ( mpFileHeader->nImageDescriptor & 0x10 ) + { + nX = nXStart = mpFileHeader->nImageWidth - 1; + nXAdd -= 2; + } + + if ( !(mpFileHeader->nImageDescriptor & 0x20 ) ) + { + nY = mpFileHeader->nImageHeight - 1; + nYAdd -=2; + } + +// nDepth = mpFileHeader->nPixelDepth - ( mpFileHeader->nImageDescriptor & 0xf ); + nDepth = mpFileHeader->nPixelDepth; + + if ( mbEncoding ) + { + if ( mbIndexing ) + { + switch( nDepth ) + { + // 16 bit encoding + indexing + case 16 : + while ( nYCount < mpFileHeader->nImageHeight ) + { + *mpTGA >> nRunCount; + if ( nRunCount & 0x80 ) // a run length packet + { + *mpTGA >> nRGB16; + if ( nRGB16 >= mpFileHeader->nColorMapLength ) + return FALSE; + nRed = (BYTE)( mpColorMap[ nRGB16 ] >> 16 ); + nGreen = (BYTE)( mpColorMap[ nRGB16 ] >> 8 ); + nBlue = (BYTE)( mpColorMap[ nRGB16 ] ); + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + else // a raw packet + { + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + *mpTGA >> nRGB16; + if ( nRGB16 >= mpFileHeader->nColorMapLength ) + return FALSE; + nRed = (BYTE)( mpColorMap[ nRGB16 ] >> 16 ); + nGreen = (BYTE)( mpColorMap[ nRGB16 ] >> 8 ); + nBlue = (BYTE)( mpColorMap[ nRGB16 ] ); + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + } + break; + + // 8 bit encoding + indexing + case 8 : + while ( nYCount < mpFileHeader->nImageHeight ) + { + *mpTGA >> nRunCount; + if ( nRunCount & 0x80 ) // a run length packet + { + *mpTGA >> nDummy; + if ( nDummy >= mpFileHeader->nColorMapLength ) + return FALSE; + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + mpAcc->SetPixel( nY, nX, (BYTE)nDummy ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + else // a raw packet + { + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + + *mpTGA >> nDummy; + if ( nDummy >= mpFileHeader->nColorMapLength ) + return FALSE; + mpAcc->SetPixel( nY, nX, (BYTE)nDummy ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + } + break; + default: + return FALSE; + } + } + else + { + switch( nDepth ) + { + // 32 bit transparent true color encoding + case 32 : + { + while ( nYCount < mpFileHeader->nImageHeight ) + { + *mpTGA >> nRunCount; + if ( nRunCount & 0x80 ) // a run length packet + { + *mpTGA >> nBlue >> nGreen >> nRed >> nDummy; + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + else // a raw packet + { + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + *mpTGA >> nBlue >> nGreen >> nRed >> nDummy; + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + } + } + break; + + // 24 bit true color encoding + case 24 : + while ( nYCount < mpFileHeader->nImageHeight ) + { + *mpTGA >> nRunCount; + if ( nRunCount & 0x80 ) // a run length packet + { + *mpTGA >> nBlue >> nGreen >> nRed; + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + else // a raw packet + { + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + *mpTGA >> nBlue >> nGreen >> nRed; + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + } + break; + + // 16 bit true color encoding + case 16 : + while ( nYCount < mpFileHeader->nImageHeight ) + { + *mpTGA >> nRunCount; + if ( nRunCount & 0x80 ) // a run length packet + { + *mpTGA >> nRGB16; + nRed = (BYTE)( nRGB16 >> 7 ) & 0xf8; + nGreen = (BYTE)( nRGB16 >> 2 ) & 0xf8; + nBlue = (BYTE)( nRGB16 << 3 ) & 0xf8; + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + else // a raw packet + { + for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ ) + { + *mpTGA >> nRGB16; + nRed = (BYTE)( nRGB16 >> 7 ) & 0xf8; + nGreen = (BYTE)( nRGB16 >> 2 ) & 0xf8; + nBlue = (BYTE)( nRGB16 << 3 ) & 0xf8; + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + nX += nXAdd; + nXCount++; + if ( nXCount == mpFileHeader->nImageWidth ) + { + nX = nXStart; + nXCount = 0; + nY += nYAdd; + nYCount++; + } + } + } + } + break; + + default: + return FALSE; + } + } + } + else + { + for ( nYCount = 0; nYCount < mpFileHeader->nImageHeight; nYCount++, nY += nYAdd ) + { + nX = nXStart; + nXCount = 0; + + if ( mbIndexing ) + { + switch( nDepth ) + { + // 16 bit indexing + case 16 : + for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd ) + { + *mpTGA >> nRGB16; + if ( nRGB16 >= mpFileHeader->nColorMapLength ) + return FALSE; + nRed = (BYTE)( mpColorMap[ nRGB16 ] >> 16 ); + nGreen = (BYTE)( mpColorMap[ nRGB16 ] >> 8 ); + nBlue = (BYTE)( mpColorMap[ nRGB16 ] ); + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + } + break; + + // 8 bit indexing + case 8 : + for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd ) + { + *mpTGA >> nDummy; + if ( nDummy >= mpFileHeader->nColorMapLength ) + return FALSE; + mpAcc->SetPixel( nY, nX, (BYTE)nDummy ); + } + break; + default: + return FALSE; + } + } + else + { + switch( nDepth ) + { + // 32 bit true color + case 32 : + { + for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd ) + { + *mpTGA >> nBlue >> nGreen >> nRed >> nDummy; + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + } + } + break; + + // 24 bit true color + case 24 : + for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd ) + { + *mpTGA >> nBlue >> nGreen >> nRed; + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + } + break; + + // 16 bit true color + case 16 : + for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd ) + { + *mpTGA >> nRGB16; + nRed = (BYTE)( nRGB16 >> 7 ) & 0xf8; + nGreen = (BYTE)( nRGB16 >> 2 ) & 0xf8; + nBlue = (BYTE)( nRGB16 << 3 ) & 0xf8; + mpAcc->SetPixel( nY, nX, BitmapColor( nRed, nGreen, nBlue ) ); + } + break; + default: + return FALSE; + } + } + } + } + return mbStatus; +} + +// ------------------------------------------------------------------------------------------- + +BOOL TGAReader::ImplReadPalette() +{ + if ( mbIndexing ) // read the colormap + { + USHORT nColors = mpFileHeader->nColorMapLength; + + if ( !nColors ) // colors == 0 ? -> we will build a grayscale palette + { + if ( mpFileHeader->nPixelDepth != 8 ) + return FALSE; + nColors = 256; + mpFileHeader->nColorMapLength = 256; + mpFileHeader->nColorMapEntrySize = 0x3f; // patch for the following switch routine + } + mpColorMap = new UINT32[ nColors ]; // we will always index dwords + if ( mpColorMap == FALSE ) + return FALSE; // out of memory %&!$&/!"�$ + + switch( mpFileHeader->nColorMapEntrySize ) + { + case 0x3f : + { + for ( ULONG i = 0; i < nColors; i++ ) + { + mpColorMap[ i ] = ( i << 16 ) + ( i << 8 ) + i; + } + } + break; + + case 32 : + mpTGA->Read( mpColorMap, 4 * nColors ); + break; + + case 24 : + { + for ( ULONG i = 0; i < nColors; i++ ) + { + mpTGA->Read( &mpColorMap[ i ], 3 ); + } + } + break; + + case 15 : + case 16 : + { + for ( ULONG i = 0; i < nColors; i++ ) + { + UINT16 nTemp; + *mpTGA >> nTemp; + mpColorMap[ i ] = ( ( nTemp & 0x7c00 ) << 9 ) + ( ( nTemp & 0x01e0 ) << 6 ) + + ( ( nTemp & 0x1f ) << 3 ); + } + } + break; + + default : + return FALSE; + } + if ( mnDestBitDepth <= 8 ) + { + USHORT nDestColors = ( 1 << mnDestBitDepth ); + if ( nColors > nDestColors ) + return FALSE; + + mpAcc->SetPaletteEntryCount( nColors ); + for ( USHORT i = 0; i < nColors; i++ ) + { + mpAcc->SetPaletteColor( i, Color( (BYTE)( mpColorMap[ i ] >> 16 ), + (BYTE)( mpColorMap[ i ] >> 8 ), (BYTE)(mpColorMap[ i ] ) ) ); + } + } + } + + return mbStatus; +} + +//================== GraphicImport - die exportierte Funktion ================ + +extern "C" BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL ) +{ + TGAReader aTGAReader; + + return aTGAReader.ReadTGA( rStream, rGraphic ); +} + +//================== ein bischen Muell fuer Windows ========================== +#ifndef GCC +#endif + +#ifdef WIN + +static HINSTANCE hDLLInst = 0; // HANDLE der DLL + +extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR ) +{ +#ifndef WNT + if ( nHeap ) + UnlockData( 0 ); +#endif + + hDLLInst = hDLL; + + return TRUE; +} + +extern "C" int CALLBACK WEP( int ) +{ + return 1; +} + +#endif + |