The Targa Truvision (.TGA) format is commonly used as a texture source file format in game development, but this format is not supported by any built-in WIC codec. These functions implement a simple reader and writer for this format.

Returns the TexMetadata from a .TGA file.

HRESULT GetMetadataFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource,
    _In_ size_t size,
    _Out_ TexMetadata& metadata );

HRESULT GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
    _Out_ TexMetadata& metadata );

Loads a .TGA file.

HRESULT LoadFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource,
    _In_ size_t size,
    _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );

HRESULT LoadFromTGAFile( _In_z_ LPCWSTR szFile,
    _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );

Saves an image to a .TGA file.
  • R8G8B8A8_UNORM, R8G8B8A8_UNORM_SRGB, B8G8R8A8_UNORM, and B8G8R8A8_UNORM_SRGB data are written as a 32-bit truecolor uncompressed .TGA file
  • B8G8R8X8_UNORM and B8G8R8X8_UNORM_SRGB data is written as a 24-bit truecolor uncompressed .TGA file
  • B5G5R5A1_UNORM data is written as a 16-bit truecolor uncompressed .TGA file
  • R8_UNORM and A8_UNORM data is written as an 8-bit uncompressed greyscale .TGA file
HRESULT SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );

HRESULT SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );


This is a simple loading example. The TGA format cannot contain complicated multi-image formats, so the TexMetadata info is redundant information.

unique_ptr<ScratchImage> image ( new ScratchImage );
HRESULT hr = LoadFromTGAFile( L"ROCKS.TGA", nullptr, *image );
if ( FAILED(hr) )
    // error

A TGA file can only store one 2D image.

const Image* img = image->GetImage(0,0,0);
assert( img );
HRESULT hr = SaveToTGAFile( *img, L"NEW_IMAGE.TGA" );
if ( FAILED(hr) )
    // error

You can also save data directly from memory without using the intermediate ScratchImage at all. This example assumes a single 2D image is being written out.

Image img;
img.width = /*<width of pixel data>*/;
img.height = /*<height of pixel data>*/;
img.format = /*<a DXGI format from the supported list above>*/;
img.rowPitch = /*<number of bytes in a scanline of the source data>*/;
img.slicePitch = /*<number of bytes in the entire 2D image>*/;
img.pixels = /*<pointer to pixel data>*/;
HRESULT hr = SaveToTGAFile( img, L"NEW_IMAGE.TGA" );
if ( FAILED(hr) )
    // error

Implementation Notes

  • The reader does not support .TGA files that contain color maps (which are rare in practice)
  • The reader does not support interleaved files (this feature was deprecated)
  • The reader only supports 8-bit greyscale, 16-bit truecolor, 24-bit truecolor, and 32-bit truecolor images
  • The writer always creates uncompressed files, although the reader can load RLE compressed files
  • The reader and writer do not support the TGA header extension metadata, which is ignored by the reader.
  • For 16-bit and 32-bit truecolor images, there is a special-case fixup if the entire alpha channel is 0 it is assumed to be fully opaque.

Windows Store apps


If you wish to load an image from a file that is specified by the user from a WinRT picker, you will need to copy the file locally to a temporary location before you can use LoadFromTGAFile on it. This is because you either won't have file access rights to the user's file location, or the StorageFile is actually not a local file system path (i.e. it's a URL).

create_task(openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
    if (file)
        auto tempFolder = Windows::Storage::ApplicationData::Current->TemporaryFolder;
        create_task(file->CopyAsync( tempFolder, file->Name, NameCollisionOption::GenerateUniqueName )).then([this](StorageFile^ tempFile)
            if ( tempFile )
                HRESULT hr = LoadFromTGAFile( ..., tempFile->Path->Data(), ... );


For SaveToTGAFile to succeed, the application must have write access to the destination path. For Windows Store apps, the file access permissions are rather restricted so you'll need to make sure you use a fully qualified path to a valid write folder. A good location to use is the app data folder:

auto folder = Windows::Storage::ApplicationData::Current->LocalFolder;
// use folder->Path->Data() as the path base

If you are going to immediately copy it to another location via StorageFolder, then use the app's temporary folder:

auto folder = Windows::Storage::ApplicationData::Current->TemporaryFolder;
// use folder->Path->Data() as the path base

Last edited Mar 10, 2014 at 11:36 PM by walbourn, version 13