Download

Help with the Image Wrapper component please

I want to use the build in image wrapper to import images from local disk so I can work on them with code (pixel manipulation and reading)

This is the image wrapper.
IImageWrapper | Unreal Engine Documentation

I’m confused about some of it’s usage.
What class should I be using it with, a UClass object or an Actor Class ?
The documentation is also very bad and does not give anything, like how to set a filepath to local disk with an FString.

I managed to compile but I get no results with the Actor class, where does the image load ? is it in the memory buffer ? There is no documentation at all.

I did manage to find some examples but only one of these examples showed how to make a path to local disk, the rest of the examples have the FString Image FIle Variable that get’s tossed around but I’m looking how to set a path and these tutorials of the forum and answer hub don’t have a link like object to local disk, like FString ImageFile = “C:/someimage.png” and there is no documentation on it, it’s a nightmare to use this wrapper, I’m stuck on it for days.

So what class should I use with it, how to set file path to it, and where to check for the image after loading into the arrays, get it out of the array uncompressed and set it’s with and height and then look where for it ? There is also a version where you can convert it to 2dtexture after you set it’s uncompressed properties. So where does the 2dtexture end up ? where to look for it, how to access it.

Here is one example that I did and I managed to compile in an actor class.

Link to source on asnwer hub:
AnswerHub (unrealengine.com)]
(Is it possible to load bitmap or JPG files at runtime and use them on assets as textures? - UE4 AnswerHub)

     FString pngfile = "myimage.png";
     IImageWrapperModule& ImageWrapperModule = 
    FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
     // Note: PNG format.  Other formats are supported
     IImageWrapperPtr ImageWrapper = 
   ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
 
     if (FFileHelper::LoadFileToArray(RawFileData, *pngfile))
     {
         if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
         {
             const TArray<uint8>* UncompressedBGRA = NULL;
             if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA))
                         {
                               mytex = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);

This has a link.
FString pngfile = “myimage.png”;
But the link is anbigus and if I try to change it to a path it does not work, and where is the location of this image for example in the engine, where do you have to put it not to make a path ?

Also what class should I use, is the actor class good for this ?
Where should I look for the image ? it’s in the buffer ? after I get it out it go’s where ?

This example has one array, there are examples with 2 Tarrays where one you put it in, then the other you take it out to it’s properties with, height, size and so on. It also has a 2dconversion way of getting a texture, there are no results.

Well I sort of solved my problem by changing some code and I got further but had crashes, and then I changed some more like:

IImageWrapperPtr ImageWrapper =
ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);

To:

IImageWrapperPtr ImageWrapper =
ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);

No more crashes.
Now I get in my log.

This is the bin array.
LogTemp: LoadFileToArray() success

Wrapper Check.
LogTemp: its valid, keep going

2nd Arr get raw data.
LogTemp: GetRaw success keep going

It went thru all the steps wrapper check, binary, unpack (but with a Jpeg image)
Not png, I wanted png.

It’s known PNG images loose conversion factors upon converting from binary back to png if the wrapper in not good this happens in python too. This must be from the png part of the wrapper because in my crash when the game engine crashes I get the crash window with the error saying it’s file PngImageWrapper.cpp on line 232.

This is what the wrapper looks like

if PLATFORM_ANDROID || PLATFORM_LUMIN || PLATFORM_LUMINGL4
// thread safety
FScopeLock PNGLock(&GPNGSection);
#endif

  	     check(CompressedData.Num());

Line 232-> check(Width > 0);

  	     check(Height > 0);
  
  	// Note that PNGs on PC tend to be BGR
  	check(InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA || InFormat 
                   == ERGBFormat::Gray)	// Other formats unsupported at present
  	check(InBitDepth == 8 || InBitDepth == 16)	// Other formats unsupported at 
                   present

So that is line 232 with the width, any idea how I can overcome this and load a png ?
So it has problems reading the width, upon conversion it looses it’s properties ? Because Png files do that, if the wrapper is not good ?

<====Edit Update===>

I changed the resolution of my png in paint brush to another value changed the width and changed the height, and now it’s accepting png. So any resolution (normal resolutions) that the wrapped does not like in png files it crashes the engine. Jpeg files work on the resolution that the png files don’t work. It’s the wrapper, it does not like some png resolutions like 520px X 520px

Come on unreal what is up with this :slight_smile:
This is known with png images on other software, but they got their wrapper in order not to cause headakes.

Before creating IImageWrapper you can check data validity by IImageWrapperModule::DetectImageFormat
This function returns EImageFormat(can return EImageFormat::Invalid), which can be used as a argument in IImageWrapperModule::CreateImageWrapper.

You can also try stb_image third-party lib to check it is a problem with UE or with the file.

You can use that I guess if you set the format to just:
IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(ImageFormat);
If it’s not set manual.

