Embedding a screenshot thumbnail in a save game?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Erwin Broekhuis

Is it possible to embed a screenshot (thumbnail) inside the save game?

I’m currently using JSON to save my data in a similar way it is explained in the official documentation.

I know about get_viewport().get_texture().get_data() to take a screenshot, but I would like to know if (and how) it could be used to save the result inside the save game file, rather than a separate image.

Any thoughts?

:bust_in_silhouette: Reply From: Calinou

Using the Marshalls class, you could serialize the image data to Base64 and save it in one of the JSON fields. Then, when loading the save, deserialize it into a PoolByteArray. This will make it 33% larger, but since it’s a thumbnail, it’s most likely relatively small anyway.

It’s not so easy for me.

  1. I think something went wrong because the data is very short:

In JSON the thumbnail data is now represented like this: “EQABAC4IAAAAAAAA”.

It was created like this:

var thumbnail = get_viewport().get_texture().get_data()
thumbnail.convert(Image.FORMAT_RGB8)
thumbnail.shrink_x2()
thumbnail = Marshalls.variant_to_base64(thumbnail)

  1. I’m struggling to find the way to deserialise the data to PoolByteArray.

I have tried this:

thumbnail = node_data[“thumbnail”]
thumbnail = thumbnail as PoolByteArray ← Pure desperation. Of course I knew this wouldn’t work
var temp = Image.new()
temp.create_from_data(200, 200,true,Image.FORMAT_RGB8,thumbnail)

Can you please nudge me a bit further in the right direction?

Erwin Broekhuis | 2020-05-24 11:15

On the deserialising part I think I am now closer. My function doesn’t throw any errors, but thumbnails are not displayed which I believe is due to them not being stored correctly in the JSON file to begin with.

My deserialising looks like this:

thumbnail = node_data["thumbnail"]
var pool = PoolByteArray()
pool.append(thumbnail)
var img = Image.new()
img = img.create_from_data(200, 200,true,Image.FORMAT_RGB8,pool)
var text = ImageTexture.new()
text = text.create_from_image(img)
thumbnail = text

Erwin Broekhuis | 2020-05-24 11:36

:bust_in_silhouette: Reply From: Erwin Broekhuis

I worked it out with support from the community. He’s the solution for future reference for anyone with a similar question. Let’s assume we know how to write the save game data to JSON following the example in the GODOT documentation.

In the SAVING method:

var thumbnail = get_viewport().get_texture().get_data()
thumbnail.flip_y()
thumbnail.resize(356, 200, Image.INTERPOLATE_LANCZOS)
	
var array : PoolByteArray = thumbnail.get_data()
var sg_width = thumbnail.get_width()
var sg_height = thumbnail.get_height()
var sg_format = thumbnail.get_format()
var sg_mipmap = thumbnail.has_mipmaps()
var sg_u_size = array.size()
array = array.compress(File.COMPRESSION_DEFLATE)
var sg_saved_img = Marshalls.raw_to_base64(array)

var metadata = {"class" : "meta",  "thumbnail" : {"image" : sg_saved_img, "size" : sg_u_size, "width" : sg_width, "height" : sg_height, "mipmap" : sg_mipmap, "format" : sg_format}}
save_game.store_line(to_json(metadata))

In the DISPLAY method of the menu that list your save games:

if node_data["class"] == "meta":
	var thumb = node_data["thumbnail"]
	var t_image = thumb["image"]
	var t_size = thumb["size"]
	var t_width = thumb["width"]
	var t_height = thumb["height"]
	var t_mipmap = thumb["mipmap"]
	var t_format = thumb["format"]
			
	var array = Marshalls.base64_to_raw(t_image)
	array = array.decompress(t_size, File.COMPRESSION_DEFLATE)
	var img = Image.new()
	img.create_from_data(t_width, t_height, t_mipmap, t_format, array)
	var text = ImageTexture.new()
	text.create_from_image(img)
	thumbnail = text

So here I create an ImageTexture in the end, because I place the thumbnail in an TextureRect of the GUI.

Hope it will help someone!

Did it work for you on mobile: Android / ios or just desktop as mentioned here ?
Thx

GameVisitor | 2020-05-25 17:53

I’m not on mobile. This is desktop. Also, my method does not actually save to disk with save_png. I store the Image directly into the PoolByteArray after it’s been created. Then, after some compression, I serialise the data into base64 and that information is saved to disk as a JSON string.

Erwin Broekhuis | 2020-05-25 20:29