# HG changeset patch # User Mike Pavone # Date 1378226189 25200 # Node ID a74776d80f95259567c24b58dadfe76e6aee5cf0 # Parent 1a7cac91f890c7c79e721602dcf1f11ccf2d2ee0 Fix a bug in selecting the best match color when an exact match is unavailable. Add some more options for choosing a line palette diff -r 1a7cac91f890 -r a74776d80f95 img2tiles.py --- a/img2tiles.py Tue Sep 03 09:35:33 2013 -0700 +++ b/img2tiles.py Tue Sep 03 09:36:29 2013 -0700 @@ -27,6 +27,49 @@ glist.reverse() return glist +def get_color_info_error(pixels, rng, threshold, exclude={}): + gencolors = {} + A = 255 + for idx in rng: + color = pixels[idx] + if len(color) == 4: + (R, G, B, A) = color + else: + (R, G, B) = color + if A > threshold: + gcolor = (gchannel(R), gchannel(G), gchannel(B)) + if not gcolor in exclude: + if not gcolor in gencolors: + _,best = best_match(gcolor, (exclude,)) + gencolors[gcolor] = color_dist(gcolor, best) + glist = [(gencolors[color], color) for color in gencolors] + glist.sort() + glist.reverse() + return glist + +def get_color_info_both(pixels, rng, threshold, exclude={}): + gencolors = {} + A = 255 + for idx in rng: + color = pixels[idx] + if len(color) == 4: + (R, G, B, A) = color + else: + (R, G, B) = color + if A > threshold: + gcolor = (gchannel(R), gchannel(G), gchannel(B)) + if not gcolor in exclude: + if not gcolor in gencolors: + _,best = best_match(gcolor, (exclude,)) + gencolors[gcolor] = (color_dist(gcolor, best), 1) + else: + (dist, count) = gencolors[gcolor] + gencolors[gcolor] = (dist, count+1) + glist = [(gencolors[color][0] * gencolors[color][1], color) for color in gencolors] + glist.sort() + glist.reverse() + return glist + def totiles(im, palette): pass @@ -34,19 +77,24 @@ pixels = im.getdata() (width, height) = im.size colors = get_color_info(pixels, xrange(0, height * width), trans_thresh) + print len(colors), 'distinct 9-bit colors in image' glob_pal = {} + print 'Static Palette:' for idx in xrange(0, min(max_global, len(colors))): (count, color) = colors[idx] + print str(idx) + ':', color, '(used', count, 'times)' glob_pal[color] = idx line_pals = [] if max_global < len(colors): for line in xrange(0, height): linestart = line * width - linecolors = get_color_info(pixels, xrange(linestart, linestart+width), trans_thresh, glob_pal) + #linecolors = get_color_info(pixels, xrange(linestart, linestart+width), trans_thresh, glob_pal) + #linecolors = get_color_info_error(pixels, xrange(linestart, linestart+width), trans_thresh, glob_pal) + linecolors = get_color_info_both(pixels, xrange(linestart, linestart+width), trans_thresh, glob_pal) line_pal = {} for idx in xrange(0, min(max_line, len(linecolors))): (count, color) = linecolors[idx] - line_pal[color] = idx + line_pal[color] = idx + max_global line_pals.append(line_pal) return (glob_pal, line_pals, max_global, max_line) @@ -55,6 +103,20 @@ (rb, gb, bb) = b return (ra-rb)**2 + (ga-gb)**2 + (ba-bb)**2 +def best_match(gpixel, pals): + bestdist = color_dist((0,0,0), (15, 15, 15)) + bestpalidx = 0 + bestcolor = (0,0,0) + for i in xrange(0, len(pals)): + pal = pals[i] + for cur in pal: + curdist = color_dist(gpixel, cur) + if curdist < bestdist: + bestdist = curdist + bestpalidx = pal[cur] + bestcolor = cur + return (bestpalidx, bestcolor) + def trans_image(im, trans_thresh, pal): (global_pal, line_pals, _, _) = pal pixels = im.getdata() @@ -79,20 +141,9 @@ if gpixel in global_pal: gpixels.append(global_pal[gpixel]) elif gpixel in line_pals[y]: - gpixels.append(line_pals[y][gpixel] + len(global_pal)) + gpixels.append(line_pals[y][gpixel]) else: - bestdist = color_dist((0,0,0), (15, 15, 15)) - bestpal = 0 - for cur in global_pal: - curdist = color_dist(gpixel, cur) - if curdist < bestdist: - bestdist = curdist - bestpal = global_pal[cur] - for cur in line_pals[y]: - curdist = color_dist(gpixel, cur) - if curdist < bestdist: - bestdist = curdist - bestpal = line_pals[y][cur] + bestpal,color = best_match(gpixel, (global_pal, line_pals[y])) gpixels.append(bestpal) else: gpixels.append(0) @@ -148,7 +199,7 @@ for line in line_pals: pal_list = [(0, 0, 0)] * max_line for entry in line: - pal_list[line[entry]] = entry + pal_list[line[entry]-max_global] = entry for entry in pal_list: (R, G, B) = entry tiles.append(B)