Announcement

Collapse
No announcement yet.

How to save UTexture2D to PNG file?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    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

    #2
    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.


    Code:
    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[i] = FormatedImageData[i];
    		OutBMP[i].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[i].R = R;
    		OutBMP[i].G = G;
    		OutBMP[i].B = B;
    		OutBMP[i].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);
    
    }

    Comment


      #3
      It's very useful!

      Thank you EddyTheTank.

      Comment


        #4
        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.

        Comment


          #5
          Hi jiangjiashi

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

          Comment


            #6
            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.
            Rule#21: Be polite, be professional, but have a plan to kill everyone you meet.

            Comment


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

              Comment


                #8
                Originally posted by Kris View Post
                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.
                Hi Kris

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

                thanks
                Email: tessaro.unrealdeveloper@hotmail.com
                BP/C++ Programmer.
                WIP Portfolio: https://filipetessaro.wixsite.com/portfolio
                UE Marketplace: https://unrealengine.com/marketplace...ions-rts-style

                Comment


                  #9
                  Hi

                  Sorry, please nevermind, the files wasn´t being saved because I used the wrong format
                  working fine now, thanks a lot!
                  Email: tessaro.unrealdeveloper@hotmail.com
                  BP/C++ Programmer.
                  WIP Portfolio: https://filipetessaro.wixsite.com/portfolio
                  UE Marketplace: https://unrealengine.com/marketplace...ions-rts-style

                  Comment


                    #10
                    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.

                    Code:
                    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[i] = FormatedImageData[i];
                                OutBMP[i].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;
                    }
                    Last edited by Rumbleball; 09-20-2018, 03:17 PM.
                    NodePrefabs | PluginBuilder | NotificationBackbone | WidgetBox | DebugWidget

                    Comment


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

                      Comment


                        #12
                        Originally posted by Gregorshin View Post
                        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.
                        NodePrefabs | PluginBuilder | NotificationBackbone | WidgetBox | DebugWidget

                        Comment


                          #13
                          Rumbleball, I can`t use SaveImage function.And I can`t find this function at FHighResScreenshotConfig.h
                          https://api.unrealengine.com/INT/API...fig/index.html
                          Maybe I make something wrong?
                          Attached Files

                          Comment


                            #14
                            Originally posted by Gregorshin View Post
                            Rumbleball, I can`t use SaveImage function.And I can`t find this function at FHighResScreenshotConfig.h
                            https://api.unrealengine.com/INT/API...fig/index.html
                            Maybe I make something wrong?
                            Seems they changed it.
                            ImageWriteQueue in FHighResScreenshotConfig looks promising
                            NodePrefabs | PluginBuilder | NotificationBackbone | WidgetBox | DebugWidget

                            Comment


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

                              Comment

                              Working...
                              X