38 sal_uInt16 nColorMapFirstEntryIndex;
39 sal_uInt16 nColorMapLength;
41 sal_uInt16 nColorMapXOrigin;
42 sal_uInt16 nColorMapYOrigin;
43 sal_uInt16 nImageWidth;
44 sal_uInt16 nImageHeight;
49#define SizeOfTGAFileFooter 26
53 sal_uInt32 nExtensionFileOffset;
54 sal_uInt32 nDeveloperDirectoryOffset;
55 sal_uInt32 nSignature[4];
60#define SizeOfTGAExtension 495
64 sal_uInt16 nExtensionSize;
66 char sAuthorComment[324];
67 char sDateTimeStamp[12];
70 sal_uInt16 nSoftwareVersionNumber;
73 sal_uInt16 nPixelAspectRatioNumerator;
74 sal_uInt16 nPixelAspectRatioDeNumerator;
75 sal_uInt16 nGammaValueNumerator;
76 sal_uInt16 nGammaValueDeNumerator;
77 sal_uInt32 nColorCorrectionOffset;
78 sal_uInt32 nPostageStampOffset;
79 sal_uInt32 nScanLineOffset;
89 std::unique_ptr<vcl::bitmap::RawBitmap>
mpBitmap;
90 std::vector<Color> mvPalette;
91 std::unique_ptr<TGAFileHeader>
93 std::unique_ptr<TGAFileFooter>
95 std::unique_ptr<TGAExtension>
97 std::unique_ptr<sal_uInt32[]>
103 sal_uInt16 mnDestBitDepth;
107 bool ImplReadHeader();
108 bool ImplReadPalette();
113 bool ReadTGA(
Graphic &rGraphic);
130bool TGAReader::ReadTGA(
Graphic & rGraphic)
132 if ( m_rTGA.GetError() )
135 m_rTGA.SetEndian( SvStreamEndian::LITTLE );
139 if ( !m_rTGA.GetError() )
141 mbStatus = ImplReadHeader();
143 mbStatus = mpFileHeader->nImageWidth && mpFileHeader->nImageHeight;
146 sal_Size nSize = mpFileHeader->nImageWidth;
147 nSize *= mpFileHeader->nImageHeight;
148 if (nSize > SAL_MAX_INT32/2/3)
153 mbStatus = ImplReadPalette();
155 mbStatus = ImplReadBody();
165bool TGAReader::ImplReadHeader()
167 mpFileHeader.reset(
new TGAFileHeader );
169 m_rTGA.ReadUChar( mpFileHeader->nImageIDLength ).ReadUChar( mpFileHeader->nColorMapType ).ReadUChar( mpFileHeader->nImageType ). ReadUInt16( mpFileHeader->nColorMapFirstEntryIndex ).ReadUInt16( mpFileHeader->nColorMapLength ).ReadUChar( mpFileHeader->nColorMapEntrySize ). ReadUInt16( mpFileHeader->nColorMapXOrigin ).ReadUInt16( mpFileHeader->nColorMapYOrigin ).ReadUInt16( mpFileHeader->nImageWidth ). ReadUInt16( mpFileHeader->nImageHeight ).ReadUChar( mpFileHeader->nPixelDepth ).ReadUChar( mpFileHeader->nImageDescriptor );
174 if ( mpFileHeader->nColorMapType > 1 )
176 if ( mpFileHeader->nColorMapType == 1 )
180 mpFileFooter.reset(
new TGAFileFooter );
183 sal_uInt64 nCurStreamPos = m_rTGA.Tell();
184 m_rTGA.Seek( STREAM_SEEK_TO_END );
185 sal_uInt64 nTemp = m_rTGA.Tell();
188 m_rTGA.ReadUInt32( mpFileFooter->nExtensionFileOffset ).ReadUInt32( mpFileFooter->nDeveloperDirectoryOffset ). ReadUInt32( mpFileFooter->nSignature[0] ).ReadUInt32( mpFileFooter->nSignature[1] ).ReadUInt32( mpFileFooter->nSignature[2] ). ReadUInt32( mpFileFooter->nSignature[3] ).ReadUChar( mpFileFooter->nPadByte ).ReadUChar( mpFileFooter->nStringTerminator );
195 if ( mpFileFooter->nSignature[ 0 ] == ((
'T'<<24)|(
'R'<<16)|(
'U'<<8)|
'E') &&
196 mpFileFooter->nSignature[ 1 ] == ((
'V'<<24)|(
'I'<<16)|(
'S'<<8)|
'I') &&
197 mpFileFooter->nSignature[ 2 ] == ((
'O'<<24)|(
'N'<<16)|(
'-'<<8)|
'X') &&
198 mpFileFooter->nSignature[ 3 ] == ((
'F'<<24)|(
'I'<<16)|(
'L'<<8)|
'E') )
200 mpExtension.reset(
new TGAExtension );
202 m_rTGA.Seek( mpFileFooter->nExtensionFileOffset );
203 m_rTGA.ReadUInt16( mpExtension->nExtensionSize );
210 m_rTGA.ReadBytes(mpExtension->sAuthorName, 41);
211 m_rTGA.ReadBytes(mpExtension->sAuthorComment, 324);
212 m_rTGA.ReadBytes(mpExtension->sDateTimeStamp, 12);
213 m_rTGA.ReadBytes(mpExtension->sJobNameID, 12);
214 m_rTGA.ReadChar( mpExtension->sJobNameID[ 0 ] ).ReadChar( mpExtension->sJobNameID[ 1 ] ).ReadChar( mpExtension->sJobNameID[ 2 ] );
215 m_rTGA.ReadBytes(mpExtension->sSoftwareID, 41);
216 m_rTGA.ReadUInt16( mpExtension->nSoftwareVersionNumber ).ReadUChar( mpExtension->nSoftwareVersionLetter )
217 .ReadUInt32( mpExtension->nKeyColor ).ReadUInt16( mpExtension->nPixelAspectRatioNumerator )
218 .ReadUInt16( mpExtension->nPixelAspectRatioDeNumerator ).ReadUInt16( mpExtension->nGammaValueNumerator )
219 .ReadUInt16( mpExtension->nGammaValueDeNumerator ).ReadUInt32( mpExtension->nColorCorrectionOffset )
220 .ReadUInt32( mpExtension->nPostageStampOffset ).ReadUInt32( mpExtension->nScanLineOffset )
221 .ReadUChar( mpExtension->nAttributesType );
227 m_rTGA.Seek( nCurStreamPos );
232 mnDestBitDepth = mpFileHeader->nPixelDepth;
234 if ( mnDestBitDepth == 8 )
237 if ( mnDestBitDepth > 32 )
239 else if ( mnDestBitDepth > 8 )
241 else if ( mnDestBitDepth > 4 )
243 else if ( mnDestBitDepth > 2 )
246 if ( !mbIndexing && ( mnDestBitDepth < 15 ) )
249 switch ( mpFileHeader->nImageType )
258 if ( mpFileHeader->nImageIDLength )
259 m_rTGA.SeekRel( mpFileHeader->nImageIDLength );
265bool TGAReader::ImplReadBody()
268 sal_uInt16 nXCount, nYCount, nRGB16;
269 sal_uInt8 nRed, nGreen, nBlue, nRunCount, nDummy, nDepth;
274 nX = nXStart = nY = 0;
275 nXCount = nYCount = 0;
278 if ( mpFileHeader->nImageDescriptor & 0x10 )
280 nX = nXStart = mpFileHeader->nImageWidth - 1;
284 if ( !(mpFileHeader->nImageDescriptor & 0x20 ) )
286 nY = mpFileHeader->nImageHeight - 1;
290 nDepth = mpFileHeader->nPixelDepth;
300 while ( nYCount < mpFileHeader->nImageHeight )
302 m_rTGA.ReadUChar( nRunCount );
305 if ( nRunCount & 0x80 )
307 m_rTGA.ReadUInt16( nRGB16 );
310 if ( nRGB16 >= mpFileHeader->nColorMapLength )
312 nRed =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] >> 16 );
313 nGreen =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] >> 8 );
314 nBlue =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] );
315 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
320 if ( nXCount == mpFileHeader->nImageWidth )
327 if( nYCount >= mpFileHeader->nImageHeight )
334 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
336 m_rTGA.ReadUInt16( nRGB16 );
339 if ( nRGB16 >= mpFileHeader->nColorMapLength )
341 nRed =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] >> 16 );
342 nGreen =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] >> 8 );
343 nBlue =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] );
349 if ( nXCount == mpFileHeader->nImageWidth )
356 if( nYCount >= mpFileHeader->nImageHeight )
366 while ( nYCount < mpFileHeader->nImageHeight )
368 m_rTGA.ReadUChar( nRunCount );
371 if ( nRunCount & 0x80 )
373 m_rTGA.ReadUChar( nDummy );
376 if ( nDummy >= mpFileHeader->nColorMapLength )
378 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
380 mpBitmap->SetPixel( nY, nX, mvPalette[nDummy] );
383 if ( nXCount == mpFileHeader->nImageWidth )
390 if( nYCount >= mpFileHeader->nImageHeight )
397 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
399 m_rTGA.ReadUChar( nDummy );
402 if ( nDummy >= mpFileHeader->nColorMapLength )
404 mpBitmap->SetPixel( nY, nX, mvPalette[nDummy] );
407 if ( nXCount == mpFileHeader->nImageWidth )
414 if( nYCount >= mpFileHeader->nImageHeight )
432 while ( nYCount < mpFileHeader->nImageHeight )
434 m_rTGA.ReadUChar( nRunCount );
437 if ( nRunCount & 0x80 )
439 m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed ).ReadUChar( nDummy );
442 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
447 if ( nXCount == mpFileHeader->nImageWidth )
454 if( nYCount >= mpFileHeader->nImageHeight )
461 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
463 m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed ).ReadUChar( nDummy );
469 if ( nXCount == mpFileHeader->nImageWidth )
476 if( nYCount >= mpFileHeader->nImageHeight )
487 while ( nYCount < mpFileHeader->nImageHeight )
489 m_rTGA.ReadUChar( nRunCount );
492 if ( nRunCount & 0x80 )
494 m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed );
497 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
502 if ( nXCount == mpFileHeader->nImageWidth )
509 if( nYCount >= mpFileHeader->nImageHeight )
516 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
518 m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed );
524 if ( nXCount == mpFileHeader->nImageWidth )
531 if( nYCount >= mpFileHeader->nImageHeight )
541 while ( nYCount < mpFileHeader->nImageHeight )
543 m_rTGA.ReadUChar( nRunCount );
546 if ( nRunCount & 0x80 )
548 m_rTGA.ReadUInt16( nRGB16 );
551 nRed =
static_cast<sal_uInt8>( nRGB16 >> 7 ) & 0xf8;
552 nGreen =
static_cast<sal_uInt8>( nRGB16 >> 2 ) & 0xf8;
553 nBlue =
static_cast<sal_uInt8>( nRGB16 << 3 ) & 0xf8;
554 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
559 if ( nXCount == mpFileHeader->nImageWidth )
566 if( nYCount >= mpFileHeader->nImageHeight )
573 for ( sal_uInt16 i = 0;
i < ( ( nRunCount & 0x7f ) + 1 );
i++ )
575 m_rTGA.ReadUInt16( nRGB16 );
578 nRed =
static_cast<sal_uInt8>( nRGB16 >> 7 ) & 0xf8;
579 nGreen =
static_cast<sal_uInt8>( nRGB16 >> 2 ) & 0xf8;
580 nBlue =
static_cast<sal_uInt8>( nRGB16 << 3 ) & 0xf8;
584 if ( nXCount == mpFileHeader->nImageWidth )
591 if( nYCount >= mpFileHeader->nImageHeight )
606 for ( nYCount = 0; nYCount < mpFileHeader->nImageHeight; nYCount++, nY += nYAdd )
617 for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
619 m_rTGA.ReadUInt16( nRGB16 );
622 if ( nRGB16 >= mpFileHeader->nColorMapLength )
624 nRed =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] >> 16 );
625 nGreen =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] >> 8 );
626 nBlue =
static_cast<sal_uInt8>( mpColorMap[ nRGB16 ] );
633 for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
635 m_rTGA.ReadUChar( nDummy );
638 if ( nDummy >= mpFileHeader->nColorMapLength )
640 mpBitmap->SetPixel( nY, nX,
Color(ColorTransparency, nDummy) );
654 for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
656 m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed ).ReadUChar( nDummy );
666 for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
668 m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed );
677 for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
679 m_rTGA.ReadUInt16( nRGB16 );
682 nRed =
static_cast<sal_uInt8>( nRGB16 >> 7 ) & 0xf8;
683 nGreen =
static_cast<sal_uInt8>( nRGB16 >> 2 ) & 0xf8;
684 nBlue =
static_cast<sal_uInt8>( nRGB16 << 3 ) & 0xf8;
698bool TGAReader::ImplReadPalette()
702 sal_uInt16 nColors = mpFileHeader->nColorMapLength;
706 if ( mpFileHeader->nPixelDepth != 8 )
709 mpFileHeader->nColorMapLength = 256;
710 mpFileHeader->nColorMapEntrySize = 0x3f;
712 mpColorMap.reset(
new sal_uInt32[ nColors ] );
714 switch( mpFileHeader->nColorMapEntrySize )
718 for (sal_uInt32 i = 0;
i < nColors; ++
i)
720 mpColorMap[
i ] = (
i << 16 ) + ( i << 8 ) +
i;
726 for (sal_uInt16 i = 0;
i < nColors;
i++)
728 m_rTGA.ReadUInt32(mpColorMap[i]);
734 for ( sal_uInt16 i = 0;
i < nColors;
i++ )
739 m_rTGA.ReadUChar(nBlue).ReadUChar(nGreen).ReadUChar(nRed);
740 mpColorMap[
i] = (nRed << 16) | (nGreen << 8) | nBlue;
748 for ( sal_uInt16 i = 0;
i < nColors;
i++ )
751 m_rTGA.ReadUInt16( nTemp );
752 if ( !m_rTGA.good() )
754 mpColorMap[
i ] = ( ( nTemp & 0x7c00 ) << 9 ) + ( ( nTemp & 0x01e0 ) << 6 ) +
755 ( ( nTemp & 0x1f ) << 3 );
763 if ( mnDestBitDepth <= 8 )
765 sal_uInt16 nDestColors = ( 1 << mnDestBitDepth );
766 if ( nColors > nDestColors )
769 mvPalette.resize( nColors );
770 for ( sal_uInt16 i = 0;
i < nColors;
i++ )
773 static_cast<sal_uInt8>( mpColorMap[ i ] >> 8 ),
static_cast<sal_uInt8>(mpColorMap[ i ] ) );
785 TGAReader aTGAReader(rStream);
787 return aTGAReader.ReadTGA(rGraphic);
Intended to be used to feed into CreateFromData to create a BitmapEx.
#define SizeOfTGAFileFooter
bool ImportTgaGraphic(SvStream &rStream, Graphic &rGraphic)
#define SizeOfTGAExtension
BitmapEx CreateFromData(sal_uInt8 const *pData, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int32 nStride, sal_Int8 nBitCount, bool bReversColors, bool bReverseAlpha)
Copy block of image data into the bitmap.