From 8482e4dc77904f44fe0288130fd6d7f7128159b1 Mon Sep 17 00:00:00 2001 From: hect0x7 <93357912+hect0x7@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:38:13 +0800 Subject: [PATCH] =?UTF-8?q?v2.5.22:=20=E6=96=B0=E5=A2=9Elong=5Fimg?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=EF=BC=8C=E5=B0=86=E6=9C=AC=E5=AD=90=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E4=B8=BA=E9=95=BF=E5=9B=BE=20(#299)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- assets/docs/sources/option_file_syntax.md | 7 ++ src/jmcomic/__init__.py | 2 +- src/jmcomic/jm_plugin.py | 95 +++++++++++++++++++++++ 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e31fde8..a5166d5 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,11 @@ jmcomic.download_album(422866, option) - `压缩文件插件` - `下载特定后缀图片插件` - `发送QQ邮件插件` - - `日志主题过滤插件` - `自动使用浏览器cookies插件` - `jpg图片合成为一个pdf插件` - `导出收藏夹为csv文件插件` + - `合并所有图片为pdf文件插件` + - `合并所有图片为长图插件` ## 使用小说明 diff --git a/assets/docs/sources/option_file_syntax.md b/assets/docs/sources/option_file_syntax.md index 9da5326..7aa6942 100644 --- a/assets/docs/sources/option_file_syntax.md +++ b/assets/docs/sources/option_file_syntax.md @@ -244,6 +244,13 @@ plugins: pdf_dir: D:/pdf/ # pdf存放文件夹 filename_rule: Aname # pdf命名规则,A代表album, name代表使用album.name也就是本子名称 + # 插件来源:https://github.com/hect0x7/JMComic-Crawler-Python/pull/294 + # long_img插件是把所有图片合并为一个png长图,效果和img2pdf类似 + - plugin: long_img + kwargs: + img_dir: D:/pdf/ # 长图存放文件夹 + filename_rule: Aname # 长图命名规则,同上 + # 请注意⚠ # 下方的j2p插件的功能不如img2pdf插件,不建议使用。 # 如有图片转pdf的需求,直接使用img2pdf即可,下面的内容请忽略。 diff --git a/src/jmcomic/__init__.py b/src/jmcomic/__init__.py index d8548b9..0f53b4d 100644 --- a/src/jmcomic/__init__.py +++ b/src/jmcomic/__init__.py @@ -2,7 +2,7 @@ # 被依赖方 <--- 使用方 # config <--- entity <--- toolkit <--- client <--- option <--- downloader -__version__ = '2.5.21' +__version__ = '2.5.22' from .api import * from .jm_plugin import * diff --git a/src/jmcomic/jm_plugin.py b/src/jmcomic/jm_plugin.py index a7af4d5..bb1ebfa 100644 --- a/src/jmcomic/jm_plugin.py +++ b/src/jmcomic/jm_plugin.py @@ -799,6 +799,101 @@ class Img2pdfPlugin(JmOptionPlugin): return pdf_dir +class LongImgPlugin(JmOptionPlugin): + plugin_key = 'long_img' + + def invoke(self, + photo: JmPhotoDetail = None, + album: JmAlbumDetail = None, + downloader=None, + img_dir=None, + filename_rule='Pid', + delete_original_file=False, + **kwargs, + ): + if photo is None and album is None: + jm_log('wrong_usage', 'long_img必须运行在after_photo或after_album时') + + try: + from PIL import Image + except ImportError: + self.warning_lib_not_install('PIL') + return + + self.delete_original_file = delete_original_file + + # 处理文件夹配置 + img_dir = self.get_img_dir(img_dir) + + # 处理生成的长图文件的路径 + filename = DirRule.apply_rule_directly(album, photo, filename_rule) + + # 长图路径 + long_img_path = os.path.join(img_dir, f'{filename}.png') + + # 调用 PIL 把 photo_dir 下的所有图片合并为长图 + img_path_ls = self.write_img_2_long_img(long_img_path, album, photo) + self.log(f'Convert Successfully: JM{album or photo} → {long_img_path}') + + # 执行删除 + self.execute_deletion(img_path_ls) + + def write_img_2_long_img(self, long_img_path, album: JmAlbumDetail, photo: JmPhotoDetail) -> List[str]: + import itertools + from PIL import Image + + if album is None: + img_dir_items = [self.option.decide_image_save_dir(photo)] + else: + img_dir_items = [self.option.decide_image_save_dir(photo) for photo in album] + + img_paths = itertools.chain(*map(files_of_dir, img_dir_items)) + img_paths = filter(lambda x: not x.startswith('.'), img_paths) # 过滤系统文件 + + images = self.open_images(img_paths) + + try: + resample_method = Image.Resampling.LANCZOS + except AttributeError: + resample_method = Image.LANCZOS + + min_img_width = min(img.width for img in images) + total_height = 0 + for i, img in enumerate(images): + if img.width > min_img_width: + images[i] = img.resize((min_img_width, int(img.height * min_img_width / img.width)), + resample=resample_method) + total_height += images[i].height + + long_img = Image.new('RGB', (min_img_width, total_height)) + y_offset = 0 + for img in images: + long_img.paste(img, (0, y_offset)) + y_offset += img.height + + long_img.save(long_img_path) + for img in images: + img.close() + + return img_paths + + def open_images(self, img_paths: List[str]): + images = [] + for img_path in img_paths: + try: + img = Image.open(img_path) + images.append(img) + except IOError as e: + self.log(f"Failed to open image {img_path}: {e}", 'error') + return images + + @staticmethod + def get_img_dir(img_dir: Optional[str]) -> str: + img_dir = fix_filepath(img_dir or os.getcwd()) + mkdir_if_not_exists(img_dir) + return img_dir + + class JmServerPlugin(JmOptionPlugin): plugin_key = 'jm_server'