【Godot4.2】图片处理函数库 - textureDB

概述

Godot中节点使用的图片是Texture2D或其子类型,而涉及图片处理,大多数功能在Image类型中,并且我们通常需要频繁的构造ImageImageTexture类型。
为了封装构造ImageImageTexture类型的代码,提供直接从文件到直接可以赋值给节点的纹理图片,或者从节点纹理直接获取处理后的纹理,所以笔者才起了创建这个静态函数库的想法。

代码

(会持续更新最新修改版本,另外请注意Godot版本)

# =============================================
# 名称:textureDB
# 类型:静态函数库
# 描述:一些简化处理ImageTexture的静态函数
# 作者:巽星石
# Godot版本:v4.2.1.stable.official [b09f793f5]
# 创建时间:20242822:48:38
# 最后修改时间:20242902:02:58
# =============================================
class_name textureDB

enum ImageType{JPG,PNG,WEBP}   # 支持存储的图片类型

# 直接从路径加载图片并返回ImageTexture
static func load_texture(img_path:String) -> ImageTexture:
	var texture = ImageTexture.new()
	var img = Image.load_from_file(img_path)
	texture = texture.create_from_image(img)
	return texture

# 水平翻转Texture2D
static func flip_x_texture(texture:Texture2D) -> ImageTexture:
	var new_texture = ImageTexture.new()
	var img = texture.get_image()
	img.flip_x()
	new_texture = new_texture.create_from_image(img)
	return new_texture

# 垂直翻转Texture2D
static func flip_y_texture(texture:Texture2D) -> ImageTexture:
	var new_texture = ImageTexture.new()
	var img = texture.get_image()
	img.flip_y()
	new_texture = new_texture.create_from_image(img)
	return new_texture
	
# 创建并返回原图片的灰度图
static func gray_scale_texture(texture:Texture2D) -> ImageTexture:
	var new_texture = ImageTexture.new()
	var img = texture.get_image()
	for x in range(img.get_width()):
		for y in range(img.get_height()):
			var old_color = img.get_pixel(x,y)
			var gray = (old_color.r +  old_color.g +  old_color.b)/3
			var new_color = Color(gray,gray,gray,old_color.a)
			img.set_pixel(x,y,new_color)
	new_texture = new_texture.create_from_image(img)
	return new_texture

# 获取并返回Texture2D的一个局部矩形区域
static func get_region(texture:Texture2D,region: Rect2i) -> ImageTexture:
	var new_texture = ImageTexture.new()
	var img = texture.get_image()
	img = img.get_region(region)
	new_texture = new_texture.create_from_image(img)
	return new_texture

# 为图片添加边框
static func draw_border(texture:Texture2D,border_size:PackedInt32Array = [10,10,10,10],border_color:Color=Color.WHITE) -> ImageTexture:
	var new_texture = ImageTexture.new()
	# 1.通过原图和边框尺寸计算新图的尺寸
	var old_img = texture.get_image() # 原图片
	var new_img = Image.new()         # 新图片
	# 新的尺寸 = 原图片尺寸 + 边框尺寸
	var new_size = old_img.get_size() + Vector2i(border_size[1] + border_size[3],border_size[0] + border_size[2])
	
	# 2.通过新尺寸构造新的Image
	new_img = new_img.create(new_size.x,new_size.y,false,Image.FORMAT_RGBA8)
	new_img.fill(border_color)  # 填充整个纹理区域为边框颜色
	
	# 3.在新图的指定位置绘制原图
	var rect = old_img.get_used_rect()                # 原图的纹理区域
	var pos = Vector2i(border_size[3],border_size[0]) # 起始位置
	new_img.blit_rect(old_img,rect,pos)               # 将原图绘制到新Image的指定区域
	
	# 4.通过新Image构造ImageTexture
	new_texture = new_texture.create_from_image(new_img)
	return new_texture

# 创建纯色块的ImageTexture
static func color_block(size:Vector2,color:Color=Color.WHITE) -> ImageTexture:
	var new_texture = ImageTexture.new()
	var img = Image.new()
	img = img.create(size.x,size.y,false,Image.FORMAT_RGBA8)
	img.fill(color)
	new_texture = new_texture.create_from_image(img)
	return new_texture

# 创建棋盘格的ImageTexture
static func checker_board(img_size:Vector2i,cell_size:Vector2i=Vector2i(10,10),color1:Color=Color.WHITE,color2:Color=Color.BLACK) -> ImageTexture:
	var new_texture = ImageTexture.new()
	var img = Image.new()
	img = img.create(img_size.x,img_size.y,false,Image.FORMAT_RGBA8)
	# 计算所需要填充的数量
	var grid_size = ceil(img_size / cell_size) 
	for x in range(grid_size.x):
		for y in range(grid_size.y):
			var rect = Rect2i(cell_size * Vector2i(x,y),cell_size)
			if (x % 2 == 0 and y % 2 == 0) or (x % 2 == 1 and y % 2 == 1): # 奇数行奇数列,或者偶数行偶数列
				img.fill_rect(rect,color1)
			else:
				img.fill_rect(rect,color2)
	new_texture = new_texture.create_from_image(img)
	return new_texture

# 直接将Texture2D保存为本地图片文件
static func save_texture(texture:Texture2D,file_path:String,img_type:ImageType=ImageType.JPG) -> void:
	var img = texture.get_image()
	match img_type:
		ImageType.JPG:
			img.save_jpg(file_path)
		ImageType.PNG:
			img.save_png(file_path)
		ImageType.WEBP:
			img.save_webp(file_path)


