Import an Image from Explorer in Runtime

Hey friends!

Guess what? After hours of banging my head against the keyboard, I finally cracked the code conundrum that was haunting me. I scoured the internet, dove deep into research, and voila! I’ve got this neat piece of code that lets you pop open a “File Dialogue,” pick an image file, and smoothly import it into your game as a Texture2D. And the best part? It works like a charm in runtime!

Check it out:

.h

UCLASS()
class MYPROJECT_API YOURCLASSNAME : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	UFUNCTION(BlueprintCallable)
		static UTexture2D* OpenFileDialogueAndLoadImage();
};

.cpp clean

UTexture2D* YOURCLASSNAME::OpenFileDialogueAndLoadImage()
{

	IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();

	if (DesktopPlatform)
	{
		
		TArray<FString> OutFilenames;
		bool bOpened = DesktopPlatform->OpenFileDialog
		(
			nullptr,
			TEXT("Choose Image"),
			FPaths::ProjectContentDir(),
			TEXT(""),
			TEXT("Image Files (*.png; *.jpg| *.png;*.jpg)"),
			EFileDialogFlags::None,
			OutFilenames
		);

		if (bOpened && OutFilenames.Num() > 0) 
		{

			FString SelectedImagePath = OutFilenames[0]; 

			TArray <uint8> ImageData; 

			if (FFileHelper::LoadFileToArray(ImageData, *SelectedImagePath))
			{
				IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));

				EImageFormat ImageFormat = ImageWrapperModule.DetectImageFormat(ImageData.GetData(), ImageData.Num()); 

				TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(ImageFormat);

				if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(ImageData.GetData(), ImageData.Num()))
				{
				
					TArray64<uint8> RawData;

					if(ImageWrapper->GetRaw(ERGBFormat::RGBA, 8, RawData))
					{
						TArray64<uint8>* RawDataProcessed = &RawData;
						UTexture2D* Texture = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_R8G8B8A8);
						                                                                                                                    
						if (Texture)
						{
							
FTexture2DMipMap& Mip = Texture->GetPlatformData()->Mips[0];// 
							void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE); 

							FMemory::Memcpy(Data, RawDataProcessed->GetData(), RawDataProcessed->Num());
							Mip.BulkData.Unlock(); 

							Texture->GetPlatformData()->SetNumSlices(1); 

							Texture->NeverStream = true; 

							Texture->UpdateResource();

							return Texture;
	}
	}		
	}
	}
	}
	}
	return nullptr;
}

.cpp with my comments

UTexture2D* YOURCLASSHERE::OpenFileDialogueAndLoadImage()
{
	//Here we initialize a pointer to the Desktop Platform Module, so we can open the file dialog. 
	//Dont forget to include "DesktopPlatform" in the Build.cs
	IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();

	if (DesktopPlatform)
	{
		
		TArray<FString> OutFilenames; //This stores the file path
		bool bOpened = DesktopPlatform->OpenFileDialog // File Dialogue so we can choose a file
		(
			nullptr,
			TEXT("Choose Image"),
			FPaths::ProjectContentDir(),
			TEXT(""),
			TEXT("Image Files (*.png; *.jpg| *.png;*.jpg)"),
			EFileDialogFlags::None,
			OutFilenames
		);

		if (bOpened && OutFilenames.Num() > 0) //if we managed to open the dialogue and we chose at least one file
		{

			FString SelectedImagePath = OutFilenames[0]; 

			TArray <uint8> ImageData; // this will be our image

			if (FFileHelper::LoadFileToArray(ImageData, *SelectedImagePath)) //here we load the data
			{
				IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));//Get a reference to the wrapper module 
				EImageFormat ImageFormat = ImageWrapperModule.DetectImageFormat(ImageData.GetData(), ImageData.Num()); // Here i wanted to get the Image format, JPG, PNG and so on so that we could create an appropriate wrapper for it 
				TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(ImageFormat); // here we create an image wrapper for the given format 
				
				if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(ImageData.GetData(), ImageData.Num()))
				{
				
					TArray64<uint8> RawData;
					if(ImageWrapper->GetRaw(ERGBFormat::RGBA, 8, RawData))// we want to take the raw data from the wrapper and put it in the raw data variable
					{
						TArray64<uint8>* RawDataProcessed = &RawData;
						UTexture2D* Texture = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_R8G8B8A8);// we want to make a transient Texture object we can modify in code
						                                                                                                                    // we also get the widht and height from the wrapper and set the pixel format
						if (Texture)
						{
							FTexture2DMipMap& Mip = Texture->GetPlatformData()->Mips[0];// we get platform specific data for the texture and select the firt mipmap
							void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE); //bulk data contains well... the bulk data of the mipmap and we want to write to it, we lock it so nothing accesses it now
							FMemory::Memcpy(Data, RawDataProcessed->GetData(), RawDataProcessed->Num()); // this copies memory data from one place to another, so we copy the image data 
							Mip.BulkData.Unlock(); // we unlock it so it can be accessed again

							Texture->GetPlatformData()->SetNumSlices(1); //we dont really need more but you can set it to more
							Texture->NeverStream = true; //if you want it streamed

							Texture->UpdateResource(); //update 
							return Texture;
						}
					}

				
				}
			}

		



		}
	}
	return nullptr;
}

Pics for proof!

Screenshot_1

Screenshot_2

Screenshot_3

Hope you all have a great day!
Cheers.

5 Likes

very useful insight

Hello ,
I don’t know if you are still up on you UE account but -
I’m trying to do exactly the same module as you , and i would have loved to see what were your includes to make it working :slight_smile:
Have a nice day.

Charles -

Rectification , found them by myself ! haha sorry !