Save entire canvas to image?

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

I’ve a canvas on which i draw a lot of stuff through draw* functions.
This canvas can be very big so it won’t fit viewport. The question is, is there a way to draw/save entire canvas to image or i have to do it other way?
I care about the final image quality.

Thanks for attention.

:bust_in_silhouette: Reply From: Justofisker

I think the way to go about this is using the custom_viewport property of CanvasLayer
I got saving of the image working with this giant label that is bigger than the main Viewport

Several paragraphs of "Lorem ipsum"

For this node setup, the node Content is a PanelContainer and therefore the size of the everything being draw on this CanvasLayer. It doesn’t need to be a PanelContainer just something that contains everything being drawn.

CanvasLayer with a PanelContainer has label as its child. A TextureRect is also the child of the CanvasLayer

The CanvasLayer has a script attached to it with the following code:

extends CanvasLayer

func _ready() -> void:
	var viewport :=
	viewport.disable_3d = true
	viewport.size = $Content.rect_size
	viewport.render_target_update_mode = Viewport.UPDATE_ONCE
	custom_viewport = viewport
	get_parent().call_deferred("add_child", viewport)
	$"../TextureRect".texture = viewport.get_texture()

The Viewport can be manually updated again (therefore updating the image) with the following line code:
custom_viewport.render_target_update_mode = Viewport.UPDATE_ONCE

If you just want to save the texture and then free everything you can call .duplicate() on the texture (this must be done after at least one frame is drawn or else it’ll be fully black) and then .queue_free() on the Viewport and your CanvasLayer

Hope this helps :slight_smile:

Ah, big thanks
I’ve already done this with viewport but more bruteforce way, hope your code 'll help do it better way

ulabael | 2023-01-27 21:33