Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pygame和blitting:白色对白色=灰色?_Python_Image_Pygame_Imaging - Fatal编程技术网

Python Pygame和blitting:白色对白色=灰色?

Python Pygame和blitting:白色对白色=灰色?,python,image,pygame,imaging,Python,Image,Pygame,Imaging,我正在使用pygame(1.9.0rc3,尽管这也发生在1.8.1中)创建热图。为了构建热图,我使用了一个24位的11x11px点PNG小图像,背景为白色,不透明度非常低的灰点正好停在边缘: 圆点周围的区域应该是完美的白色,#ffffff。但是,当我使用pygame使用BLEND_MULT将图像多次blit到一个新曲面时,会出现一个灰色的正方形,好像点背景不是完美的白色,这是没有意义的 以下代码,加上附带的图像,可以重现这一点: import os import numpy import py

我正在使用pygame(1.9.0rc3,尽管这也发生在1.8.1中)创建热图。为了构建热图,我使用了一个24位的11x11px点PNG小图像,背景为白色,不透明度非常低的灰点正好停在边缘:

圆点周围的区域应该是完美的白色,#ffffff。但是,当我使用pygame使用BLEND_MULT将图像多次blit到一个新曲面时,会出现一个灰色的正方形,好像点背景不是完美的白色,这是没有意义的

以下代码,加上附带的图像,可以重现这一点:

import os
import numpy
import pygame

os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.display.init()
pygame.display.set_mode((1,1), 0, 32)

dot_image = pygame.image.load('dot.png').convert_alpha()

surf = pygame.Surface((100, 100), 0, 32)
surf.fill((255, 255, 255))
surf = surf.convert_alpha()

for i in range(50):
    surf.blit(dot_image, (20, 40), None, pygame.BLEND_MULT)    

for i in range(100):
    surf.blit(dot_image, (60, 40), None, pygame.BLEND_MULT)      

pygame.image.save(surf, 'result.png')
运行代码时,您将看到以下图像:


这有什么原因吗?我怎样才能解决这个问题呢?

试过之后,我唯一能看到的是你是100%正确的。乘255的结果是每次减1。最后,我下载了pygame源代码,答案就在那里,在
surface.h

#define BLEND_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \
    dR = (dR && sR) ? (dR * sR) >> 8 : 0;          \
    dG = (dG && sG) ? (dG * sG) >> 8 : 0;          \
    dB = (dB && sB) ? (dB * sB) >> 8 : 0;
Pygame实现了多重混合

new_val = old_dest * old_source / 256
而不是,这才是正确的方法,就像

new_val = old_dest * old_source / 255
这可能是出于优化目的——位移位比除法快得多。由于比率
255/256
非常接近1,因此唯一的区别是“off by 1”:得到的值是期望值减去1——除非期望值为零,在这种情况下,结果是正确的

所以,你有这些可能性:

  • 忽略它,因为在大多数情况下,按一关闭并不重要
  • 1
    添加到所有结果值。最接近预期结果,但丢失零
  • 如果总体正确性并不重要,但您需要
    255*255==255
    (您知道我的意思),则ORing
    1
    而不是添加足够的内容,而且速度更快

  • 请注意,如果您不选择答案1,出于性能原因,您可能必须编写一个C扩展,而不是直接使用Python。

    在制作热图时也遇到了这个问题,在阅读了balpha的答案后,选择了“正确”(如果较慢)的方法来修复它。改变各种

    (s * d) >> 8
    


    这需要在
    alphablit.c
    中修补乘法函数(尽管我也修补了
    surface.h
    )。不确定这对性能有多大影响,但对于特定的(热图)应用程序,它会生成更漂亮的图像。

    不只是两分钟前,我才意识到同样的事情(它是“关闭一”),但我无法在pygame源代码中找到计算的位置。由于此错误在乘以255*255时会产生巨大的差异(我确实需要它用于热图),因此如何实现选项#3?我对C一点也不熟悉,所以如果你能给我指出实现的正确方向,你可能会让我保持理智(或者说,现在还剩下什么)。性能和简单性之间的最佳折衷可能是通过在结果上添加一个all-(1,1,1)曲面来实现#2。但是,如果您想深入研究C扩展,可以先看看cython,它是C-Python-Hybrid:。请注意,我自己在这方面没有太多经验。而且,如果这在您的情况下是可行的,您可能只是更改并重新编译pygame本身。但是,这会使分发程序变得更加困难,因为最终会得到一个非标准版本的pygame。我刚刚在surface.h中的结果中添加了1,并重新编译了自己——效果非常好!因为我不会分发应用程序,所以应该不会有问题。再次感谢
    (s * d) / 255