2009-07-21 13 views
5

ヒートマップを作成するには、私はpygame(1.9.0rc3、これは1.8.1でも起こりますが)を使用しています。ドットの周囲の領域パイゲームとブリッティング:白い白い=灰色?

Dot image http://img442.imageshack.us/img442/465/dot.png

:ヒートマップを構築するために、私は白い背景と正確エッジで停止する非常に低不透明グレードットのドットPNG画像11x11px小、24ビットを使用します#ffffffのように完璧な白です。しかし、BLEND_MULTを使用してpygameを使ってイメージを複数回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') 

を:

Resulting image after blending http://img263.imageshack.us/img263/4568/result.png

することは、この理由があります起こる?どのように私はそれを回避することができますか?

答えて

6

私が見ることのできる唯一のことは、あなたが100%正しいということでした。 255を掛けると、毎回1が減算されます。最後に、surface.hに、私はpygameのソースコードをダウンロードして、答えはすぐそこです:

#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 

はなく、

として、 as

new_val = old_dest * old_source/255 

これはおそらく最適化のために行われます。ビットシフトは除算よりもはるかに高速です。比率255/256が1に非常に近いので、これは「オフ・バイ・ワン」になります。得られる値は期待値から1を引いた値です。ただし、ゼロを期待した場合を除き、結果は正しいです。

だから、あなたはこれらの可能性があります。

  1. をオフすることにより-1は、ほとんどの目的のために重要ではありませんので、それを無視します。
  2. すべての結果値に1を追加します。あなたがゼロを失うことを除いて、期待される結果に最も近い。
  3. 全体的な正しさは重要ではありませんが、あなたは追加で足りるのではなく、1を論理和、(あなたは私が何を意味するか知っている)255 * 255 == 255を必要とし、速い場合。

Answer 1を選択しなかった場合、パフォーマンス上の理由から、Pythonを直接使用するのではなく、C拡張を記述する必要があることに注意してください。

+0

2分前に私は同じことを実現しましたが(それは "1つだけ"外れています)、計算の場所がパイゲームソースのどこにあるのかわかりませんでした。 ヒートマップに255 * 255を掛けたときにこのエラーが大きく異なるため、オプション3を実装するにはどうすればよいですか?私はCに精通していないので、実装で正しい方向に向けることができれば、あなたはおそらく私の正気(または今のところ残っているもの)を節約するでしょう。 –

+0

パフォーマンスとシンプルさの最適な妥協点は、結果にオール(1,1,1)サーフェスをADDブリッジすることによって、おそらく#2を実装することです。しかし、Cの拡張を掘り下げたい場合は、C-Pythonハイブリッドであるcython(http://www.cython.org)を見てみるとよいでしょう。私は自分自身がその分野で多くの経験を持っていないことに注意してください。 – balpha

+0

また、これが可能な場合は、pygame自体を変更して再コンパイルするだけかもしれません。しかし、それはpygameの非標準版で終わるので、あなたのプログラムの配布をより困難にするでしょう。 – balpha

1

はまた、この問題は、ヒートマップをやって発生したbalphaの答えを読んだ後、「右」(遅くなる場合)の方法、それを修正することを選びました。様々な

(s * d) >> 8 

(私もsurface.hにパッチを当てても)これはalphablit.cで乗算機能にパッチを当てる必要

(s * d)/255 

に変更してください。これがパフォーマンスにどれだけ影響を与えるかはわかりませんが、特定の(ヒートマップ)アプリケーションの場合、よりきれいな画像が生成されます。

関連する問題