|
@ -7,12 +7,20 @@ from PIL import Image |
|
|
class FileInWrongDirError(Exception): |
|
|
class FileInWrongDirError(Exception): |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
class InkscapeError(Exception): |
|
|
class ConversionProgramError(Exception): |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
class ImageMagickError(Exception): |
|
|
class InkscapeError(ConversionProgramError): |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
class ImageMagickError(ConversionProgramError): |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
class AsyError(ConversionProgramError): |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ImageProcessor: |
|
|
class ImageProcessor: |
|
|
def __init__(self, public_dir: str, web_path: str, cache_dir: str, *lookup_dirs: list[str]): |
|
|
def __init__(self, public_dir: str, web_path: str, cache_dir: str, *lookup_dirs: list[str]): |
|
|
self.public_dir = public_dir |
|
|
self.public_dir = public_dir |
|
@ -32,6 +40,9 @@ class ImageProcessor: |
|
|
if full_path is None: |
|
|
if full_path is None: |
|
|
raise FileNotFoundError(f'Image {input_filename} not found in {self.lookup_dirs} or {source_dir}.') |
|
|
raise FileNotFoundError(f'Image {input_filename} not found in {self.lookup_dirs} or {source_dir}.') |
|
|
|
|
|
|
|
|
|
|
|
if format == "jpg": |
|
|
|
|
|
format = "jpeg" |
|
|
|
|
|
|
|
|
# Locate all dependencies |
|
|
# Locate all dependencies |
|
|
deps_full = [full_path] |
|
|
deps_full = [full_path] |
|
|
for dep in deps: |
|
|
for dep in deps: |
|
@ -67,6 +78,21 @@ class ImageProcessor: |
|
|
elif self.find_image(target_name, [source_dir]) is not None and not self.is_outdated(self.find_image(target_name, [source_dir]), deps): |
|
|
elif self.find_image(target_name, [source_dir]) is not None and not self.is_outdated(self.find_image(target_name, [source_dir]), deps): |
|
|
shutil.copyfile(self.find_image(target_name, [source_dir]), target_path) |
|
|
shutil.copyfile(self.find_image(target_name, [source_dir]), target_path) |
|
|
|
|
|
|
|
|
|
|
|
# Process asymptote |
|
|
|
|
|
elif ext == "asy": |
|
|
|
|
|
# Collect dependencies |
|
|
|
|
|
deps_dir = self.cache_dir + "/" + name + "_deps" |
|
|
|
|
|
if not os.path.isdir(deps_dir): |
|
|
|
|
|
os.mkdir(deps_dir) |
|
|
|
|
|
for dep_full in deps_full: |
|
|
|
|
|
dep = os.path.basename(dep_full) |
|
|
|
|
|
if not os.path.isfile(deps_dir + "/" + dep) or os.path.getmtime(deps_dir + "/" + dep) < os.path.getmtime(dep_full): |
|
|
|
|
|
shutil.copyfile(dep_full, deps_dir + "/" + dep) |
|
|
|
|
|
dpi_arg = ['-render', str(dpi/72)] if dpi is not None else [] |
|
|
|
|
|
if subprocess.run(['asy', name, '-o', target_name, '-f', format, *dpi_arg], cwd=deps_dir).returncode != 0: |
|
|
|
|
|
raise AsyError(f"Could not convert '{full_path}' to '{format}'") |
|
|
|
|
|
shutil.move(deps_dir + "/" + target_name, self.cache_dir + "/" + target_name) |
|
|
|
|
|
|
|
|
# Convert SVGs using inkscape |
|
|
# Convert SVGs using inkscape |
|
|
elif ext == "svg": |
|
|
elif ext == "svg": |
|
|
width_arg = ['--export-width', str(width)] if width is not None else [] |
|
|
width_arg = ['--export-width', str(width)] if width is not None else [] |
|
@ -125,3 +151,6 @@ class ImageProcessor: |
|
|
for dir in [*self.lookup_dirs, *additional_dirs]: |
|
|
for dir in [*self.lookup_dirs, *additional_dirs]: |
|
|
if os.path.isfile(dir + "/" + input_filename): |
|
|
if os.path.isfile(dir + "/" + input_filename): |
|
|
return dir + "/" + input_filename |
|
|
return dir + "/" + input_filename |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|