Merge branch 'textgen'

This commit is contained in:
Mike Swanson 2017-07-31 14:39:05 -07:00
commit 7a8cdec79a
15 changed files with 301 additions and 315 deletions

View file

@ -1,10 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
VERSION=$(shell git describe --dirty 2>/dev/null || cat VERSION) VERSION=$(shell git describe --abbrev=8 --dirty 2>/dev/null || cat VERSION)
WADS=wads WADS=wads
CPP=scripts/simplecpp CPP=scripts/simplecpp
DEUTEX=deutex DEUTEX=deutex
DEUTEX_BASIC_ARGS=-v0 -rate accept -rgb 0 255 255 DEUTEX_BASIC_ARGS=-v0 -rate accept
DEUTEX_ARGS=$(DEUTEX_BASIC_ARGS) -doom2 bootstrap/ DEUTEX_ARGS=$(DEUTEX_BASIC_ARGS) -doom2 bootstrap/
FREEDOOM1=$(WADS)/freedoom1.wad FREEDOOM1=$(WADS)/freedoom1.wad
@ -16,8 +16,7 @@ OBJS=$(FREEDM) $(FREEDOOM1) $(FREEDOOM2)
all: $(OBJS) all: $(OBJS)
subdirs: subdirs:
$(MAKE) -C graphics/text $(MAKE) VERSION=$(VERSION) -C graphics/text
$(MAKE) VERSION=$(VERSION) -C graphics/titlepic
$(MAKE) -C lumps/playpal $(MAKE) -C lumps/playpal
$(MAKE) -C lumps/colormap $(MAKE) -C lumps/colormap
$(MAKE) -C lumps/genmidi $(MAKE) -C lumps/genmidi
@ -62,7 +61,7 @@ $(FREEDM): wadinfo_freedm.txt subdirs
$(FREEDOOM1): wadinfo_phase1.txt subdirs $(FREEDOOM1): wadinfo_phase1.txt subdirs
@mkdir -p $(WADS) @mkdir -p $(WADS)
rm -f $@ rm -f $@
$(DEUTEX) $(DEUTEX_ARGS) -iwad -lumps -patch -flats -sounds -musics -graphics -sprites -levels -build wadinfo_phase1.txt $@ $(DEUTEX) $(DEUTEX_ARGS) -iwad -build wadinfo_phase1.txt $@
#--------------------------------------------------------- #---------------------------------------------------------
# phase 2 (doom2) iwad # phase 2 (doom2) iwad
@ -70,7 +69,7 @@ $(FREEDOOM1): wadinfo_phase1.txt subdirs
$(FREEDOOM2): wadinfo_phase2.txt subdirs $(FREEDOOM2): wadinfo_phase2.txt subdirs
@mkdir -p $(WADS) @mkdir -p $(WADS)
rm -f $@ rm -f $@
$(DEUTEX) $(DEUTEX_ARGS) -iwad -lumps -patch -flats -sounds -musics -graphics -sprites -levels -build wadinfo_phase2.txt $@ $(DEUTEX) $(DEUTEX_ARGS) -iwad -build wadinfo_phase2.txt $@
%.html: %.adoc %.html: %.adoc
TZ=UTC asciidoc $< TZ=UTC asciidoc $<
@ -111,7 +110,6 @@ clean:
$(MAKE) -C dist clean $(MAKE) -C dist clean
$(MAKE) -C graphics/text clean $(MAKE) -C graphics/text clean
$(MAKE) -C graphics/titlepic clean
$(MAKE) -C lumps/playpal clean $(MAKE) -C lumps/playpal clean
$(MAKE) -C lumps/colormap clean $(MAKE) -C lumps/colormap clean
$(MAKE) -C lumps/genmidi clean $(MAKE) -C lumps/genmidi clean

View file

@ -16,3 +16,5 @@ credtext*.png
freettl.png freettl.png
helptext*.png helptext*.png
wikilrs_horiz.png wikilrs_horiz.png
fd?title.png
m_*.png

View file

