[英]Why does referring to a class in (python) pyglet.image cause heavy cpu load on Windows?
[英]Why are pyglet.image and texture so heavy?
管環境:
這是我的代碼和結果:
import pyglet
images = []
textures = []
with_textures = True
count = 10
for x in range(count):
image = pyglet.image.load("big.png") # 2.1 Mb source 2400*2400px
images.append(image)
if with_textures:
texture_grid = pyglet.image.ImageGrid(image, 10, 10).get_texture_sequence()
textures.append(texture_grid)
# RES in htop result without textures
# count = 10 - 300Mb
# count = 20 - 553Mb
# count = 30 - 753Mb
# count = 40 - 973Mb
# ~23Mb just for each Image
# RES in htop result with textures
# count = 10 - 996Mb
# count = 20 - 1878Mb
# count = 30 - 2716Mb
# count = 40 - 3597Mb
# ~86Mb for Image and prepared grid
input("Press enter to exit")
PS:第一次將應用程序從pygame
重寫為pyglet
,是因為我沒有考慮pygame
中事件循環的某些方面,現在我沒有針對用例測試pyglet
庫的資源使用情況。
我正在使用ImageGrid
作為頂點的3d部分以及pyglet.sprite.Sprite的 2d部分
在3D零件中使用的示例:
# texture_group is created once for each sprite sheet, same as texture_grid
texture_group = pyglet.graphics.TextureGroup(texture_grid, order_group)
...
tex_map = texture_grid[self.texture_grid_index].texture.tex_coords
tex_coords = ('t3f', tex_map)
self.entity = self.batch.add(
4, pyglet.gl.GL_QUADS,
texture_group,
('v3f', (x, y, z,
x_, y, z,
x_, y_, z,
x, y_, z)
),
tex_coords)
在2D零件中使用的示例:
pyglet.sprite.Sprite(img=texture_grid[self.texture_grid_index], x=0, y=0,
batch=self.batch, group=some_order_group)
我發現,允許使用pyglet.image.CompressedImageData的大小是:
1 True
2 True
4 True
8 True
16 True
32 True
64 True
128 True
256 True
512 True
1024 True
2048 True
4096 True
但是無法從CompressedImageData
獲取紋理:
big = pyglet.image.load("big.png") # 2048*2048
compressed_format = pyglet.graphics.GL_COMPRESSED_ALPHA
compressed_image = pyglet.image.CompressedImageData(
big.width, big.height, compressed_format, big.data)
compressed_image.texture # exception GLException: b'invalid enumerant'
在pyglet中嘗試了所有可能的GL_COMPRESS:
allowed_formats = [x for x in dir(pyglet.graphics) if "GL_COMPRESSED_" in x]
big = pyglet.image.load("big.png") # 2048*2048
for form in allowed_formats:
compressed_image = pyglet.image.CompressedImageData(
big.width, big.height, form, big.data)
try:
compressed_image.texture
print("positive:", form) # 0 positive prints
except Exception:
pass
例外情況是:
Traceback (most recent call last):
File "<ipython-input-72-1b802ff07742>", line 7, in <module>
compressed_image.texture
File "/<venv>/lib/python3.6/site-packages/pyglet/image/__init__.py", line 410, in texture
return self.get_texture()
File "/<venv>/lib/python3.6/site-packages/pyglet/image/__init__.py", line 1351, in get_texture
len(self.data), self.data)
ctypes.ArgumentError: argument 3: <class 'TypeError'>: wrong type
pyglet中發生了什么:
if self._have_extension():
glCompressedTexImage2DARB(texture.target, texture.level,
self.gl_format,
self.width, self.height, 0,
len(self.data), self.data)
IPDB:
> /<venv>/lib/python3.6/site-packages/pyglet/image/__init__.py(1349)get_texture()
1348 import ipdb;ipdb.set_trace()
-> 1349 glCompressedTexImage2DARB(texture.target, texture.level,
1350 self.gl_format,
ipdb> glCompressedTexImage2DARB
<_FuncPtr object at 0x7fca957ee1d8>
ipdb> texture.target
3553
ipdb> texture.level
0
ipdb> self.gl_format
'GL_COMPRESSED_TEXTURE_FORMATS_ARB'
ipdb> self.width
2048
ipdb> self.height
2048
ipdb> len(self.data)
16777216
ipdb> type(self.data)
<class 'bytes'>
#1的答案很簡單:PNG是一種壓縮格式。 解壓縮后,即使2400×2400映像的磁盤大小為2 MB,也只需要在RAM中占用2400×2400×32bit = 23040000字節。
解決此問題的可能方法很多,但是所有這些方法都歸結為在內存需求,圖像質量和訪問速度之間找到合適的折衷方案。
例如,在Pyglet中有一個名為CompressedImageData的類,當您使用OpenGL進行渲染時,該類允許您使用GPU內置的紋理壓縮。 如果不是這樣,您可能會堅持在軟件中實現這些方法之一,因為PNG壓縮最不適合快速像素訪問。 在這里您可以找到有關GPU紋理壓縮的更多信息。
作為一種快速而骯臟的解決方法,您可以嘗試將圖像中的顏色數量減少到≤256,並使用調色板。 那將立即給您帶來4倍的內存優勢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.