Need to generate and save textures(to disk)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Nuno Donato
:warning: Old Version Published before Godot 3 was released.

Hi folks!

So my situation is this: I’m generating icons to represent certain objects when the inventory shows up. I need to do the icons in-game instead of static files, because they change based on a number of parameters.
I’m basically using a viewport scene to load the object and then get the viewport texture, so that I have the object I need.

I can use this nicely anywhere, but later I will need to save the game and it would be great to save these icons too instead of re-generating everything when loading the game. So now the problem comes, how the hell can I save a texture to an image?

It seems easy to create a texture from an image, but not the reverse. Am I missing anything?

As a last resort I can forget the ViewportTexture and just do a screenshot from that viewport, but … :confused:

thanks

A capture like this?
How to merge two png files during runtime and save to disk ? - Archive - Godot Forum

But yes the screen capture sounds weird, you can get the image from TextureImage, not sure about the RenderTargetTexture.

ViewportTexture is a Godot 3 resource, are you talking about 3? (could be nice to have that option on this new resource, btw).

eons | 2017-04-11 22:38

oh yeah sorry, I’m in 3. I can’t find a way to get the image from a texture. I can get it from TextureImage but I can’t build a TextureImage from another texture so… :confused:

Nuno Donato | 2017-04-12 08:03

:bust_in_silhouette: Reply From: dquigz

I had the same issue and figured out a way.
To get an image from any texture and save to disk, first:

var img = urtexture.get_data()

this returns an Image object from the Texture object.

Next, in order to save the image, you need to convert it to a PoolByteArray. However, you need some other info saved as well it in order to load it back up. I store this data in a dictionary for reasons, but its more efficient to throw in an array

var idat = {'w': img.get_width, 'h': img.get_height(), 'f': img.get_format()}

Now we can go ahead and pool the byte array from the Image object. This is done with Image.get_data(). Note: get_data() on a Texture object returns an Image object. get_data() on an Image object returns a PoolByteArray object.

var ibytes = img.get_data()

Not done yet, we need to know how many bytes the image is when we reload it. So, lets add another key to our dictionary:

idat['blen'] = len(ibytes)

Now we’re ready to save. I save the reference data in a separate file. When serializing, I append the dictionaries to an array so the order of the array corresponds to the position of the bytes when reloading.

var img_out = File.new()
var dat_out = File.new()
img_out.open('user://path2sys32nawdowndothat', File.WRITE)
dat_out.open('res://project.godot.naw.dont', File.WRITE)

img_out.store_buffer(ibytes)
dat_out.store_line(to_json(idat))
img_out.close()
dat_out.close()

Okay, now to restore, things get nifty.

var img_in = File.new()
var indat_in = File.new()
img_in.open('whateverisaidabove', File.READ)
dat_in.open('thatpathagain', File.READ)

var dat = parse_json(dat_in.get_line())
var inbytes = img_in.get_bytes(dat['blen'])
var urimage = Image.new()
i.create_from_data(dat['w'], dat['h'], [bool- set flag mipmaps if u want], dat['f'], inbytes)
var t = ImageTexture.new()
t.create_from_image(i)
img_in.close()
dat_in.close()

And bam! You got your texture back as ‘t’. Of course, set methods up for this, especially if you’re saving more than one. I just broke it down to make it clear how the process works. Wax on.

This seems unnecessarily complex. Have you tried just saving and loading the Image instance directly? See my answer.

ArdaE | 2020-06-02 01:30

:bust_in_silhouette: Reply From: ArdaE

To save: file.store_var(myImageTexture.get_data(), true)
To load: myImageTexture.set_data(file.get_var(true))

file is simply an instance of Godot’s File class that has opened a file in WRITE or READ mode. See https://docs.godotengine.org/en/stable/classes/class_file.html for a complete example on how to open/close a file for write or read.

Another simple option that fit my use case was Image’s save_png.

Reference:
Image — Godot Engine (stable) documentation in English

jshorty | 2020-07-18 16:58