# 生成Image的缩略图
static func create_thumb(img:Image,size:Vector2) -> ImageTexture:
	var texture = ImageTexture.new()
	var old_size = img.get_size()  # 原图尺寸
	var aspect_ratio = old_size.aspect()
	
	# 原图比缩略图宽或高时
	if old_size.x > size.x or old_size.y > size.y:
		if old_size.x > old_size.y: # 图片水平方向比较长
			var new_w = size.x
			var new_h = size.x / aspect_ratio
			img.resize(new_w,new_h)
		else:
			var new_h = size.y 
			var new_w = size.y * aspect_ratio
			img.resize(new_w,new_h,Image.INTERPOLATE_LANCZOS)
	texture = texture.create_from_image(img)
	return texture

# 生成指定路径文件的缩略图
static func create_thumb_from_file(img_path:String,size:Vector2) -> ImageTexture:
	var texture = ImageTexture.new()
	if img_path.get_extension() in ["png","jpg","svg"]:
		var img = Image.load_from_file(img_path)
		if img:
			texture = create_thumb(img,size)
		return texture
	else:
		return null

用法示例

我们创建一个测试场景,添加一个TextureRect控件。

【Godot4.2】图片处理函数库 - textureDB_第1张图片

并设定如下:

【Godot4.2】图片处理函数库 - textureDB_第2张图片

加载图片文件到节点

为根节点创建如下代码:

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	# 从文件加载图片
	texture_rect.texture = textureDB.load_texture("res://icon.svg")

运行后就可以看到图片被正确加载,这种直接加载图片文件为纹理的形式,比构造ImageTextureImage要简化的多了。

【Godot4.2】图片处理函数库 - textureDB_第3张图片

水平翻转图片

为了更好的展示图片处理效果,我们使用一张更大更复杂的图片。下面是原图加载后的效果:

修改设置如下:

【Godot4.2】图片处理函数库 - textureDB_第4张图片

根节点代码修改如下:

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值水平翻转后的图片
	texture_rect.texture = textureDB.flip_x_texture(texture)

运行后的效果:


可以看到图片被水平翻转,而且没有涉及Image的底层操作。

垂直翻转图片

垂直翻转的代码很类似,只需要将flip_x_texture改为flip_y_texture就可以了。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值水平翻转后的图片
	texture_rect.texture = textureDB.flip_y_texture(texture)

垂直翻转效果:

局部裁切(显示图片局部)

通过get_region可以获取相应纹理的的一个局部。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值局部裁切图片
	texture_rect.texture = textureDB.get_region(texture,Rect2i(100,100,500,500))

效果如下:

【Godot4.2】图片处理函数库 - textureDB_第5张图片

可以应用于用户头像、封面图片裁切等场景。

绘制边框

在图片处理中有时候需要描边或绘制边框,draw_border可以为原图外部添加四个边上的描边,而且可以设定每个边不一样的宽度。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值添加描边效果的图片
	texture_rect.texture = textureDB.draw_border(texture)

默认的10像素边框:


可以自定义各个边的尺寸,顺序为:上右底左。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值添加描边效果的图片
	texture_rect.texture = textureDB.draw_border(texture,[200,100,200,100])

自定义边框宽度效果:

另外,边框颜色也可以自定义:

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值添加描边效果的图片
	texture_rect.texture = textureDB.draw_border(texture,[200,100,200,100],Color.YELLOW_GREEN)

纯色块

color_block指定一个大小和颜色,就可以直接创建一个纯色块图片。默认为白色。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	# 赋值纯色块
	texture_rect.texture = textureDB.color_block(Vector2(200,200))

【Godot4.2】图片处理函数库 - textureDB_第6张图片

棋盘格

checker_board用于参数化的创建棋盘格纹理,可以看做是我的第一个纹理图片生成函数,当然基于CanvasItem的绘制函数,已经创建过棋盘格了。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	# 赋值棋盘格
	texture_rect.texture = textureDB.checker_board(Vector2i(100,100),Vector2i(10,10))

【Godot4.2】图片处理函数库 - textureDB_第7张图片
通过设定两个颜色,可以绘制彩色棋盘格。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	# 赋值棋盘格
	texture_rect.texture = textureDB.checker_board(Vector2i(100,100),Vector2i(10,10),Color.AQUA,Color.AQUAMARINE)

【Godot4.2】图片处理函数库 - textureDB_第8张图片

创建灰度图

基于每个像素点RGB值相加除以3的做法,相对效率不是太高。但算勉强实现,使用多线程可能会加速一些。不过确实可以实现图片处理并输出为本地文件,一般使用还是用Shader实现吧,效率高多了。

extends Control

@onready var texture_rect = $TextureRect

func _ready():
	var img_path = "C:/Users/Lenovo/Pictures/Screenshots/屏幕截图 2024-02-06 150512.png"
	# 从文件加载图片
	var texture = textureDB.load_texture(img_path)
	# 赋值灰度图
	texture_rect.texture = textureDB.gray_scale_texture(texture)

创建缩略图

(等待施工…2024年2月9日01:37:37)

保存纹理为本地文件

(等待施工…2024年2月9日01:37:37)

你可能感兴趣的:(Godot4.0,Godot函数库,godot,gdscript)