Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DirectXTexTGA.cpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------------------
2 // DirectXTexTGA.cpp
3 //
4 // DirectX Texture Library - Targa Truevision (TGA) file format reader/writer
5 //
6 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
7 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
8 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
9 // PARTICULAR PURPOSE.
10 //
11 // Copyright (c) Microsoft Corporation. All rights reserved.
12 //
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
15 
16 #include "directxtexp.h"
17 
18 //
19 // The implementation here has the following limitations:
20 // * Does not support files that contain color maps (these are rare in practice)
21 // * Interleaved files are not supported (deprecated aspect of TGA format)
22 // * Only supports 8-bit grayscale; 16-, 24-, and 32-bit truecolor images
23 // * Always writes uncompressed files (i.e. can read RLE compression, but does not write it)
24 //
25 
27 {
35 };
36 
38 {
41  TGA_FLAGS_INTERLEAVED_2WAY = 0x40, // Deprecated
42  TGA_FLAGS_INTERLEAVED_4WAY = 0x80, // Deprecated
43 };
44 
45 const char* g_TGA20_Signature = "TRUEVISION-XFILE.";
46 
47 #pragma pack(push,1)
48 struct TGA_HEADER
49 {
53  uint16_t wColorMapFirst;
54  uint16_t wColorMapLength;
56  uint16_t wXOrigin;
57  uint16_t wYOrigin;
58  uint16_t wWidth;
59  uint16_t wHeight;
62 };
63 
64 struct TGA_FOOTER
65 {
68  char Signature[18];
69 };
70 
72 {
73  uint16_t wSize;
74  char szAuthorName[41];
75  char szAuthorComment[324];
76  uint16_t wStampMonth;
77  uint16_t wStampDay;
78  uint16_t wStampYear;
79  uint16_t wStampHour;
80  uint16_t wStampMinute;
81  uint16_t wStampSecond;
82  char szJobName[41];
83  uint16_t wJobHour;
84  uint16_t wJobMinute;
85  uint16_t wJobSecond;
86  char szSoftwareId[41];
87  uint16_t wVersionNumber;
89  uint32_t dwKeyColor;
90  uint16_t wPixelNumerator;
92  uint16_t wGammaNumerator;
94  uint32_t dwColorOffset;
95  uint32_t dwStampOffset;
96  uint32_t dwScanOffset;
98 };
99 #pragma pack(pop)
100 
102 {
104  CONV_FLAGS_EXPAND = 0x1, // Conversion requires expanded pixel size
105  CONV_FLAGS_INVERTX = 0x2, // If set, scanlines are right-to-left
106  CONV_FLAGS_INVERTY = 0x4, // If set, scanlines are top-to-bottom
107  CONV_FLAGS_RLE = 0x8, // Source data is RLE compressed
108 
109  CONV_FLAGS_SWIZZLE = 0x10000, // Swizzle BGR<->RGB data
110  CONV_FLAGS_888 = 0x20000, // 24bpp format
111 };
112 
113 namespace DirectX
114 {
115 
116 //-------------------------------------------------------------------------------------
117 // Decodes TGA header
118 //-------------------------------------------------------------------------------------
119 static HRESULT _DecodeTGAHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t size, _Out_ TexMetadata& metadata, size_t& offset,
120  _Inout_opt_ DWORD* convFlags )
121 {
122  if ( !pSource )
123  return E_INVALIDARG;
124 
125  memset( &metadata, 0, sizeof(TexMetadata) );
126 
127  if ( size < sizeof(TGA_HEADER) )
128  {
129  return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
130  }
131 
132  auto pHeader = reinterpret_cast<const TGA_HEADER*>( pSource );
133 
134  if ( pHeader->bColorMapType != 0
135  || pHeader->wColorMapLength != 0 )
136  {
137  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
138  }
139 
140  if ( pHeader->bDescriptor & (TGA_FLAGS_INTERLEAVED_2WAY|TGA_FLAGS_INTERLEAVED_4WAY) )
141  {
142  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
143  }
144 
145  if ( !pHeader->wWidth || !pHeader->wHeight )
146  {
147  return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
148  }
149 
150  switch ( pHeader->bImageType )
151  {
152  case TGA_TRUECOLOR:
153  case TGA_TRUECOLOR_RLE:
154  switch( pHeader->bBitsPerPixel )
155  {
156  case 16:
157  metadata.format = DXGI_FORMAT_B5G5R5A1_UNORM;
158  break;
159 
160  case 24:
161  metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
162  if ( convFlags )
163  *convFlags |= CONV_FLAGS_EXPAND;
164  // We could use DXGI_FORMAT_B8G8R8X8_UNORM, but we prefer DXGI 1.0 formats
165  break;
166 
167  case 32:
168  metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
169  // We could use DXGI_FORMAT_B8G8R8A8_UNORM, but we prefer DXGI 1.0 formats
170  break;
171  }
172 
173  if ( convFlags && (pHeader->bImageType == TGA_TRUECOLOR_RLE) )
174  {
175  *convFlags |= CONV_FLAGS_RLE;
176  }
177  break;
178 
179  case TGA_BLACK_AND_WHITE:
181  switch( pHeader->bBitsPerPixel )
182  {
183  case 8:
184  metadata.format = DXGI_FORMAT_R8_UNORM;
185  break;
186 
187  default:
188  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
189  }
190 
191  if ( convFlags && (pHeader->bImageType == TGA_BLACK_AND_WHITE_RLE) )
192  {
193  *convFlags |= CONV_FLAGS_RLE;
194  }
195  break;
196 
197  case TGA_NO_IMAGE:
198  case TGA_COLOR_MAPPED:
200  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
201 
202  default:
203  return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
204  }
205 
206  metadata.width = pHeader->wWidth;
207  metadata.height = pHeader->wHeight;
208  metadata.depth = metadata.arraySize = metadata.mipLevels = 1;
209  metadata.dimension = TEX_DIMENSION_TEXTURE2D;
210 
211  if ( convFlags )
212  {
213  if ( pHeader->bDescriptor & TGA_FLAGS_INVERTX )
214  *convFlags |= CONV_FLAGS_INVERTX;
215 
216  if ( pHeader->bDescriptor & TGA_FLAGS_INVERTY )
217  *convFlags |= CONV_FLAGS_INVERTY;
218  }
219 
220  offset = sizeof( TGA_HEADER );
221 
222  if ( pHeader->bIDLength != 0 )
223  {
224  offset += pHeader->bIDLength;
225  }
226 
227  return S_OK;
228 }
229 
230 
231 //-------------------------------------------------------------------------------------
232 // Set alpha for images with all 0 alpha channel
233 //-------------------------------------------------------------------------------------
234 static HRESULT _SetAlphaChannelToOpaque( _In_ const Image* image )
235 {
236  assert( image );
237 
238  auto pPixels = reinterpret_cast<uint8_t*>( image->pixels );
239  if ( !pPixels )
240  return E_POINTER;
241 
242  for( size_t y = 0; y < image->height; ++y )
243  {
244  _CopyScanline( pPixels, image->rowPitch, pPixels, image->rowPitch, image->format, TEXP_SCANLINE_SETALPHA );
245  pPixels += image->rowPitch;
246  }
247 
248  return S_OK;
249 }
250 
251 
252 //-------------------------------------------------------------------------------------
253 // Uncompress pixel data from a TGA into the target image
254 //-------------------------------------------------------------------------------------
255 static HRESULT _UncompressPixels( _In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image* image, _In_ DWORD convFlags )
256 {
257  assert( pSource && size > 0 );
258 
259  if ( !image || !image->pixels )
260  return E_POINTER;
261 
262  // Compute TGA image data pitch
263  size_t rowPitch;
264  if ( convFlags & CONV_FLAGS_EXPAND )
265  {
266  rowPitch = image->width * 3;
267  }
268  else
269  {
270  size_t slicePitch;
271  ComputePitch( image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE );
272  }
273 
274  auto sPtr = reinterpret_cast<const uint8_t*>( pSource );
275  const uint8_t* endPtr = sPtr + size;
276 
277  switch( image->format )
278  {
279  //--------------------------------------------------------------------------- 8-bit
280  case DXGI_FORMAT_R8_UNORM:
281  for( size_t y=0; y < image->height; ++y )
282  {
283  size_t offset = ( (convFlags & CONV_FLAGS_INVERTX ) ? (image->width - 1) : 0 );
284  assert( offset < rowPitch);
285 
286  uint8_t* dPtr = reinterpret_cast<uint8_t*>( image->pixels )
287  + ( image->rowPitch * ( (convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1) ) )
288  + offset;
289 
290  for( size_t x=0; x < image->width; )
291  {
292  if ( sPtr >= endPtr )
293  return E_FAIL;
294 
295  if ( *sPtr & 0x80 )
296  {
297  // Repeat
298  size_t j = (*sPtr & 0x7F) + 1;
299  if ( ++sPtr >= endPtr )
300  return E_FAIL;
301 
302  for( ; j > 0; --j, ++x )
303  {
304  if ( x >= image->width )
305  return E_FAIL;
306 
307  *dPtr = *sPtr;
308 
309  if ( convFlags & CONV_FLAGS_INVERTX )
310  --dPtr;
311  else
312  ++dPtr;
313  }
314 
315  ++sPtr;
316  }
317  else
318  {
319  // Literal
320  size_t j = (*sPtr & 0x7F) + 1;
321  ++sPtr;
322 
323  if ( sPtr+j > endPtr )
324  return E_FAIL;
325 
326  for( ; j > 0; --j, ++x )
327  {
328  if ( x >= image->width )
329  return E_FAIL;
330 
331  *dPtr = *(sPtr++);
332 
333  if ( convFlags & CONV_FLAGS_INVERTX )
334  --dPtr;
335  else
336  ++dPtr;
337  }
338  }
339  }
340  }
341  break;
342 
343  //-------------------------------------------------------------------------- 16-bit
344  case DXGI_FORMAT_B5G5R5A1_UNORM:
345  {
346  bool nonzeroa = false;
347  for( size_t y=0; y < image->height; ++y )
348  {
349  size_t offset = ( (convFlags & CONV_FLAGS_INVERTX ) ? (image->width - 1) : 0 );
350  assert( offset*2 < rowPitch);
351 
352  uint16_t* dPtr = reinterpret_cast<uint16_t*>( reinterpret_cast<uint8_t*>( image->pixels )
353  + ( image->rowPitch * ( (convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1) ) ) )
354  + offset;
355 
356  for( size_t x=0; x < image->width; )
357  {
358  if ( sPtr >= endPtr )
359  return E_FAIL;
360 
361  if ( *sPtr & 0x80 )
362  {
363  // Repeat
364  size_t j = (*sPtr & 0x7F) + 1;
365  ++sPtr;
366 
367  if ( sPtr+1 >= endPtr )
368  return E_FAIL;
369 
370  uint16_t t = *sPtr | (*(sPtr+1) << 8);
371  if ( t & 0x8000 )
372  nonzeroa = true;
373  sPtr += 2;
374 
375  for( ; j > 0; --j, ++x )
376  {
377  if ( x >= image->width )
378  return E_FAIL;
379 
380  *dPtr = t;
381 
382  if ( convFlags & CONV_FLAGS_INVERTX )
383  --dPtr;
384  else
385  ++dPtr;
386  }
387  }
388  else
389  {
390  // Literal
391  size_t j = (*sPtr & 0x7F) + 1;
392  ++sPtr;
393 
394  if ( sPtr+(j*2) > endPtr )
395  return E_FAIL;
396 
397  for( ; j > 0; --j, ++x )
398  {
399  if ( x >= image->width )
400  return E_FAIL;
401 
402  uint16_t t = *sPtr | (*(sPtr+1) << 8);
403  if ( t & 0x8000 )
404  nonzeroa = true;
405  sPtr += 2;
406  *dPtr = t;
407 
408  if ( convFlags & CONV_FLAGS_INVERTX )
409  --dPtr;
410  else
411  ++dPtr;
412  }
413  }
414  }
415  }
416 
417  // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
418  if ( !nonzeroa )
419  {
420  HRESULT hr = _SetAlphaChannelToOpaque( image );
421  if ( FAILED(hr) )
422  return hr;
423  }
424  }
425  break;
426 
427  //----------------------------------------------------------------------- 24/32-bit
428  case DXGI_FORMAT_R8G8B8A8_UNORM:
429  {
430  bool nonzeroa = false;
431  for( size_t y=0; y < image->height; ++y )
432  {
433  size_t offset = ( (convFlags & CONV_FLAGS_INVERTX ) ? (image->width - 1) : 0 );
434 
435  uint32_t* dPtr = reinterpret_cast<uint32_t*>( reinterpret_cast<uint8_t*>( image->pixels )
436  + ( image->rowPitch * ( (convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1) ) ) )
437  + offset;
438 
439  for( size_t x=0; x < image->width; )
440  {
441  if ( sPtr >= endPtr )
442  return E_FAIL;
443 
444  if ( *sPtr & 0x80 )
445  {
446  // Repeat
447  size_t j = (*sPtr & 0x7F) + 1;
448  ++sPtr;
449 
450  DWORD t;
451  if ( convFlags & CONV_FLAGS_EXPAND )
452  {
453  assert( offset*3 < rowPitch);
454 
455  if ( sPtr+2 >= endPtr )
456  return E_FAIL;
457 
458  // BGR -> RGBA
459  t = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | 0xFF000000;
460  sPtr += 3;
461 
462  nonzeroa = true;
463  }
464  else
465  {
466  assert( offset*4 < rowPitch);
467 
468  if ( sPtr+3 >= endPtr )
469  return E_FAIL;
470 
471  // BGRA -> RGBA
472  t = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | ( *(sPtr+3) << 24 );
473 
474  if ( *(sPtr+3) > 0 )
475  nonzeroa = true;
476 
477  sPtr += 4;
478  }
479 
480  for( ; j > 0; --j, ++x )
481  {
482  if ( x >= image->width )
483  return E_FAIL;
484 
485  *dPtr = t;
486 
487  if ( convFlags & CONV_FLAGS_INVERTX )
488  --dPtr;
489  else
490  ++dPtr;
491  }
492  }
493  else
494  {
495  // Literal
496  size_t j = (*sPtr & 0x7F) + 1;
497  ++sPtr;
498 
499  if ( convFlags & CONV_FLAGS_EXPAND )
500  {
501  if ( sPtr+(j*3) > endPtr )
502  return E_FAIL;
503  }
504  else
505  {
506  if ( sPtr+(j*4) > endPtr )
507  return E_FAIL;
508  }
509 
510  for( ; j > 0; --j, ++x )
511  {
512  if ( x >= image->width )
513  return E_FAIL;
514 
515  if ( convFlags & CONV_FLAGS_EXPAND )
516  {
517  assert( offset*3 < rowPitch);
518 
519  if ( sPtr+2 >= endPtr )
520  return E_FAIL;
521 
522  // BGR -> RGBA
523  *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | 0xFF000000;
524  sPtr += 3;
525 
526  nonzeroa = true;
527  }
528  else
529  {
530  assert( offset*4 < rowPitch);
531 
532  if ( sPtr+3 >= endPtr )
533  return E_FAIL;
534 
535  // BGRA -> RGBA
536  *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | ( *(sPtr+3) << 24 );
537 
538  if ( *(sPtr+3) > 0 )
539  nonzeroa = true;
540 
541  sPtr += 4;
542  }
543 
544  if ( convFlags & CONV_FLAGS_INVERTX )
545  --dPtr;
546  else
547  ++dPtr;
548  }
549  }
550  }
551  }
552 
553  // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
554  if ( !nonzeroa )
555  {
556  HRESULT hr = _SetAlphaChannelToOpaque( image );
557  if ( FAILED(hr) )
558  return hr;
559  }
560  }
561  break;
562 
563  //---------------------------------------------------------------------------------
564  default:
565  return E_FAIL;
566  }
567 
568  return S_OK;
569 }
570 
571 
572 //-------------------------------------------------------------------------------------
573 // Copies pixel data from a TGA into the target image
574 //-------------------------------------------------------------------------------------
575 static HRESULT _CopyPixels( _In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image* image, _In_ DWORD convFlags )
576 {
577  assert( pSource && size > 0 );
578 
579  if ( !image || !image->pixels )
580  return E_POINTER;
581 
582  // Compute TGA image data pitch
583  size_t rowPitch;
584  if ( convFlags & CONV_FLAGS_EXPAND )
585  {
586  rowPitch = image->width * 3;
587  }
588  else
589  {
590  size_t slicePitch;
591  ComputePitch( image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE );
592  }
593 
594  const uint8_t* sPtr = reinterpret_cast<const uint8_t*>( pSource );
595  const uint8_t* endPtr = sPtr + size;
596 
597  switch( image->format )
598  {
599  //--------------------------------------------------------------------------- 8-bit
600  case DXGI_FORMAT_R8_UNORM:
601  for( size_t y=0; y < image->height; ++y )
602  {
603  size_t offset = ( (convFlags & CONV_FLAGS_INVERTX ) ? (image->width - 1) : 0 );
604  assert( offset < rowPitch);
605 
606  uint8_t* dPtr = reinterpret_cast<uint8_t*>( image->pixels )
607  + ( image->rowPitch * ( (convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1) ) )
608  + offset;
609 
610  for( size_t x=0; x < image->width; ++x )
611  {
612  if ( sPtr >= endPtr )
613  return E_FAIL;
614 
615  *dPtr = *(sPtr++);
616 
617  if ( convFlags & CONV_FLAGS_INVERTX )
618  --dPtr;
619  else
620  ++dPtr;
621  }
622  }
623  break;
624 
625  //-------------------------------------------------------------------------- 16-bit
626  case DXGI_FORMAT_B5G5R5A1_UNORM:
627  {
628  bool nonzeroa = false;
629  for( size_t y=0; y < image->height; ++y )
630  {
631  size_t offset = ( (convFlags & CONV_FLAGS_INVERTX ) ? (image->width - 1) : 0 );
632  assert( offset*2 < rowPitch);
633 
634  uint16_t* dPtr = reinterpret_cast<uint16_t*>( reinterpret_cast<uint8_t*>( image->pixels )
635  + ( image->rowPitch * ( (convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1) ) ) )
636  + offset;
637 
638  for( size_t x=0; x < image->width; ++x )
639  {
640  if ( sPtr+1 >= endPtr )
641  return E_FAIL;
642 
643  uint16_t t = *sPtr | (*(sPtr+1) << 8);
644  sPtr += 2;
645  *dPtr = t;
646 
647  if ( t & 0x8000 )
648  nonzeroa = true;
649 
650  if ( convFlags & CONV_FLAGS_INVERTX )
651  --dPtr;
652  else
653  ++dPtr;
654  }
655  }
656 
657  // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
658  if ( !nonzeroa )
659  {
660  HRESULT hr = _SetAlphaChannelToOpaque( image );
661  if ( FAILED(hr) )
662  return hr;
663  }
664  }
665  break;
666 
667  //----------------------------------------------------------------------- 24/32-bit
668  case DXGI_FORMAT_R8G8B8A8_UNORM:
669  {
670  bool nonzeroa = false;
671  for( size_t y=0; y < image->height; ++y )
672  {
673  size_t offset = ( (convFlags & CONV_FLAGS_INVERTX ) ? (image->width - 1) : 0 );
674 
675  uint32_t* dPtr = reinterpret_cast<uint32_t*>( reinterpret_cast<uint8_t*>( image->pixels )
676  + ( image->rowPitch * ( (convFlags & CONV_FLAGS_INVERTY) ? y : (image->height - y - 1) ) ) )
677  + offset;
678 
679  for( size_t x=0; x < image->width; ++x )
680  {
681  if ( convFlags & CONV_FLAGS_EXPAND )
682  {
683  assert( offset*3 < rowPitch);
684 
685  if ( sPtr+2 >= endPtr )
686  return E_FAIL;
687 
688  // BGR -> RGBA
689  *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | 0xFF000000;
690  sPtr += 3;
691 
692  nonzeroa = true;
693  }
694  else
695  {
696  assert( offset*4 < rowPitch);
697 
698  if ( sPtr+3 >= endPtr )
699  return E_FAIL;
700 
701  // BGRA -> RGBA
702  *dPtr = ( *sPtr << 16 ) | ( *(sPtr+1) << 8 ) | ( *(sPtr+2) ) | ( *(sPtr+3) << 24 );
703 
704  if ( *(sPtr+3) > 0 )
705  nonzeroa = true;
706 
707  sPtr += 4;
708  }
709 
710  if ( convFlags & CONV_FLAGS_INVERTX )
711  --dPtr;
712  else
713  ++dPtr;
714  }
715  }
716 
717  // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
718  if ( !nonzeroa )
719  {
720  HRESULT hr = _SetAlphaChannelToOpaque( image );
721  if ( FAILED(hr) )
722  return hr;
723  }
724  }
725  break;
726 
727  //---------------------------------------------------------------------------------
728  default:
729  return E_FAIL;
730  }
731 
732  return S_OK;
733 }
734 
735 
736 //-------------------------------------------------------------------------------------
737 // Encodes TGA file header
738 //-------------------------------------------------------------------------------------
739 static HRESULT _EncodeTGAHeader( _In_ const Image& image, _Out_ TGA_HEADER& header, _Inout_ DWORD& convFlags )
740 {
741  memset( &header, 0, sizeof(TGA_HEADER) );
742 
743  if ( (image.width > 0xFFFF)
744  || (image.height > 0xFFFF) )
745  {
746  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
747  }
748 
749  header.wWidth = static_cast<uint16_t>( image.width );
750  header.wHeight = static_cast<uint16_t>( image.height );
751 
752  switch( image.format )
753  {
754  case DXGI_FORMAT_R8G8B8A8_UNORM:
755  case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
756  header.bImageType = TGA_TRUECOLOR;
757  header.bBitsPerPixel = 32;
758  header.bDescriptor = TGA_FLAGS_INVERTY | 8;
759  convFlags |= CONV_FLAGS_SWIZZLE;
760  break;
761 
762  case DXGI_FORMAT_B8G8R8A8_UNORM:
763  case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
764  header.bImageType = TGA_TRUECOLOR;
765  header.bBitsPerPixel = 32;
766  header.bDescriptor = TGA_FLAGS_INVERTY | 8;
767  break;
768 
769  case DXGI_FORMAT_B8G8R8X8_UNORM:
770  case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
771  header.bImageType = TGA_TRUECOLOR;
772  header.bBitsPerPixel = 24;
773  header.bDescriptor = TGA_FLAGS_INVERTY;
774  convFlags |= CONV_FLAGS_888;
775  break;
776 
777  case DXGI_FORMAT_R8_UNORM:
778  case DXGI_FORMAT_A8_UNORM:
779  header.bImageType = TGA_BLACK_AND_WHITE;
780  header.bBitsPerPixel = 8;
781  header.bDescriptor = TGA_FLAGS_INVERTY;
782  break;
783 
784  case DXGI_FORMAT_B5G5R5A1_UNORM:
785  header.bImageType = TGA_TRUECOLOR;
786  header.bBitsPerPixel = 16;
787  header.bDescriptor = TGA_FLAGS_INVERTY | 1;
788  break;
789 
790  default:
791  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
792  }
793 
794  return S_OK;
795 }
796 
797 
798 //-------------------------------------------------------------------------------------
799 // Copies BGRX data to form BGR 24bpp data
800 //-------------------------------------------------------------------------------------
801 #pragma warning(suppress: 6001 6101) // In the case where outSize is insufficient we do not write to pDestination
802 static void _Copy24bppScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
803  _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize )
804 {
805  assert( pDestination && outSize > 0 );
806  assert( pSource && inSize > 0 );
807 
808  assert( pDestination != pSource );
809 
810  const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
811  uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
812 
813  if ( inSize >= 4 && outSize >= 3 )
814  {
815  const uint8_t* endPtr = dPtr + outSize;
816 
817  for( size_t count = 0; count < ( inSize - 3 ); count += 4 )
818  {
819  uint32_t t = *(sPtr++);
820 
821  if ( dPtr+3 > endPtr )
822  return;
823 
824  *(dPtr++) = uint8_t(t & 0xFF); // Blue
825  *(dPtr++) = uint8_t((t & 0xFF00) >> 8); // Green
826  *(dPtr++) = uint8_t((t & 0xFF0000) >> 16); // Red
827  }
828  }
829 }
830 
831 
832 //=====================================================================================
833 // Entry-points
834 //=====================================================================================
835 
836 //-------------------------------------------------------------------------------------
837 // Obtain metadata from TGA file in memory/on disk
838 //-------------------------------------------------------------------------------------
839 _Use_decl_annotations_
840 HRESULT GetMetadataFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata& metadata )
841 {
842  if ( !pSource || size == 0 )
843  return E_INVALIDARG;
844 
845  size_t offset;
846  return _DecodeTGAHeader( pSource, size, metadata, offset, 0 );
847 }
848 
849 _Use_decl_annotations_
850 HRESULT GetMetadataFromTGAFile( LPCWSTR szFile, TexMetadata& metadata )
851 {
852  if ( !szFile )
853  return E_INVALIDARG;
854 
855 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
856  ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 ) ) );
857 #else
858  ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
859  FILE_FLAG_SEQUENTIAL_SCAN, 0 ) ) );
860 #endif
861  if ( !hFile )
862  {
863  return HRESULT_FROM_WIN32( GetLastError() );
864  }
865 
866  // Get the file size
867  LARGE_INTEGER fileSize = {0};
868 
869 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
870  FILE_STANDARD_INFO fileInfo;
871  if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )
872  {
873  return HRESULT_FROM_WIN32( GetLastError() );
874  }
875  fileSize = fileInfo.EndOfFile;
876 #else
877  if ( !GetFileSizeEx( hFile.get(), &fileSize ) )
878  {
879  return HRESULT_FROM_WIN32( GetLastError() );
880  }
881 #endif
882 
883  // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid TGA file)
884  if ( fileSize.HighPart > 0 )
885  {
886  return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
887  }
888 
889  // Need at least enough data to fill the standard header to be a valid TGA
890  if ( fileSize.LowPart < ( sizeof(TGA_HEADER) ) )
891  {
892  return E_FAIL;
893  }
894 
895  // Read the standard header (we don't need the file footer to parse the file)
896  uint8_t header[sizeof(TGA_HEADER)];
897  DWORD bytesRead = 0;
898  if ( !ReadFile( hFile.get(), header, sizeof(TGA_HEADER), &bytesRead, 0 ) )
899  {
900  return HRESULT_FROM_WIN32( GetLastError() );
901  }
902 
903  size_t offset;
904  return _DecodeTGAHeader( header, bytesRead, metadata, offset, 0 );
905 }
906 
907 
908 //-------------------------------------------------------------------------------------
909 // Load a TGA file in memory
910 //-------------------------------------------------------------------------------------
911 _Use_decl_annotations_
912 HRESULT LoadFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata* metadata, ScratchImage& image )
913 {
914  if ( !pSource || size == 0 )
915  return E_INVALIDARG;
916 
917  image.Release();
918 
919  size_t offset;
920  DWORD convFlags = 0;
921  TexMetadata mdata;
922  HRESULT hr = _DecodeTGAHeader( pSource, size, mdata, offset, &convFlags );
923  if ( FAILED(hr) )
924  return hr;
925 
926  if ( offset > size )
927  return E_FAIL;
928 
929  auto pPixels = reinterpret_cast<LPCVOID>( reinterpret_cast<const uint8_t*>(pSource) + offset );
930 
931  size_t remaining = size - offset;
932  if ( remaining == 0 )
933  return E_FAIL;
934 
935  hr = image.Initialize2D( mdata.format, mdata.width, mdata.height, 1, 1 );
936  if ( FAILED(hr) )
937  return hr;
938 
939  if ( convFlags & CONV_FLAGS_RLE )
940  {
941  hr = _UncompressPixels( pPixels, remaining, image.GetImage(0,0,0), convFlags );
942  }
943  else
944  {
945  hr = _CopyPixels( pPixels, remaining, image.GetImage(0,0,0), convFlags );
946  }
947 
948  if ( FAILED(hr) )
949  {
950  image.Release();
951  return hr;
952  }
953 
954  if ( metadata )
955  memcpy( metadata, &mdata, sizeof(TexMetadata) );
956 
957  return S_OK;
958 }
959 
960 
961 //-------------------------------------------------------------------------------------
962 // Load a TGA file from disk
963 //-------------------------------------------------------------------------------------
964 _Use_decl_annotations_
965 HRESULT LoadFromTGAFile( LPCWSTR szFile, TexMetadata* metadata, ScratchImage& image )
966 {
967  if ( !szFile )
968  return E_INVALIDARG;
969 
970  image.Release();
971 
972 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
973  ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 ) ) );
974 #else
975  ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
976  FILE_FLAG_SEQUENTIAL_SCAN, 0 ) ) );
977 #endif
978  if ( !hFile )
979  {
980  return HRESULT_FROM_WIN32( GetLastError() );
981  }
982 
983  // Get the file size
984  LARGE_INTEGER fileSize = {0};
985 
986 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
987  FILE_STANDARD_INFO fileInfo;
988  if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )
989  {
990  return HRESULT_FROM_WIN32( GetLastError() );
991  }
992  fileSize = fileInfo.EndOfFile;
993 #else
994  if ( !GetFileSizeEx( hFile.get(), &fileSize ) )
995  {
996  return HRESULT_FROM_WIN32( GetLastError() );
997  }
998 #endif
999 
1000  // File is too big for 32-bit allocation, so reject read (4 GB should be plenty large enough for a valid TGA file)
1001  if ( fileSize.HighPart > 0 )
1002  {
1003  return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
1004  }
1005 
1006  // Need at least enough data to fill the header to be a valid TGA
1007  if ( fileSize.LowPart < sizeof(TGA_HEADER) )
1008  {
1009  return E_FAIL;
1010  }
1011 
1012  // Read the header
1013  uint8_t header[sizeof(TGA_HEADER)];
1014  DWORD bytesRead = 0;
1015  if ( !ReadFile( hFile.get(), header, sizeof(TGA_HEADER), &bytesRead, 0 ) )
1016  {
1017  return HRESULT_FROM_WIN32( GetLastError() );
1018  }
1019 
1020  size_t offset;
1021  DWORD convFlags = 0;
1022  TexMetadata mdata;
1023  HRESULT hr = _DecodeTGAHeader( header, bytesRead, mdata, offset, &convFlags );
1024  if ( FAILED(hr) )
1025  return hr;
1026 
1027  // Read the pixels
1028  DWORD remaining = static_cast<DWORD>( fileSize.LowPart - offset );
1029  if ( remaining == 0 )
1030  return E_FAIL;
1031 
1032  if ( offset > sizeof(TGA_HEADER) )
1033  {
1034  // Skip past the id string
1035  LARGE_INTEGER filePos = { static_cast<DWORD>(offset), 0 };
1036  if ( !SetFilePointerEx( hFile.get(), filePos, 0, FILE_BEGIN ) )
1037  {
1038  return HRESULT_FROM_WIN32( GetLastError() );
1039  }
1040  }
1041 
1042  hr = image.Initialize2D( mdata.format, mdata.width, mdata.height, 1, 1 );
1043  if ( FAILED(hr) )
1044  return hr;
1045 
1046  assert( image.GetPixels() );
1047 
1048  if ( !(convFlags & (CONV_FLAGS_RLE | CONV_FLAGS_EXPAND | CONV_FLAGS_INVERTX)) && (convFlags & CONV_FLAGS_INVERTY) )
1049  {
1050  // This case we can read directly into the image buffer in place
1051  if ( !ReadFile( hFile.get(), image.GetPixels(), static_cast<DWORD>( image.GetPixelsSize() ), &bytesRead, 0 ) )
1052  {
1053  image.Release();
1054  return HRESULT_FROM_WIN32( GetLastError() );
1055  }
1056 
1057  if ( bytesRead != image.GetPixelsSize() )
1058  {
1059  image.Release();
1060  return E_FAIL;
1061  }
1062 
1063  switch( mdata.format )
1064  {
1065  case DXGI_FORMAT_R8G8B8A8_UNORM:
1066  {
1067  // TGA stores 32-bit data in BGRA form, need to swizzle to RGBA
1068  assert( image.GetImageCount() == 1 );
1069  const Image* img = image.GetImage(0,0,0);
1070  if ( !img )
1071  return E_POINTER;
1072 
1073  uint8_t *pPixels = img->pixels;
1074  if ( !pPixels )
1075  return E_POINTER;
1076 
1077  size_t rowPitch = img->rowPitch;
1078 
1079  // Scan for non-zero alpha channel
1080  bool nonzeroa = false;
1081 
1082  for( size_t h = 0; h < img->height; ++h )
1083  {
1084  const uint32_t* sPtr = reinterpret_cast<const uint32_t*>( pPixels );
1085 
1086  for( size_t x=0; x < img->width; ++x )
1087  {
1088  if ( (*sPtr) & 0xff000000 )
1089  {
1090  nonzeroa = true;
1091  break;
1092  }
1093 
1094  ++sPtr;
1095  }
1096 
1097  if ( nonzeroa )
1098  break;
1099 
1100  pPixels += rowPitch;
1101  }
1102 
1103  DWORD tflags = ( !nonzeroa ) ? TEXP_SCANLINE_SETALPHA : TEXP_SCANLINE_NONE;
1104 
1105  // Swizzle scanlines
1106  pPixels = img->pixels;
1107 
1108  for( size_t h = 0; h < img->height; ++h )
1109  {
1110  _SwizzleScanline( pPixels, rowPitch, pPixels, rowPitch, mdata.format, tflags );
1111  pPixels += rowPitch;
1112  }
1113  }
1114  break;
1115 
1116  // If we start using DXGI_FORMAT_B8G8R8X8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM we need to check for a fully 0 alpha channel
1117 
1118  case DXGI_FORMAT_B5G5R5A1_UNORM:
1119  {
1120  assert( image.GetImageCount() == 1 );
1121  const Image* img = image.GetImage(0,0,0);
1122  if ( !img )
1123  return E_POINTER;
1124 
1125  // Scan for non-zero alpha channel
1126  bool nonzeroa = false;
1127 
1128  const uint8_t *pPixels = img->pixels;
1129  if ( !pPixels )
1130  return E_POINTER;
1131 
1132  size_t rowPitch = img->rowPitch;
1133 
1134  for( size_t h = 0; h < img->height; ++h )
1135  {
1136  const uint16_t* sPtr = reinterpret_cast<const uint16_t*>( pPixels );
1137 
1138  for( size_t x=0; x < img->width; ++x )
1139  {
1140  if ( *sPtr & 0x8000 )
1141  {
1142  nonzeroa = true;
1143  break;
1144  }
1145 
1146  ++sPtr;
1147  }
1148 
1149  if ( nonzeroa )
1150  break;
1151 
1152  pPixels += rowPitch;
1153  }
1154 
1155  // If there are no non-zero alpha channel entries, we'll assume alpha is not used and force it to opaque
1156  if ( !nonzeroa )
1157  {
1158  hr = _SetAlphaChannelToOpaque( img );
1159  if ( FAILED(hr) )
1160  return hr;
1161  }
1162  }
1163  break;
1164  }
1165  }
1166  else // RLE || EXPAND || INVERTX || !INVERTY
1167  {
1168  std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ remaining ] );
1169  if ( !temp )
1170  {
1171  image.Release();
1172  return E_OUTOFMEMORY;
1173  }
1174 
1175  if ( !ReadFile( hFile.get(), temp.get(), remaining, &bytesRead, 0 ) )
1176  {
1177  image.Release();
1178  return HRESULT_FROM_WIN32( GetLastError() );
1179  }
1180 
1181  if ( bytesRead != remaining )
1182  {
1183  image.Release();
1184  return E_FAIL;
1185  }
1186 
1187  if ( convFlags & CONV_FLAGS_RLE )
1188  {
1189  hr = _UncompressPixels( temp.get(), remaining, image.GetImage(0,0,0), convFlags );
1190  }
1191  else
1192  {
1193  hr = _CopyPixels( temp.get(), remaining, image.GetImage(0,0,0), convFlags );
1194  }
1195 
1196  if ( FAILED(hr) )
1197  {
1198  image.Release();
1199  return hr;
1200  }
1201  }
1202 
1203  if ( metadata )
1204  memcpy( metadata, &mdata, sizeof(TexMetadata) );
1205 
1206  return S_OK;
1207 }
1208 
1209 
1210 //-------------------------------------------------------------------------------------
1211 // Save a TGA file to memory
1212 //-------------------------------------------------------------------------------------
1213 _Use_decl_annotations_
1214 HRESULT SaveToTGAMemory( const Image& image, Blob& blob )
1215 {
1216  if ( !image.pixels )
1217  return E_POINTER;
1218 
1219  TGA_HEADER tga_header;
1220  DWORD convFlags = 0;
1221  HRESULT hr = _EncodeTGAHeader( image, tga_header, convFlags );
1222  if ( FAILED(hr) )
1223  return hr;
1224 
1225  blob.Release();
1226 
1227  // Determine memory required for image data
1228  size_t rowPitch, slicePitch;
1229  if ( convFlags & CONV_FLAGS_888 )
1230  {
1231  rowPitch = image.width * 3;
1232  slicePitch = image.height * rowPitch;
1233  }
1234  else
1235  {
1236  ComputePitch( image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE );
1237  }
1238 
1239  hr = blob.Initialize( sizeof(TGA_HEADER) + slicePitch );
1240  if ( FAILED(hr) )
1241  return hr;
1242 
1243  // Copy header
1244  auto dPtr = reinterpret_cast<uint8_t*>( blob.GetBufferPointer() );
1245  assert( dPtr != 0 );
1246  memcpy_s( dPtr, blob.GetBufferSize(), &tga_header, sizeof(TGA_HEADER) );
1247  dPtr += sizeof(TGA_HEADER);
1248 
1249  auto pPixels = reinterpret_cast<const uint8_t*>( image.pixels );
1250  assert( pPixels );
1251 
1252  for( size_t y = 0; y < image.height; ++y )
1253  {
1254  // Copy pixels
1255  if ( convFlags & CONV_FLAGS_888 )
1256  {
1257  _Copy24bppScanline( dPtr, rowPitch, pPixels, image.rowPitch );
1258  }
1259  else if ( convFlags & CONV_FLAGS_SWIZZLE )
1260  {
1261  _SwizzleScanline( dPtr, rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE );
1262  }
1263  else
1264  {
1265  _CopyScanline( dPtr, rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE );
1266  }
1267 
1268  dPtr += rowPitch;
1269  pPixels += image.rowPitch;
1270  }
1271 
1272  return S_OK;
1273 }
1274 
1275 
1276 //-------------------------------------------------------------------------------------
1277 // Save a TGA file to disk
1278 //-------------------------------------------------------------------------------------
1279 _Use_decl_annotations_
1280 HRESULT SaveToTGAFile( const Image& image, LPCWSTR szFile )
1281 {
1282  if ( !szFile )
1283  return E_INVALIDARG;
1284 
1285  if ( !image.pixels )
1286  return E_POINTER;
1287 
1288  TGA_HEADER tga_header;
1289  DWORD convFlags = 0;
1290  HRESULT hr = _EncodeTGAHeader( image, tga_header, convFlags );
1291  if ( FAILED(hr) )
1292  return hr;
1293 
1294  // Create file and write header
1295 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1296  ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) );
1297 #else
1298  ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
1299 #endif
1300  if ( !hFile )
1301  {
1302  return HRESULT_FROM_WIN32( GetLastError() );
1303  }
1304 
1305  // Determine size for TGA pixel data
1306  size_t rowPitch, slicePitch;
1307  if ( convFlags & CONV_FLAGS_888 )
1308  {
1309  rowPitch = image.width * 3;
1310  slicePitch = image.height * rowPitch;
1311  }
1312  else
1313  {
1314  ComputePitch( image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE );
1315  }
1316 
1317  if ( slicePitch < 65535 )
1318  {
1319  // For small images, it is better to create an in-memory file and write it out
1320  Blob blob;
1321 
1322  hr = SaveToTGAMemory( image, blob );
1323  if ( FAILED(hr) )
1324  return hr;
1325 
1326  // Write blob
1327  const DWORD bytesToWrite = static_cast<DWORD>( blob.GetBufferSize() );
1328  DWORD bytesWritten;
1329  if ( !WriteFile( hFile.get(), blob.GetBufferPointer(), bytesToWrite,
1330  &bytesWritten, 0 ) )
1331  {
1332  return HRESULT_FROM_WIN32( GetLastError() );
1333  }
1334 
1335  if ( bytesWritten != bytesToWrite )
1336  {
1337  return E_FAIL;
1338  }
1339  }
1340  else
1341  {
1342  // Otherwise, write the image one scanline at a time...
1343  std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ rowPitch ] );
1344  if ( !temp )
1345  return E_OUTOFMEMORY;
1346 
1347  // Write header
1348  DWORD bytesWritten;
1349  if ( !WriteFile( hFile.get(), &tga_header, sizeof(TGA_HEADER), &bytesWritten, 0 ) )
1350  {
1351  return HRESULT_FROM_WIN32( GetLastError() );
1352  }
1353 
1354  if ( bytesWritten != sizeof(TGA_HEADER) )
1355  return E_FAIL;
1356 
1357  // Write pixels
1358  auto pPixels = reinterpret_cast<const uint8_t*>( image.pixels );
1359 
1360  for( size_t y = 0; y < image.height; ++y )
1361  {
1362  // Copy pixels
1363  if ( convFlags & CONV_FLAGS_888 )
1364  {
1365  _Copy24bppScanline( temp.get(), rowPitch, pPixels, image.rowPitch );
1366  }
1367  else if ( convFlags & CONV_FLAGS_SWIZZLE )
1368  {
1369  _SwizzleScanline( temp.get(), rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE );
1370  }
1371  else
1372  {
1373  _CopyScanline( temp.get(), rowPitch, pPixels, image.rowPitch, image.format, TEXP_SCANLINE_NONE );
1374  }
1375 
1376  pPixels += image.rowPitch;
1377 
1378  if ( !WriteFile( hFile.get(), temp.get(), static_cast<DWORD>( rowPitch ), &bytesWritten, 0 ) )
1379  {
1380  return HRESULT_FROM_WIN32( GetLastError() );
1381  }
1382 
1383  if ( bytesWritten != rowPitch )
1384  return E_FAIL;
1385  }
1386  }
1387 
1388  return S_OK;
1389 }
1390 
1391 }; // namespace
HRESULT LoadFromTGAFile(_In_z_ LPCWSTR szFile, _Out_opt_ TexMetadata *metadata, _Out_ ScratchImage &image)
uint16_t dwExtensionOffset
HRESULT GetMetadataFromTGAFile(_In_z_ LPCWSTR szFile, _Out_ TexMetadata &metadata)
const Image * GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const
uint8_t * pixels
Definition: DirectXTex.h:230
uint16_t wStampMonth
uint8_t bAttributesType
uint8_t bDescriptor
uint16_t wJobMinute
size_t outSize
char szJobName[41]
public std::unique_ptr< void, handle_closer > ScopedHandle
Definition: scoped.h:32
uint16_t wStampDay
DXGI_FORMAT format
Definition: DirectXTex.h:125
void _CopyScanline(_When_(pDestination==pSource, _Inout_updates_bytes_(outSize)) _When_(pDestination!=pSource, _Out_writes_bytes_(outSize)) LPVOID pDestination, _In_ size_t outSize, _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize, _In_ DXGI_FORMAT format, _In_ DWORD flags)
size_t GetPixelsSize() const
Definition: DirectXTex.h:267
TGADescriptorFlags
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
HRESULT Initialize(_In_ size_t size)
static HRESULT _CopyPixels(_In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image *image, _In_ DWORD convFlags)
uint8_t bVersionLetter
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
TGAImageType
uint16_t wJobSecond
HRESULT Initialize2D(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags=CP_FLAGS_NONE)
char szAuthorName[41]
void * GetBufferPointer() const
Definition: DirectXTex.h:298
size_t rowPitch
Definition: DirectXTex.h:228
HRESULT SaveToTGAMemory(_In_ const Image &image, _Out_ Blob &blob)
size_t GetImageCount() const
Definition: DirectXTex.h:264
char Signature[18]
uint16_t wWidth
HRESULT LoadFromTGAMemory(_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _Out_opt_ TexMetadata *metadata, _Out_ ScratchImage &image)
uint8_t bIDLength
uint16_t wHeight
_In_ size_t _In_ const TexMetadata & metadata
Definition: DirectXTexP.h:116
_In_ size_t count
Definition: DirectXTexP.h:174
_Use_decl_annotations_ void _SwizzleScanline(LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags)
void ComputePitch(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _Out_ size_t &rowPitch, _Out_ size_t &slicePitch, _In_ DWORD flags=CP_FLAGS_NONE)
static HRESULT _UncompressPixels(_In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image *image, _In_ DWORD convFlags)
uint16_t wJobHour
uint16_t wPixelNumerator
char szSoftwareId[41]
uint8_t bBitsPerPixel
size_t _In_ DXGI_FORMAT size_t inSize
uint16_t wStampHour
uint8_t bColorMapSize
size_t _In_ DXGI_FORMAT _In_reads_bytes_(inSize) LPCVOID pSource
static void _Copy24bppScanline(_Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize, _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize)
const char * g_TGA20_Signature
uint32_t dwColorOffset
uint8_t bImageType
static HRESULT _DecodeTGAHeader(_In_reads_bytes_(size) LPCVOID pSource, size_t size, _Out_ TexMetadata &metadata, size_t &offset, _Inout_opt_ DWORD *convFlags)
uint16_t wStampSecond
uint16_t wVersionNumber
uint32_t dwScanOffset
HRESULT SaveToTGAFile(_In_ const Image &image, _In_z_ LPCWSTR szFile)
HANDLE safe_handle(HANDLE h)
Definition: scoped.h:34
static HRESULT _SetAlphaChannelToOpaque(_In_ const Image *image)
uint8_t bColorMapType
uint32_t dwKeyColor
uint16_t wYOrigin
uint8_t * GetPixels() const
Definition: DirectXTex.h:266
uint32_t dwStampOffset
uint16_t wPixelDenominator
DXGI_FORMAT format
Definition: DirectXTex.h:227
CONVERSION_FLAGS
uint16_t wXOrigin
uint16_t wColorMapLength
static HRESULT _EncodeTGAHeader(_In_ const Image &image, _Out_ TGA_HEADER &header, _Inout_ DWORD &convFlags)
uint16_t wColorMapFirst
uint16_t wStampYear
uint16_t dwDeveloperOffset
_In_ size_t _In_ size_t size
Definition: DirectXTexP.h:175
uint16_t wStampMinute
HRESULT GetMetadataFromTGAMemory(_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _Out_ TexMetadata &metadata)
size_t GetBufferSize() const
Definition: DirectXTex.h:299
char szAuthorComment[324]
uint16_t wGammaDenominator
uint16_t wGammaNumerator