需要帮助来理解surfarray.array2d - 它似乎无法正确保存颜色

时间:2017-06-07 10:09:57

标签: python pygame

我做了一个测试,我将Surface转换为array2d,然后将其转换回来,如下所示:

fg = pygame.surfarray.make_surface(pygame.surfarray.array2d(fg))

这是完整的代码(如果您愿意,可以复制并粘贴到Pygame中进行快速测试):

pygame.init()


SURFACE_MAIN = pygame.display.set_mode((300, 300))
fg = pygame.Surface((300, 300))
fg.fill((70, 53, 52))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_s:
                fg = pygame.surfarray.make_surface(pygame.surfarray.array2d(fg))

    SURFACE_MAIN.blit(pygame.Surface.copy(fg), (0, 0))
    pygame.display.update()

当您按 s 键时,原始棕色变为绿色。

旧颜色:(70,53,52,255)
新颜色:(85,182,0,255)

对此的解决方案原来是使用array3d,但我不明白为什么会这样。有人可以向我解释一下吗?非常感谢!

参考:https://www.pygame.org/docs/ref/surfarray.html#pygame.surfarray.array2d

1 个答案:

答案 0 :(得分:3)

函数pygame.surfarray.make_surface将2D阵列转换为位深度为8的表面,将3D阵列转换为位深度为32的表面。这很重要,因为pygame处理位深度。

位深度

位深度是表示颜色的信息量。 32位深度允许我们表示2^32 = 4,294,967,296颜色,这与分配每个颜色分量(红色,绿色,蓝色,Alpha)8位(0-255之间的值)相同。

8位深度允许我们表示2^8 = 256颜色。对于每个颜色分量,这将是2比特(0-3之间的值)。然而,这并不是pygame如何处理这个位深度的颜色。

pygame如何处理它

Pygame不存储RGBA的每个值,而是将像素存储为单个整数,只要位深度大于8,就可以对其进行解码以获取颜色分量的值。位深度pygame使用表面的调色板。现在,每个像素值成为具有256色的调色板的索引,而不是编码的整数。此调色板可通过surface.get_palette()方法获得,并可使用surface.set_palette()进行设置。

这种转换会让你的颜色值变得怪异。这是一个简短的程序,用于演示和试验(使用控制台,通过键入以逗号和/或空格分隔的值,以32位深度和颜色开始):

import pygame
pygame.init()

screen = pygame.display.set_mode((1, 1))

depth = int(input('\nDepth size: '))
color = [int(x) for x in input('Color: ').replace(',', ' ').split()]

surface = pygame.Surface((1, 1), depth=depth)  # Valid bit depth sizes are 8, 12, 16, 24 or 32
surface.fill(color)
print('\nSurface 1 has bit depth', surface.get_bitsize(), ' | The color is: ', surface.get_at((0, 0)))

surface2 = pygame.surfarray.make_surface(pygame.surfarray.array2d(surface))
print('\nSurface 2 has bit depth', surface2.get_bitsize(), ' | The color is: ', surface2.get_at((0, 0)))
surface2.set_palette([(123, 123, 123) for _ in range(256)])  # Set whole color palette to one color
print('Surface 2 now has the color: ', surface2.get_at((0, 0)))

surface3 = pygame.surfarray.make_surface(pygame.surfarray.array3d(surface))
print('\nSurface 3 has bit depth', surface3.get_bitsize(), ' | The color is: ', surface3.get_at((0, 0)))
print('Surface 3 has no color palette since it has a bit depth greater than 8')