Creating a Texture the Canvas can display out of an RGBA Stream?

Hey,

i’m testing around with Steamworks and tried to get my Avatar.
Steam returns a unique ID for the Avatar that you can use to get
the size of the Avatar and the raw RGBA Data.

But what can i do with this? I would need to make a UTexture to display
with DrawHUD and the canvas :open_mouth:


int Picture = SteamFriends()->GetMediumFriendAvatar(SteamUser()->GetSteamID());
	uint32 height;
	uint32 width;
	if (SteamUtils()->GetImageSize(Picture, &width, &height))
	{
		FString ResolutionH = FString::FromInt(height);
		FString ResolutionW = FString::FromInt(width);
		//GEngine->AddOnScreenDebugMessage(1, 20.0F, FColor::Red, ResolutionH + ResolutionW);
	}
	else
	{
		//GEngine->AddOnScreenDebugMessage(1, 20.0F, FColor::Red, TEXT("Didn't work :("));
	}

	if (width > 0 && height > 0)
	{
		BYTE *oAvatarRGBA = new BYTE[width * height * 4];
		SteamUtils()->GetImageRGBA(Picture, (uint8*)oAvatarRGBA, width * height * 4);
	}

Here is what i’ve done so far. Got my avatar and the imagesize. Used this for “GetImageRGBA”, but i’m not sure that i’ve done it right.
Isn’t the raw RGBA Data just every single RGBA data of (for example) 64x64 pixels?

How can i use this to get a texture that i can display? :open_mouth:

EDIT: Ok, Stuff said, there is no easy way to do this without customcode. So i won’t implement Avatars -_-

1 Like


	// Create the texture we're going to fill with data.
	UTexture2D* Tex2D = UTexture2D::CreateTransient(Width, Height, PF_B8G8R8A8);

	// Fill in the base mip for the texture we created
	uint8* MipData = (uint8*)Tex2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
	FMemory::Memcpy(MipData, SrcData, Size);
	Tex2D->PlatformData->Mips[0].BulkData.Unlock();

	// Set options					
#ifdef WITH_EDITORONLY_DATA

#endif // WITH_EDITORONLY_DATA
	Tex2D->PlatformData->NumSlices = 1;
	Tex2D->NeverStream = true;
	Tex2D->Rename(*FileName);
	Tex2D->CompressionSettings = TC_Default;

	// Update the remote texture data
	Tex2D->UpdateResource();
	return Tex2D;


SrcData is your buffer of raw (uncompressed) image data. You can set the filename part to TEXT("") or whatever FString you want.

That looks crisp! :smiley:

The Staff guy mentioned Mip as well but couldn’t give me an example.

So Srcdata would be my Byte from the code above? Is the Size of FMemory::Memcpy set somewhere?

Thanks so far! (:

Yep, you’d just replace SrcData with oAvatarRGBA. Might need to cast it, like (void*)oAvatarRBGA.

For the Memcpy size, it’s the width * height * number of bytes per pixel (looks like 4), just like when you declared your oAvatarRBGA buffer.

Lemme know if you have any issues, I’d be happy to check back and help. Hope this helps :slight_smile:

(: I will post as soon as i find time to test this. For today i might stop working on it. Need to learn for university (:

Thanks so far! I guess tomorrow about that time (24h later) i will bump the thread with information on what i achieved!

After reading this thread I´ve tried it myself and this is how I´ve come so far:


UTexture2D* UDDChelper::DDCsteamAvatar(bool& IsValid)
{
	uint32 Width;
	uint32 Height;
	
	IsValid = false;


	if (SteamAPI_Init())
	{
		//Getting the PictureID from the SteamAPI and getting the Size with the ID
		int Picture = SteamFriends()->GetMediumFriendAvatar(SteamUser()->GetSteamID());
		SteamUtils()->GetImageSize(Picture, &Width, &Height);


		if (Width > 0 && Height > 0)
		{
			IsValid = true;

			//Creating the buffer "oAvatarRGBA" and then filling it with the RGBA Stream from the Steam Avatar
			BYTE *oAvatarRGBA = new BYTE[Width * Height * 4];

			//Filling the buffer with the RGBA Stream from the Steam Avatar and creating a UTextur2D to parse the RGBA Steam in
			SteamUtils()->GetImageRGBA(Picture, (uint8*)oAvatarRGBA, 4 * Height * Width * sizeof(char));
			UTexture2D* Avatar = UTexture2D::CreateTransient(Width, Height, PF_B8G8R8A8);

			//MAGIC!
			uint8* MipData = (uint8*)Avatar->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
			FMemory::Memcpy(MipData, (void*)oAvatarRGBA, Height * Width * 4);
			Avatar->PlatformData->Mips[0].BulkData.Unlock();

		#ifdef WITH_EDITORONLY_DATA

		#endif //WITH_EDITORONLY_DATA


			//Setting some Parameters for the Texture and finally returning it
			Avatar->PlatformData->NumSlices = 1;
			Avatar->NeverStream = true;
			Avatar->Rename(TEXT("Avatar"));
			Avatar->CompressionSettings = TC_EditorIcon;

			Avatar->UpdateResource();

			return Avatar;
		}

		return nullptr;
	}

	return nullptr;
}

However, there are still some issues with this code:

  1. The colors blue and red seem to be switched, maybe the UTexture2D takes a “BGRAStream” or a stream with no alpha channel.
  2. When this Function gets called a second time the engine will crash.

Maybe someone can provide further information on how to make this code running correctly.

Kind Regards
Alex

Thanks for the code (: This is really helpful for the start!

What header file do I need to include in order to get access to these functions?

include “steam/steam_api.h”
include “steam/isteamuser.h”

in your header file

Sorry for bumping this old thread, just wanted to share what I found while testing this…

  1. Apparently UMG doesn’t like it if you leave the transient texture’s name attribute empty. If you don’t give it a valid name the texture shows up in UMG as a white / blank image.

So once you create the transient texture, don’t do this:


Tex2D->Rename(TEXT("")); // shows up blank in UMG!

Instead, give it a name:


Tex2D->Rename(TEXT("SomeAppropriateName")); // works in UMG too!

  1. Pass PF_R8G8B8A8 as the EPixelFormat while creating the transient texture if it’s a Steam Avatar. This ensures the color channels aren’t flipped (thanks to Philip Ramirez for this tip in this answer hub post)

And thanks to everyone on this thread for sharing, I ended up using nearly every tidbit that was posted here to get my stuff working :slight_smile:

You should add


delete] oAvatarRGBA;

after Avatar->UpdateResource(), otherwise you will have a huge memory leak!