Pregunta

Estoy usando pygame (1.9.0rc3, aunque esto también sucede en 1.8.1) para crear un mapa de calor. Para construir el mapa de calor, utilizo una pequeña, de 24 bits de imagen PNG 11x11px punto con un fondo blanco y un punto gris muy baja opacidad que se detiene exactamente en los bordes:

punto de imagen http://img442.imageshack.us/img442/465/dot.png

El área alrededor del punto blanco es perfecto, #ffffff, como debe ser. Sin embargo, cuando uso pygame a blit la imagen varias veces para una nueva superficie usando BLEND_MULT, aparece un cuadrado gris, como si el fondo del punto blanco no era perfecto, lo que no tiene sentido.

El siguiente código, además de las imágenes incluidas, puede reproducir este:

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')

Cuando se ejecuta el código, obtendrá la siguiente imagen:

imagen resultante después de la mezcla http://img263.imageshack.us/img263/4568/result.png

¿Hay alguna razón esto sucede? ¿Cómo puedo trabajar alrededor de ella?

¿Fue útil?

Solución

Después de probar todo, lo único que pude ver fue que usted es 100% correcto. La multiplicación por 255 da como resultado una resta de 1 - cada vez. Al final, he descargado el código fuente de pygame, y la respuesta es allí mismo, en 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 implementa de fusión Multiplicar como

new_val = old_dest * old_source / 256

y no, que sería la forma correcta, como

new_val = old_dest * old_source / 255

Esto se hizo probablemente con fines de optimización - un desplazamiento de bits es mucho más rápido que una división. A medida que la relación 255 / 256 está muy cerca de uno, la única diferencia que esto hace es un "apagado por uno": el valor que se obtiene es el valor esperado menos uno - a no ser que se esperaba cero, en cuyo caso el resultado es correcto <. / p>

Por lo tanto, usted tiene estas posibilidades:

  1. No haga caso de ella, porque el off-by-one no tiene importancia para la mayoría de los propósitos.
  2. Añadir 1 a todos los valores de los resultados. Más cercano al resultado esperado, excepto a perder el cero.
  3. Si la corrección general no es importante, pero hay que 255 * 255 == 255 (ya saben a qué me refiero), la operación lógica OR 1 en lugar de añadir basta, y es más rápido.

Tenga en cuenta que si usted no elige la respuesta 1, por razones de rendimiento es probable que tenga que escribir una extensión C en lugar de utilizar Python directamente.

Otros consejos

También encontrado con este problema en hacer mapas de calor y después de leer la respuesta de balpha, eligió para solucionarlo el "derecho" (si es más lento) camino. Modificar las diferentes

(s * d) >> 8

a

(s * d) / 255 

Esto requirió de parches funciones se multiplican en alphablit.c (aunque remendé surface.h también). No está seguro de lo mucho que esto afecta al rendimiento, pero para la aplicación específica (mapa de calor), produce imágenes mucho más bonita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top