+1 vote

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 getviewport().gettexture().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?

asked May 23 in Engine by Erwin Broekhuis (22 points)

2 Answers

+1 vote
Best answer

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.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}}

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()
    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!

answered May 25 by Erwin Broekhuis (22 points)

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

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.

+1 vote

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.

answered May 23 by Calinou (6,336 points)

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 = getviewport().gettexture().getdata()
thumbnail = Marshalls.variant

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

I have tried this:

thumbnail = nodedata["thumbnail"]
thumbnail = thumbnail as PoolByteArray <-- Pure desperation. Of course I knew this wouldn't work
var temp = Image.new()
fromdata(200, 200,true,Image.FORMATRGB8,thumbnail)

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

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()
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
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.