godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.1k stars 21.16k forks source link

ImageTexture fails to "create_from_image" with error "Invalid image: image is empty" from an Image generated by one or more GradientTexture1D stored in an array #89321

Open Lothari opened 7 months ago

Lothari commented 7 months ago

Tested versions

Godot 4.2

System information

Godot v4.2.stable - Windows 10.0.22631 - Vulkan (Forward+) - dedicated AMD Radeon RX 6700 XT (Advanced Micro Devices, Inc.; 31.0.22024.3) - AMD Ryzen 7 7700X 8-Core Processor (16 Threads)

Issue description

I am trying to combine multiple GradientTexture1D gradients into a array to generate an image to texture a planet. using the code below, how while i can read the data and generate an "Image" i cant generate an ImageTexture... it trows the error "Invalid image: image is empty" while the "data" that is needed is apparently read extracted and valid... Unless i am making a mistake the code below should work.

func update_biome_texture() -> ImageTexture:
    var image_texture = ImageTexture.new()
    var dyn_image = Image.new()
    var h : int = biomes.size()
    if h > 0:
        var w : int = biomes[0].gradient.width
        var data : PackedByteArray
        for b in biomes:
            var gradient_image = b.gradient.get_image()
            if gradient_image.get_width() > 0 and gradient_image.get_height() > 0:
                data.append_array(gradient_image.get_data())
        if data.size() > 0:
            dyn_image.create_from_data(w, h, false, Image.FORMAT_RGBA8, data)
            image_texture.create_from_image(dyn_image)
            image_texture.resource_name = "biome texture"
        else:
            print("Error: Gradient data is empty.")
    return image_texture

Steps to reproduce

Boot up the MRP.

  1. Go from main to planet.
  2. Click on the Planet object in the scene.
  3. Open the PlanetData.gd script (the code is in there)
  4. Search for "func update_biome_texture()" (to find the code)
  5. in the inspector, toggle the "dev_code_or_data_edit_mode" bool. (this should force the project to regenerate the planet object and try to load and apply a texture)
  6. you have your error.

Minimal reproduction project (MRP)

Dark Stars.zip

Mickeon commented 7 months ago

Image.create_from_data is a static function and it returns a new Image outright. The code should be:

var dyn_image = Image.create_from_data(w, h, false, Image.FORMAT_RGBA8, data)

The editor even warns you about it. image

This has been "reported" in the past maaaaany times and I can't exactly blame you, as this is a change in behavior compared to 3.x that is not readily apparent. But do pay attention at the signature.

AThousandShips commented 7 months ago

You can also use set_data and set_image, instead of the assignment, if you want to keep the code as it is

Lothari commented 7 months ago

The following code works:

func update_biome_texture() -> ImageTexture:
    var image_texture = ImageTexture.new()
    var h : int = biomes.size()
    if h > 0:
        var w : int = biomes[0].gradient.width
        @warning_ignore("unassigned_variable")
        var data : PackedByteArray
        for b in biomes:
            var gradient_image = b.gradient.get_image()
            if gradient_image.get_width() > 0 and gradient_image.get_height() > 0:
                data.append_array(gradient_image.get_data())
        if data.size() > 0:
            var dyn_image = Image.create_from_data(w, h, false, Image.FORMAT_RGBA8, data)
            image_texture.set_image(dyn_image)
            image_texture.resource_name = "biome texture"
        else:
            print("Error: Gradient data is empty.")
    return image_texture
Mickeon commented 7 months ago

So, there's no issue. This can be closed?