Original Post
So I am trying to create a script that will do custom dithering while applying a palette. Basically, I want to make sure that errors do not bleed across any 32x32 boundary. Here is the code I came up with. Unfortunately, it looks very messy and inelegant. In my experience, using lots of nested loops in a Python program means you're doing something wrong, but I can't figure out any ways to do it better. So how can I improve this code?
[source lang='python']
def applyPaletteDither(pixels, pal):
def closest_ind(pt):
return ((pal - pt)**2).sum(1).argmin()
h,w,ch = pixels.shape
vals = np.empty((h,w), dtype=int)
size = 32
for ty in xrange(0, pixels.shape[0], size):
for tx in xrange(0, pixels.shape[1], size):
errs = np.zeros((size,size,ch))
for r in xrange(size):
for c in xrange(size):
#FSD weights: [7,3,5,1]/16
px = pixels[ty+r,tx+c] + errs[r,c]/16
ind = closest_ind(px)
vals[ty+r,tx+c] = ind
err = px - pal[ind]
if c errs[r,c+1] += err*7
if r if c>0:
errs[r+1,c-1] += err*3
errs[r+1,c] += err*5
if c errs[r+1,c+1] += err
assert(max(vals.flat[:9]) <= len(pal)) #sanity check
return vals[/source]
[source lang='python']
def applyPaletteDither(pixels, pal):
def closest_ind(pt):
return ((pal - pt)**2).sum(1).argmin()
h,w,ch = pixels.shape
vals = np.empty((h,w), dtype=int)
size = 32
for ty in xrange(0, pixels.shape[0], size):
for tx in xrange(0, pixels.shape[1], size):
errs = np.zeros((size,size,ch))
for r in xrange(size):
for c in xrange(size):
#FSD weights: [7,3,5,1]/16
px = pixels[ty+r,tx+c] + errs[r,c]/16
ind = closest_ind(px)
vals[ty+r,tx+c] = ind
err = px - pal[ind]
if c
if r
errs[r+1,c-1] += err*3
errs[r+1,c] += err*5
if c
assert(max(vals.flat[:9]) <= len(pal)) #sanity check
return vals[/source]