Download an image from a URL and set it as the texture for a Sprite2D node

This my code,I don’t know why this code doesn’t work in version 4.2 but works fine in version 3.5. Is there something that needs to be configured?:
extends Sprite2D

@export var texture2_url: String = “https://lms.jinhyung.kim/api/file/1_1_2.png

var http_request: HTTPRequest

func _ready() → void:
if texture2_url:
download_texture_from_url(texture2_url)
else:
print(“No texture2_url provided.”)

# Test setting a built-in texture
var test_texture = preload("res://path_to_a_test_texture.png")
texture = test_texture

Download the image from the server

func download_texture_from_url(url: String) → void:
http_request = HTTPRequest.new()
add_child(http_request)
http_request.connect(“request_completed”, Callable(self, “_on_request_completed”))
http_request.request(url)
print(“Request sent to URL: %s” % url)

Handle the HTTP request completion

func _on_request_completed(result: int, response_code: int, headers: Array, body: PackedByteArray) → void:
print(“Request completed with result: %d, response_code: %d” % [result, response_code])

if response_code == 200:
    var img = Image.new()
    var err = img.load_png_from_buffer(body)
    if err == OK:
        print("Image loaded successfully.")
        print("Image size: %s" % img.get_size())
        
        var img_texture = ImageTexture.new()
        img_texture.create_from_image(img)
        if img_texture:
            print("ImageTexture created successfully.")
        else:
            print("Failed to create ImageTexture.")
            
        texture = img_texture
        print("Texture set successfully.")
    else:
        print("Failed to load image from buffer with error: %d" % err)
else:
    print("Failed to download image. Response code: %d" % response_code)

Can you be more specific on “doesnt work”. What exactly doesnt work? downloading the image? handling request completion? displaying the image? any error messages?

Here is the feedback result in Godot 4.2.:
Starting to load image from URL: https://lms.jinhyung.kim/api/file/1_1_3.png
HTTP request started successfully.
HTTP request completed with response code: 200
Image loaded from buffer successfully.
Image size: 1920 x 1080
Texture created from image successfully.
Error: Texture size is 0x0

It displays correctly in Godot 3.5.:
Request sent to URL: https://lms.jinhyung.kim/api/file/2_1_1.png
Request completed with result: 0, response_code: 200
Image loaded successfully.
Image size: (1920, 1080)
ImageTexture created successfully.
Texture set successfully

The problem is the way you set the ImageTexture: Youre doing this:

var img_texture = ImageTexture.new()
img_texture.create_from_image(img)

but you have to do it this way:

var img_texture: ImageTexture = ImageTexture.create_from_image(img)

the method “create_from_image” is a static method that RETURNs the new ImageTexture and doesnt set it to the referenced image texture

Thank you for your response.Based on the code you provided, a new issue has arisen.
(HTTP request started successfully.
HTTP request completed with response code: 200
Image loaded from buffer successfully.
Image size: 1920 x 1080
Texture created from image successfully.
Texture applied to sprite.
Sprite2D texture is not set.)

extends Sprite2D

var image_url = “https://lms.jinhyung.kim/api/file/1_1_1.png

func _ready():
self.visible = true

print("Starting to load image from URL: %s" % image_url)
load_image_from_url(image_url)

func load_image_from_url(url):
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(self._on_request_completed)
var err = http_request.request(url)
if err != OK:
print(“Failed to start the HTTP request. Error: %s” % err)
else:
print(“HTTP request started successfully.”)

func _on_request_completed(result, response_code, headers, body):
print(“HTTP request completed with response code: %d” % response_code)
if response_code == 200:
var image = Image.new()
var error = image.load_png_from_buffer(body)

	if error != OK:
		print("Failed to load PNG image from buffer. Trying JPEG format.")
		error = image.load_jpg_from_buffer(body)
	
	if error != OK:
		print("Failed to load image from buffer. Error code: %d" % error)
		return
	
	print("Image loaded from buffer successfully.")
	print("Image size: %d x %d" % [image.get_width(), image.get_height()])

	if image.is_empty():
		print("Error: Image data is empty.")
		return

	var img_texture: ImageTexture = ImageTexture.create_from_image(image)

	print("Texture created from image successfully.")
	
	if img_texture.get_width() == 0 or img_texture.get_height() == 0:
		print("Error: Texture size is 0x0")
		return

	self.texture = texture
	print("Texture applied to sprite.")
	

	if self.texture:
		print("Sprite2D texture size: %d x %d" % [self.texture.get_width(), self.texture.get_height()])
	else:
		print("Sprite2D texture is not set.")
