您最多能選擇 25 個主題 主題必須以字母或數字為開頭,可包含連接號「-」且最長為 35 個字元。

136 行
5.4 KiB

此檔案含有易混淆的 Unicode 字元!

此檔案含有易混淆的 Unicode 字元,這些字元的處理方式可能和下面呈現的不同。若您是有意且合理的使用,您可以放心地忽略此警告。使用 Escape 按鈕標記這些字元。

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 <path_to_image>'.'''
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()}")