python - 如何在pyglet中使用原始像素数据来改变图像大小
问题描述
在将图像加载到精灵之前,我需要能够更改图像的宽度或高度。我目前正在使用 numpy 来获取中心行或列,并继续将其插入图像中,直到它的大小正确为止。我不知道这段代码是否还有效,因为我也无法将 raw_image 加载回精灵并显示它。
def set_image_size(img, x, y):
raw_img = img.get_image_data()
format = 'RGBA'
pitch = raw_img.width * len(format)
rgba = np.array(list(img.get_image_data().get_data(format, pitch))).reshape(-1, raw_img.width, len(format))
mid_y = rgba[round(raw_img.height/2),:] # This is needed to stretch along Y
while rgba.shape[0] < y:
rgba = np.insert(rgba, round(raw_img.height/2), mid_y, 0)
mid_x = rgba[:,round(raw_img.width/2)] # This is needed to stretch along X
while rgba.shape[1] < x:
rgba = np.insert(rgba, round(raw_img.width/2), mid_x, 1)
raw_img.set_data(format, pitch, ''.join(map(chr, rgba.tostring())))
return raw_img
当我尝试将其粘贴到抽象图像上并将其粘贴到屏幕上时,我得到了一个奇怪的红色条纹版本的图像。我不需要太担心质量,我只想“拉伸/平铺”图像的内部,这样边缘就不会变形。此外,我的图像非常小,只有 15 x 15 像素左右。
我该如何解决这些问题?
编辑:
当我使用 sprite.scale 时,它会以奇怪的方式拉伸:
self.sprite = pyglet.sprite.Sprite(self.image, self.x, self.y, batch=batch)
self.sprite.scale_x = self.width / 16
拉伸(使用 sprite.scale):
这对这个精灵来说不是什么大问题,因为我可以使用 OpenGL Quads 来绘制它,但是我需要开始使用需要以上述方式缩放的更复杂的精灵。
解决方案
因此,问题在于您最初使用的图像分辨率的比例,即16px
宽且7px
高。默认情况下,放大图像不会像您期望的那样做任何巧妙的邻域插值和“填充空白”。
为了解决这个问题,你可以告诉 OpenGL 放大图像中的每个新像素都应该从它的邻居那里获取“灵感”。每次渲染精灵时,您可以通过在渲染循环中添加以下内容来做到这一点:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
在您需要添加过滤器的精灵的每次渲染之前调用它是很重要的。不确定技术术语是什么,但必须设置每个渲染序列,因为下次循环渲染函数时它会重置。我敢肯定,这有一个花哨的词。
这是一个工作示例:
from pyglet import *
from pyglet.gl import *
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
glEnable(GL_TEXTURE_2D) # Strictly speaking not needed, I think this is default or won't affect this test image in any significant way.
self.keys = {}
self.mouse_x = 0
self.mouse_y = 0
# The image itself is 800x400 originally
# Positioned at x=0 and y=50 will place it at the bottom essentially
self.sprite = pyglet.sprite.Sprite(pyglet.image.load('test.png'), 50, 50, batch=None)
self.sprite.scale = 20 # Scale the height, not the width
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
self.mouse_x = x
def on_key_release(self, symbol, modifiers):
try:
del self.keys[symbol]
except:
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
self.keys[symbol] = True
def render(self):
self.clear()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
self.sprite.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
这是您可以使用的测试图像: (<-- 白色小方块,未放大效果)
结果如下:
推荐阅读
- typescript - Webpack:自定义加载器和插件顺序
- c# - 如何使用在 Unity 中创建的多个数据读回 JPG?( C# )
- javascript - 获取firebase数据后异步函数不返回值
- woocommerce - Woocommerce 强制更新数据库卡住
- php - Is it possible get table structures of a .frm file using PHP?
- javascript - 如何将变量传递给javascript中的正则表达式?
- c# - mvc按钮避免页面刷新而不使用ajax
- reactjs - redux:在异步获取和文档创建后重新渲染组件
- python - python flask app运行失败(404、405响应码)
- ios - 快速从应用程序打开图库