@ -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: text_strings help.png credit.png wikilrs.png wivctms.png titlepic
# textgen creates multiple outputs, which is awkward to express in # Generate the menu and level strings
# make. Use a witness file (graphics.stamp) as suggested in the text_strings: config.py fontchars ../../lumps/dehacked.lmp
# automake manual: "Handling Tools that Produce Many Outputs" python textgen
graphics.stamp: textgen.mk $(TEXTGEN_GRAPHICS)
cp $(TEXTGEN_GRAPHIC_LUMPS) ../ cp $(TEXTGEN_GRAPHIC_LUMPS) ../
@touch $@
# Construct a file of Make directives for each text graphic. # Background for the help screen is a color shifted version of INTERPIC:
# Each graphic depends on the directives file, so we tell textgen helpbg.png: ../interpic.png
# what its name is, as a command line parameter. The directives python tint.py ../interpic.png '#57b9b0' helpbg.png
# file depends on textgen's input (config, font, dehacked).
textgen.mk: config.py fontchars ../../lumps/dehacked.lmp
./textgen $@ > $@
# Then, include the file of Make directives constructed above.
include textgen.mk
# Generate transparent image containing text for the HELP screen: # Generate transparent image containing text for the HELP screen:
helptext.png: helpttl.png help.png: text_strings 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" \
@ -107,8 +97,8 @@ helptext.png: helpttl.png
128,107 "file:../../sprites/pstra0.png" \ 128,107 "file:../../sprites/pstra0.png" \
170,115 "Armor" \ 170,115 "Armor" \
220,113 "file:../../sprites/bon2a0.png" \ 220,113 "file:../../sprites/bon2a0.png" \
240,105 "file:../../sprites/arm1b0.png" \ 240,113 "file:../../sprites/arm1b0.png" \
280,105 "file:../../sprites/arm2b0.png" \ 280,110 "file:../../sprites/arm2b0.png" \
145,140 "Map" \ 145,140 "Map" \
175,130 "file:../../sprites/pmapa0.png" \ 175,130 "file:../../sprites/pmapa0.png" \
10,140 "Overdrive" \ 10,140 "Overdrive" \
@ -129,35 +119,14 @@ 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: text_strings 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 $@ ../ cp $@ ../
wikilrs_horiz.png: wikilrs_horiz.png:
@ -165,7 +134,7 @@ wikilrs_horiz.png:
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 270 $@
cp $@ ../ cp $@ ../
wivctms.png: wivctms.png:
@ -173,11 +142,27 @@ wivctms.png:
0,0 victims 0,0 victims
cp $@ ../ cp $@ ../
titlepic: fd1title.png fd2title.png fdmtitle.png
fd1title.png: text_strings ../titlepic/titlepic.png ../m_doom.png ../t_phase1.png
python create_caption.py ../titlepic/titlepic.png ../m_doom.png ../t_phase1.png $@
cp $@ ../
fd2title.png: text_strings ../titlepic/titlepic.png ../m_doom.png ../t_phase2.png
python create_caption.py ../titlepic/titlepic.png ../m_doom.png ../t_phase2.png $@
cp $@ ../
fdmtitle.png: ../titlepic/freedm_titlepic.png
python create_caption.py $< $@
cp $@ ../
clean: clean:
rm -f $(TEXTGEN_GRAPHICS) helpbg.png help.png helptext.png \ rm -f $(TEXTGEN_GRAPHICS) helpbg.png help.png \
helptext2.png graphics.stamp textgen.mk *.pyc credtext.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 \
fd1title.png fd2title.png fdmtitle.png \
../fd1title.png ../fd2title.png ../fdmtitle.png
for graphic in $(TEXTGEN_GRAPHICS); do rm -f ../$$graphic; done for graphic in $(TEXTGEN_GRAPHICS); do rm -f ../$$graphic; done
rm -fr __pycache__ rm -fr __pycache__

View file

@ -1,47 +0,0 @@
# SPDX-License-Identifier: BSD-3-Clause
import re
import subprocess
import sys
# ImageMagick commands used by this script:
CONVERT_COMMAND = 'convert'
IDENTIFY_COMMAND = 'identify'
# Output from 'identify' looks like this:
# fontchars/font033.png GIF 9x16 9x16+0+0 8-bit sRGB 32c 194B 0.000u 0:00.000
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)
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')
match = IDENTIFY_OUTPUT_RE.match(line)
assert match is not None
return (int(match.group(3)), int(match.group(4)))
def invoke_command(command):
"""Invoke a command, printing the command to stdout.
Args:
command: Command and arguments as a list.
"""
for arg in command:
if arg.startswith('-'):
sys.stdout.write("\\\n ")
if ' ' in arg or '#' in arg:
sys.stdout.write(repr(arg))
else:
sys.stdout.write(arg)
sys.stdout.write(' ')
sys.stdout.write('\n')
return subprocess.call(command)

View file

