summaryrefslogtreecommitdiff
path: root/common/pixmap.py
diff options
context:
space:
mode:
Diffstat (limited to 'common/pixmap.py')
-rw-r--r--common/pixmap.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/common/pixmap.py b/common/pixmap.py
new file mode 100644
index 0000000..13142d5
--- /dev/null
+++ b/common/pixmap.py
@@ -0,0 +1,163 @@
+from __future__ import generators
+import cStringIO
+
+def decodepixmap(data):
+ f = cStringIO.StringIO(data)
+ sig = f.readline().strip()
+ assert sig == "P6"
+ while 1:
+ line = f.readline().strip()
+ if not line.startswith('#'):
+ break
+ wh = line.split()
+ w, h = map(int, wh)
+ sig = f.readline().strip()
+ assert sig == "255"
+ data = f.read()
+ f.close()
+ return w, h, data
+
+def encodepixmap(w, h, data):
+ return 'P6\n%d %d\n255\n%s' % (w, h, data)
+
+def cropimage((w, h, data), (x1, y1, w1, h1)):
+ assert 0 <= x1 <= x1+w1 <= w
+ assert 0 <= y1 <= y1+h1 <= h
+ scanline = w*3
+ lines = [data[p:p+w1*3]
+ for p in range(y1*scanline + x1*3,
+ (y1+h1)*scanline + x1*3,
+ scanline)]
+ return w1, h1, ''.join(lines)
+
+def vflip(w, h, data):
+ scanline = w*3
+ lines = [data[p:p+scanline] for p in range(0, len(data), scanline)]
+ lines.reverse()
+ return ''.join(lines)
+
+def hflip(w, h, data):
+ scanline = w*3
+ lines = [''.join([data[p:p+3] for p in range(p1+scanline-3, p1-3, -3)])
+ for p1 in range(0, len(data), scanline)]
+ return ''.join(lines)
+
+def rotate_cw(w, h, data):
+ scanline = w*3
+ lastline = len(data) - scanline
+ lines = [''.join([data[p:p+3] for p in range(lastline + p1, -1, -scanline)])
+ for p1 in range(0, scanline, 3)]
+ return ''.join(lines)
+
+def rotate_ccw(w, h, data):
+ scanline = w*3
+ lines = [''.join([data[p:p+3] for p in range(p1, len(data), scanline)])
+ for p1 in range(scanline-3, -3, -3)]
+ return ''.join(lines)
+
+def rotate_180(w, h, data):
+ scanline = w*3
+ lines = [''.join([data[p:p+3] for p in range(p1+scanline-3, p1-3, -3)])
+ for p1 in range(0, len(data), scanline)]
+ lines.reverse()
+ return ''.join(lines)
+
+def makebkgnd(w, h, data):
+ scanline = 3*w
+ result = []
+ for position in range(0, scanline*h, scanline):
+ line = []
+ for p in range(position, position+scanline, 3):
+ line.append(2 * (chr(ord(data[p ]) >> 3) +
+ chr(ord(data[p+1]) >> 3) +
+ chr(ord(data[p+2]) >> 3)))
+ line = ''.join(line)
+ result.append(line)
+ result.append(line)
+ return w*2, h*2, ''.join(result)
+
+translation_darker = ('\x00\x01' + '\x00'*126 +
+ ''.join([chr(n//4) for n in range(0,128)]))
+translation_dragon = translation_darker[:255] + '\xC0'
+
+def make_dark((w, h, data), translation):
+ return w, h, data.translate(translation)
+
+def col((r, g, b)):
+ r = ord(r)
+ g = ord(g)
+ b = ord(b)
+ return ((g>>2 + r>>3) << 24) | (b << 16) | (g << 8) | r
+
+def imagezoomer(w, h, data):
+ "Zoom a cartoon image by a factor of three, progressively."
+ scale = 3
+ scanline = 3*w
+ rw = (w-1)*scale+1
+ rh = (h-1)*scale+1
+ pixels = []
+ colcache = {}
+ revcache = {}
+ for base in range(0, scanline*h, scanline):
+ line = []
+ for x in range(w):
+ key = data[base + 3*x : base + 3*(x+1)]
+ try:
+ c = colcache[key]
+ except KeyError:
+ c = colcache[key] = col(key)
+ revcache[c] = key
+ line.append(c)
+ pixels.append(line)
+ yield None
+
+ Pairs = {
+ (0, 0): [(0, 0, 0, 0),
+ (-1,0, 1, 0),
+ (0,-1, 0, 1)],
+ (1, 0): [(0, 0, 1, 0),
+ (0, 1, 1,-1),
+ (0,-1, 1, 1)],
+ (2, 0): [(0, 0, 1, 0),
+ (0, 1, 1,-1),
+ (0,-1, 1, 1)],
+ (0, 1): [(0, 0, 0, 1),
+ (-1,0, 1, 1),
+ (1, 0,-1, 1)],
+ (1, 1): [(0, 0, 1, 1),
+ (0, 1, 1, -1),
+ (1, 0,-1, 1)],
+ (2, 1): [(1, 0, 0, 1),
+ (0,-1, 1, 1),
+ (0, 0, 2, 1)],
+ (0, 2): [(0, 0, 0, 1),
+ (-1,0, 1, 1),
+ (1, 0,-1, 1)],
+ (1, 2): [(0, 1, 1, 0),
+ (-1,0, 1, 1),
+ (0, 0, 1, 2)],
+ (2, 2): [(0, 0, 1, 1),
+ (0, 1, 2, 0),
+ (1, 0, 0, 2)],
+ }
+ result = []
+ for y in range(rh):
+ yield None
+ for x in range(rw):
+ # ______________________________
+
+ i = x//scale
+ j = y//scale
+ ps = []
+ for dx1, dy1, dx2, dy2 in Pairs[x%scale, y%scale]:
+ if (0 <= i+dx1 < w and 0 <= i+dx2 < w and
+ 0 <= j+dy1 < h and 0 <= j+dy2 < h):
+ p1 = pixels[j+dy1][i+dx1]
+ p2 = pixels[j+dy2][i+dx2]
+ ps.append(max(p1, p2))
+ p1 = min(ps)
+
+ # ______________________________
+ result.append(revcache[p1])
+ data = ''.join(result)
+ yield (rw, rh, data)