else:
	print("Failed to load image. Response code: %d" % response_code)

change this:

self.texture = texture
print("Texture applied to sprite.")

to this:

self.texture = img_texture
print("Texture applied to sprite.")
1 Like

The issue has been resolved, thank you. Thank you very much! :grinning: :grinning:

1 Like

Can you help me take a look? It’s still an issue with the image not displaying. I integrated it into my project, but the image isn’t showing up again, and I can’t find the problem:
extends Control

var current_lesson = 1
const BASE_URL = “https://lms.jinhyung.kim/api/section/1/lesson/
const FILE_BASE_URL = “https://lms.jinhyung.kim/api/file/

func _ready():
print(“Clean Energy scene loaded, let’s dive in!”)
if Globals.jwt_token == “”:
print(“No JWT token found, performing a magical login journey…”)
_perform_login()
else:
print(“JWT token found, sending a radiant section request…”)
_send_section_request(current_lesson)

_debug_nodes()
_connect_button_signals()

func _debug_nodes():
print(“Debugging nodes, ensuring everything is in place…”)
for node in get_children():
print(“Node: %s” % node.name)

func _connect_button_signals():
var turnpage1_button = $Turnpage1
if turnpage1_button.is_connected(“pressed”, Callable(self, “_on_turnpage1_pressed”)):
turnpage1_button.disconnect(“pressed”, Callable(self, “_on_turnpage1_pressed”))
turnpage1_button.connect(“pressed”, Callable(self, “_on_turnpage1_pressed”))

var turnpage2_button = $Turnpage2
if turnpage2_button.is_connected("pressed", Callable(self, "_on_turnpage2_pressed")):
	turnpage2_button.disconnect("pressed", Callable(self, "_on_turnpage2_pressed"))
turnpage2_button.connect("pressed", Callable(self, "_on_turnpage2_pressed"))

var logout_button = $LogoutButton
if logout_button.is_connected("pressed", Callable(self, "_on_clean_energy_logout_button_pressed")):
	logout_button.disconnect("pressed", Callable(self, "_on_clean_energy_logout_button_pressed"))
logout_button.connect("pressed", Callable(self, "_on_clean_energy_logout_button_pressed"))

func _perform_login():
var login_url = “https://lms.jinhyung.kim/api/auth/login
var login_data = {“email”: “qq”, “name”: “qq”, “password”: “qq”}
var login_request = HTTPRequest.new()
add_child(login_request)
login_request.request_completed.connect(Callable(self, “_on_login_request_completed”))
var headers = [“Content-Type: application/json”]
var err = login_request.request(login_url, headers, HTTPClient.METHOD_POST, JSON.stringify(login_data))
if err != OK:
print(“Login request initiation failed with error code: %d” % err)

func _on_login_request_completed(result, response_code, headers, body):
print(“Login request completed with response code: %d” % response_code)
print(“Response body: %s” % body.get_string_from_utf8())
if response_code == 201:
var json_parser = JSON.new()
var parse_result = json_parser.parse(body.get_string_from_utf8())
if parse_result == OK:
var response = json_parser.get_data()
if response.has(“access_token”):
Globals.jwt_token = response[“access_token”]
if response.has(“user_id”):
Globals.user_id = response[“user_id”]
print(“Access token received: %s” % Globals.jwt_token)
_send_section_request(current_lesson)
else:
print(“Error: access_token not found in the response.”)
else:
print(“Error parsing login JSON: %s” % json_parser.error_string)
else:
print(“Login request failed with response code: %d” % response_code)
print(“Response body: %s” % body.get_string_from_utf8())
self.remove_child(get_child(get_child_count() - 1))

func _send_section_request(lesson_id):
print(“Sending section request with token: %s” % Globals.jwt_token)
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(Callable(self, “_on_section_request_completed”))
var url = BASE_URL + str(lesson_id)
print(“Requesting URL: %s” % url)
var headers = ["Authorization: Bearer " + Globals.jwt_token]
var err = http_request.request(url, headers, HTTPClient.METHOD_GET)
if err != OK:
print(“Section request initiation failed with error code: %d” % err)