@ -28,7 +28,7 @@ FONT_KERNING_RULES = {
# Left character fits under right character: # Left character fits under right character:
r'L[TY]': -4, r'L[TY]': -4,
r'L[014COQV]': -3, r'L[014COQV]': -3,
r'L[O09]': -2, r'L[9]': -2,
r'[0O][4TY]': -2, r'[0O][4TY]': -2,
r'[0O][1]': -1, r'[0O][1]': -1,
r'Q[1T]': -2, r'Q[1T]': -2,

40
graphics/text/create_caption.py Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
# encoding: utf-8
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import unicode_literals
from PIL import Image, ImageFont, ImageDraw
import sys
import os
#create_caption.py <background_image> <title?> <phase?> <outfile>
font = ImageFont.load_default()
txt1= "© 2001-2017"
txt2= os.environ['VERSION']
background_image = Image.open(sys.argv[1])
background_image.load()
background_image = background_image.convert("RGBA")
image = Image.new("RGBA", background_image.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
txt1_size = draw.textsize(txt1, font=font)
txt2_size = draw.textsize(txt2, font=font)
draw.text((5, int(image.height - txt1_size[1] - 5)), txt1, font=font, fill=(255,165,0,255))
draw.text((int(image.width - txt2_size[0] - 10), int(image.height - txt2_size[1] - 5)), txt2, font=font, fill=(255,165,0,255))
if len(sys.argv) > 3:
#paste the other stuff onto the thing.
logo = Image.open(sys.argv[2])
logo.load()
phase = Image.open(sys.argv[3])
phase.load
image.paste(logo, ((int(image.width/2) - int(logo.width/2), 18)))
image.paste(phase, ((int(image.width/2) - int(phase.width/2)), int(image.height - phase.height - 30)))
outfile_name = sys.argv[4]
else:
outfile_name = sys.argv[2]
image = Image.alpha_composite(background_image, image)
image.save(outfile_name)

View file

@ -0,0 +1,24 @@
#!/usr/bin/env python
# SPDX-License-Identifier: BSD-3-Clause
import re
from PIL import Image
def get_image_dimensions(filename):
"""Get image dimensions w x h
Args:
filename: filename of the image
"""
with Image.open(filename) as img:
width, height = img.size
return (width, height)
if __name__ == '__main__':
import sys
x,y = get_image_dimensions(sys.argv[1])
string = "%i %i" % (x, y)
sys.stdout.write(string)

27
graphics/text/rotate.py Executable file
View file

@ -0,0 +1,27 @@
#/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()
angle = int(sys.argv[2])
if angle % 90 == 0:
if angle == 90 or angle == -270:
method = Image.ROTATE_90
elif abs(angle) == 180:
method = Image.ROTATE_180
else:
method = Image.ROTATE_270
img2 = img.transpose(method)
else:
img2 = img.rotate(int(sys.argv[2]), 0, True)
img2 = img2.crop()
if os.path.exists(sys.argv[3]): # delete any previous result file
os.remove(sys.argv[3])
img2.save(sys.argv[3])

View file

@ -4,27 +4,24 @@
# 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 image_dimensions import *
from tint import image_tint
# Background color for output files.
BACKGROUND_COLOR = '#00ffff'
# Width of a space character in pixels.
SPACE_WIDTH = 4
# Height of the font.
FONT_HEIGHT = 8
# Regexp to match dimensions/x,y coordinate pair.
DIMENSION_MATCH_RE = re.compile(r'(\d+)[x,](\d+)') DIMENSION_MATCH_RE = re.compile(r'(\d+)[x,](\d+)')
class Font(object): class SmallTextGenerator(object):
def __init__(self): def __init__(self):
self.get_font_widths() self.get_font_widths()
# Width of a space character in pixels.
SPACE_WIDTH = 4
# Height of the font.
FONT_HEIGHT = 8
# Regexp to match dimensions/x,y coordinate pair.
def compile_kerning_table(self, kerning_table): def compile_kerning_table(self, kerning_table):
"""Given a dictionary of kerning patterns, compile Regexps.""" """Given a dictionary of kerning patterns, compile Regexps."""
@ -53,31 +50,33 @@ 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 = [] new_image = image.copy()
x1, y1 = x, y x1, y1 = x, y
for c in text: for c in text:
if c == '\n': if c == '\n':
y1 += FONT_HEIGHT y1 += self.FONT_HEIGHT
x1 = x x1 = x
elif c == ' ': elif c == ' ':
x1 += SPACE_WIDTH x1 += self.SPACE_WIDTH
if c not in self: if c not in self:
continue continue
filename = self.char_filename(c) filename = self.char_filename(c)
result.extend([ char_image = Image.open(filename)
'-draw', char_image.load()
'image over %i,%i 0,0 "%s"' % new_image = self.paste_image(new_image, char_image, x1, y1)
(x1, y1, filename)
])
x1 += self.char_width(c) x1 += self.char_width(c)
return new_image
return result def paste_image(self, image, src, x, y):
int_image = Image.new("RGBA", image.size, (0, 0, 0, 0))
int_image.paste(src, (x, y))
new_image = Image.alpha_composite(image, int_image)
return new_image
def parse_command_line(args): def parse_command_line(args):
@ -86,6 +85,7 @@ def parse_command_line(args):
result = { result = {
'filename': args[0], 'filename': args[0],
'background': None,
'strings': [], 'strings': [],
} }
@ -96,6 +96,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
@ -108,23 +113,26 @@ def parse_command_line(args):
return result return result
args = parse_command_line(sys.argv[1:]) if __name__ == '__main__':
if not args: args = parse_command_line(sys.argv[1:])
if not args:
print("Usage: smtextgen <filename> <size> [...text commands...]") print("Usage: smtextgen <filename> <size> [...text commands...]")
print("Where each text command looks like:") print("Where each text command looks like:")
print(" [x,y] [text]") print(" [x,y] [text]")
sys.exit(0) sys.exit(0)
smallfont = Font() smallfont = SmallTextGenerator()
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")
]
for xy, string in args['strings']: image = Image.new("RGBA", args['dimensions'],(0,0,0,0))
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('include:'):
with open(string[8:]) as f: with open(string[8:]) as f:
@ -133,19 +141,14 @@ for xy, string in args['strings']:
# 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 = smallfont.paste_image(image, src_image, xy[0], xy[1])
xy[0], xy[1], string[5:]),
))
else: else:
command_line.extend(smallfont.draw_commands_for_text( image = smallfont.draw_for_text(image, string, xy[0], xy[1])
string, xy[0], xy[1]))
command_line.extend(( if args['background'] is not None:
'-background', BACKGROUND_COLOR, image = Image.alpha_composite(background_image, image)
'-flatten', args['filename'],
))
invoke_command(command_line) image.save(args['filename'])

