Refactor TeamColorizer into a Python library (#7604)

* Refactor TeamColorizer into a Python library

* Use TeamColorizer as library
This commit is contained in:
Slayer95 2023-05-07 16:54:18 -05:00 committed by GitHub
parent f7fadba928
commit eded720ee2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 117 additions and 98 deletions

93
data/tools/TeamColorizer Normal file
View file

@ -0,0 +1,93 @@
#!/usr/bin/env python3
import sys, argparse
from unit_tree.team_colorizer import colorize
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="""Map the magenta team-color patches in the input image to red (or a custom
color) in the output image, copy the result to output.""",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument(
"-d", "--dryrun",
action="store_true",
help="""Print the command to be executed, but don't actually
generate the output image.""")
parser.add_argument(
"-v", "--verbose",
action="count",
default=0,
help="""Print extra information about what is going on.""")
parser.add_argument(
"-x", "--hex",
action="store_true",
help="""Use base 16 for defining custom colors. Works with the
-r, -g, and -b options.""")
parser.add_argument(
"-m", "--magick",
action="store",
default="convert",
help="""Command that executes the convert(1) program of the
imagemagick(1) suite. Supports subcommands (e.g. `magick convert`).""")
parser.add_argument(
"-l", "--luminance",
action="store_const",
dest="method",
const="luminance",
default="average",
help="""Use luminance instead of average value for computing
color brightness when mapping colors. This produces
results that are noticeably poorer than those produced
by the in-game algorithm (which is used in the absence
of -l).""")
parser.add_argument(
"-r", "--red",
action="store",
default=None,
help="""Set the desired red value to RED. Should be an integer
between 0 and 255, or a hex value in the same range if
-x is given.""")
parser.add_argument(
"-g", "--green",
action="store",
default=None,
help="Same as -r, but for green value.")
parser.add_argument(
"-b", "--blue",
action="store",
default=None,
help="Same as -r, but for blue value.")
parser.add_argument(
"--color",
action="store",
choices=sorted(team_colors.keys()),
default=None,
help="""Causes -r, -g, and -b to be ignored. Sets the desired
color (default: red). This method uses a more complex
color definition but produces results identical to the
in-game algorithm.""")
parser.add_argument(
"input_file",
action="store")
parser.add_argument(
"output_file",
action="store")
namespace = parser.parse_args()
verbose = namespace.verbose
dryrun = namespace.dryrun
if dryrun:
verbose = max(1, verbose)
exit_code = colorize(
namespace.color,
namespace.input_file,
namespace.output_file,
magick=namespace.magick,
method=namespace.method,
hex=namespace.hex,
namespace=namespace
)
if not dryrun and exit_code != 0:
sys.exit(exit_code)
# TeamColorizer ends here.

View file

@ -10,6 +10,8 @@ import time
import urllib.parse
from subprocess import Popen
from unit_tree.team_colorizer import colorize
#
# HTML template bits
#
@ -360,7 +362,6 @@ def output(path, url, datadir, data):
sys.stderr.write("Done outputting html, now generating %d TC'ed images\n" % len(images_to_tc))
for pair in images_to_tc:
# wait() to ensure only one process exists at any time
Popen([os.path.join(am_dir, "../unit_tree/TeamColorizer"), pair[0], pair[1]]).wait()
colorize(None, pair[0], pair[1])
# kate: indent-mode normal; encoding utf-8; space-indent on;

View file

@ -6,6 +6,7 @@ Various helpers for use by the wmlunits tool.
import sys, os, re, glob, shutil, copy, subprocess
import wesnoth.wmlparser3 as wmlparser3
from unit_tree.team_colorizer import colorize
def get_datadir(wesnoth_exe):
p = subprocess.Popen([wesnoth_exe, "--data-path"],
@ -34,7 +35,7 @@ class ImageCollector:
A class to collect all the images which need to be copied to the HTML
output folder.
"""
def __init__(self, wesnoth_exe, userdir, datadir):
def __init__(self, wesnoth_exe, userdir, datadir, magick_exe="convert"):
self.images_by_addon_name = {}
self.images_by_ipath = {}
self.binary_paths_per_addon = {}
@ -44,6 +45,7 @@ class ImageCollector:
self.userdir = userdir
if not self.userdir:
self.userdir = get_userdir(wesnoth_exe)
self.magick = magick_exe
def add_binary_paths_from_WML(self, addon, WML):
for binpath in WML.get_all(tag="binary_path"):
@ -147,12 +149,7 @@ class ImageCollector:
if no_tc:
shutil.copy2(ipath, opath)
else:
# We assume TeamColorizer is in the same directory as the
# helpers.py currently executing.
command = os.path.join(os.path.dirname(__file__),
"TeamColorizer")
p = subprocess.Popen([command, ipath, opath])
p.wait()
colorize(None, ipath, opath, magick=self.magick)
else:
sys.stderr.write(
"Warning: Required image %s does not exist (referenced by %s).\n" % (

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
import sys, subprocess
import sys, argparse, subprocess
MAGICK_CMD = 'convert'
# Note: Luminance formula taken from the Wikipedia article on luminance:
# http://en.wikipedia.org/wiki/Luminance_(colorimetry)
@ -137,7 +137,7 @@ def convert_color(color, hex=False):
'max': { 'r': 0xff, 'g': 0xff, 'b': 0xff },
'min': { 'r': 0x00, 'g': 0x00, 'b': 0x00 },}
def get_convert_options(color):
def get_convert_options(color, method):
'''
Takes a dictionary containing 'r', 'g', and 'b' keys each with an integer
value in the range [0, 255]. Returns a list containing all of the arguments
@ -185,100 +185,24 @@ def get_convert_options(color):
"#%02x%02x%02x" % (old_r, old_g, old_b) ]
return options
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="""Map the magenta team-color patches in the input image to red (or a custom
color) in the output image, copy the result to output.""",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument(
"-d", "--dryrun",
action="store_true",
help="""Print the command to be executed, but don't actually
generate the output image.""")
parser.add_argument(
"-v", "--verbose",
action="count",
default=0,
help="""Print extra information about what is going on.""")
parser.add_argument(
"-x", "--hex",
action="store_true",
help="""Use base 16 for defining custom colors. Works with the
-r, -g, and -b options.""")
parser.add_argument(
"-l", "--luminance",
action="store_const",
dest="method",
const="luminance",
default="average",
help="""Use luminance instead of average value for computing
color brightness when mapping colors. This produces
results that are noticeably poorer than those produced
by the in-game algorithm (which is used in the absence
of -l).""")
parser.add_argument(
"-r", "--red",
action="store",
default=None,
help="""Set the desired red value to RED. Should be an integer
between 0 and 255, or a hex value in the same range if
-x is given.""")
parser.add_argument(
"-g", "--green",
action="store",
default=None,
help="Same as -r, but for green value.")
parser.add_argument(
"-b", "--blue",
action="store",
default=None,
help="Same as -r, but for blue value.")
parser.add_argument(
"--color",
action="store",
choices=sorted(team_colors.keys()),
default=None,
help="""Causes -r, -g, and -b to be ignored. Sets the desired
color (default: red). This method uses a more complex
color definition but produces results identical to the
in-game algorithm.""")
parser.add_argument(
"input_file",
action="store")
parser.add_argument(
"output_file",
action="store")
namespace = parser.parse_args()
verbose = namespace.verbose
dryrun = namespace.dryrun
if dryrun:
verbose = max(1, verbose)
hex = namespace.hex
method = namespace.method
color = namespace.color
def colorize(color, in_file, out_file, magick=MAGICK_CMD, method="average", hex=False, namespace=None):
if not color:
r = 255 if namespace.red is None else namespace.red
g = 0 if namespace.green is None else namespace.green
b = 0 if namespace.blue is None else namespace.blue
r = 255 if namespace is None or namespace.red is None else namespace.red
g = 0 if namespace is None or namespace.green is None else namespace.green
b = 0 if namespace is None or namespace.blue is None else namespace.blue
color = { 'mid': { 'r': r, 'g': g, 'b': b },
'max': { 'r':0xff, 'g':0xff, 'b':0xff },
'min': { 'r':0x00, 'g':0x00, 'b':0x00 }}
infilename = namespace.input_file
outfilename = namespace.output_file
color = convert_color(color, hex)
options = get_convert_options(color)
command = ['convert'] + options +\
[infilename, outfilename]
options = get_convert_options(color, method)
command = magick.split(" ") + options + [in_file, out_file]
if verbose:
if namespace and namespace.verbose:
print(' '.join(command))
if not dryrun:
if not namespace or not namespace.dryrun:
ret = subprocess.call(command)
if ret != 0:
print("Error: Conversion command exited with error "\
"code %d." % ret, file=sys.stderr)
sys.exit(ret)
# TeamColorizer ends here.
return ret

View file

@ -572,6 +572,9 @@ if __name__ == '__main__':
ap.add_argument("-t", "--transdir",
help="Specify the directory with gettext message catalogues. " +
"Defaults to ./translations.", default="translations")
ap.add_argument("-m", "--magick", default="convert",
help="Command that executes the convert(1) program of the " +
"imagemagick(1) suite. Supports subcommands (e.g. `magick convert`).")
ap.add_argument("-T", "--timeout",
help="Use the timeout iven in seconds when parsing WML, default is 20 " +
"seconds.")
@ -627,7 +630,8 @@ if __name__ == '__main__':
image_collector = helpers.ImageCollector(options.wesnoth,
options.config_dir,
options.data_dir)
options.data_dir,
magick_exe=options.magick)
html_output.image_collector = image_collector
if options.language == "all":