changeset 5:a74776d80f95

Fix a bug in selecting the best match color when an exact match is unavailable. Add some more options for choosing a line palette
author Mike Pavone <pavone@retrodev.com>
date Tue, 03 Sep 2013 09:36:29 -0700
parents 1a7cac91f890
children 3148b6389042
files img2tiles.py
diffstat 1 files changed, 67 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- 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)