View file

@ -5,37 +5,39 @@
# 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 image_dimensions import *
from tint import image_tint
# ImageMagick -colorize parameters for colorizing text:
COLOR_BLUE = (100, 100, 0)
COLOR_RED = (0, 100, 100)
COLOR_WHITE = (0, 0, 0)
# Background color for output files.
BACKGROUND_COLOR = '#00ffff'
# Height of font in pixels. class TextGenerator(object):
FONT_HEIGHT = 15
FONT_LC_HEIGHT = 15 #12
# If true, the font only has uppercase characters.
UPPERCASE_FONT = False
# Width of a space character in pixels.
SPACE_WIDTH = 7
class Font(object):
def __init__(self, fontdir, kerning_table={}): def __init__(self, fontdir, kerning_table={}):
self.fontdir = fontdir self.fontdir = fontdir
self.kerning_table = self.compile_kerning_table(kerning_table) self.kerning_table = self.compile_kerning_table(kerning_table)
self.get_font_widths() self.get_font_widths()
# Tinting parameters for colorizing text:
COLOR_BLUE = "#000001"
COLOR_RED = "#010000"
COLOR_WHITE = None
# Height of font in pixels.
FONT_HEIGHT = 15
FONT_LC_HEIGHT = 15 # 12
# If true, the font only has uppercase characters.
UPPERCASE_FONT = False
# Width of a space character in pixels.
SPACE_WIDTH = 7
LOWERCASE_RE = re.compile(r'^[a-z\!\. ]*$')
def compile_kerning_table(self, kerning_table): def compile_kerning_table(self, kerning_table):
"""Given a dictionary of kerning patterns, compile Regexps.""" """Given a dictionary of kerning patterns, compile Regexps."""
@ -83,7 +85,7 @@ class Font(object):
last_c = ' ' last_c = ' '
for c in text: for c in text:
if c == ' ': if c == ' ':
x += SPACE_WIDTH x += self.SPACE_WIDTH
if c in self: if c in self:
x += self.kerning_adjust(last_c, c) x += self.kerning_adjust(last_c, c)
@ -106,67 +108,46 @@ 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, color=None):
"""Get command to render text to a file
with the given background color.
"""
if self.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)
if LOWERCASE_RE.match(text): if self.LOWERCASE_RE.match(text):
height = FONT_LC_HEIGHT height = self.FONT_LC_HEIGHT
else: else:
height = FONT_HEIGHT height = self.FONT_HEIGHT
command_line = [
CONVERT_COMMAND,
'-size', '%ix%i' % (width, height),
'xc:none',
]
txt_image = Image.new("RGBA", (width, height), (0, 0, 0, 0))
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' % int_image = Image.new("RGBA", txt_image.size, (0, 0, 0, 0))
(x, height - FONT_HEIGHT, filename) int_image.paste(char_image, (x, height - self.FONT_HEIGHT))
]) txt_image = Image.alpha_composite(txt_image, int_image)
command_line.extend([ txt_image = image_tint(txt_image, color)
'-colorize', '%i,%i,%i,0' % color, return txt_image
])
return command_line
def get_command(self, text, output_filename, def generate_graphics(font, graphics, color=None):
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):
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, image = font.generate_graphic(text, color=color)
color=color, bgcolor=bgcolor) image.save(target)
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(font):
pairs = [] pairs = []
for c1 in sorted(font.char_widths): for c1 in sorted(font.char_widths):
char1 = "%c" % c1 char1 = "%c" % c1
@ -175,15 +156,11 @@ 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) if __name__ == '__main__':
# Enable to generate test image file for tweaking kerning values:
#generate_kerning_test()
generate_graphics(red_graphics, color=COLOR_RED)
generate_graphics(blue_graphics, color=COLOR_BLUE)
generate_graphics(white_graphics, color=COLOR_WHITE)
font = TextGenerator('fontchars', kerning_table=FONT_KERNING_RULES)
generate_graphics(font, red_graphics, color=font.COLOR_RED)
generate_graphics(font, blue_graphics, color=font.COLOR_BLUE)
generate_graphics(font, white_graphics, color=font.COLOR_WHITE)

