blob: 166ed3606b380be20a898118e218cfa3a5e1cea6 [file] [log] [blame]
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from numpy import linspace
from collections import namedtuple
Color = namedtuple('Color', ['r', 'g', 'b'])
WHITE = Color(255, 255, 255)
BLACK = Color(0, 0, 0)
RED = Color(255, 0, 0)
GREEN = Color(0, 255, 0)
BLUE = Color(0, 0, 255)
MAGENTA = Color(255, 0, 255)
CYAN = Color(0, 255, 255)
YELLOW = Color(128, 128, 0)
PPM_MAGIC_NUMBER = 'P3'
BIT_DEPTH = 255
LINE_NUM_STEPS = 1000
class Image:
""" A simple PPM image manipulation class
A ppm image is a simple, ascii human readable image format. This class
allows you to create an image, draw simple shapes on it or access the
idividual pixels and save the resulting picture to the hard drive.
http://en.wikipedia.org/wiki/Netpbm_format
"""
def __init__(self, width, height):
self.width = int(width)
self.height = int(height)
self.pixels = [[WHITE] * self.height for i in range(self.width)]
def Save(self, filename):
with open(filename, 'w') as fo:
fo.write('%s\n' % PPM_MAGIC_NUMBER)
fo.write('%d %d\n' % (self.width, self.height))
fo.write('%d\n' % BIT_DEPTH)
for y in range(self.height):
for x in range(self.width):
fo.write('%d %d %d ' % self[x, y])
fo.write('\n')
def Circle(self, coords, color, radius=4):
x, y = coords
x = int(x)
y = int(y)
r_sq = radius ** 2
for x1 in range(x - radius, x + radius):
for y1 in range(y - radius, y + radius):
d_sq = (x - x1) ** 2 + (y - y1) ** 2
if d_sq <= r_sq:
self[(x1, y1)] = color
def Line(self, coord1, coord2, color):
""" Use Bresenham's line algorithm to connect coord1 and coord2 """
x1, y1 = coord1
x1 = int(x1)
y1 = int(y1)
x2, y2 = coord2
x2 = int(x2)
y2 = int(y2)
is_steep = abs(y2-y1) > abs(x2-x1)
if is_steep:
x1, y1 = y1, x1
x2, y2 = y2, x2
if x1 > x2:
x1, x2 = x2, x1
y1, y2 = y2, y1
dx = x2 - x1
dy = abs(y2 - y1)
ystep = 1 if y1 < y2 else -1
error = int(dx / 2)
y = y1
for x in range(x1, x2 + 1):
self[(x, y) if not is_steep else (y, x)] = color
error -= dy
if error < 0:
y += ystep
error += dx
def __getitem__(self, coords):
x, y = coords
if x >= 0 and x < self.width and y >= 0 and y < self.height:
return self.pixels[int(x)][int(y)]
else:
return None
def __setitem__(self, coords, color):
x, y = coords
if x >= 0 and x < self.width and y >= 0 and y < self.height:
self.pixels[int(x)][int(y)] = color