v2.5.22: 新增long_img插件,将本子合并为长图 (#299)

This commit is contained in:
hect0x7 2024-10-16 21:38:13 +08:00 committed by GitHub
parent b0cd90468e
commit 8482e4dc77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 105 additions and 2 deletions

View File

@ -121,10 +121,11 @@ jmcomic.download_album(422866, option)
- `压缩文件插件`
- `下载特定后缀图片插件`
- `发送QQ邮件插件`
- `日志主题过滤插件`
- `自动使用浏览器cookies插件`
- `jpg图片合成为一个pdf插件`
- `导出收藏夹为csv文件插件`
- `合并所有图片为pdf文件插件`
- `合并所有图片为长图插件`
## 使用小说明

View File

@ -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即可下面的内容请忽略。

View File

@ -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 *

View File

@ -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'