Thanks for the link. I will be checking that and I will give it a try.
I used this to check my wrapper
if(ImageWrapper.IsValid())
{
UE_LOG(LogTemp, Log, TEXT(“What ever”));

But I will be trying that as well, just for practicality

I’m all familiar with the stb loader lib image, you can use it in opengl as well to import images, but I wanted to use unreal’s wrapper because the conversion is simpler to array maybe, if you use the stb lib maybe you need to do additional tests to turn image into binary and back.

Well I managed to pull it off and got it, but it’s really strange.
Can anyone help me on this please.

What I did is I set a material on an object, on a cube mesh.

I set UPROPERTY withEditAnywhere option for my texture that I uploaded, this is a way to sort of see if I uploaded anything, because the uproperty edit anywhere has an icon inside the editor, it will create a section for the variable and it is the texture it loaded from the disk in fact, so I was happy to see it as an icon there inside the editor.

The problem is when I try to attach with C++ the texture to the material it crashed my editor.
But if I try to add any other texture with C++ to the material that is set on the mesh then it does not crash.

Why is this texture causing a crash.
I set the texture on the material like this.

DynamicMaterialInst->SetTextureParameterValue(FName(“DynamicTexture”), TextureD);
Component1->SetMaterial(0, DynamicMaterialInst);

I get a crash.

But I have another texture for tests, TextureB.
The only thing about this textureB compared to TextureD is that I imported it to the editor with the editor import buton, it’s imported from the editor, so I used the editor to load a file from disk, and this file texture works and the other does not :neutral_face:

I use it like this.

	  static >ConstructorHelpers::FObjectFinder<UTexture2D>TextureFinder(TEXT("Texture2D'/Game/container.container'"));

Then

TextureB = TextureFinder.Object;

Later in the start play function I set the material on the static mesh.

DynamicMaterialInst->SetTextureParameterValue(FName(“DynamicTexture”), TextureB);
Component1->SetMaterial(0, DynamicMaterialInst);

So it works with this texture but not with that ?
How come , what is the difference between the uploaded texture from the editor with import button near add components, and this one imported from C++

Really this wrapper is full of bugs, or I’m not doing things the way they should be done.
But I think it’s just more of a bug since my texture appears in the editor as a variable(editanywhere) with an icon, so it loads the image, converts it into 2DTexture, but refuse to attach to material and to component mesh

The two textures declared inside the header file.

UPROPERTY(EditAnywhere)
UTexture2D* TextureB;

UPROPERTY(EditAnywhere)
UTexture2D* TextureD;

I also have this in my constructor.

DynamicMaterialInst = UMaterialInstanceDynamic::Create(StoredMaterial, Mesh);

In the begin play I have the convertor to convert the image to a 2DTexture once it exits the raw array.

  >  Width = ImageWrapper->GetWidth();
  >  Height = ImageWrapper->GetHeight();
  >  TextureD = UTexture2D::CreateTransient(Width, Height, PF_B8G8R8A8);
  >  void* MipData = TextureD->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
  >  FMemory::Memcpy(MipData, RawData->GetData(), RawData->Num());
  >  TextureD->PlatformData->Mips[0].BulkData.Unlock();
  >  TextureD->UpdateResource();

and later in the begin play I set the texture.

DynamicMaterialInst->SetTextureParameterValue(FName(“DynamicTexture”), TextureD);
Component1->SetMaterial(0, DynamicMaterialInst);

This causes a crash with TextureD,
If I use texture B then it works and no more crash I see all textures loaded textureB textureD when I hit play, break it with console key and look in the Detail tab of the components.,

I use the constructor helper to find TextureB in the editor folder location, and just set it down here in the begin play.
Change it to TextureB

DynamicMaterialInst->SetTextureParameterValue(FName(“DynamicTexture”), TextureB);
Component1->SetMaterial(0, DynamicMaterialInst);

I can see TextureD because tho I don’t set it on the material (to cause a crash) The texture is loaded from the disk with C++ but not attached to the material that is attached to the mesh.

All textures are visible except that TextureB is set on the material not TextureD, I Set it with textureD I get a crash. It taken me already a week, it’s so frustrating :hushed:

Can someone at least tell me the difrence between the two textures.

I will even upload an image if anyone can help me.

So i set the TextureB but TextureD also appears in the tab where I highlited in the image because tho it’s not set to the material instance that is attached to the mesh of the box, tho it is not, it is loaded from disk and I converted to 2DTexture and I assigned a Uproperty so I can view it inside the editor like the image displays regardless if I try to set it on the material or not.

Since this is in begin play I can only view the textures after I hit play, I hit the console key and I can move the mouse inside the editor , click on tabs etc, to show what variables come up alive during play.

Anyone, any ideas ?
All I want is to import an image from disk, convert it to a texture and apply it on static meshes, but all done in C++

This is because once you compile a game and publish it’s binaries, you cannot bring assets otherwise since the editor is gone, so the only way to bring assets into the game is to reload the game inside the editor otherwise no new textures, and this sucks so we have to have some sort of gate to load things inside the game even after it’s published. I also wanted for layerd heghtmaps, to do what the editor can’t do, have different levels of layers upon layers and so on.

I could import the height maps with the import button but that is not very nice since I don’t have control over the image before changing it to a texture, as I seen unreal converts your image to a texture instatly as soon as you use the import button to load an image into the editor.

I finally solved my problem. But I would like to know other solutions as well to get by this.

So I’m not going to mark this as solved because there are other ways when it comes to dynamic texturing and materials, so it’s open for debate, come in, don’t be shy :slight_smile: :frowning:

I used
UMaterialInterface* LoadedMaterial = LoadObject(nullptr, TEXT("/Game/container_Mat.container_Mat"), nullptr, LOAD_None, nullptr);
I loaded the material without the constructor helper and made a parameter.

Removed TextureB I don’t need it anymore, it now takes feed from TextureD

If you manage to upload/import an image from disk and don’t know how to do and get stuck like me , this thread will help and it helped me, credits to the solver of the thread.
How to apply a UTexture2D to a UStaticMeshComponent? - Development Discussion / C++ Programming - Unreal Engine Forums

So you also have to set the material inside the material options in the editor, and give it a parametric name.

:smiley: :grinning_face_with_smiling_eyes: :smiley:
Cheers