Is there a way to get a Texture2D from a SpriteActor?

I’d like to be able to get the Texture2D from a SpriteActor.

And then the holy grail would be can I get the raw bytes from Texture2D?

Is there a way to encode a PNG from a Texture2D through blueprints?

I’d like the raw encoded bytes from a Texture2D so I can pass to the Android side so I can save the image to the sdcard.

It looks like UTexture2D might be an option. And maybe from a resource the PNG could be encoded?
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UTexture2D/index.html

From the UTexture2D there must be a way to encode to a raw byte array…

Something like this has potential.

Except I’m going from a UTexture2D to raw bytes.

Thanks,

~Tim Graupmann

It looks like this option should work.

To BMP:

To TGA:

If somehow I can extract a byte array of the raw files in memory…

Okay I’m noticing this documentation has gone foobar.

The example code has mixed in meta tags that were mis-formatted.

I don’t think the example code is even compilable as the API might have changed…?

How does this look? I’m wondering if I can use GetMipData passing the address of rawData which is a TArray. //bytes

And what is the recommended way to get the uint8 array out of FArchive after it’s been encoded?

void AOuyaModEditor::AddScreenshot(UTexture2D* screenshot)
{
#if PLATFORM_ANDROID

	if (!screenshot)
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Screenshot is null");
		return;
	}

	FArchive fArchive;

	int32 SizeX = screenshot->GetSizeX();
	int32 SizeY = screenshot->GetSizeY();

	TArray<uint8> rawData;
	screenshot->GetMipData(0, (void**)&rawData);

	FBitmapFileHeader bmf;
	FBitmapInfoHeader bmhdr;

	// File header.
	bmf.bfType = 'B' + (256*(int32)'M');
	bmf.bfReserved1 = 0;
	bmf.bfReserved2 = 0;
	int32 biSizeImage = SizeX * SizeY * 3;
	bmf.bfOffBits = sizeof(FBitmapFileHeader)+sizeof(FBitmapInfoHeader);
	bmhdr.biBitCount = 24;

	bmf.bfSize = bmf.bfOffBits + biSizeImage;
	fArchive << bmf;

	// Info header.
	bmhdr.biSize = sizeof(FBitmapInfoHeader);
	bmhdr.biWidth = SizeX;
	bmhdr.biHeight = SizeY;
	bmhdr.biPlanes = 1;
	bmhdr.biCompression = BCBI_RGB;
	bmhdr.biSizeImage = biSizeImage;
	bmhdr.biXPelsPerMeter = 0;
	bmhdr.biYPelsPerMeter = 0;
	bmhdr.biClrUsed = 0;
	bmhdr.biClrImportant = 0;
	fArchive << bmhdr;

#endif
}

After writing to the fArchive, how do you extract the buffer? It’s telling me the total size is -1???

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Write to FArchive");
#endif
	fArchive << bmhdr;

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Flush the FArchive");
#endif
	fArchive.Flush();

	int64 bufferSize = fArchive.TotalSize();

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "BMP bufferSize=%lld", bufferSize);
#endif

The final solution that worked.

https://github.com/tgraupmann/UnrealEngine/blob/4.6-OUYA/Engine/Source/Runtime/Engine/Private/OuyaSDK/OuyaModEditor.cpp#L64

void AOuyaModEditor::AddScreenshot(UTexture2D* screenshot)
{
#if PLATFORM_ANDROID

	if (!screenshot)
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Screenshot is null");
		return;
	}

	if (!_ouyaModEditor.GetInstance())
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "OuyaModEditor reference is null");
		return;
	}

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Grab first mipmap");
#endif

	FTexture2DMipMap* mipmap = &screenshot->PlatformData->Mips[0];
	if (!mipmap)
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Mipmap is null");
		return;
	}

	int32 width = mipmap->SizeX;
	int32 height = mipmap->SizeY;

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Mipmap width=%d height=%d", width, height);
#endif

	FByteBulkData* rawImageData = &mipmap->BulkData;
	if (!rawImageData)
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "RawImageData is null");
		return;
	}

	FColor* formatedImageData = static_cast<FColor*>(rawImageData->Lock( LOCK_READ_ONLY));
	if (!formatedImageData)
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "FormatedImageData is null");
		return;
	}

	Config config = Config::ARGB_8888();
	Bitmap bitmap = Bitmap::createBitmap(width, height, config);
	config.Dispose();
	if (!bitmap.GetInstance())
	{
		__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Bitmap reference is null");
		return;
	}

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Created bitmap");
#endif

	int* pixels = new int[width * height];
	for (int32 y = 0; y < height; ++y)
	{
		for (int32 x = 0; x < width; ++x)
		{
			int index = y * width + x;
			FColor pixelColor = formatedImageData[index];

			uint8 alpha = pixelColor.A;
			uint8 red = pixelColor.R;
			uint8 green = pixelColor.G;
			uint8 blue = pixelColor.B;

			int color = alpha << 24 | red << 16 | green << 8 | blue;
			pixels[index] = color;
		}
	}

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Set bitmap pixels");
#endif

	bitmap.setPixels(pixels, width*height, 0, width, 0, 0, width, height);

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Delete pixels");
#endif

	delete pixels;

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Add Screenshot");
#endif

	_ouyaModEditor.addScreenshot(bitmap);

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Unlock image buffer");
#endif

	rawImageData->Unlock();

#if ENABLE_VERBOSE_LOGGING
	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "Add Screenshot done.");
#endif
#endif
}