shithub: pokecrystal

Download patch

ref: ee36bd9342cce0e728431428b91d6f2074db2f21
parent: ec1fe073a341a796cf7e3125ef95280c615a5eb8
author: Rangi <[email protected]>
date: Mon Mar 15 12:47:35 EDT 2021

Add tools/palfix.py, and make Python tools executable

--- /dev/null
+++ b/tools/palfix.py
@@ -1,0 +1,62 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function
+
+import sys
+from pokemontools import png
+
+def rgb8_to_rgb5(c):
+	r, g, b = c
+	return (r // 8, g // 8, b // 8)
+
+def rgb5_to_rgb8(c):
+	r, g, b = c
+	return ((r * 8) | (r // 4), (g * 8) | (g // 4), (b * 8) | (b // 4))
+
+def invert(c):
+	r, g, b = c
+	return (31 - r, 31 - g, 31 - b)
+
+def luminance(c):
+	r, g, b = c
+	return (0.299 * r**2 + 0.587 * g**2 + 0.114 * b**2)**0.5
+
+def rgb5_pixels(row):
+	for x in range(0, len(row), 4):
+		yield rgb8_to_rgb5(row[x:x+3])
+
+def fix_pal(filename):
+	with open(filename, 'rb') as file:
+		width, height, data = png.Reader(file).asRGBA8()[:3]
+		data = list(data)
+	b_and_w = {(0, 0, 0), (31, 31, 31)}
+	colors = set(c for row in data for c in rgb5_pixels(row)) - b_and_w
+	if not colors:
+		colors = {(20, 20, 20), (10, 10, 10)}
+	elif len(colors) == 1:
+		c = colors.pop()
+		colors = {c, invert(c)}
+	elif len(colors) != 2:
+		return False
+	palette = tuple(sorted(colors | b_and_w, key=luminance, reverse=True))
+	assert len(palette) == 4
+	data = [list(map(palette.index, rgb5_pixels(row))) for row in data]
+	palette = tuple(map(rgb5_to_rgb8, palette))
+	writer = png.Writer(width, height, palette=palette, compression=9)
+	with open(filename, 'wb') as file:
+		writer.write(file, data)
+	return True
+
+def main():
+	if len(sys.argv) < 2:
+		print('Usage: %s pic.png' % sys.argv[0], file=sys.stderr)
+		sys.exit(1)
+	for filename in sys.argv[1:]:
+		if not filename.lower().endswith('.png'):
+			print(filename, 'is not a .png file!', file=sys.stderr)
+		elif not fix_pal(filename):
+			print(filename, 'has too many colors!', file=sys.stderr)
+
+if __name__ == '__main__':
+	main()