mirror of
https://github.com/freedoom/freedoom.git
synced 2025-09-01 13:25:46 -04:00
BUILD: switch to use pillow instead
create_caption still relies on ImageMagick
This commit is contained in:
parent
d3038fad30
commit
6724ef5aba
7 changed files with 171 additions and 171 deletions
|
@ -52,31 +52,21 @@ TEXTGEN_GRAPHIC_LUMPS = \
|
||||||
TEXTGEN_GRAPHICS = $(TEXTGEN_GRAPHIC_LUMPS) \
|
TEXTGEN_GRAPHICS = $(TEXTGEN_GRAPHIC_LUMPS) \
|
||||||
helpttl.png freettl.png
|
helpttl.png freettl.png
|
||||||
|
|
||||||
all: graphics.stamp help.png credit.png wikilrs.png wivctms.png
|
all: textgen.mk help.png credit.png wikilrs.png wivctms.png
|
||||||
|
|
||||||
# textgen creates multiple outputs, which is awkward to express in
|
|
||||||
# make. Use a witness file (graphics.stamp) as suggested in the
|
|
||||||
# automake manual: "Handling Tools that Produce Many Outputs"
|
|
||||||
|
|
||||||
graphics.stamp: textgen.mk $(TEXTGEN_GRAPHICS)
|
|
||||||
cp $(TEXTGEN_GRAPHIC_LUMPS) ../
|
|
||||||
@touch $@
|
|
||||||
|
|
||||||
# Construct a file of Make directives for each text graphic.
|
|
||||||
# Each graphic depends on the directives file, so we tell textgen
|
|
||||||
# what its name is, as a command line parameter. The directives
|
|
||||||
# file depends on textgen's input (config, font, dehacked).
|
|
||||||
|
|
||||||
|
# Generate the menu and level strings
|
||||||
textgen.mk: config.py fontchars ../../lumps/dehacked.lmp
|
textgen.mk: config.py fontchars ../../lumps/dehacked.lmp
|
||||||
./textgen $@ > $@
|
./textgen $@
|
||||||
|
cp $(TEXTGEN_GRAPHIC_LUMPS) ../
|
||||||
|
|
||||||
# Then, include the file of Make directives constructed above.
|
# Background for the help screen is a color shifted version of INTERPIC:
|
||||||
|
helpbg.png: ../interpic.png
|
||||||
include textgen.mk
|
python tint.py ../interpic.png '#5599ff' helpbg.png
|
||||||
|
|
||||||
# Generate transparent image containing text for the HELP screen:
|
# Generate transparent image containing text for the HELP screen:
|
||||||
helptext.png: helpttl.png
|
help.png: helpttl.png helpbg.png
|
||||||
python smtextgen helptext.png 320x200 \
|
python smtextgen help.png 320x200 \
|
||||||
|
-background "helpbg.png" \
|
||||||
150,5 "file:helpttl.png" \
|
150,5 "file:helpttl.png" \
|
||||||
10,25 "Weapons" \
|
10,25 "Weapons" \
|
||||||
80,25 "file:../../sprites/shota0.png" \
|
80,25 "file:../../sprites/shota0.png" \
|
||||||
|
@ -129,43 +119,21 @@ helptext.png: helpttl.png
|
||||||
276,162 "file:../../sprites/bskua0.png" \
|
276,162 "file:../../sprites/bskua0.png" \
|
||||||
130,163 "Hazard suit" \
|
130,163 "Hazard suit" \
|
||||||
215,142 "file:../../sprites/suita0.png"
|
215,142 "file:../../sprites/suita0.png"
|
||||||
|
|
||||||
# Make background transparent so it can be overlayed.
|
|
||||||
helptext2.png : helptext.png
|
|
||||||
convert helptext.png -transparent '#00ffff' helptext2.png
|
|
||||||
|
|
||||||
# Background for the help screen is a color shifted version of INTERPIC:
|
|
||||||
helpbg.png: ../interpic.png
|
|
||||||
convert ../interpic.png -fill '#5599ff' -tint 100 helpbg.png
|
|
||||||
|
|
||||||
# Draw the overlay with text and sprites onto the background to get the
|
|
||||||
# HELP screen:
|
|
||||||
help.png: helpbg.png helptext2.png
|
|
||||||
convert helpbg.png \
|
|
||||||
-draw 'image over 0,0 0,0 helptext2.png' \
|
|
||||||
help.png
|
|
||||||
cp $@ ../
|
cp $@ ../
|
||||||
|
|
||||||
credtext.png: freettl.png credit.txt
|
|
||||||
python smtextgen credtext.png 320x200 \
|
credit.png: freettl.png helpbg.png credit.txt
|
||||||
|
python smtextgen credit.png 320x200 \
|
||||||
|
-background "helpbg.png" \
|
||||||
120,5 "file:freettl.png" \
|
120,5 "file:freettl.png" \
|
||||||
10,30 "include:credit.txt"
|
10,30 "include:credit.txt"
|
||||||
|
|
||||||
credtext2.png: credtext.png
|
|
||||||
convert credtext.png -transparent '#00ffff' credtext2.png
|
|
||||||
|
|
||||||
credit.png: helpbg.png credtext2.png
|
|
||||||
convert helpbg.png \
|
|
||||||
-draw 'image over 0,0 0,0 credtext2.png' \
|
|
||||||
credit.png
|
|
||||||
cp $@ ../
|
|
||||||
|
|
||||||
wikilrs_horiz.png:
|
wikilrs_horiz.png:
|
||||||
python smtextgen $@ 49x7 \
|
python smtextgen $@ 49x7 \
|
||||||
0,0 killers
|
0,0 killers
|
||||||
|
|
||||||
wikilrs.png: wikilrs_horiz.png
|
wikilrs.png: wikilrs_horiz.png
|
||||||
convert wikilrs_horiz.png -rotate 270 $@
|
python rotate.py wikilrs_horiz.png 90 $@
|
||||||
cp $@ ../
|
cp $@ ../
|
||||||
|
|
||||||
wivctms.png:
|
wivctms.png:
|
||||||
|
@ -175,8 +143,8 @@ wivctms.png:
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TEXTGEN_GRAPHICS) helpbg.png help.png helptext.png \
|
rm -f $(TEXTGEN_GRAPHICS) helpbg.png help.png helptext.png \
|
||||||
helptext2.png graphics.stamp textgen.mk *.pyc credtext.png \
|
helptext2.png graphics.stamp *.pyc credtext.png \
|
||||||
credtext2.png credit.png dmwilv*.png wikilrs.png \
|
credtext.png credit.png dmwilv*.png wikilrs.png \
|
||||||
wivctms.png wikilrs_horiz.png ../credit.png ../help.png \
|
wivctms.png wikilrs_horiz.png ../credit.png ../help.png \
|
||||||
../wikilrs.png ../wivctms.png
|
../wikilrs.png ../wivctms.png
|
||||||
for graphic in $(TEXTGEN_GRAPHICS); do rm -f ../$$graphic; done
|
for graphic in $(TEXTGEN_GRAPHICS); do rm -f ../$$graphic; done
|
||||||
|
|
|
@ -4,9 +4,7 @@ import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# ImageMagick commands used by this script:
|
from PIL import Image
|
||||||
CONVERT_COMMAND = 'convert'
|
|
||||||
IDENTIFY_COMMAND = 'identify'
|
|
||||||
|
|
||||||
# Output from 'identify' looks like this:
|
# Output from 'identify' looks like this:
|
||||||
# fontchars/font033.png GIF 9x16 9x16+0+0 8-bit sRGB 32c 194B 0.000u 0:00.000
|
# fontchars/font033.png GIF 9x16 9x16+0+0 8-bit sRGB 32c 194B 0.000u 0:00.000
|
||||||
|
@ -15,33 +13,34 @@ IDENTIFY_OUTPUT_RE = re.compile(r'(\S+)\s(\S+)\s(\d+)x(\d+)(\+\d+\+\d+)?\s')
|
||||||
# Regexp to identify strings that are all lowercase (can use shorter height)
|
# Regexp to identify strings that are all lowercase (can use shorter height)
|
||||||
LOWERCASE_RE = re.compile(r'^[a-z\!\. ]*$')
|
LOWERCASE_RE = re.compile(r'^[a-z\!\. ]*$')
|
||||||
|
|
||||||
def get_image_dimensions(filename):
|
|
||||||
proc = subprocess.Popen([IDENTIFY_COMMAND, filename],
|
|
||||||
stdout=subprocess.PIPE)
|
|
||||||
proc.wait()
|
|
||||||
|
|
||||||
line = proc.stdout.readline().decode('utf-8')
|
def get_image_dimensions(filename):
|
||||||
match = IDENTIFY_OUTPUT_RE.match(line)
|
"""Get image dimensions w x h
|
||||||
assert match is not None
|
|
||||||
return (int(match.group(3)), int(match.group(4)))
|
Args:
|
||||||
|
filename: filename of the image
|
||||||
|
"""
|
||||||
|
with Image.open(filename) as img:
|
||||||
|
width, height = img.size
|
||||||
|
return (width, height)
|
||||||
|
|
||||||
|
|
||||||
def invoke_command(command):
|
def invoke_command(command):
|
||||||
"""Invoke a command, printing the command to stdout.
|
"""Invoke a command, printing the command to stdout.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
command: Command and arguments as a list.
|
command: Command and arguments as a list.
|
||||||
"""
|
"""
|
||||||
for arg in command:
|
for arg in command:
|
||||||
if arg.startswith('-'):
|
if arg.startswith('-'):
|
||||||
sys.stdout.write("\\\n ")
|
sys.stdout.write("\\\n ")
|
||||||
|
|
||||||
if ' ' in arg or '#' in arg:
|
if ' ' in arg or '#' in arg:
|
||||||
sys.stdout.write(repr(arg))
|
sys.stdout.write(repr(arg))
|
||||||
else:
|
else:
|
||||||
sys.stdout.write(arg)
|
sys.stdout.write(arg)
|
||||||
|
|
||||||
sys.stdout.write(' ')
|
sys.stdout.write(' ')
|
||||||
|
|
||||||
sys.stdout.write('\n')
|
|
||||||
return subprocess.call(command)
|
|
||||||
|
|
||||||
|
sys.stdout.write('\n')
|
||||||
|
return subprocess.call(command)
|
16
graphics/text/rotate.py
Normal file
16
graphics/text/rotate.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#/usr/bin/env python
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
img = Image.open(sys.argv[1])
|
||||||
|
img.load()
|
||||||
|
img2 = img.rotate(int(sys.argv[2]), None, True)
|
||||||
|
img2.crop()
|
||||||
|
if os.path.exists(sys.argv[3]): # delete any previous result file
|
||||||
|
os.remove(sys.argv[3])
|
||||||
|
img2.save(sys.argv[3])
|
|
@ -4,11 +4,13 @@
|
||||||
# Script to generate text graphics using the "small" (HUD) font.
|
# Script to generate text graphics using the "small" (HUD) font.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
from glob import glob
|
from glob import glob
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from common import *
|
from common import *
|
||||||
|
from tint import image_tint
|
||||||
|
|
||||||
# Background color for output files.
|
# Background color for output files.
|
||||||
BACKGROUND_COLOR = None
|
BACKGROUND_COLOR = None
|
||||||
|
@ -53,9 +55,8 @@ class Font(object):
|
||||||
def char_filename(self, c):
|
def char_filename(self, c):
|
||||||
return '../stcfn%03d.png' % (ord(c))
|
return '../stcfn%03d.png' % (ord(c))
|
||||||
|
|
||||||
def draw_commands_for_text(self, text, x, y):
|
def draw_for_text(self, image, text, x, y):
|
||||||
text = text.upper()
|
text = text.upper()
|
||||||
result = []
|
|
||||||
|
|
||||||
x1, y1 = x, y
|
x1, y1 = x, y
|
||||||
|
|
||||||
|
@ -70,22 +71,17 @@ class Font(object):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
filename = self.char_filename(c)
|
filename = self.char_filename(c)
|
||||||
result.extend([
|
char_image = Image.open(filename)
|
||||||
'-draw',
|
image.paste(char_image, (x1, y1))
|
||||||
'image over %i,%i 0,0 "%s"' %
|
|
||||||
(x1, y1, filename)
|
|
||||||
])
|
|
||||||
x1 += self.char_width(c)
|
x1 += self.char_width(c)
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def parse_command_line(args):
|
def parse_command_line(args):
|
||||||
if len(args) < 4 or (len(args) % 2) != 0:
|
if len(args) < 4 or (len(args) % 2) != 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'filename': args[0],
|
'filename': args[0],
|
||||||
|
'background': None,
|
||||||
'strings': [],
|
'strings': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +92,11 @@ def parse_command_line(args):
|
||||||
|
|
||||||
i = 2
|
i = 2
|
||||||
while i < len(args):
|
while i < len(args):
|
||||||
|
if args[i] == '-background':
|
||||||
|
result['background'] = args[i+1]
|
||||||
|
i += 2
|
||||||
|
continue
|
||||||
|
|
||||||
m = DIMENSION_MATCH_RE.match(args[i])
|
m = DIMENSION_MATCH_RE.match(args[i])
|
||||||
if not m:
|
if not m:
|
||||||
return None
|
return None
|
||||||
|
@ -118,36 +119,30 @@ if not args:
|
||||||
|
|
||||||
smallfont = Font()
|
smallfont = Font()
|
||||||
|
|
||||||
command_line = [
|
if args['background'] is not None:
|
||||||
CONVERT_COMMAND,
|
background_image = Image.open(args['background'])
|
||||||
'-size', '%ix%i' % args['dimensions'],
|
background_image.load()
|
||||||
'xc:none',
|
background_image = background_image.convert("RGBA")
|
||||||
]
|
|
||||||
|
image = Image.new("RGBA", args['dimensions'],(0,0,0,0))
|
||||||
|
|
||||||
for xy, string in args['strings']:
|
for xy, string in args['strings']:
|
||||||
# Allow contents of a file to be included with special prefix:
|
# Allow contents of a file to be included with special prefix:
|
||||||
if string.startswith('include:'):
|
if string.startswith(':'):
|
||||||
with open(string[8:]) as f:
|
with open(string[8:]) as f:
|
||||||
string = f.read()
|
string = f.read()
|
||||||
|
|
||||||
# Allow special notation to indicate an image file to just draw
|
# Allow special notation to indicate an image file to just draw
|
||||||
# rather than rendering a string.
|
# rather than rendering a string.
|
||||||
if string.startswith('file:'):
|
if string.startswith('file:'):
|
||||||
command_line.extend((
|
src_image = Image.open(string[5:])
|
||||||
'-draw',
|
src_image.load()
|
||||||
'image over %i,%i 0,0 "%s"' % (
|
image.paste(src_image, (xy[0], xy[1]))
|
||||||
xy[0], xy[1], string[5:]),
|
|
||||||
))
|
|
||||||
else:
|
else:
|
||||||
command_line.extend(smallfont.draw_commands_for_text(
|
smallfont.draw_for_text(image, string, xy[0], xy[1])
|
||||||
string, xy[0], xy[1]))
|
|
||||||
|
|
||||||
if BACKGROUND_COLOR is not None:
|
if args['background'] is not None:
|
||||||
command_line.extend((
|
image = Image.alpha_composite(background_image, image)
|
||||||
'-background', BACKGROUND_COLOR,
|
|
||||||
'-flatten'
|
|
||||||
))
|
|
||||||
|
|
||||||
command_line.extend((args['filename'],))
|
image.save(args['filename'])
|
||||||
invoke_command(command_line)
|
|
||||||
|
|
||||||
|
|
|
@ -5,24 +5,26 @@
|
||||||
# Freedoom, by compositing individual font character graphics together.
|
# Freedoom, by compositing individual font character graphics together.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
from glob import glob
|
from glob import glob
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from config import *
|
from config import *
|
||||||
from common import *
|
from common import *
|
||||||
|
from tint import image_tint
|
||||||
|
|
||||||
# ImageMagick -colorize parameters for colorizing text:
|
# ImageMagick -colorize parameters for colorizing text:
|
||||||
COLOR_BLUE = (100, 100, 0)
|
COLOR_BLUE = "#000001"
|
||||||
COLOR_RED = (0, 100, 100)
|
COLOR_RED = "#010000"
|
||||||
COLOR_WHITE = (0, 0, 0)
|
COLOR_WHITE = None
|
||||||
|
|
||||||
# Background color for output files.
|
# Background color for output files.
|
||||||
BACKGROUND_COLOR = None
|
BACKGROUND_COLOR = None
|
||||||
|
|
||||||
# Height of font in pixels.
|
# Height of font in pixels.
|
||||||
FONT_HEIGHT = 15
|
FONT_HEIGHT = 15
|
||||||
FONT_LC_HEIGHT = 15 #12
|
FONT_LC_HEIGHT = 15 # 12
|
||||||
|
|
||||||
# If true, the font only has uppercase characters.
|
# If true, the font only has uppercase characters.
|
||||||
UPPERCASE_FONT = False
|
UPPERCASE_FONT = False
|
||||||
|
@ -30,6 +32,7 @@ UPPERCASE_FONT = False
|
||||||
# Width of a space character in pixels.
|
# Width of a space character in pixels.
|
||||||
SPACE_WIDTH = 7
|
SPACE_WIDTH = 7
|
||||||
|
|
||||||
|
|
||||||
class Font(object):
|
class Font(object):
|
||||||
def __init__(self, fontdir, kerning_table={}):
|
def __init__(self, fontdir, kerning_table={}):
|
||||||
self.fontdir = fontdir
|
self.fontdir = fontdir
|
||||||
|
@ -106,7 +109,14 @@ class Font(object):
|
||||||
if c is None:
|
if c is None:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def _make_command_line(self, text, color):
|
def generate_graphic(self, text, output_filename,
|
||||||
|
color=COLOR_WHITE, bgcolor=BACKGROUND_COLOR):
|
||||||
|
"""Get command to render text to a file
|
||||||
|
with the given background color.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if UPPERCASE_FONT:
|
||||||
|
text = text.upper()
|
||||||
"""Command line construction helper, used in render functions"""
|
"""Command line construction helper, used in render functions"""
|
||||||
width = self.text_width(text)
|
width = self.text_width(text)
|
||||||
|
|
||||||
|
@ -115,56 +125,27 @@ class Font(object):
|
||||||
else:
|
else:
|
||||||
height = FONT_HEIGHT
|
height = FONT_HEIGHT
|
||||||
|
|
||||||
command_line = [
|
txt_image = Image.new("RGBA", (width, height), (0, 0, 0, 0))
|
||||||
CONVERT_COMMAND,
|
|
||||||
'-size', '%ix%i' % (width, height),
|
|
||||||
'xc:none',
|
|
||||||
]
|
|
||||||
|
|
||||||
for c, x in self.iterate_char_positions(text):
|
for c, x in self.iterate_char_positions(text):
|
||||||
if c is None:
|
if c is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
filename = self.char_filename(c)
|
filename = self.char_filename(c)
|
||||||
command_line.extend([
|
char_image = Image.open(filename)
|
||||||
'-draw',
|
char_image.load()
|
||||||
'image over %i,%i 0,0 %s' %
|
txt_image.paste(char_image, (x, height - FONT_HEIGHT))
|
||||||
(x, height - FONT_HEIGHT, filename)
|
|
||||||
])
|
|
||||||
|
|
||||||
command_line.extend([
|
txt_image = image_tint(txt_image, color)
|
||||||
'-colorize', '%i,%i,%i,0' % color,
|
txt_image.save(output_filename)
|
||||||
])
|
|
||||||
|
|
||||||
return command_line
|
|
||||||
|
|
||||||
def get_command(self, text, output_filename,
|
|
||||||
color=COLOR_WHITE, bgcolor=BACKGROUND_COLOR):
|
|
||||||
"""Get command to render text to a file
|
|
||||||
with the given background color.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if UPPERCASE_FONT:
|
|
||||||
text = text.upper()
|
|
||||||
command_line = self._make_command_line(text, color)
|
|
||||||
|
|
||||||
if bgcolor is not None:
|
|
||||||
command_line.extend([
|
|
||||||
'-background', bgcolor, '-flatten'])
|
|
||||||
|
|
||||||
command_line.append(output_filename)
|
|
||||||
|
|
||||||
return command_line
|
|
||||||
|
|
||||||
def generate_graphics(graphics, color=COLOR_WHITE, bgcolor=BACKGROUND_COLOR):
|
def generate_graphics(graphics, color=COLOR_WHITE, bgcolor=BACKGROUND_COLOR):
|
||||||
for name, text in sorted(graphics.items()):
|
for name, text in sorted(graphics.items()):
|
||||||
print("# %s.png: '%s'" % (name, text))
|
|
||||||
# write a makefile fragment
|
# write a makefile fragment
|
||||||
target = '%s.png' % name
|
target = '%s.png' % name
|
||||||
cmd = font.get_command(text, target,
|
font.generate_graphic(text, target,
|
||||||
color=color, bgcolor=bgcolor)
|
color=color, bgcolor=bgcolor)
|
||||||
print("%s: %s" % (target, " ".join(sys.argv[1:])))
|
|
||||||
print("\t" + " ".join("'%s'" % i for i in cmd))
|
|
||||||
|
|
||||||
def generate_kerning_test():
|
def generate_kerning_test():
|
||||||
pairs = []
|
pairs = []
|
||||||
|
@ -175,8 +156,8 @@ def generate_kerning_test():
|
||||||
if font.kerning_adjust(char1, char2) != 0:
|
if font.kerning_adjust(char1, char2) != 0:
|
||||||
pairs.append(char1 + char2)
|
pairs.append(char1 + char2)
|
||||||
|
|
||||||
cmd = font.get_command(" ".join(pairs), "kerning.png")
|
cmd = font.generate_graphic(" ".join(pairs), "kerning.png")
|
||||||
invoke_command(cmd)
|
|
||||||
|
|
||||||
font = Font('fontchars', kerning_table=FONT_KERNING_RULES)
|
font = Font('fontchars', kerning_table=FONT_KERNING_RULES)
|
||||||
|
|
||||||
|
@ -186,4 +167,3 @@ font = Font('fontchars', kerning_table=FONT_KERNING_RULES)
|
||||||
generate_graphics(red_graphics, color=COLOR_RED)
|
generate_graphics(red_graphics, color=COLOR_RED)
|
||||||
generate_graphics(blue_graphics, color=COLOR_BLUE)
|
generate_graphics(blue_graphics, color=COLOR_BLUE)
|
||||||
generate_graphics(white_graphics, color=COLOR_WHITE)
|
generate_graphics(white_graphics, color=COLOR_WHITE)
|
||||||
|
|
||||||
|
|
55
graphics/text/tint.py
Normal file
55
graphics/text/tint.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#/usr/bin/env python
|
||||||
|
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# Copyright (c) 2017 Martin Miller
|
||||||
|
# https://stackoverflow.com/questions/12251896/colorize-image-while-preserving-transparency-with-pil
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
from ImageColor import getcolor, getrgb
|
||||||
|
from ImageOps import grayscale
|
||||||
|
|
||||||
|
def image_tint(image, tint=None):
|
||||||
|
if tint is None:
|
||||||
|
return image
|
||||||
|
if image.mode not in ['RGB', 'RGBA']:
|
||||||
|
image = image.convert('RGBA')
|
||||||
|
|
||||||
|
tr, tg, tb = getrgb(tint)
|
||||||
|
tl = getcolor(tint, "L") # tint color's overall luminosity
|
||||||
|
if not tl:
|
||||||
|
tl = 1 # avoid division by zero
|
||||||
|
tl = float(tl) # compute luminosity preserving tint factors
|
||||||
|
sr, sg, sb = map(lambda tv: tv / tl, (tr, tg, tb)
|
||||||
|
) # per component adjustments
|
||||||
|
|
||||||
|
# create look-up tables to map luminosity to adjusted tint
|
||||||
|
# (using floating-point math only to compute table)
|
||||||
|
luts = (map(lambda lr: int(lr * sr + 0.5), range(256)) +
|
||||||
|
map(lambda lg: int(lg * sg + 0.5), range(256)) +
|
||||||
|
map(lambda lb: int(lb * sb + 0.5), range(256)))
|
||||||
|
l = grayscale(image) # 8-bit luminosity version of whole image
|
||||||
|
if Image.getmodebands(image.mode) < 4:
|
||||||
|
merge_args = (image.mode, (l, l, l)) # for RGB verion of grayscale
|
||||||
|
else: # include copy of image's alpha layer
|
||||||
|
a = Image.new("L", image.size)
|
||||||
|
a.putdata(image.getdata(3))
|
||||||
|
merge_args = (image.mode, (l, l, l, a)) # for RGBA verion of grayscale
|
||||||
|
luts += range(256) # for 1:1 mapping of copied alpha values
|
||||||
|
|
||||||
|
return Image.merge(*merge_args).point(luts)
|
||||||
|
|
||||||
|
def main(input_image_path, tintcolor, result_image_path):
|
||||||
|
image = Image.open(input_image_path)
|
||||||
|
|
||||||
|
image.load()
|
||||||
|
|
||||||
|
result = image_tint(image, tintcolor)
|
||||||
|
if os.path.exists(result_image_path): # delete any previous result file
|
||||||
|
os.remove(result_image_path)
|
||||||
|
result.save(result_image_path) # file name's extension determines format
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
main(sys.argv[1], sys.argv[2], sys.argv[3])
|
|
@ -1,23 +1,11 @@
|
||||||
titlepic: fd1title.png fd2title.png fdmtitle.png
|
titlepic: fd1title.png fd2title.png fdmtitle.png
|
||||||
|
|
||||||
m_doom.png: ../m_doom.png
|
fd1title.png: titlepic.png ../m_doom.png ../t_phase1.png
|
||||||
convert -transparent '#00ffff' ../m_doom.png m_doom.png
|
./create_caption titlepic.png ../m_doom.png ../t_phase1.png $@
|
||||||
|
|
||||||
m_dm.png: ../m_dm.png
|
|
||||||
convert -transparent '#00ffff' ../m_dm.png m_dm.png
|
|
||||||
|
|
||||||
t_phase1.png: ../t_phase1.png
|
|
||||||
convert -transparent '#00ffff' ../t_phase1.png t_phase1.png
|
|
||||||
|
|
||||||
t_phase2.png: ../t_phase2.png
|
|
||||||
convert -transparent '#00ffff' ../t_phase2.png t_phase2.png
|
|
||||||
|
|
||||||
fd1title.png: titlepic.png m_doom.png t_phase1.png
|
|
||||||
./create_caption titlepic.png m_doom.png t_phase1.png $@
|
|
||||||
cp $@ ../
|
cp $@ ../
|
||||||
|
|
||||||
fd2title.png: titlepic.png m_doom.png t_phase2.png
|
fd2title.png: titlepic.png ../m_doom.png ../t_phase2.png
|
||||||
./create_caption titlepic.png m_doom.png t_phase2.png $@
|
./create_caption titlepic.png ../m_doom.png ../t_phase2.png $@
|
||||||
cp $@ ../
|
cp $@ ../
|
||||||
|
|
||||||
fdmtitle.png: freedm_titlepic.png
|
fdmtitle.png: freedm_titlepic.png
|
||||||
|
@ -25,8 +13,7 @@ fdmtitle.png: freedm_titlepic.png
|
||||||
cp $@ ../
|
cp $@ ../
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f m_dm.png m_doom.png fd1title.png fd2title.png fdmtitle.png \
|
rm -f fd1title.png fd2title.png fdmtitle.png \
|
||||||
../fd1title.png ../fd2title.png ../fdmtitle.png t_phase1.png \
|
../fd1title.png ../fd2title.png ../fdmtitle.png
|
||||||
t_phase2.png
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue