25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
5.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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>'.'''
if self.chrooted:
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"Can not parse: '{result}'")
else:
raise ImageMagickError(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:
convert = Process(*command)
if convert.success():
return True
else:
raise ImageMagickError(convert.read_error())
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"{identify.read_error()}")