You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.1 KiB
Python
92 lines
2.1 KiB
Python
from collections import namedtuple
|
|
|
|
class Pixel(namedtuple('Pixel', ['r', 'g', 'b'])):
|
|
def _verify(self):
|
|
if max(self.r, self.g, self.b) > 255:
|
|
raise ValueError('Some component too bright.')
|
|
if min(self.r, self.g, self.b) < 0:
|
|
raise ValueError('Some component negative.')
|
|
def __add__(self, other):
|
|
return Pixel(
|
|
self.r + other.r,
|
|
self.g + other.g,
|
|
self.b + other.b,
|
|
)
|
|
def __mul__(self, other):
|
|
if not isinstance(other, int) or not isinstance(other, float):
|
|
raise ValueError('Can only multiply by number')
|
|
return Pixel(
|
|
other*pixel.r,
|
|
other*pixel.g,
|
|
other*pixel.b,
|
|
)
|
|
|
|
def weighted_average(p1, w1, p2, w2):
|
|
too_big = w1*p1 + w2*p2
|
|
coef = 1/(w1+w2)
|
|
return coef * too_big
|
|
|
|
class Picture:
|
|
def __init__(self, data):
|
|
self.pixels = data
|
|
self.w = len(data[0])
|
|
self.h = len(data)
|
|
|
|
@classmethod
|
|
def load(cls, filename):
|
|
from PIL import Image
|
|
im = Image.open(filename)
|
|
im = im.convert('RGB')
|
|
ht = im.height
|
|
wt = im.width
|
|
data = []
|
|
access = im.getdata().pixel_access()
|
|
for y in range(ht):
|
|
line = []
|
|
for x in range(wt):
|
|
line.append(Pixel(*(access[x, y])))
|
|
data.append(line)
|
|
|
|
result = cls(data)
|
|
assert result.w == wt
|
|
assert result.h == ht
|
|
return result
|
|
|
|
def _to_pil(self):
|
|
# Create int iterable
|
|
# TODO: If this is slow, we should use a generator.
|
|
seq = []
|
|
for line in self.pixels:
|
|
for pix in line:
|
|
seq.extend(pix)
|
|
|
|
# bytes…
|
|
b = bytes(seq)
|
|
|
|
# PIL image
|
|
from PIL import Image
|
|
img = Image.frombytes('RGB', (self.w, self.h), b)
|
|
return img
|
|
|
|
def show(self):
|
|
img = self._to_pil()
|
|
img.show()
|
|
|
|
def save(self, filename):
|
|
img = self._to_pil()
|
|
img.save(filename)
|
|
|
|
class Interpolator:
|
|
def interpolate(self, picture, new_h, new_w):
|
|
quantum_x = new_w / picture.w
|
|
quantum_y = new_h / picture.h
|
|
result = [[None for _ in range(new_w)] for _ in range(new_h)]
|
|
for x in range(new_w):
|
|
for y in range(new_h):
|
|
result[y][x] = self.get_pixel(picture, x, y, result, quantum_x, quantum_y)
|
|
return Picture(result)
|
|
|
|
|
|
def get_pixel(self, picture, x, y, result, quantum_x, quantum_y):
|
|
raise NotImplementedError('You write this :-)')
|