Download

How to save UTexture2D to PNG file?

I made a tool to generate a simple texture on runtime.(a Verify Pic)

now I need save to PNG file…

But I don’t know how to save the UTexture2D to PNG file. (Windows platform)

Should call UTexture2D::Serialize(…) to save it ?
And how?

plz help me, thanks

Hi I think I have 2 functions that will solve your problem

They are almost identical, I used it to debug my CEF3 embedding implementation.

I hope this is of use for you.


void SaveTexture2DDebug(UTexture2D* PTexture, FString Filename)
{
	PTexture->UpdateResourceW();
	FTexture2DMipMap* MM = &PTexture->PlatformData->Mips[0];

	TArray<FColor> OutBMP;
	int w = MM->SizeX;
	int h = MM->SizeY;

	OutBMP.InsertZeroed(0, w*h);

	FByteBulkData* RawImageData = &MM->BulkData;

	FColor* FormatedImageData = static_cast<FColor*>(RawImageData->Lock(LOCK_READ_ONLY));

	for (int i = 0; i < (w*h); ++i)
	{
		OutBMP* = FormatedImageData*;
		OutBMP*.A = 255;
	}

	RawImageData->Unlock();
	FIntPoint DestSize(w, h);

	FString ResultPath;
	FHighResScreenshotConfig& HighResScreenshotConfig = GetHighResScreenshotConfig();
	bool bSaved = HighResScreenshotConfig.SaveImage(Filename, OutBMP, DestSize, &ResultPath);
	/*
	FTexture2DResource* PR = (FTexture2DResource*)PTexture->Resource;

	if (PR)
	{
		uint32 Stride;
		void* buf = RHILockTexture2D(PR->GetTexture2DRHI(), 0, RLM_ReadOnly, Stride, false);

	
	}*/



	UE_LOG(LogHTML5UI, Warning, TEXT("UHTML5UIWidget::SaveTexture2DDebug: %d %d"), w,h);
	UE_LOG(LogHTML5UI, Warning, TEXT("UHTML5UIWidget::SaveTexture2DDebug: %s %d"),*ResultPath,bSaved==true ? 1 : 0);

}

void SaveTexture2DDebug(const uint8* PPixelData, int width, int height, FString Filename)
{
	TArray<FColor> OutBMP;
	int w = width;
	int h = height;

	OutBMP.InsertZeroed(0, w*h);

	for (int i = 0; i < (w*h); ++i)
	{
		uint8 R = PPixelData[i * 4 + 2];
		uint8 G = PPixelData[i * 4 + 1];
		uint8 B = PPixelData[i * 4 + 0];
		uint8 A = PPixelData[i * 4 + 3];

		OutBMP*.R = R;
		OutBMP*.G = G;
		OutBMP*.B = B;
		OutBMP*.A = A;
	}

	FIntPoint DestSize(w, h);

	FString ResultPath;
	FHighResScreenshotConfig& HighResScreenshotConfig = GetHighResScreenshotConfig();
	bool bSaved = HighResScreenshotConfig.SaveImage(Filename, OutBMP, DestSize, &ResultPath);


	UE_LOG(LogHTML5UI, Warning, TEXT("UHTML5UIWidget::SaveTexture2DDebug: %d %d"), w, h);
	UE_LOG(LogHTML5UI, Warning, TEXT("UHTML5UIWidget::SaveTexture2DDebug: %s %d"), *ResultPath, bSaved == true ? 1 : 0);

}

It’s very useful!

Thank you EddyTheTank.

Hi, I want to realize the reverse function: generate texture2D from a given picture(like PNG) using C++ code.

Hoping you can offer me some aid.

Hi jiangjiashi

UTexture2D* tmpTex = UTexture2D::CreateTransient(size, size);
tmpTex->Source.Init(…)

To save you reinventing the wheel, check out the C++ source for Rama’s Extra Blueprint nodes.
It includes saving/loading textures, including textures from scene capture components.

哥们你下面这句语法都有问题 ,哪来的SOURCE对象:confused:

Hi Kris

The function isn´t saving the file, maybe I´m doing something wrong with the path?

thanks

Hi

Sorry, please nevermind, the files wasn´t being saved because I used the wrong format :slight_smile:
working fine now, thanks a lot!

I modified the function a bit.
The issue is that the texture settings must be set properly for the export.
-No Compression
-No Mipmaps

The function changes the settings of the texture temporarly.


void SaveTextureToDisk(UTexture2D* texture, const FString& file)
{
    // Here I tried to work with a temporary texture, but that did not work. Changing the settings
    // of the texture after copy did not have effect.
    //UTexture2D* tempTex = texture->CreateTransient(texture->GetSizeX(), texture->GetSizeY());
    //void* dest = tempTex->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
    //texture->PlatformData->Mips[0].BulkData.GetCopy(&dest, false);
    //tempTex->PlatformData->Mips[0].BulkData.Unlock();
    //tempTex->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
    //tempTex->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
    //tempTex->UpdateResource();

    TextureCompressionSettings prevCompression = texture->CompressionSettings;
    TextureMipGenSettings prevMipSettings = texture->MipGenSettings;
    texture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
    texture->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
    texture->UpdateResource();
    FTexture2DMipMap* MM = &texture->PlatformData->Mips[0];

    TArray<FColor> OutBMP;
    int w = MM->SizeX;
    int h = MM->SizeY;

    OutBMP.SetNumUninitialized(w*h);

    FByteBulkData* RawImageData = &MM->BulkData;

    FColor* FormatedImageData = static_cast<FColor*>(RawImageData->Lock(LOCK_READ_ONLY));
    if (FormatedImageData)
    {
        for (int i = 0; i < (w*h); ++i)
        {
            OutBMP* = FormatedImageData*;
            OutBMP*.A = 255;
        }

        RawImageData->Unlock();
        FIntPoint DestSize(w, h);

        FString ResultPath;
        FHighResScreenshotConfig& HighResScreenshotConfig = GetHighResScreenshotConfig();
        HighResScreenshotConfig.SaveImage(file, OutBMP, DestSize, nullptr);
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("SaveTextureToDisk: could not access bulk data of texture! Texture: %s"), *texture->GetFullName());
    }

    texture->CompressionSettings = prevCompression;
    texture->MipGenSettings = prevMipSettings;
}

@Rumbleball, faced with difficulties with HighResScreenshotConfig.SaveImage (I can`t use it in 4.20 version). How I can replace it?Thanks in advance

what is not working? We are still on 4.19.

Rumbleball, I cant use SaveImage function.And I cant find this function at FHighResScreenshotConfig.h
https://api.unrealengine.com/INT/API/Runtime/Engine/FHighResScreenshotConfig/index.html
Maybe I make something wrong?

Seems they changed it.
ImageWriteQueue in FHighResScreenshotConfig looks promising

I think the old system has been replaced by UImageWriteBlueprintLibrary::ExportToDisk(). Here an example of usage.

This was one of the threads that I stumbled across while trying to figure out how to get screenshots to save to a completely outside-the-engine location. It’s not directly related to saving UTexture2D, but I did come up with a way to save a TArray<FColor>: quick code tutorial, how to get a screenshot and write the texture data to a file - Unreal Engine Forums

Hi! Rumbleball solution does not work in packaged game because UTexture::MipGenSettings is editor-only data.
Besides, BulkData size is different between cooked and non-cooked data…
How can I extract texture pixel array for cooked UTexture?
Thank you!

I’m pretty sure that worked for us in 4.16/4.19. Haven’t been packing for long time now, but maybe will run into this then.