Import .HDR Image at Runtime

I was able to come up with the following function which seems to be working

#include "UObject/UObjectGlobals.h" 
#include "Misc/FileHelper.h" 
#include "IImageWrapperModule.h" 
#include "Modules/ModuleManager.h" 
#include "Formats/HdrImageWrapper.h" 
#include "IImageWrapper.h" 
#include "Engine/TextureCube.h" 
#include "Factories/Factory.h" 
#include "Misc/SecureHash.h" 
#include "EditorFramework/AssetImportData.h" 
#include "UObject/ObjectMacros.h" 


UTextureCube* CreateTextureCube( UObject* InParent, FName Name, EObjectFlags Flags )
{
	return Cast<UTextureCube>(NewObject<UObject>(InParent, UTextureCube::StaticClass(), Name, Flags));	
}

// Filename should be absolute path 
UTextureCube* ImportHDRFile(FString Filename) {
    FString PackageName = "/Game/198L";
    FString Name = "198L";
    UPackage* Pkg = CreatePackage( *PackageName);

    EObjectFlags Flags =  RF_Public | RF_Standalone | RF_Transactional;



    TArray<uint8> Data;
    if (!FFileHelper::LoadFileToArray(Data, *Filename))
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load file '%s' to array"), *Filename);
    }
    Data.Add(0);
    const uint8* Buffer = &Data[0];
    const uint8* BufferEnd = Buffer + Data.Num() - 1;
    const int32 Length = BufferEnd - Buffer;
    UTextureCube* TextureCube = nullptr; 

    IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
	if (ImageWrapperModule.DetectImageFormat(Buffer, Length) == EImageFormat::HDR)
	{
		FHdrImageWrapper HdrImageWrapper;
		if (HdrImageWrapper.SetCompressedFromView(TArrayView64<const uint8>(Buffer, Length)))
		{
			TArray64<uint8> UnCompressedData;
			if (HdrImageWrapper.GetRaw(ERGBFormat::BGRE, 8, UnCompressedData))
			{
				// create the cube texture
				TextureCube = CreateTextureCube(Pkg, FName(*Name), Flags);
				if ( TextureCube )
				{
					TextureCube->Source.Init(
						HdrImageWrapper.GetWidth(),
						HdrImageWrapper.GetHeight(),
						/*NumSlices=*/ 1,
						/*NumMips=*/ 1,
						TSF_BGRE8,
						UnCompressedData.GetData()
						);
					// the loader can suggest a compression setting
					TextureCube->CompressionSettings = TC_HDR;
					TextureCube->SRGB = false;
                }
                FMD5Hash FileHash = FMD5Hash::HashFile(*Filename);
                TextureCube->AssetImportData->Update(Filename, FileHash.IsValid() ? &FileHash : nullptr);

                TextureCube->PostEditChange();
            }
        }
    }
    return TextureCube;
}

Most of the code was borrowed from EditorFactories.cpp file in UE 5.0.3 release.

This function can even be called from blueprint function library to return a TextureCube.

1 Like