How to save a UTexture2D as 16/32bit image?

I am creating an array of FLinearColors which I am then turning into a UTexture2D using the code on this page: A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums

Using Rama’s plugin code, I am then able to save the resultant texture fine to an 8-bit .png file, but what I really need is to be able to save this dynamic texture out to either a 16 or 32-bit image format.

I found the function FImageUtils::ExportTexture2DAsHDR which claims that it “exports a UTexture2D as an HDR image on the disk”.This sound promising, but I’m not sure how to get it to work since it only takes a texture and FArchive as inputs, and doesn’t seem to actually save anything to disk. I am trying similar code I have used previously to save an FArchive:


void UTextureUtility::SaveTexture(UTexture2D * PTexture, FString Filename)
{
    FBufferArchive ToBinary;

    FImageUtils::ExportTexture2DAsHDR(PTexture, ToBinary);

    if (FFileHelper::SaveArrayToFile(ToBinary, *Filename))
    {
        // Free Binary Array    
        ToBinary.FlushCache();
        ToBinary.Empty();

        UE_LOG(LogTemp, Warning, TEXT("Object successfully saved!"));
    }

    // Free Binary Array    
    ToBinary.FlushCache();
    ToBinary.Empty();

    UE_LOG(LogTemp, Warning, TEXT("Object could not be saved!"));
}

But this crashes everything.

Does anyone know how this function should work, or else can recommend a way to save an array of FLinearColor values / UTexture2D out to a 16 or 32-bit image format?

Looking at the source (ImageUtils.cpp) - it looks like it just converts the raw texture data and outputs it to the FArchive, which you can then save to disk (FArchive is just a useful wrapper for binary data).

You might have to do some custom code to export it as a .png file - since i imagine the FArchive won’t have any file-specific headers, but I also found ExportRenderTarget2DAsPNG(). In there is the following:



PNGImageWrapper->SetRaw(RawData.GetData(), RawData.GetAllocatedSize(), Size.X, Size.Y, ERGBFormat::BGRA, 8);


That last parameter is the bit-depth, so in theory you can use the 16 or 32-bit PNG formats by copy-pasting some code around.