func _on_section_request_completed(result, response_code, headers, body):
print(“Section request completed with response code: %d” % response_code)
print(“Response body: %s” % body.get_string_from_utf8())
if response_code == 200:
var json_parser = JSON.new()
var parse_result = json_parser.parse(body.get_string_from_utf8())
if parse_result == OK:
var data = json_parser.get_data()
if data.has(“lesson”):
var lesson = data[“lesson”]
if lesson.has(“titleText”):
_set_title(lesson[“titleText”])
if lesson.has(“headerText”):
_set_header(lesson[“headerText”])
if lesson.has(“contentImage”) and lesson[“contentImage”] != “”:
var content_image_url = lesson[“contentImage”]
if !content_image_url.begins_with(“http”):
content_image_url = FILE_BASE_URL + content_image_url
print(“Content image URL before correction: %s” % content_image_url)
var contentImageX = 0
if lesson.has(“contentImageX”):
contentImageX = lesson[“contentImageX”]
var contentImageY = 0
if lesson.has(“contentImageY”):
contentImageY = lesson[“contentImageY”]
content_image_url = content_image_url.replace(“http://”, “https://”)
print(“Content image URL after correction: %s” % content_image_url)
_download_image(content_image_url, “content_image”, contentImageX, contentImageY)
if lesson.has(“contentText”):
var contentTextX = 0
if lesson.has(“contentTextX”):
contentTextX = lesson[“contentTextX”]
var contentTextY = 0
if lesson.has(“contentTextY”):
contentTextY = lesson[“contentTextY”]
var contentTextW = 0
if lesson.has(“contentTextW”):
contentTextW = lesson[“contentTextW”]
var contentTextH = 0
if lesson.has(“contentTextH”):
contentTextH = lesson[“contentTextH”]
_set_content_text(lesson[“contentText”], contentTextX, contentTextY, contentTextW, contentTextH)
else:
print(“Error parsing JSON: %s” % json_parser.error_string)
else:
print(“Section request failed with response code: %d” % response_code)
print(“Response body: %s” % body.get_string_from_utf8())
print(“Failed section request headers: %s” % headers)
self.remove_child(get_child(get_child_count() - 1))

func _download_image(url: String, target: String, x: int = 0, y: int = 0):
if url == “”:
print(“No URL provided for image download”)
return

var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(Callable(self, "_on_image_request_completed").bind(target, x, y))
var err = http_request.request(url)
if err != OK:
	print("Failed to start the HTTP request. Error: %s" % err)
else:
	print("HTTP request started successfully for URL: %s" % url)

func _on_image_request_completed(result, response_code, headers, body, target, x, y):
print(“HTTP request completed with response code: %d” % response_code)
if response_code == 200:
var image = Image.new()
var error = image.load_png_from_buffer(body)

	if error != OK:
		print("Failed to load PNG image from buffer. Trying JPEG format.")
		error = image.load_jpg_from_buffer(body)
	
	if error != OK:
		print("Failed to load image from buffer. Error code: %d" % error)
		_set_default_texture([target, x, y])
		return
	
	print("Image loaded from buffer successfully.")
	print("Image size: %d x %d" % [image.get_width(), image.get_height()])

	if image.is_empty():
		print("Error: Image data is empty.")
		_set_default_texture([target, x, y])
		return

	var img_texture: ImageTexture = ImageTexture.create_from_image(image)

	print("Texture created from image successfully.")
	
	if img_texture.get_width() == 0 or img_texture.get_height() == 0:
		print("Error: Texture size is 0x0")
		_set_default_texture([target, x, y])
		return

	if target == "content_image":
		_set_content_image(img_texture, x, y)
	
	print("Image applied to target: %s" % target)
else:
	print("Failed to load image. Response code: %d" % response_code)
	_set_default_texture([target, x, y])


var http_request = get_child(get_child_count() - 1)
if http_request is HTTPRequest:
	remove_child(http_request)
	http_request.queue_free()

func _set_default_texture(user_data):
if user_data[0] == “content_image”:
_set_content_image(_get_default_texture(), user_data[1], user_data[2])

func _get_default_texture() → ImageTexture:
var image = Image.new()
image.create(512, 512, false, Image.FORMAT_RGBA8)
if image.is_empty():
print(“Image creation failed: image is empty”)
return null
print(“Image created with size: %s, format: %s” % [str(image.get_size()), str(image.get_format())])

image.fill(Color(0.5, 0.5, 0.5, 1.0))
if image.is_empty():
	print("Image fill failed: image is empty")
	return null
print("Image filled with color")

var texture = ImageTexture.new()
texture.create_from_image(image)
print("Texture created from image")

return texture

func _set_title(text: String):
var title = $Title
if title:
title.text = text
print(“Title text set successfully”)
else:
print(“Title node not found”)

func _set_header(text: String):
var header = $Header
if header:
header.text = text
print(“Header text set successfully”)
else:
print(“Header node not found”)

func _set_content_image(texture: ImageTexture, x: int, y: int):
var content_image = $ContentImage
if content_image and content_image is TextureRect:
content_image.texture = texture
content_image.rect_position = Vector2(x, y)
print(“Content image set successfully at position (%d, %d)” % [x, y])
else:
print(“Content Image node not found or is not a TextureRect”)

func _set_content_text(text: String, x: int, y: int, w: int, h: int):
var content_text = $ContentText
if content_text:
if content_text is RichTextLabel:
content_text.bbcode_text = text
content_text.position = Vector2(x, y)
content_text.set(“custom_constants/minimum_size”, Vector2(w, h))
print(“Content text set successfully”)
else:
print(“Content Text node is not a RichTextLabel”)
else:
print(“Content Text node not found”)

func _on_turnpage1_pressed():
if current_lesson > 1:
current_lesson -= 1
else:
current_lesson = 1
_send_section_request(current_lesson)

func _on_turnpage2_pressed():
var total_lessons = 3
if current_lesson < total_lessons:
current_lesson += 1
else:
current_lesson = 1
_send_section_request(current_lesson)

func _upload_study_info():
var study_info_url = “https://lms.jinhyung.kim/api/section/1/complete
var study_info_data = {
“user_id”: Globals.user_id,
“lesson_id”: current_lesson,
“progress”: “completed”
}
var study_info_request = HTTPRequest.new()
add_child(study_info_request)
study_info_request.request_completed.connect(Callable(self, “_on_study_info_request_completed”))
var headers = ["Authorization: Bearer " + Globals.jwt_token, “Content-Type: application/json”]
var err = study_info_request.request(study_info_url, headers, HTTPClient.METHOD_PUT, JSON.stringify(study_info_data))
if err != OK:
print(“Study info request initiation failed with error code: %d” % err)

func _on_study_info_request_completed(result, response_code, headers, body):
if response_code == 200:
var json_parser = JSON.new()
var parse_result = json_parser.parse(body.get_string_from_utf8())

	if parse_result == OK:
		var response = json_parser.get_data()
		if response.has("progress"):
			var progress = response["progress"]
			print("Progress ID: %s" % progress["id"])
			print("Start Date: %s" % progress["startDate"])
			print("End Date: %s" % progress["endDate"])
		else:
			print("Error: 'progress' field not found in the response.")
	else:
		print("Error parsing JSON: %s" % json_parser.error_string)
else:
	print("Request failed with response code: %d" % response_code)

get_tree().change_scene_to_file("res://Scene/main_board.tscn")

func _on_clean_energy_logout_button_pressed():
_upload_study_info()

Are there error messages? And what does get printed?

The same mistake as last time. Change this:

var texture = ImageTexture.new()
texture.create_from_image(image)
print("Texture created from image")

to this:

var texture = ImageTexture.create_from_image(image)
print("Texture created from image")

The method “ImageTexture.create_from_image(image)” RETURN’s a new ImageTexture with the given image (in Godot 4)-> so you have to assign it

The image still isn’t displaying.

The request_completed-signal is never recieved. Update this line of code in the “_download_image”-method to the new syntax and try again:
Old Syntax (Godot 3):

http_request.request_completed.connect(Callable(self, "_on_image_request_completed").bind(target, x, y))

New Syntax (Godot 4):

http_request.request_completed.connect(_on_image_request_completed.bind(target, x, y))

Although the image still isn’t displaying, I’ll keep trying to find a solution. Thank you for your help.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.