Miscellaneous cleanup
- Remove old dither code from dither.py - Commit an old color-distance experiment
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Playing with measuring color distances
|
||||||
|
# Cleaned-up transcript from an ipython session, mostly experimental.
|
||||||
|
# The actual compression algorithm probably won't use this.
|
||||||
|
|
||||||
|
from dither import *
|
||||||
|
|
||||||
|
def distance(x, y):
|
||||||
|
return 2.5*((x[0]-y[0])/255)**2 + 4*((x[1]-y[1])/255)**2 + 2.5*((x[2]-y[2])/255)**2
|
||||||
|
|
||||||
|
distances = {(i,j): distance(PICO_RGB[i],PICO_RGB[j]) for i in range(len(PICO_RGB)) for j in range(len(PICO_RGB))}
|
||||||
|
|
||||||
|
def rect_distance_sum(img1, img2, xy1, xy2):
|
||||||
|
"""Returns summed color distance of two images, using a rectangular mask"""
|
||||||
|
result = 0.0
|
||||||
|
x1, y1 = xy1
|
||||||
|
x2, y2 = xy2
|
||||||
|
for y in range(y1, y2):
|
||||||
|
for x in range(x1, x2):
|
||||||
|
c1 = img1.getpixel((x, y))
|
||||||
|
c2 = img2.getpixel((x, y))
|
||||||
|
result += distances[(c1, c2)]
|
||||||
|
return result
|
||||||
|
|
||||||
|
# d = dithered version of resized (peacock image, RGB color)
|
||||||
|
d = pattern_dither(resized, PICO_RGB[:16], amount=1)
|
||||||
|
|
||||||
|
# s = nearest-color image
|
||||||
|
s = Image.new(size=d.size, mode='P', color=1)
|
||||||
|
s.putpalette([c for rgb in PICO_RGB[:16] for c in rgb])
|
||||||
|
|
||||||
|
def solid_cost(img, xy1, xy2, color):
|
||||||
|
"""Returns cost of approximating a rectangular region with a solid color"""
|
||||||
|
x1, y1 = xy1
|
||||||
|
x2, y2 = xy2
|
||||||
|
result = 0.0
|
||||||
|
for y in range(y1, y2):
|
||||||
|
for x in range(x1, x2):
|
||||||
|
p = img.getpixel((x, y))
|
||||||
|
result += distances[(color, p)]
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Downsample the dithered image with a given size of rectangles
|
||||||
|
skip = 2
|
||||||
|
for y in range(0, 128, skip):
|
||||||
|
for x in range(0, 128, skip):
|
||||||
|
_, i = min( (solid_cost(d, (x,y), (x+skip,y+skip), c), c) for c in range(16) )
|
||||||
|
for x2 in range(x, x + skip):
|
||||||
|
for y2 in range(y, y + skip):
|
||||||
|
s.putpixel((x2,y2), i)
|
||||||
|
# s.show()
|
||||||
@@ -108,38 +108,3 @@ def pattern_dither(img, palette, *, pat_size=4, amount=0.75):
|
|||||||
result.putpalette([c for rgb in old_palette for c in rgb])
|
result.putpalette([c for rgb in old_palette for c in rgb])
|
||||||
result.putdata([old_palette_indexes[i] for i in output_indexes])
|
result.putdata([old_palette_indexes[i] for i in output_indexes])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def dither_pixel(img, xy, pal):
|
|
||||||
global bayer
|
|
||||||
pal2 = [np.array(rgb_to_linear(c)) for c in pal]
|
|
||||||
counts = [0]*len(pal)
|
|
||||||
x, y = xy
|
|
||||||
def diff(c1, c2):
|
|
||||||
return sum((c1-c2)**2)
|
|
||||||
def nearest(rgb):
|
|
||||||
cost, index = min((diff(rgb,c), i) for i,c in enumerate(pal2))
|
|
||||||
return index
|
|
||||||
color = np.array(rgb_to_linear(img.getpixel(xy)))
|
|
||||||
err = np.array([0.0,0.0,0.0])
|
|
||||||
for _ in range(bayer.size):
|
|
||||||
err += color
|
|
||||||
i = nearest(err)
|
|
||||||
counts[i] += 1
|
|
||||||
err -= pal2[i]
|
|
||||||
thresh = bayer[y % bayer.shape[0]][x % bayer.shape[1]]
|
|
||||||
for i, count in enumerate(counts):
|
|
||||||
thresh -= count
|
|
||||||
if thresh < 0:
|
|
||||||
return i
|
|
||||||
|
|
||||||
dithered = Image.new('P', resized.size)
|
|
||||||
dithered.putpalette([x for rgb in PICO_RGB[:16] for x in rgb])
|
|
||||||
def do_it():
|
|
||||||
global dithered, resized
|
|
||||||
for x in tqdm(range(128)):
|
|
||||||
for y in range(128):
|
|
||||||
i = dither_pixel(resized, (x,y), PICO_RGB[:16])
|
|
||||||
dithered.putpixel((x,y), i)
|
|
||||||
# import cProfile
|
|
||||||
# cProfile.run('do_it()')
|
|
||||||
#do_it()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user