forked from standardebooks/tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild-images
executable file
·152 lines (119 loc) · 5.46 KB
/
build-images
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env python3
import argparse
import os
import errno
import base64
import fnmatch
import shutil
import subprocess
import regex
import se
def clean_inkscape_svg(filename, clean_path):
with open(filename, "r+") as file:
svg = file.read()
# Time to clean up Inkscape's mess
svg = regex.sub(r"id=\"[^\"]+?\"", "", svg)
svg = regex.sub(r"<metadata[^>]*?>.*?</metadata>", "", svg, flags=regex.MULTILINE | regex.DOTALL)
svg = regex.sub(r"<defs[^>]*?/>", "", svg, flags=regex.MULTILINE | regex.DOTALL)
svg = regex.sub(r"xmlns:(dc|cc|rdf)=\"[^\"]*?\"", "", svg, flags=regex.MULTILINE | regex.DOTALL)
# Inkscape includes font and letter-spacing info even though we've removed font information
svg = regex.sub(r"font-.+?:.+?([;\"])", "\\1", svg)
svg = regex.sub(r"text-anchor:.+?([;\"])", "\\1", svg)
svg = regex.sub(r"letter-spacing:.+?([;\"])", "\\1", svg)
svg = regex.sub(r";+", ";", svg)
svg = regex.sub(r" style=\";", " style=\"", svg)
svg = regex.sub(r" style=\"\"", "", svg)
file.seek(0)
file.write(svg)
file.truncate()
subprocess.run([clean_path, filename])
def remove_metadata(filename, exiftool_path):
# After lots of research there just isn't a good way to reliably edit exif metadata in pure Python.
# So unfortunately we're stuck with this dependency on `exiftool`.
subprocess.run([exiftool_path, "-overwrite_original", "-all=", filename], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def main():
parser = argparse.ArgumentParser(description="Build ebook covers and titlepages for a Standard Ebook source directory, and place the output in DIRECTORY/src/epub/images/.")
parser.add_argument("-v", "--verbose", action="store_true", help="increase output verbosity")
parser.add_argument("directories", metavar="DIRECTORY", nargs="+", help="a Standard Ebooks source directory")
args = parser.parse_args()
# Check for required utilities
clean_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "clean")
inkscape_path = shutil.which("inkscape")
exiftool_path = shutil.which("exiftool")
if inkscape_path is None:
se.print_error("Couldn't locate Inkscape. Is it installed?")
exit(1)
if exiftool_path is None:
se.print_error("Couldn't locate exiftool. Is it installed?")
exit(1)
for directory in args.directories:
directory = os.path.abspath(directory)
if args.verbose:
print("Processing {} ...".format(directory))
if not os.path.isdir(directory):
if args.verbose:
print("\t", end="", flush=True)
se.print_error("Not a directory: {}".format(directory))
exit(1)
source_images_directory = os.path.join(directory, "images")
source_cover_jpg_filename = os.path.join(source_images_directory, "cover.jpg")
source_cover_svg_filename = os.path.join(source_images_directory, "cover.svg")
source_titlepage_svg_filename = os.path.join(source_images_directory, "titlepage.svg")
dest_images_directory = os.path.join(directory, "src", "epub", "images")
dest_cover_svg_filename = os.path.join(dest_images_directory, "cover.svg")
dest_titlepage_svg_filename = os.path.join(dest_images_directory, "titlepage.svg")
try:
os.makedirs(dest_images_directory)
except OSError as exception:
if exception.errno != errno.EEXIST:
if args.verbose:
print("\t", end="", flush=True)
se.print_error("Couldn't create directory: {}".format(dest_images_directory))
exit(1)
# Remove useless metadata from jpg files
for root, _, filenames in os.walk(source_images_directory):
for filename in fnmatch.filter(filenames, "cover.source.*"):
remove_metadata(os.path.join(root, filename), exiftool_path)
# Build cover.svg
if os.path.isfile(source_cover_jpg_filename):
remove_metadata(source_cover_jpg_filename, exiftool_path)
if os.path.isfile(source_cover_svg_filename):
if args.verbose:
print("\tBuilding cover.svg ...", end="", flush=True)
# base64 encode cover.jpg
with open(source_cover_jpg_filename, "rb") as file:
source_cover_jpg_base64 = base64.b64encode(file.read()).decode()
# Convert text to paths
# Inkscape adds a ton of crap to the SVG and we clean that crap a little later
subprocess.run([inkscape_path, source_cover_svg_filename, "--without-gui", "--export-text-to-path", "--export-plain-svg", dest_cover_svg_filename])
# Embed cover.jpg
with open(dest_cover_svg_filename, "r+", encoding="utf-8") as file:
svg = file.read()
svg = regex.sub(r"xlink:href=\".*?cover\.jpg", "xlink:href=\"data:image/jpeg;base64," + source_cover_jpg_base64, svg, flags=regex.MULTILINE | regex.DOTALL)
file.seek(0)
file.write(svg)
file.truncate()
clean_inkscape_svg(dest_cover_svg_filename, clean_path)
if args.verbose:
print(" OK")
else:
if args.verbose:
print("\t./images/cover.svg not found, skipping ...")
else:
if args.verbose:
print("\t./images/cover.jpg not found, skipping ...")
# Build titlepage.svg
if os.path.isfile(source_titlepage_svg_filename):
if args.verbose:
print("\tBuilding titlepage.svg ...", end="", flush=True)
# Convert text to paths
# inkscape adds a ton of crap to the SVG and we clean that crap a little later
subprocess.run([inkscape_path, source_titlepage_svg_filename, "--without-gui", "--export-text-to-path", "--export-plain-svg", dest_titlepage_svg_filename])
clean_inkscape_svg(dest_titlepage_svg_filename, clean_path)
if args.verbose:
print(" OK")
else:
if args.verbose:
print("\t./images/titlepage.svg not found, skipping ...")
if __name__ == "__main__":
main()