图片拼接插件

在聊天框中横向或纵向拼接多张图片。
作者: 蜥蜴


背景

在社群中分享截图或排版图片时,常需要将多张图片拼接为一张。传统方式需要借助 Photoshop 或在线拼图工具,操作步骤较多,也难以在聊天过程中即时完成。

koishi-plugin-pic-splice-lizard 将多图收集与拼接交由机器人执行,用户只需在聊天中发送图片并确认,即可获得拼接结果。


工具定位

koishi-plugin-pic-splice-lizard 是一款基于 Koishi 框架的图片处理插件,主要能力如下:

能力 说明
横向拼接 将多张图片按行并排拼接
纵向拼接 将多张图片按列依次拼接(默认)
自动收集 自动收集当前会话中发送的图片
手动 / 自动完成 输入「完成」立即拼接,或等待 10 秒自动拼接
结果下发 以 PNG 图片形式返回拼接结果

当前版本为 1.0.0,依赖 Koishi ^4.17.11 与 koishi-plugin-puppeteer。


安装

前置条件

  • 已搭建并可正常运行的 Koishi 项目(koishi-app)
  • 已安装并启用 puppeteer 插件(插件声明 inject: ['puppeteer'],拼接渲染依赖该服务)

方式一:通过插件市场安装(推荐)

  1. 启动 Koishi 项目,打开控制台(默认地址 http://localhost:5140)。
  2. 进入左侧「插件市场」。
  3. 在搜索框中输入 pic-splice-lizard。
  4. 找到插件后点击「添加」,Koishi 会自动完成依赖安装与配置写入。

方式二:通过 npm 安装

在 Koishi 项目根目录执行:

1
npm install koishi-plugin-pic-splice-lizard

随后在 koishi.yml 中手动添加配置:

1
2
plugins:
pic-splice-lizard: {}

方式三:通过 yarn / pnpm 安装

若项目使用 yarn 或 pnpm,可执行:

1
2
3
4
5
# yarn
yarn add koishi-plugin-pic-splice-lizard

# pnpm
pnpm add koishi-plugin-pic-splice-lizard

安装 puppeteer

插件声明了 inject: ['puppeteer'],拼接渲染依赖 puppeteer 服务。若尚未安装,可执行:

1
npm install koishi-plugin-puppeteer

在 koishi.yml 中相应配置:

1
2
3
plugins:
puppeteer:
# 按需配置

首次使用 puppeteer 时,Koishi 会自动下载 Chromium,请确保网络可用。

验证安装

在任意已接入机器人的聊天窗口输入:

1
拼图

若能返回「请发送图片,输入 “完成” 开始拼接。」,则说明安装成功。


配置

当前版本无需额外配置,安装并启用即可使用:

1
2
plugins:
pic-splice-lizard: {}

使用流程

指令列表

指令 说明 示例
拼图 [方向] 开始拼图,方向可选横向或纵向 拼图 横向

方向参数支持 横向 与 纵向,默认 纵向。若填入其他内容,插件返回「方向只能是 “横向” 或 “纵向”。」。


流程一:拼接多张图片

步骤 1:发送拼图指令

在群聊或私聊中输入:

1
拼图 横向

机器人返回「请发送图片,输入 “完成” 开始拼接。」,并开始收集当前会话中的图片。

步骤 2:发送图片

依次发送或一次性发送多张图片。每收到图片,插件返回当前已获取的数量:

1
已获取 3 张图片。

步骤 3:确认拼接

可通过两种方式触发拼接:

  • 输入「完成」:立即开始拼接
  • 不输入任何内容:等待 10 秒后自动拼接

每次收到图片后,10 秒的计时会重新开始。

步骤 4:接收结果

拼接完成后,机器人以 PNG 图片形式发送拼接结果。

步骤 5:异常处理

  • 图片不足两张时,插件返回「请提供至少两张图片。」
  • 拼接失败时,插件返回「拼接失败,请稍后重试。」
  • 任务正在处理中时,插件返回「任务正在处理中,请稍候。」

使用场景

场景一:拼接聊天截图

将多张聊天截图拼接为一张,便于存档或分享。

场景二:多图排版

将多张图片按横向或纵向排列,用于群内展示。


技术实现

技术栈

技术 用途
Koishi 机器人框架
TypeScript 开发语言
koishi-plugin-puppeteer 页面渲染与截图

核心设计

任务状态管理

每次拼图以 userId 为键记录一个任务,包含方向、图片列表与处理状态:

1
const tasks = new Map<string, { dir: '横向' | '纵向'; imgs: string[]; processing: boolean }>();

processing 用于防止同一任务被重复处理。

图片收集

图片通过 ctx.middleware 从会话消息中提取:

1
2
const images = h.select(session.content, 'img').map(img => img.attrs.src);
task.imgs.push(...images);

每收到图片后,重置 10 秒的自动拼接计时。

HTML 渲染拼接

拼接通过在 puppeteer 页面中排布 <img> 元素实现。方向通过 flex-direction 控制:

1
2
3
4
body {
display: flex;
flex-direction: ${dir === '横向' ? 'row' : 'column'};
}

纵向拼接时图片宽度设为 100%,横向拼接时高度设为 100%,以此统一尺寸。

截图与重试

页面加载后先获取实际尺寸,再据此设置视口与截图区域:

1
2
3
4
5
6
7
const { width, height } = await page.evaluate(() => ({
width: document.body.scrollWidth,
height: document.body.scrollHeight,
}));

await page.setViewport({ width, height });
const screenshot = await page.screenshot({ clip: { x: 0, y: 0, width, height } });

渲染最多重试 3 次,若因连接关闭导致失败,则等待 1 秒后重试。


注意事项

1. puppeteer 依赖

插件声明了 inject: ['puppeteer'],拼接渲染依赖 puppeteer 服务。若未启用该插件,指令将不可用。首次使用时会自动下载 Chromium。

2. 图片数量

插件未限制图片数量,但图片数量越多,拼接耗时越长。建议单次不超过 10 张。

3. 自动拼接

发送图片后若未输入「完成」,插件将在 10 秒后自动拼接。每次发送图片后计时会重新开始。

4. 图片可达性

拼接渲染在 puppeteer 页面中进行,图片需能被页面加载。若图片地址不可达,可能影响拼接结果。

5. 会话独立性

任务状态按 userId 存储,不同用户之间互不影响。


常见问题

Q1:输入指令无响应?

依次检查以下项:

  • 插件是否已在控制台启用
  • koishi-plugin-puppeteer 是否已安装并启用
  • 机器人是否已成功连接至目标平台
  • 指令是否完整输入(拼图 与方向之间以空格分隔)

Q2:提示「请提供至少两张图片」?

拼图至少需要两张图片。请确认已发送足够的图片后再输入「完成」或等待自动拼接。

Q3:拼接失败如何处理?

提示「拼接失败,请稍后重试。」说明渲染过程中发生异常。可检查 puppeteer 是否正常运行、图片地址是否可达,然后重新发起拼图。

Q4:方向参数填错了怎么办?

方向参数仅支持 横向 与 纵向。填入其他内容时插件会返回提示,重新输入正确方向即可。

Q5:可以一次发送多张图片吗?

可以。插件会一次性收集消息中附带的多张图片,并累加到当前任务中。

Q6:拼接结果的分辨率如何决定?

拼接结果的尺寸由 Puppeteer 页面内实际排布尺寸决定,纵向拼接时图片宽度会统一为 100%,横向拼接时高度统一为 100%。


获取工具