53
graphics/text/tint.py Executable file
View file

@ -0,0 +1,53 @@
#/usr/bin/env python
# SPDX-License-Identifier: MIT
# Copyright (c) 2017 Martin Miller, Nick Zatkovich
# https://stackoverflow.com/questions/12251896/colorize-image-while-preserving-transparency-with-pil
from PIL import Image, ImageColor, ImageOps
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 = ImageColor.getrgb(tint)
tl = ImageColor.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 = (tuple(map(lambda lr: int(lr * sr + 0.5), range(256))) +
tuple(map(lambda lg: int(lg * sg + 0.5), range(256))) +
tuple(map(lambda lb: int(lb * sb + 0.5), range(256))))
l = ImageOps.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 += tuple(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])

View file

@ -1,2 +0,0 @@
fd?title.png
m_*.png

View file

@ -1,32 +0,0 @@
titlepic: fd1title.png fd2title.png fdmtitle.png
m_doom.png: ../m_doom.png
convert -transparent '#00ffff' ../m_doom.png m_doom.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 $@ ../
fd2title.png: titlepic.png m_doom.png t_phase2.png
./create_caption titlepic.png m_doom.png t_phase2.png $@
cp $@ ../
fdmtitle.png: freedm_titlepic.png
./create_caption $< $@
cp $@ ../
clean:
rm -f m_dm.png m_doom.png fd1title.png fd2title.png fdmtitle.png \
../fd1title.png ../fd2title.png ../fdmtitle.png t_phase1.png \
t_phase2.png
.PHONY: clean

View file

@ -1,4 +1,2 @@
This directory contains a shell script that uses ImageMagick to layer This directory contains template images for generating the title screen
some text information about the build version onto the game's title for Freedoom Phase 1, Phase 2, and FreeDM
screen. The same is performed for each of the three IWADs.

View file

@ -1,40 +0,0 @@
#!/bin/sh
find_font() {
local font fontlist
fontlist=$(convert -list font | awk '$1=="Font:" { print $2 }')
for font in "$@" ; do
if echo $fontlist | grep -q $font ; then
echo $font
return
fi
done
}
font=$(find_font Helvetica-Bold Liberation-Sans-Bold DejaVu-Sans-Condensed-Bold)
if [ -z "$font" ] ; then echo "Cannot find any fonts" ; exit 1 ; fi
draw_with_footer() {
input_file=$1;
output_file=$2;
shift; shift
convert $input_file -fill orange -font "$font" +dither \
-pointsize 11 \
-gravity southwest \
-draw "text 5,5 '© 2001-2017'" \
-gravity southeast \
-draw "text 10,5 '$VERSION'" \
"$@" \
$output_file
}
if [ $# = 4 ]; then
draw_with_footer "$1" "$4" \
-gravity north \
-draw "image over 0,18 0,0 '$2'" \
-gravity south \
-draw "image over 0,30 0,0 '$3'"
else
draw_with_footer "$1" "$2"
fi