LibreOffice Module vcl (master)  1
itga.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <vcl/graph.hxx>
22 #include <vcl/BitmapTools.hxx>
23 #include <tools/stream.hxx>
24 #include <memory>
25 #include <filter/TgaReader.hxx>
26 
27 class FilterConfigItem;
28 
29 //============================ TGAReader ==================================
30 
31 namespace {
32 
33 struct TGAFileHeader
34 {
35  sal_uInt8 nImageIDLength;
36  sal_uInt8 nColorMapType;
37  sal_uInt8 nImageType;
38  sal_uInt16 nColorMapFirstEntryIndex;
39  sal_uInt16 nColorMapLength;
40  sal_uInt8 nColorMapEntrySize;
41  sal_uInt16 nColorMapXOrigin;
42  sal_uInt16 nColorMapYOrigin;
43  sal_uInt16 nImageWidth;
44  sal_uInt16 nImageHeight;
45  sal_uInt8 nPixelDepth;
46  sal_uInt8 nImageDescriptor;
47 };
48 
49 #define SizeOfTGAFileFooter 26
50 
51 struct TGAFileFooter
52 {
53  sal_uInt32 nExtensionFileOffset;
54  sal_uInt32 nDeveloperDirectoryOffset;
55  sal_uInt32 nSignature[4];
56  sal_uInt8 nPadByte;
57  sal_uInt8 nStringTerminator;
58 };
59 
60 #define SizeOfTGAExtension 495
61 
62 struct TGAExtension
63 {
64  sal_uInt16 nExtensionSize;
65  char sAuthorName[41];
66  char sAuthorComment[324];
67  char sDateTimeStamp[12];
68  char sJobNameID[41];
69  char sSoftwareID[41];
70  sal_uInt16 nSoftwareVersionNumber;
71  sal_uInt8 nSoftwareVersionLetter;
72  sal_uInt32 nKeyColor;
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;
80  sal_uInt8 nAttributesType;
81 };
82 
83 class TGAReader {
84 
85 private:
86 
87  SvStream& m_rTGA;
88 
89  std::unique_ptr<vcl::bitmap::RawBitmap> mpBitmap;
90  std::vector<Color> mvPalette;
91  std::unique_ptr<TGAFileHeader>
92  mpFileHeader;
93  std::unique_ptr<TGAFileFooter>
94  mpFileFooter;
95  std::unique_ptr<TGAExtension>
96  mpExtension;
97  std::unique_ptr<sal_uInt32[]>
98  mpColorMap;
99 
100  bool mbStatus;
101 
102  sal_uInt8 mnTGAVersion; // Enhanced TGA is defined as Version 2.0
103  sal_uInt16 mnDestBitDepth;
104  bool mbIndexing; // sal_True if source contains indexing color values
105  bool mbEncoding; // sal_True if source is compressed
106 
107  bool ImplReadHeader();
108  bool ImplReadPalette();
109  bool ImplReadBody();
110 
111 public:
112  explicit TGAReader(SvStream &rTGA);
113  bool ReadTGA(Graphic &rGraphic);
114 };
115 
116 }
117 
118 //=================== Methods of TGAReader ==============================
119 
120 TGAReader::TGAReader(SvStream &rTGA)
121  : m_rTGA(rTGA)
122  , mbStatus(true)
123  , mnTGAVersion(1)
124  , mnDestBitDepth(8)
125  , mbIndexing(false)
126  , mbEncoding(false)
127 {
128 }
129 
130 bool TGAReader::ReadTGA(Graphic & rGraphic)
131 {
132  if ( m_rTGA.GetError() )
133  return false;
134 
135  m_rTGA.SetEndian( SvStreamEndian::LITTLE );
136 
137  // Kopf einlesen:
138 
139  if ( !m_rTGA.GetError() )
140  {
141  mbStatus = ImplReadHeader();
142  if (mbStatus)
143  mbStatus = mpFileHeader->nImageWidth && mpFileHeader->nImageHeight;
144  if (mbStatus)
145  {
146  sal_Size nSize = mpFileHeader->nImageWidth;
147  nSize *= mpFileHeader->nImageHeight;
148  if (nSize > SAL_MAX_INT32/2/3)
149  return false;
150 
151  mpBitmap.reset( new vcl::bitmap::RawBitmap( Size( mpFileHeader->nImageWidth, mpFileHeader->nImageHeight ), 24 ) );
152  if ( mbIndexing )
153  mbStatus = ImplReadPalette();
154  if ( mbStatus )
155  mbStatus = ImplReadBody();
156 
157  if ( mbStatus )
158  rGraphic = vcl::bitmap::CreateFromData(std::move(*mpBitmap));
159  }
160  }
161  return mbStatus;
162 }
163 
164 
165 bool TGAReader::ImplReadHeader()
166 {
167  mpFileHeader.reset( new TGAFileHeader );
168 
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 );
170 
171  if ( !m_rTGA.good())
172  return false;
173 
174  if ( mpFileHeader->nColorMapType > 1 )
175  return false;
176  if ( mpFileHeader->nColorMapType == 1 )
177  mbIndexing = true;
178 
179  // first we want to get the version
180  mpFileFooter.reset( new TGAFileFooter ); // read the TGA-File-Footer to determine whether
181  // we got an old TGA format or the new one
182 
183  sal_uInt64 nCurStreamPos = m_rTGA.Tell();
184  m_rTGA.Seek( STREAM_SEEK_TO_END );
185  sal_uInt64 nTemp = m_rTGA.Tell();
186  m_rTGA.Seek( nTemp - SizeOfTGAFileFooter );
187 
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 );
189 
190 
191  if ( !m_rTGA.good())
192  return false;
193 
194  // check for sal_True, VISI, ON-X, FILE in the signatures
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') )
199  {
200  mpExtension.reset( new TGAExtension );
201 
202  m_rTGA.Seek( mpFileFooter->nExtensionFileOffset );
203  m_rTGA.ReadUInt16( mpExtension->nExtensionSize );
204  if ( !m_rTGA.good())
205  return false;
206  if ( mpExtension->nExtensionSize >= SizeOfTGAExtension )
207  {
208  mnTGAVersion = 2;
209 
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 );
222 
223  if ( !m_rTGA.good())
224  return false;
225  }
226  }
227  m_rTGA.Seek( nCurStreamPos );
228 
229  // using the TGA file specification this was the correct form but adobe photoshop sets nImageDescriptor
230  // equal to nPixelDepth
231  // mnDestBitDepth = mpFileHeader->nPixelDepth - ( mpFileHeader->nImageDescriptor & 0xf );
232  mnDestBitDepth = mpFileHeader->nPixelDepth;
233 
234  if ( mnDestBitDepth == 8 ) // this is a patch for grayscale pictures not including a palette
235  mbIndexing = true;
236 
237  if ( mnDestBitDepth > 32 ) // maybe the pixeldepth is invalid
238  return false;
239  else if ( mnDestBitDepth > 8 )
240  mnDestBitDepth = 24;
241  else if ( mnDestBitDepth > 4 )
242  mnDestBitDepth = 8;
243  else if ( mnDestBitDepth > 2 )
244  mnDestBitDepth = 4;
245 
246  if ( !mbIndexing && ( mnDestBitDepth < 15 ) )
247  return false;
248 
249  switch ( mpFileHeader->nImageType )
250  {
251  case 9 : // encoding for colortype 9, 10, 11
252  case 10 :
253  case 11 :
254  mbEncoding = true;
255  break;
256  }
257 
258  if ( mpFileHeader->nImageIDLength ) // skip the Image ID
259  m_rTGA.SeekRel( mpFileHeader->nImageIDLength );
260 
261  return mbStatus;
262 }
263 
264 
265 bool TGAReader::ImplReadBody()
266 {
267 
268  sal_uInt16 nXCount, nYCount, nRGB16;
269  sal_uInt8 nRed, nGreen, nBlue, nRunCount, nDummy, nDepth;
270 
271  // this four variables match the image direction
272  tools::Long nY, nYAdd, nX, nXAdd, nXStart;
273 
274  nX = nXStart = nY = 0;
275  nXCount = nYCount = 0;
276  nYAdd = nXAdd = 1;
277 
278  if ( mpFileHeader->nImageDescriptor & 0x10 )
279  {
280  nX = nXStart = mpFileHeader->nImageWidth - 1;
281  nXAdd -= 2;
282  }
283 
284  if ( !(mpFileHeader->nImageDescriptor & 0x20 ) )
285  {
286  nY = mpFileHeader->nImageHeight - 1;
287  nYAdd -=2;
288  }
289 
290  nDepth = mpFileHeader->nPixelDepth;
291 
292  if ( mbEncoding )
293  {
294  if ( mbIndexing )
295  {
296  switch( nDepth )
297  {
298  // 16 bit encoding + indexing
299  case 16 :
300  while ( nYCount < mpFileHeader->nImageHeight )
301  {
302  m_rTGA.ReadUChar( nRunCount );
303  if ( !m_rTGA.good())
304  return false;
305  if ( nRunCount & 0x80 ) // a run length packet
306  {
307  m_rTGA.ReadUInt16( nRGB16 );
308  if (!m_rTGA.good())
309  return false;
310  if ( nRGB16 >= mpFileHeader->nColorMapLength )
311  return false;
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++ )
316  {
317  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
318  nX += nXAdd;
319  nXCount++;
320  if ( nXCount == mpFileHeader->nImageWidth )
321  {
322  nX = nXStart;
323  nXCount = 0;
324  nY += nYAdd;
325  nYCount++;
326 
327  if( nYCount >= mpFileHeader->nImageHeight )
328  break;
329  }
330  }
331  }
332  else // a raw packet
333  {
334  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
335  {
336  m_rTGA.ReadUInt16( nRGB16 );
337  if ( !m_rTGA.good())
338  return false;
339  if ( nRGB16 >= mpFileHeader->nColorMapLength )
340  return false;
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 ] );
344  if ( !m_rTGA.good())
345  return false;
346  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
347  nX += nXAdd;
348  nXCount++;
349  if ( nXCount == mpFileHeader->nImageWidth )
350  {
351  nX = nXStart;
352  nXCount = 0;
353  nY += nYAdd;
354  nYCount++;
355 
356  if( nYCount >= mpFileHeader->nImageHeight )
357  break;
358  }
359  }
360  }
361  }
362  break;
363 
364  // 8 bit encoding + indexing
365  case 8 :
366  while ( nYCount < mpFileHeader->nImageHeight )
367  {
368  m_rTGA.ReadUChar( nRunCount );
369  if ( !m_rTGA.good())
370  return false;
371  if ( nRunCount & 0x80 ) // a run length packet
372  {
373  m_rTGA.ReadUChar( nDummy );
374  if ( !m_rTGA.good())
375  return false;
376  if ( nDummy >= mpFileHeader->nColorMapLength )
377  return false;
378  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
379  {
380  mpBitmap->SetPixel( nY, nX, mvPalette[nDummy] );
381  nX += nXAdd;
382  nXCount++;
383  if ( nXCount == mpFileHeader->nImageWidth )
384  {
385  nX = nXStart;
386  nXCount = 0;
387  nY += nYAdd;
388  nYCount++;
389 
390  if( nYCount >= mpFileHeader->nImageHeight )
391  break;
392  }
393  }
394  }
395  else // a raw packet
396  {
397  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
398  {
399  m_rTGA.ReadUChar( nDummy );
400  if ( !m_rTGA.good())
401  return false;
402  if ( nDummy >= mpFileHeader->nColorMapLength )
403  return false;
404  mpBitmap->SetPixel( nY, nX, mvPalette[nDummy] );
405  nX += nXAdd;
406  nXCount++;
407  if ( nXCount == mpFileHeader->nImageWidth )
408  {
409  nX = nXStart;
410  nXCount = 0;
411  nY += nYAdd;
412  nYCount++;
413 
414  if( nYCount >= mpFileHeader->nImageHeight )
415  break;
416  }
417  }
418  }
419  }
420  break;
421  default:
422  return false;
423  }
424  }
425  else
426  {
427  switch( nDepth )
428  {
429  // 32 bit transparent true color encoding
430  case 32 :
431  {
432  while ( nYCount < mpFileHeader->nImageHeight )
433  {
434  m_rTGA.ReadUChar( nRunCount );
435  if ( !m_rTGA.good())
436  return false;
437  if ( nRunCount & 0x80 ) // a run length packet
438  {
439  m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed ).ReadUChar( nDummy );
440  if ( !m_rTGA.good())
441  return false;
442  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
443  {
444  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
445  nX += nXAdd;
446  nXCount++;
447  if ( nXCount == mpFileHeader->nImageWidth )
448  {
449  nX = nXStart;
450  nXCount = 0;
451  nY += nYAdd;
452  nYCount++;
453 
454  if( nYCount >= mpFileHeader->nImageHeight )
455  break;
456  }
457  }
458  }
459  else // a raw packet
460  {
461  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
462  {
463  m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed ).ReadUChar( nDummy );
464  if ( !m_rTGA.good())
465  return false;
466  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
467  nX += nXAdd;
468  nXCount++;
469  if ( nXCount == mpFileHeader->nImageWidth )
470  {
471  nX = nXStart;
472  nXCount = 0;
473  nY += nYAdd;
474  nYCount++;
475 
476  if( nYCount >= mpFileHeader->nImageHeight )
477  break;
478  }
479  }
480  }
481  }
482  }
483  break;
484 
485  // 24 bit true color encoding
486  case 24 :
487  while ( nYCount < mpFileHeader->nImageHeight )
488  {
489  m_rTGA.ReadUChar( nRunCount );
490  if ( !m_rTGA.good())
491  return false;
492  if ( nRunCount & 0x80 ) // a run length packet
493  {
494  m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed );
495  if ( !m_rTGA.good())
496  return false;
497  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
498  {
499  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
500  nX += nXAdd;
501  nXCount++;
502  if ( nXCount == mpFileHeader->nImageWidth )
503  {
504  nX = nXStart;
505  nXCount = 0;
506  nY += nYAdd;
507  nYCount++;
508 
509  if( nYCount >= mpFileHeader->nImageHeight )
510  break;
511  }
512  }
513  }
514  else // a raw packet
515  {
516  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
517  {
518  m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed );
519  if ( !m_rTGA.good())
520  return false;
521  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
522  nX += nXAdd;
523  nXCount++;
524  if ( nXCount == mpFileHeader->nImageWidth )
525  {
526  nX = nXStart;
527  nXCount = 0;
528  nY += nYAdd;
529  nYCount++;
530 
531  if( nYCount >= mpFileHeader->nImageHeight )
532  break;
533  }
534  }
535  }
536  }
537  break;
538 
539  // 16 bit true color encoding
540  case 16 :
541  while ( nYCount < mpFileHeader->nImageHeight )
542  {
543  m_rTGA.ReadUChar( nRunCount );
544  if ( !m_rTGA.good())
545  return false;
546  if ( nRunCount & 0x80 ) // a run length packet
547  {
548  m_rTGA.ReadUInt16( nRGB16 );
549  if ( !m_rTGA.good())
550  return false;
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++ )
555  {
556  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
557  nX += nXAdd;
558  nXCount++;
559  if ( nXCount == mpFileHeader->nImageWidth )
560  {
561  nX = nXStart;
562  nXCount = 0;
563  nY += nYAdd;
564  nYCount++;
565 
566  if( nYCount >= mpFileHeader->nImageHeight )
567  break;
568  }
569  }
570  }
571  else // a raw packet
572  {
573  for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
574  {
575  m_rTGA.ReadUInt16( nRGB16 );
576  if ( !m_rTGA.good())
577  return false;
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;
581  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
582  nX += nXAdd;
583  nXCount++;
584  if ( nXCount == mpFileHeader->nImageWidth )
585  {
586  nX = nXStart;
587  nXCount = 0;
588  nY += nYAdd;
589  nYCount++;
590 
591  if( nYCount >= mpFileHeader->nImageHeight )
592  break;
593  }
594  }
595  }
596  }
597  break;
598 
599  default:
600  return false;
601  }
602  }
603  }
604  else
605  {
606  for ( nYCount = 0; nYCount < mpFileHeader->nImageHeight; nYCount++, nY += nYAdd )
607  {
608  nX = nXStart;
609  nXCount = 0;
610 
611  if ( mbIndexing )
612  {
613  switch( nDepth )
614  {
615  // 16 bit indexing
616  case 16 :
617  for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
618  {
619  m_rTGA.ReadUInt16( nRGB16 );
620  if ( !m_rTGA.good())
621  return false;
622  if ( nRGB16 >= mpFileHeader->nColorMapLength )
623  return false;
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 ] );
627  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
628  }
629  break;
630 
631  // 8 bit indexing
632  case 8 :
633  for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
634  {
635  m_rTGA.ReadUChar( nDummy );
636  if ( !m_rTGA.good())
637  return false;
638  if ( nDummy >= mpFileHeader->nColorMapLength )
639  return false;
640  mpBitmap->SetPixel( nY, nX, Color(ColorTransparency, nDummy) );
641  }
642  break;
643  default:
644  return false;
645  }
646  }
647  else
648  {
649  switch( nDepth )
650  {
651  // 32 bit true color
652  case 32 :
653  {
654  for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
655  {
656  m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed ).ReadUChar( nDummy );
657  if ( !m_rTGA.good())
658  return false;
659  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
660  }
661  }
662  break;
663 
664  // 24 bit true color
665  case 24 :
666  for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
667  {
668  m_rTGA.ReadUChar( nBlue ).ReadUChar( nGreen ).ReadUChar( nRed );
669  if ( !m_rTGA.good())
670  return false;
671  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
672  }
673  break;
674 
675  // 16 bit true color
676  case 16 :
677  for (;nXCount < mpFileHeader->nImageWidth; nXCount++, nX += nXAdd )
678  {
679  m_rTGA.ReadUInt16( nRGB16 );
680  if ( !m_rTGA.good())
681  return false;
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;
685  mpBitmap->SetPixel( nY, nX, Color( nRed, nGreen, nBlue ) );
686  }
687  break;
688  default:
689  return false;
690  }
691  }
692  }
693  }
694  return mbStatus;
695 }
696 
697 
698 bool TGAReader::ImplReadPalette()
699 {
700  if ( mbIndexing ) // read the colormap
701  {
702  sal_uInt16 nColors = mpFileHeader->nColorMapLength;
703 
704  if ( !nColors ) // colors == 0 ? -> we will build a grayscale palette
705  {
706  if ( mpFileHeader->nPixelDepth != 8 )
707  return false;
708  nColors = 256;
709  mpFileHeader->nColorMapLength = 256;
710  mpFileHeader->nColorMapEntrySize = 0x3f; // patch for the following switch routine
711  }
712  mpColorMap.reset( new sal_uInt32[ nColors ] ); // we will always index dwords
713 
714  switch( mpFileHeader->nColorMapEntrySize )
715  {
716  case 0x3f :
717  {
718  for (sal_uInt32 i = 0; i < nColors; ++i)
719  {
720  mpColorMap[ i ] = ( i << 16 ) + ( i << 8 ) + i;
721  }
722  }
723  break;
724 
725  case 32 :
726  for (sal_uInt16 i = 0; i < nColors; i++)
727  {
728  m_rTGA.ReadUInt32(mpColorMap[i]);
729  }
730  break;
731 
732  case 24 :
733  {
734  for ( sal_uInt16 i = 0; i < nColors; i++ )
735  {
736  sal_uInt8 nBlue;
737  sal_uInt8 nGreen;
738  sal_uInt8 nRed;
739  m_rTGA.ReadUChar(nBlue).ReadUChar(nGreen).ReadUChar(nRed);
740  mpColorMap[i] = (nRed << 16) | (nGreen << 8) | nBlue;
741  }
742  }
743  break;
744 
745  case 15 :
746  case 16 :
747  {
748  for ( sal_uInt16 i = 0; i < nColors; i++ )
749  {
750  sal_uInt16 nTemp;
751  m_rTGA.ReadUInt16( nTemp );
752  if ( !m_rTGA.good() )
753  return false;
754  mpColorMap[ i ] = ( ( nTemp & 0x7c00 ) << 9 ) + ( ( nTemp & 0x01e0 ) << 6 ) +
755  ( ( nTemp & 0x1f ) << 3 );
756  }
757  }
758  break;
759 
760  default :
761  return false;
762  }
763  if ( mnDestBitDepth <= 8 )
764  {
765  sal_uInt16 nDestColors = ( 1 << mnDestBitDepth );
766  if ( nColors > nDestColors )
767  return false;
768 
769  mvPalette.resize( nColors );
770  for ( sal_uInt16 i = 0; i < nColors; i++ )
771  {
772  mvPalette[i] = Color( static_cast<sal_uInt8>( mpColorMap[ i ] >> 16 ),
773  static_cast<sal_uInt8>( mpColorMap[ i ] >> 8 ), static_cast<sal_uInt8>(mpColorMap[ i ] ) );
774  }
775  }
776  }
777 
778  return mbStatus;
779 }
780 
781 //================== GraphicImport - the exported function ================
782 
783 bool ImportTgaGraphic(SvStream & rStream, Graphic & rGraphic)
784 {
785  TGAReader aTGAReader(rStream);
786 
787  return aTGAReader.ReadTGA(rGraphic);
788 }
789 
790 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Long
FPDF_BITMAP mpBitmap
#define SizeOfTGAFileFooter
Definition: itga.cxx:49
int i
#define SizeOfTGAExtension
Definition: itga.cxx:60
Intended to be used to feed into CreateFromData to create a BitmapEx.
Definition: RawBitmap.hxx:21
unsigned char sal_uInt8
BitmapEx CreateFromData(sal_uInt8 const *pData, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int32 nStride, vcl::PixelFormat ePixelFormat, bool bReversColors, bool bReverseAlpha)
Copy block of image data into the bitmap.
bool ImportTgaGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: itga.cxx:783