1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itga.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
34 #include <vcl/graph.hxx>
35 #include <vcl/bmpacc.hxx>
36 #include <svtools/fltcall.hxx>
38 //============================ TGAReader ==================================
45 UINT16 nColorMapFirstEntryIndex
;
46 UINT16 nColorMapLength
;
47 BYTE nColorMapEntrySize
;
48 UINT16 nColorMapXOrigin
;
49 UINT16 nColorMapYOrigin
;
53 BYTE nImageDescriptor
;
56 #define SizeOfTGAFileFooter 26
60 UINT32 nExtensionFileOffset
;
61 UINT32 nDeveloperDirectoryOffset
;
64 BYTE nStringTerminator
;
67 #define SizeOfTGAExtension 495
71 UINT16 nExtensionSize
;
73 char sAuthorComment
[324];
74 char sDateTimeStamp
[12];
78 UINT16 nSoftwareVersionNumber
;
79 BYTE nSoftwareVersionLetter
;
81 UINT16 nPixelAspectRatioNumerator
;
82 UINT16 nPixelAspectRatioDeNumerator
;
83 UINT16 nGammaValueNumerator
;
84 UINT16 nGammaValueDeNumerator
;
85 UINT32 nColorCorrectionOffset
;
86 UINT32 nPostageStampOffset
;
87 UINT32 nScanLineOffset
;
97 BitmapWriteAccess
* mpAcc
;
98 TGAFileHeader
* mpFileHeader
;
99 TGAFileFooter
* mpFileFooter
;
100 TGAExtension
* mpExtension
;
105 ULONG mnTGAVersion
; // Enhanced TGA is defined as Version 2.0
106 UINT16 mnDestBitDepth
;
107 BOOL mbIndexing
; // TRUE if source contains indexing color values
108 BOOL mbEncoding
; // TRUE if source is compressed
110 BOOL
ImplReadHeader();
111 BOOL
ImplReadPalette();
117 BOOL
ReadTGA( SvStream
& rTGA
, Graphic
& rGraphic
);
120 //=================== Methoden von TGAReader ==============================
122 TGAReader::TGAReader() :
124 mpFileHeader ( NULL
),
125 mpFileFooter ( NULL
),
126 mpExtension ( NULL
),
130 mbIndexing ( FALSE
),
135 TGAReader::~TGAReader()
143 // -------------------------------------------------------------------------------------------
145 BOOL
TGAReader::ReadTGA( SvStream
& rTGA
, Graphic
& rGraphic
)
147 if ( rTGA
.GetError() )
151 mpTGA
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
155 if ( !mpTGA
->GetError() )
157 mbStatus
= ImplReadHeader();
162 aBitmap
= Bitmap( Size( mpFileHeader
->nImageWidth
, mpFileHeader
->nImageHeight
), mnDestBitDepth
);
163 mpAcc
= aBitmap
.AcquireWriteAccess();
167 mbStatus
= ImplReadPalette();
169 mbStatus
= ImplReadBody();
175 aBitmap
.ReleaseAccess ( mpAcc
), mpAcc
= NULL
;
184 // -------------------------------------------------------------------------------------------
186 BOOL
TGAReader::ImplReadHeader()
188 mpFileHeader
= new TGAFileHeader
;
189 if ( mpFileHeader
== NULL
)
192 *mpTGA
>> mpFileHeader
->nImageIDLength
>> mpFileHeader
->nColorMapType
>> mpFileHeader
->nImageType
>>
193 mpFileHeader
->nColorMapFirstEntryIndex
>> mpFileHeader
->nColorMapLength
>> mpFileHeader
->nColorMapEntrySize
>>
194 mpFileHeader
->nColorMapXOrigin
>> mpFileHeader
->nColorMapYOrigin
>> mpFileHeader
->nImageWidth
>>
195 mpFileHeader
->nImageHeight
>> mpFileHeader
->nPixelDepth
>> mpFileHeader
->nImageDescriptor
;
197 if ( mpFileHeader
->nColorMapType
> 1 )
199 if ( mpFileHeader
->nColorMapType
== 1 )
202 // first we want to get the version
203 mpFileFooter
= new TGAFileFooter
; // read the TGA-File-Footer to determine whether
204 if ( mpFileFooter
) // we got an old TGA format or the new one
206 ULONG nCurStreamPos
= mpTGA
->Tell();
207 mpTGA
->Seek( STREAM_SEEK_TO_END
);
208 ULONG nTemp
= mpTGA
->Tell();
209 mpTGA
->Seek( nTemp
- SizeOfTGAFileFooter
);
211 *mpTGA
>> mpFileFooter
->nExtensionFileOffset
>> mpFileFooter
->nDeveloperDirectoryOffset
>>
212 mpFileFooter
->nSignature
[0] >> mpFileFooter
->nSignature
[1] >> mpFileFooter
->nSignature
[2] >>
213 mpFileFooter
->nSignature
[3] >> mpFileFooter
->nPadByte
>> mpFileFooter
->nStringTerminator
;
215 // check for TRUE, VISI, ON-X, FILE in the signatures
216 if ( mpFileFooter
->nSignature
[ 0 ] == (('T'<<24)|('R'<<16)|('U'<<8)|'E') &&
217 mpFileFooter
->nSignature
[ 1 ] == (('V'<<24)|('I'<<16)|('S'<<8)|'I') &&
218 mpFileFooter
->nSignature
[ 2 ] == (('O'<<24)|('N'<<16)|('-'<<8)|'X') &&
219 mpFileFooter
->nSignature
[ 3 ] == (('F'<<24)|('I'<<16)|('L'<<8)|'E') )
221 mpExtension
= new TGAExtension
;
224 mpTGA
->Seek( mpFileFooter
->nExtensionFileOffset
);
225 *mpTGA
>> mpExtension
->nExtensionSize
;
226 if ( mpExtension
->nExtensionSize
>= SizeOfTGAExtension
)
230 mpTGA
->Read( mpExtension
->sAuthorName
, 41 );
231 mpTGA
->Read( mpExtension
->sAuthorComment
, 324 );
232 mpTGA
->Read( mpExtension
->sDateTimeStamp
, 12 );
233 mpTGA
->Read( mpExtension
->sJobNameID
, 12 );
234 *mpTGA
>> mpExtension
->sJobNameID
[ 0 ] >> mpExtension
->sJobNameID
[ 1 ] >> mpExtension
->sJobNameID
[ 2 ];
235 mpTGA
->Read( mpExtension
->sSoftwareID
, 41 );
236 *mpTGA
>> mpExtension
->nSoftwareVersionNumber
>> mpExtension
->nSoftwareVersionLetter
237 >> mpExtension
->nKeyColor
>> mpExtension
->nPixelAspectRatioNumerator
238 >> mpExtension
->nPixelAspectRatioDeNumerator
>> mpExtension
->nGammaValueNumerator
239 >> mpExtension
->nGammaValueDeNumerator
>> mpExtension
->nColorCorrectionOffset
240 >> mpExtension
->nPostageStampOffset
>> mpExtension
->nScanLineOffset
241 >> mpExtension
->nAttributesType
;
246 mpTGA
->Seek( nCurStreamPos
);
249 // using the TGA file specification this was the correct form but adobe photoshop sets nImageDescriptor
250 // equal to nPixelDepth
251 // mnDestBitDepth = mpFileHeader->nPixelDepth - ( mpFileHeader->nImageDescriptor & 0xf );
252 mnDestBitDepth
= mpFileHeader
->nPixelDepth
;
254 if ( mnDestBitDepth
== 8 ) // this is a patch for grayscale pictures not including a palette
257 if ( mnDestBitDepth
> 32 ) // maybe the pixeldepth is invalid
259 else if ( mnDestBitDepth
> 8 )
261 else if ( mnDestBitDepth
> 4 )
263 else if ( mnDestBitDepth
> 2 )
266 if ( !mbIndexing
&& ( mnDestBitDepth
< 15 ) )
269 switch ( mpFileHeader
->nImageType
)
271 case 9 : // encoding for colortype 9, 10, 11
278 if ( mpFileHeader
->nImageIDLength
) // skip the Image ID
279 mpTGA
->SeekRel( mpFileHeader
->nImageIDLength
);
284 // -------------------------------------------------------------------------------------------
286 BOOL
TGAReader::ImplReadBody()
289 USHORT nXCount
, nYCount
, nRGB16
;
290 BYTE nRed
, nGreen
, nBlue
, nRunCount
, nDummy
, nDepth
;
292 // this four variables match the image direction
293 long nY
, nYAdd
, nX
, nXAdd
, nXStart
;
295 nX
= nXStart
= nY
= 0;
296 nXCount
= nYCount
= 0;
299 if ( mpFileHeader
->nImageDescriptor
& 0x10 )
301 nX
= nXStart
= mpFileHeader
->nImageWidth
- 1;
305 if ( !(mpFileHeader
->nImageDescriptor
& 0x20 ) )
307 nY
= mpFileHeader
->nImageHeight
- 1;
311 // nDepth = mpFileHeader->nPixelDepth - ( mpFileHeader->nImageDescriptor & 0xf );
312 nDepth
= mpFileHeader
->nPixelDepth
;
320 // 16 bit encoding + indexing
322 while ( nYCount
< mpFileHeader
->nImageHeight
)
325 if ( nRunCount
& 0x80 ) // a run length packet
328 if ( nRGB16
>= mpFileHeader
->nColorMapLength
)
330 nRed
= (BYTE
)( mpColorMap
[ nRGB16
] >> 16 );
331 nGreen
= (BYTE
)( mpColorMap
[ nRGB16
] >> 8 );
332 nBlue
= (BYTE
)( mpColorMap
[ nRGB16
] );
333 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
335 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
338 if ( nXCount
== mpFileHeader
->nImageWidth
)
349 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
352 if ( nRGB16
>= mpFileHeader
->nColorMapLength
)
354 nRed
= (BYTE
)( mpColorMap
[ nRGB16
] >> 16 );
355 nGreen
= (BYTE
)( mpColorMap
[ nRGB16
] >> 8 );
356 nBlue
= (BYTE
)( mpColorMap
[ nRGB16
] );
357 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
360 if ( nXCount
== mpFileHeader
->nImageWidth
)
372 // 8 bit encoding + indexing
374 while ( nYCount
< mpFileHeader
->nImageHeight
)
377 if ( nRunCount
& 0x80 ) // a run length packet
380 if ( nDummy
>= mpFileHeader
->nColorMapLength
)
382 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
384 mpAcc
->SetPixel( nY
, nX
, (BYTE
)nDummy
);
387 if ( nXCount
== mpFileHeader
->nImageWidth
)
398 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
402 if ( nDummy
>= mpFileHeader
->nColorMapLength
)
404 mpAcc
->SetPixel( nY
, nX
, (BYTE
)nDummy
);
407 if ( nXCount
== mpFileHeader
->nImageWidth
)
426 // 32 bit transparent true color encoding
429 while ( nYCount
< mpFileHeader
->nImageHeight
)
432 if ( nRunCount
& 0x80 ) // a run length packet
434 *mpTGA
>> nBlue
>> nGreen
>> nRed
>> nDummy
;
435 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
437 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
440 if ( nXCount
== mpFileHeader
->nImageWidth
)
451 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
453 *mpTGA
>> nBlue
>> nGreen
>> nRed
>> nDummy
;
454 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
457 if ( nXCount
== mpFileHeader
->nImageWidth
)
470 // 24 bit true color encoding
472 while ( nYCount
< mpFileHeader
->nImageHeight
)
475 if ( nRunCount
& 0x80 ) // a run length packet
477 *mpTGA
>> nBlue
>> nGreen
>> nRed
;
478 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
480 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
483 if ( nXCount
== mpFileHeader
->nImageWidth
)
494 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
496 *mpTGA
>> nBlue
>> nGreen
>> nRed
;
497 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
500 if ( nXCount
== mpFileHeader
->nImageWidth
)
512 // 16 bit true color encoding
514 while ( nYCount
< mpFileHeader
->nImageHeight
)
517 if ( nRunCount
& 0x80 ) // a run length packet
520 nRed
= (BYTE
)( nRGB16
>> 7 ) & 0xf8;
521 nGreen
= (BYTE
)( nRGB16
>> 2 ) & 0xf8;
522 nBlue
= (BYTE
)( nRGB16
<< 3 ) & 0xf8;
523 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
525 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
528 if ( nXCount
== mpFileHeader
->nImageWidth
)
539 for ( USHORT i
= 0; i
< ( ( nRunCount
& 0x7f ) + 1 ); i
++ )
542 nRed
= (BYTE
)( nRGB16
>> 7 ) & 0xf8;
543 nGreen
= (BYTE
)( nRGB16
>> 2 ) & 0xf8;
544 nBlue
= (BYTE
)( nRGB16
<< 3 ) & 0xf8;
545 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
548 if ( nXCount
== mpFileHeader
->nImageWidth
)
567 for ( nYCount
= 0; nYCount
< mpFileHeader
->nImageHeight
; nYCount
++, nY
+= nYAdd
)
578 for (;nXCount
< mpFileHeader
->nImageWidth
; nXCount
++, nX
+= nXAdd
)
581 if ( nRGB16
>= mpFileHeader
->nColorMapLength
)
583 nRed
= (BYTE
)( mpColorMap
[ nRGB16
] >> 16 );
584 nGreen
= (BYTE
)( mpColorMap
[ nRGB16
] >> 8 );
585 nBlue
= (BYTE
)( mpColorMap
[ nRGB16
] );
586 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
592 for (;nXCount
< mpFileHeader
->nImageWidth
; nXCount
++, nX
+= nXAdd
)
595 if ( nDummy
>= mpFileHeader
->nColorMapLength
)
597 mpAcc
->SetPixel( nY
, nX
, (BYTE
)nDummy
);
611 for (;nXCount
< mpFileHeader
->nImageWidth
; nXCount
++, nX
+= nXAdd
)
613 *mpTGA
>> nBlue
>> nGreen
>> nRed
>> nDummy
;
614 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
621 for (;nXCount
< mpFileHeader
->nImageWidth
; nXCount
++, nX
+= nXAdd
)
623 *mpTGA
>> nBlue
>> nGreen
>> nRed
;
624 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
630 for (;nXCount
< mpFileHeader
->nImageWidth
; nXCount
++, nX
+= nXAdd
)
633 nRed
= (BYTE
)( nRGB16
>> 7 ) & 0xf8;
634 nGreen
= (BYTE
)( nRGB16
>> 2 ) & 0xf8;
635 nBlue
= (BYTE
)( nRGB16
<< 3 ) & 0xf8;
636 mpAcc
->SetPixel( nY
, nX
, BitmapColor( nRed
, nGreen
, nBlue
) );
648 // -------------------------------------------------------------------------------------------
650 BOOL
TGAReader::ImplReadPalette()
652 if ( mbIndexing
) // read the colormap
654 USHORT nColors
= mpFileHeader
->nColorMapLength
;
656 if ( !nColors
) // colors == 0 ? -> we will build a grayscale palette
658 if ( mpFileHeader
->nPixelDepth
!= 8 )
661 mpFileHeader
->nColorMapLength
= 256;
662 mpFileHeader
->nColorMapEntrySize
= 0x3f; // patch for the following switch routine
664 mpColorMap
= new UINT32
[ nColors
]; // we will always index dwords
665 if ( mpColorMap
== FALSE
)
666 return FALSE
; // out of memory %&!$&/!"�$
668 switch( mpFileHeader
->nColorMapEntrySize
)
672 for ( ULONG i
= 0; i
< nColors
; i
++ )
674 mpColorMap
[ i
] = ( i
<< 16 ) + ( i
<< 8 ) + i
;
680 mpTGA
->Read( mpColorMap
, 4 * nColors
);
685 for ( ULONG i
= 0; i
< nColors
; i
++ )
687 mpTGA
->Read( &mpColorMap
[ i
], 3 );
695 for ( ULONG i
= 0; i
< nColors
; i
++ )
699 mpColorMap
[ i
] = ( ( nTemp
& 0x7c00 ) << 9 ) + ( ( nTemp
& 0x01e0 ) << 6 ) +
700 ( ( nTemp
& 0x1f ) << 3 );
708 if ( mnDestBitDepth
<= 8 )
710 USHORT nDestColors
= ( 1 << mnDestBitDepth
);
711 if ( nColors
> nDestColors
)
714 mpAcc
->SetPaletteEntryCount( nColors
);
715 for ( USHORT i
= 0; i
< nColors
; i
++ )
717 mpAcc
->SetPaletteColor( i
, Color( (BYTE
)( mpColorMap
[ i
] >> 16 ),
718 (BYTE
)( mpColorMap
[ i
] >> 8 ), (BYTE
)(mpColorMap
[ i
] ) ) );
726 //================== GraphicImport - die exportierte Funktion ================
728 extern "C" BOOL __LOADONCALLAPI
GraphicImport(SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
*, BOOL
)
730 TGAReader aTGAReader
;
732 return aTGAReader
.ReadTGA( rStream
, rGraphic
);
735 //================== ein bischen Muell fuer Windows ==========================
741 static HINSTANCE hDLLInst
= 0; // HANDLE der DLL
743 extern "C" int CALLBACK
LibMain( HINSTANCE hDLL
, WORD
, WORD nHeap
, LPSTR
)
755 extern "C" int CALLBACK
WEP( int )