Last active
June 2, 2022 19:39
-
-
Save eldar/4be8c630a93a1680121c3304f71ff78c to your computer and use it in GitHub Desktop.
The script parses latex file, finds the \includegraphics commands with trim and crops the images producing a new latex document without trims.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pathlib import Path | |
import re | |
import argparse | |
import imageio | |
import numpy as np | |
from tqdm import tqdm | |
def crop_or_pad(img, crop): | |
""" | |
crop: [left bottom right top] | |
if crop is negative then we pad instead of crop | |
""" | |
# left | |
cr = crop[0] | |
sh = img.shape | |
if cr >= 0: | |
img = img[:, cr:, :] | |
else: | |
pad = np.ones((sh[0], -cr, sh[2]), dtype=img.dtype) * 255 | |
img = np.concatenate([pad, img], axis=1) | |
# right | |
cr = crop[2] | |
sh = img.shape | |
if cr >= 0: | |
img = img[:, :sh[1]-cr, :] | |
else: | |
pad = np.ones((sh[0], -cr, sh[2]), dtype=img.dtype) * 255 | |
img = np.concatenate([img, pad], axis=1) | |
# top | |
cr = crop[3] | |
sh = img.shape | |
if cr >= 0: | |
img = img[cr:, :, :] | |
else: | |
pad = np.ones((-cr, sh[1], sh[2]), dtype=img.dtype) * 255 | |
img = np.concatenate([pad, img], axis=0) | |
# bottom | |
cr = crop[1] | |
sh = img.shape | |
if cr >= 0: | |
img = img[:sh[0]-cr, :, :] | |
else: | |
pad = np.ones((-cr, sh[1], sh[2]), dtype=img.dtype) * 255 | |
img = np.concatenate([img, pad], axis=0) | |
return img | |
def main(args): | |
filename = args.filename | |
root = args.figure_dir | |
out_filename = str(Path(filename).stem) + "_trimmed.tex" | |
fig_dir = Path(root) | |
with open(filename) as f: | |
lines = f.readlines() | |
out_f = open(out_filename, "w") | |
for line in tqdm(lines): | |
# match crop parameters and filename | |
match = re.search(r'.*includegraphics\[.*trim=(.*),\s*clip.*\]\s*\{(.*)\}', line) | |
if match is None: | |
out_f.write(line) | |
continue | |
img_file_src = match.group(2) | |
img_file = Path(img_file_src) | |
crop_str = match.group(1) | |
# parse trim specification into a list of integers | |
m = re.search(r'^\s*([-?0-9]+)pt\s*([-?0-9]+)pt\s*([-?0-9]+)pt\s*([-?0-9]+)pt\s*.*', crop_str) | |
crop = [int(m.group(i+1)) for i in range(4)] | |
if not img_file.exists(): | |
img_file = fig_dir.joinpath(img_file) | |
if not args.skip_write_images: | |
img = imageio.imread(img_file) | |
img = crop_or_pad(img, crop) | |
imageio.imwrite(img_file, img) | |
# completely remove trim=..., clip section | |
match = re.search(r'.*includegraphics\[.*(,+\s*trim=.*,\s*clip).*\]\s*\{(.*)\}', line) | |
new_line = line.replace(match.group(1), "") | |
new_path = list(img_file.parts) | |
new_path.remove(root) | |
if args.remove_ext: | |
new_path = new_path[:-1] + [Path(new_path[-1]).stem] | |
new_path = str(Path(*new_path)) | |
new_line = new_line.replace(img_file_src, new_path) | |
print(new_line) | |
out_f.write(new_line) | |
out_f.close() | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser() | |
parser.add_argument("filename") | |
parser.add_argument("--figure-dir", type=str, default="figures") | |
parser.add_argument("--remove-ext", action='store_true') | |
parser.add_argument("--skip-write-images", action='store_true') | |
args = parser.parse_args() | |
main(args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment