You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
5.4 KiB

  1. import os
  2. # import hashlib
  3. from calculate.utils.files import Process, join_paths
  4. from calculate.templates.format.base_format import FormatError
  5. from typing import NoReturn, Union, List, Tuple, Optional
  6. class ImageMagickError(FormatError):
  7. pass
  8. class ImageMagick:
  9. def __init__(self, chroot: str = '/'):
  10. self._chroot_path: str = chroot
  11. self.init_commands(chroot)
  12. self.default_opts: List[str] = []
  13. @property
  14. def available(self) -> bool:
  15. return bool(self.convert_cmd and self.identify_cmd)
  16. @property
  17. def chrooted(self) -> bool:
  18. return self._chroot_path != '/'
  19. def init_commands(self, chroot: str) -> NoReturn:
  20. self.convert_cmd: str = "/usr/bin/convert"
  21. self.identify_cmd: str = "/usr/bin/identify"
  22. self.chroot_cmd: str = "/bin/chroot"
  23. self.bash_cmd: str = "/bin/bash"
  24. if not os.path.exists(join_paths(chroot, self.convert_cmd)):
  25. self.convert_cmd = None
  26. if not os.path.exists(join_paths(chroot, self.identify_cmd)):
  27. self.identify_cmd = None
  28. def trim_prefix_path(self, filename: str) -> Union[str, None]:
  29. retpath = "/{}".format(os.path.relpath(filename, self._chroot_path))
  30. if retpath.startswith("/.."):
  31. return None
  32. return retpath
  33. def get_image_resolution(self, source: str
  34. ) -> Union[None, Tuple[int, int]]:
  35. '''Метод для получения разрешения указанного изображения,
  36. с помощью команды 'identify -format %w %h <path_to_image>'.'''
  37. print(f"SOURCE: {source}")
  38. if self.chrooted:
  39. print(f"CHROOT_PATH: {self._chroot_path}")
  40. identify = Process(self.chroot_cmd, self._chroot_path,
  41. self.bash_cmd, "-c",
  42. " ".join([self.identify_cmd,
  43. "-format '%w %h'", source]))
  44. else:
  45. identify = Process(self.identify_cmd, "-format", "%w %h", source)
  46. if identify.success():
  47. result = identify.read()
  48. swidth, sheight = result.split(" ")
  49. if swidth.isdigit() and sheight.isdigit():
  50. return int(swidth), int(sheight)
  51. else:
  52. raise ImageMagickError(f"ERROR: can not parse: '{result}'")
  53. else:
  54. raise ImageMagickError(f"ERROR: {identify.read_error()}")
  55. def convert(self, source: str, target: str, *opts: List[str],
  56. image_format: Optional[str] = None) -> bool:
  57. command = [self.convert_cmd, "-quality", "95",
  58. source]
  59. command.extend(self.default_opts)
  60. command.extend(opts)
  61. if image_format is not None:
  62. command.append(f"{image_format}:{target}")
  63. else:
  64. command.append(target)
  65. if self.chrooted:
  66. convert = Process(self.chroot_cmd, self._chroot_path,
  67. self.bash_cmd, "-c",
  68. " ".join(command))
  69. else:
  70. print("OPTIONS:")
  71. print(command)
  72. convert = Process(*command)
  73. if convert.success():
  74. print("CREATED: {}".format(target))
  75. return True
  76. else:
  77. print("ERROR:", convert.read_error())
  78. return False
  79. def convert_resize_crop_center(self, source: str, target: str,
  80. height: int, width: int,
  81. image_format: Optional[str] = None) -> bool:
  82. # if ((width == self.source_width and height == self.source_height) and
  83. # (source.rpartition('.')[2] == target.rpartition('.')[2])):
  84. # with write_file(target) as sf:
  85. # sf.write(read_file(source))
  86. # return True
  87. res = f"{width}x{height}"
  88. return self.convert(source, target, "-quality", "95",
  89. "-resize", f"{res}^",
  90. "-strip", "-gravity", "center",
  91. "-crop", f"{res}+0+0",
  92. image_format=image_format)
  93. def convert_resize_gfxboot(self, source: str, target: str,
  94. height: int, width: int,
  95. image_format: Optional[str] = None) -> bool:
  96. res = f"{width}x{height}"
  97. return self.convert(source, target, "-quality", "95",
  98. "-resize", f"{res}^",
  99. "-strip", "-gravity", "center",
  100. "-crop", f"{res}+0+0",
  101. "-sampling-factor", "2x2",
  102. "-interlace", "none",
  103. "-set", "units", "PixelsPerSecond",
  104. image_format=image_format)
  105. def get_image_format(self, source: str) -> str:
  106. """Метод для получения формата указанного файла."""
  107. if self.chrooted:
  108. identify = Process(self.chroot_cmd, self._chroot_path,
  109. self.bash_cmd, "-c",
  110. " ".join([self.identify_cmd,
  111. "-format '%m'", source]))
  112. else:
  113. identify = Process(self.identify_cmd, "-format", "%m", source)
  114. if identify.success():
  115. image_format = identify.read()
  116. return image_format
  117. else:
  118. raise ImageMagickError(f"ERROR: {identify.read_error()}")