Download

[Resolved]Question for load texture2D from file from Victory plugin

Hi i am quite new to programming and unreal engine.
i want to learn how to load texture at runtime and so that i was trying to analyse Rama’s Victory plugin.
here is the code i was analyzing.


UTexture2D* UVictoryBPFunctionLibrary::Victory_LoadTexture2D_FromFile(const FString& FullFilePath,EJoyImageFormats ImageFormat, bool& IsValid,int32& Width, int32& Height)
{


    IsValid = false;
    UTexture2D* LoadedT2D = NULL;

    IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
    TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(GetJoyImageFormat(ImageFormat));

    //Load From File
    TArray<uint8> RawFileData;
    if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) return NULL;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    //Create T2D!
    if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
    {
        const TArray<uint8>* UncompressedBGRA = NULL;
        if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA))
        {
            LoadedT2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);

            //Valid?
            if(!LoadedT2D) return NULL;
            //~~~~~~~~~~~~~~

            //Out!
            Width = ImageWrapper->GetWidth();
            Height = ImageWrapper->GetHeight();

            //Copy!
            void* TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
            FMemory::Memcpy(TextureData, UncompressedBGRA->GetData(), UncompressedBGRA->Num());
            LoadedT2D->PlatformData->Mips[0].BulkData.Unlock();

            //Update!
            LoadedT2D->UpdateResource();
        }
    }

    // Success!
    IsValid = true;
    return LoadedT2D;
}

as i researched, i guess code flow works like this.

  1. Get ImageWrapper (which uses for handle binary file as Image file follow by given format) from ImageWrapperModule (which the manager like class for image wrapper).
  2. Use FFileHelper to read binary file and store it’s binary data in an array.
  3. Put that binary data into ImageWrapper so that wrapper convert binary data into image data.
  4. Extract image data from ImageWrapper to UTexture2D variable.
  5. Check image extracting work was succeed, and set return variables (width, height).

(please let me know if i was wrong) so the question is, why it does copying work?
it locks the texture’s memory and copy that into TextureData variable which is local variable which will be gone when function ended, than unlock it.
i think that is totally meaningless unless you edit or actually copy for other place.

Plus, i have two small questions.

  1. when lock the texture, it locks the data of first index of Mipmap array which stored in PlatformData. but how this code sure there is at lease one mipmap data? is unreal create texture’s mipmap automatically? or default texture size is first index of mipmap array?
  2. why it uses RGB format as BGRA? what is diffrence with ARGB or RGBA ?

i am quite new to this community and Eng is not my first language, so if my behavior seems rude or something like that, please let me know.
thanks for reading :slight_smile:

Locking the resource returns a pointer on the memory of the resource. Before the lock, he obtains the raw image pixel data and stores it into the UncompressedBGRA array, which is discarded at the end of the code block as you correctly saw. That’s why he copies the data over to the internal texture memory. This is not useless but required.

TextureData = pointer to internal memory for Texture2D
UncompressedBGRA = data, which needs to be copied / moved to where TextureData points at

After copying, UncompressedBGRA is no longer needed and really should be free’d.

Plus questions: There is always at least one mip level (0) even if you don’t have any mipmaps at all because this is the max resolution the texture has.
The difference between ARGB and BGRA is the order of bytes. ARGB = 0xAARRGGBB in hex code, whereas BGRA is 0xBBGGRRAA in hex code. I think there were differences between OpenGL and D3D in terms of what color format works better but I’m not sure about this. It could be that Unreal just perfers BGRA? Again, not sure here, but that’s the difference between BGRA and ARGB.

Thanks for kind detailed answer. that BGRA thing really confused me cause i’ve been never seen that before.

Btw, after read your post, i read the code again from start to end. and i think i have got the point.

So, when < ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA) > this code works, ImageWrapper do kind of ‘Unzipping’ work and put the real texture data in UncompressedBGRA variable.
than, at <UTexture2D::CreateTransient> point ( which i thought this is when Real texture store into LoadedT2D ) , it just create empty (or filled with garbage data) memory block for texture.
and at copy section, it copies real texture data(from given file path) into LoadedT2D by accessing TextureData. than by doing UpdateResource() it makes some resources for use that texture.

am i understood correctly?

Yes that is correct.

Hi,
Do you have any idea about ImageWrapper->GetRaw(ERGBFormat::Gray, 16, Uncompressedraw))
about this.

Actually I want Victory_LoadTexture2D_FromFile_Pixels to accept grayscale 16 bit image. so I would like to get an idea about how rawdata will be stored in uncompressedraw.