From 00013ee112a429a149a79c0ff58e0401a1ccc422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E7=8A=80=E9=BA=9F?= Date: Tue, 1 Sep 2026 10:21:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BE=E7=89=87=E8=BD=AC=20ICO=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=90=E5=B0=BA=E5=AF=B8=E5=8D=95=E7=8B=AC?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E4=B8=8E=E5=A4=9A=E5=B0=BA=E5=AF=B8=E6=89=93?= =?UTF-8?q?=E5=8C=85=20ZIP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .workbuddy/memory/CHANGELOG.md | 2 ++ src/utils/ico.ts | 5 +++ src/views/image-to-ico/ImageToIcoView.vue | 41 +++++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/.workbuddy/memory/CHANGELOG.md b/.workbuddy/memory/CHANGELOG.md index f1ee56a..edb2846 100644 --- a/.workbuddy/memory/CHANGELOG.md +++ b/.workbuddy/memory/CHANGELOG.md @@ -1,6 +1,8 @@ # tool.xpcool.com 变更记录 > 倒序:最新在上。格式:YYYY-MM-DD | 类型 | 摘要 +2026-09-01 | CHG | 图片转 ICO 结果区增强:逐尺寸单独 ICO 下载(buildIco 新增 singles 字段,复用条目数据零额外编码)+ 多尺寸一键打包 ZIP 下载(jszip);另修复 pnpm wrapper 中 node 版本路径(22.22.2 → 22.22.2-2) + 2026-08-31 | CHG | 新增「图片转 ICO」工具:src/utils/ico.ts(纯前端自实现 PNG/BMP DIB/ICO 编码 + 中位切分量化 + 自适应滤波 + 体积上限自动降级),src/views/image-to-ico/ImageToIcoView.vue(尺寸组合/填充/编码方式/量化/体积限制/预览下载/历史),路由注册于 src/router/tools.ts;Pillow 独立解码验证通过 2026-08-26 | CFG | CHANGELOG 纳入 git 管理(.gitignore 放行 .workbuddy/memory/CHANGELOG.md),中央工作空间迁移至 ../workbuddy.xpcool.com(相对路径索引) diff --git a/src/utils/ico.ts b/src/utils/ico.ts index ade8a4e..92814fd 100644 --- a/src/utils/ico.ts +++ b/src/utils/ico.ts @@ -55,6 +55,8 @@ export interface IcoBuildResult { quantized: boolean /** 各尺寸的预览图(DataURL),供页面回显 */ previews: Array<{ size: number; url: string }> + /** 每个尺寸单独封装的 ICO 文件(与合成包内条目数据一致,用于逐尺寸下载 / 打包 ZIP) */ + singles: Array<{ size: number; blob: Blob }> } /** ICO 内部单条目:尺寸 + 编码后的图像数据 */ @@ -727,12 +729,15 @@ export async function buildIco(source: HTMLImageElement, params: IcoBuildParams) const blob = encodeIco(encoded.images) const previews = active.map((size) => ({ size, url: imageDataToDataUrl(rendered.get(size) as ImageData) })) + // 单尺寸 ICO 直接复用合成包里已编码的条目数据,只多包一层 6+16 字节的头部,几乎零开销 + const singles = encoded.images.map((img) => ({ size: img.size, blob: encodeIco([img]) })) return { blob, entries: encoded.meta, droppedSizes: sizes.filter((s) => !active.includes(s)), quantized: quantize, previews, + singles, } } diff --git a/src/views/image-to-ico/ImageToIcoView.vue b/src/views/image-to-ico/ImageToIcoView.vue index 3091d95..755a356 100644 --- a/src/views/image-to-ico/ImageToIcoView.vue +++ b/src/views/image-to-ico/ImageToIcoView.vue @@ -111,12 +111,16 @@
下载 ICO + + + 打包下载 ZIP +
-

各尺寸预览(点击右下角可单独下载 PNG)

+

各尺寸预览(点击右下角可单独下载 PNG / ICO)

@@ -124,7 +128,10 @@
{{ p.size }}×{{ p.size }} - PNG +
+ PNG + ICO +
@@ -136,6 +143,7 @@