How to create a new image inside godot, from fragments of other images?

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

Hi all

I am trying to find a way to use small images to create a bigger image and then use it to texture a 3D node. My purpose is to create handwriting style image from a series of alphabet type images, create an image and use it for texturing. I said the same thing twice!!

However, no images can be seen when I do this! I even tried adding a texture rect and set it’s $texture_rect.texture=imain. Still nothing shows up. If I try $texture_rect.texture=abx[“image1”], that shows up well however.

Any help please?
Thanks

extends Spatial


var imain #the new image I want to greate with Image.new()

var abx={} #load the images


func _ready():

#create a new image on ready and set size/format
imain=Image.new()
imain.create(640,480,false,Image.FORMAT_RGB8)

#load up pngfiles from the images dir as StreamTexture and store with the file name w/o extension
for n in my_list_png("res://lib/kfonts/f1"):
	abx[n.replace(".png","")]=load("res://lib/kfonts/f1/"+n)


#add some of the images from the alphabets to the newly minted image
imain.blit_rect(abx["image1"],Rect2(0,0,64,64),Vector2(32,32))
imain.blit_rect(abx["image2"],Rect2(0,0,64,64),Vector2(64,32))
imain.blit_rect(abx["image3"],Rect2(0,0,64,64),Vector2(96,32))
imain.blit_rect(abx["image4"],Rect2(0,0,64,64),Vector2(32,64))
imain.blit_rect(abx["image5"],Rect2(0,0,64,64),Vector2(64,64))
imain.blit_rect(abx["image6"],Rect2(0,0,64,64),Vector2(96,64))


#now set the image as a tex to the mesh
var stx=ImageTexture.new()
stx.set_data(imain)
var mat=$mx.get_surface_material(0)
mat.albedo_texture=imain

func my_list_png(path="res://"):
	var files = []
	var dir = Directory.new()
	dir.open(path)
	dir.list_dir_begin()
	while true:
		var file = dir.get_next()
		if file == "":
			break
		elif not file.begins_with(".") and file.extension() == "png":
			files.append(file)
	dir.list_dir_end()
	return files

Not really an answer but - lock / unlock the image before manipulating it? I’ve done some image manipulation before and that’s what I remember forgetting (or not knowing) to do.

creativeape | 2020-09-22 22:50

Hi creativeape

I tried that. I will add the simplest case code below in a sec but no luck.

Thanks

sxkod | 2020-09-23 14:10

:bust_in_silhouette: Reply From: klaas

Hi,
i think this could be the problem …

#now set the image as a tex to the mesh
var stx=ImageTexture.new()
stx.set_data(imain) # replace this

stx.create_from_image ( imain ) # with this

Hi Klaas

Thanks for the reply. I will add the simplest case code below to show. I even tried to save the image as a png so that it will exclude UV problems etc. Even the saved image is flat black. I tried different formats too. Still no luck!

Thanks

extends Spatial



func _ready():
	var tex=ImageTexture.new()
	var img=Image.new()
	img.lock()
	img.create(400,400,false,Image.FORMAT_RGB8)
	img.blit_rect(load("res://icon.png"),img.get_used_rect(),Vector2(40,40))
	img.unlock()
	tex.create_from_image(img)
	img.save_png("res://test_output.png")
	var mat=$mx.get_surface_material(0)
	mat.albedo_texture=tex

sxkod | 2020-09-23 14:12

Hi,
in your example the format of your created img does not match the format of the image to blit.
You create a FORMAT_RGB8 but the png has alpha and uses FORMAT_RGBA8

You either must supply image with the same format or use Image.convert.

AND load(“res://icon.png”) loads it as StreaminTexture not as image. You have to use Image.load()

func _ready():
	var tex = ImageTexture.new()
	var img = Image.new()
	img.create(400,400,false,Image.FORMAT_RGBA8)
	var blitImage = Image.new()
	blitImage.load("res://icon.png")
	img.blit_rect( blitImage, blitImage.get_used_rect() ,Vector2(40,40))
	tex.create_from_image( img )
	img.save_png("res://test_output.png")
	var mat = get_surface_material(0)
	mat.albedo_texture = tex

klaas | 2020-09-23 14:43

That worked. Thanks a bunch.

sxkod | 2020-09-23 19:22