Loading TGA files at runtime


I am using the ImageWrapperModule to attempt to load a external TGA at runtime.

I am stuck at this place.
IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::???);

the EImageFormat does not have a TGA option


the rest of the image loading code can be sourced from the answers on various forum posts, they pertain to JPG, PNG.

How can i load a TGA using UE4 Image wrapper module.

Thanks in advance for your input.

Here is the solution I found to load targa files at runtime, using stb library.
First add the image functions to you project. It’s all in this c header file: https://github.com/nothings/stb/blob/master/stb_image.h

Then you can add these methods in your C++ class:

UTexture2D* UImageLoader::CreateTexture(UObject* Outer, const TArray<uint8>& PixelData, int32 InSizeX, int32 InSizeY, EPixelFormat InFormat, FName BaseName)
	// Shamelessly copied from UTexture2D::CreateTransient with a few modifications
	if (InSizeX <= 0 || InSizeY <= 0 ||
		(InSizeX % GPixelFormats[InFormat].BlockSizeX) != 0 ||
		(InSizeY % GPixelFormats[InFormat].BlockSizeY) != 0)
		UIL_LOG(Warning, TEXT("Invalid parameters specified for UImageLoader::CreateTexture()"));
		return nullptr;

	// Most important difference with UTexture2D::CreateTransient: we provide the new texture with a name and an owner
	FName TextureName = MakeUniqueObjectName(Outer, UTexture2D::StaticClass(), BaseName);
	UTexture2D* NewTexture = NewObject<UTexture2D>(Outer, TextureName, RF_Transient);

	NewTexture->PlatformData = new FTexturePlatformData();
	NewTexture->PlatformData->SizeX = InSizeX;
	NewTexture->PlatformData->SizeY = InSizeY;
	NewTexture->PlatformData->PixelFormat = InFormat;

	// Allocate first mipmap and upload the pixel data
	int32 NumBlocksX = InSizeX / GPixelFormats[InFormat].BlockSizeX;
	int32 NumBlocksY = InSizeY / GPixelFormats[InFormat].BlockSizeY;
	FTexture2DMipMap* Mip = new(NewTexture->PlatformData->Mips) FTexture2DMipMap();
	Mip->SizeX = InSizeX;
	Mip->SizeY = InSizeY;
	void* TextureData = Mip->BulkData.Realloc(NumBlocksX * NumBlocksY * GPixelFormats[InFormat].BlockBytes);
	FMemory::Memcpy(TextureData, PixelData.GetData(), PixelData.Num());

	return NewTexture;

UTexture2D* UImageLoader::LoadTGAImageFromDisk(UObject* Outer, const FString& ImagePath)
	// Check if the file exists first
	if (!FPaths::FileExists(ImagePath))
		UIL_LOG(Error, TEXT("File not found: %s"), *ImagePath);
		return nullptr;

	// Load the compressed byte data from the file
	TArray<uint8> FileData;
	if (!FFileHelper::LoadFileToArray(FileData, *ImagePath))
		UIL_LOG(Error, TEXT("Failed to load file: %s"), *ImagePath);
		return nullptr;

	int x,y,n;
	unsigned char *data = stbi_load(TCHAR_TO_ANSI(*ImagePath), &x, &y, &n, 4);

	if (data == nullptr)
		UIL_LOG(Error, TEXT("Failed to load TGA data for file: %s"), *ImagePath);
	TArray<uint8> RawData;
	RawData.Append(data, x*y*GPixelFormats[PF_R8G8B8A8].BlockBytes);


	// Create the texture and upload the uncompressed image data
	FString TextureBaseName = TEXT("Texture_") + FPaths::GetBaseFilename(ImagePath);
	return CreateTexture(Outer, RawData, x, y, PF_R8G8B8A8, FName(*TextureBaseName));

To make it blueprint callable you add the following in your header :

	UFUNCTION(BlueprintCallable, Category = ImageLoader, meta = (HidePin = "Outer", DefaultToSelf = "Outer"))
		static UTexture2D* LoadTGAImageFromDisk(UObject* Outer, const FString& ImagePath);

Here are the includes and declaration needed:

#include "ModuleManager.h"
#include "FileHelper.h"

#include "IImageWrapper.h"
#include "IImageWrapperModule.h"

#include "stb_image.h"
#include <vector>

// Change the UE_LOG log category name below to whichever log category you want to use.
#define UIL_LOG(Verbosity, Format, ...)	UE_LOG(LogTemp, Verbosity, Format, __VA_ARGS__)

You also might have to add those dependency modules in your Build.cs file

PrivateDependencyModuleNames.AddRange(new string[] { "ImageWrapper", "RenderCore" });

By the way, the library supports JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC file formats; so you can also use the same method to load all the files that are not supported by the natieve imagewrapper.