import os # import hashlib from calculate.utils.files import Process, join_paths from calculate.templates.format.base_format import FormatError from typing import NoReturn, Union, List, Tuple, Optional class ImageMagickError(FormatError): pass class ImageMagick: def __init__(self, chroot: str = '/'): self._chroot_path: str = chroot self.init_commands(chroot) self.default_opts: List[str] = [] @property def available(self) -> bool: return bool(self.convert_cmd and self.identify_cmd) @property def chrooted(self) -> bool: return self._chroot_path != '/' def init_commands(self, chroot: str) -> NoReturn: self.convert_cmd: str = "/usr/bin/convert" self.identify_cmd: str = "/usr/bin/identify" self.chroot_cmd: str = "/bin/chroot" self.bash_cmd: str = "/bin/bash" if not os.path.exists(join_paths(chroot, self.convert_cmd)): self.convert_cmd = None if not os.path.exists(join_paths(chroot, self.identify_cmd)): self.identify_cmd = None def trim_prefix_path(self, filename: str) -> Union[str, None]: retpath = "/{}".format(os.path.relpath(filename, self._chroot_path)) if retpath.startswith("/.."): return None return retpath def get_image_resolution(self, source: str ) -> Union[None, Tuple[int, int]]: '''Метод для получения разрешения указанного изображения, с помощью команды 'identify -format %w %h '.''' print(f"SOURCE: {source}") if self.chrooted: print(f"CHROOT_PATH: {self._chroot_path}") identify = Process(self.chroot_cmd, self._chroot_path, self.bash_cmd, "-c", " ".join([self.identify_cmd, "-format '%w %h'", source])) else: identify = Process(self.identify_cmd, "-format", "%w %h", source) if identify.success(): result = identify.read() swidth, sheight = result.split(" ") if swidth.isdigit() and sheight.isdigit(): return int(swidth), int(sheight) else: raise ImageMagickError(f"ERROR: can not parse: '{result}'") else: raise ImageMagickError(f"ERROR: {identify.read_error()}") def convert(self, source: str, target: str, *opts: List[str], image_format: Optional[str] = None) -> bool: command = [self.convert_cmd, "-quality", "95", source] command.extend(self.default_opts) command.extend(opts) if image_format is not None: command.append(f"{image_format}:{target}") else: command.append(target) if self.chrooted: convert = Process(self.chroot_cmd, self._chroot_path, self.bash_cmd, "-c", " ".join(command)) else: print("OPTIONS:") print(command) convert = Process(*command) if convert.success(): print("CREATED: {}".format(target)) return True else: print("ERROR:", convert.read_error()) return False def convert_resize_crop_center(self, source: str, target: str, height: int, width: int, image_format: Optional[str] = None) -> bool: # if ((width == self.source_width and height == self.source_height) and # (source.rpartition('.')[2] == target.rpartition('.')[2])): # with write_file(target) as sf: # sf.write(read_file(source)) # return True res = f"{width}x{height}" return self.convert(source, target, "-quality", "95", "-resize", f"{res}^", "-strip", "-gravity", "center", "-crop", f"{res}+0+0", image_format=image_format) def convert_resize_gfxboot(self, source: str, target: str, height: int, width: int, image_format: Optional[str] = None) -> bool: res = f"{width}x{height}" return self.convert(source, target, "-quality", "95", "-resize", f"{res}^", "-strip", "-gravity", "center", "-crop", f"{res}+0+0", "-sampling-factor", "2x2", "-interlace", "none", "-set", "units", "PixelsPerSecond", image_format=image_format) def get_image_format(self, source: str) -> str: """Метод для получения формата указанного файла.""" if self.chrooted: identify = Process(self.chroot_cmd, self._chroot_path, self.bash_cmd, "-c", " ".join([self.identify_cmd, "-format '%m'", source])) else: identify = Process(self.identify_cmd, "-format", "%m", source) if identify.success(): image_format = identify.read() return image_format else: raise ImageMagickError(f"ERROR: {identify.read_error()}")