Add a blend_add transform
[naja.git] / naja / resources / mutators.py
1 '''Mutations to apply to images'''
2
3 from pygame.transform import flip, rotate, scale
4
5 from naja.constants import EIGHT_BIT_SCALE
6
7 from pygame import surface
8 import pygame.locals as pgl
9
10
11 class Mutator(object):
12     def __init__(self, func, *args):
13         self._func = func
14         self._args = tuple(args)
15
16     def __call__(self, image):
17         return self._func(image, *self._args)
18
19     def __hash__(self):
20         return hash((self._func, self._args))
21
22     def __eq__(self, other):
23         if not isinstance(other, Mutator):
24             return NotImplemented
25         return (self._func == other._func) and (self._args == other._args)
26
27     def __repr__(self):
28         return '<%s %r>' % (self.__class__.__name__, self._args)
29
30
31 def rotator(angle):
32     return Mutator(rotate, angle)
33
34
35 def scaler(size):
36     return Mutator(scale, size)
37
38
39 def scale_multiplier(image, factor):
40     size = image.get_width() * factor, image.get_height() * factor
41     return scale(image, size)
42
43
44 def blend_add(image, colour):
45     """Overlay the image with the given colour using BLEND_ADD"""
46     blend = surface.Surface(image.get_size())
47     blend.fill(colour)
48     # We return a copy
49     blended_image = image.copy()
50     blended_image.blit(blend, (0, 0), special_flags=pgl.BLEND_ADD)
51     return blended_image
52
53
54 def blender(colour):
55     return Mutator(blend_add, tuple(colour))
56
57
58 # Identity mutator
59 NULL = Mutator(lambda x: x)
60
61 # Rotation
62 R90 = rotator(90)
63 R180 = rotator(180)
64 R270 = rotator(-90)
65
66 FLIP_H = Mutator(flip, True, False)
67 FLIP_V = Mutator(flip, False, True)
68
69 EIGHT_BIT = Mutator(scale_multiplier, EIGHT_BIT_SCALE)