itertoolとかmapとかzipとかを使って。
P98 リスト4-1 すべての色を含む画像の生成(allcolors.py)
元のコード。三重ループなのでネストが深くなってしまっている。
import pygame from itertools import product pygame.init() screen = pygame.display.set_mode((640, 480)) all_colors = pygame.Surface((4096, 4096), depth=24) for r in xrange(256): print r+1, "out of 256" x = (r&15)*256 y = (r>>4)*256 for g in xrange(256): for b in xrange(256): all_colors.set_at((x+g, y+b), (r, g, b)) pygame.image.save(all_colors, "all_colors.bmp")
itertool.productを利用すると一段で記述できる。r,g,bという変数の並びを見るだけでそれなりに気分がいい。
import pygame from itertools import product pygame.init() screen = pygame.display.set_mode((640, 480)) all_colors = pygame.Surface((4096, 4096), depth=24) rng = xrange(256) for r, g, b in product(rng, rng, rng): print r+1, "out of 256" x = (r&15)*256 y = (r>>4)*256 all_colors.set_at((x+g, y+b), (r, g, b)) pygame.image.save(all_colors, "all_colors.bmp")
P102 リスト4-3 色をスケーリングするための関数
元のコードは丁寧にcolorを三色の一時変数に分配して、それぞれ計算を行ったあと集約し直している。
def scale_color(color, scale): red, green, blue = color red = int(red*scale) green = int(green*scale) blue = int(blue*scale) return red, green, blue
mapとlambdaを組み合わせると一行で書き直せる。mapの返り値はlistになるのね。tupleあまり使わないから不明な点が多い。
def scale_color(color, scale): return tuple(map(lambda x: int(x*scale), color)) fireball_orange = (221, 99, 20) print scale_color(fireball_orange, .5) # => (110, 49, 10)
saturate_colorについても同様。
def saturate_color(color): return tuple(map(lambda x: min(x, 255), color)) print saturate_color((442, 198, 40)) # => (255, 198, 40)
P104 リスト4-6 線形補間による色のブレンディング
元のコード(一部)。
def blend_color(color1, color2, blend_factor): red1, green1, blue1 = color1 red2, green2, blue2 = color2 red = red1 + (red2 - red1)*blend_factor green = green1 + (green2 - green1)*blend_factor blue = blue1 + (blue2 - blue1)*blend_factor return int(red), int(green), int(blue)
一行で書くと、zip関数を使って次のようになる。
def blend_color(color1, color2, blend_factor): return tuple(map(lambda x: int(x[0]+(x[1]-x[0])*blend_factor), zip(color1, color2)))
と言いたいところだが、これは横に長すぎる(88文字)。一行80文字以下というPythonのコーディングスタイルに反するため、適当に分割する。
def blend_color(color1, color2, blend_factor): blend = lambda x: int(x[0] + (x[1] - x[0])*blend_factor) return tuple(map(blend, zip(color1, color2)))