身为一个仓鼠党,下了一些图集,需要保存图片到一个文件夹、擦除 EXIF、快速重命名,工具倒是都有,但是都需要打开各种不同的软件,略有麻烦。
于是根据我自己的需求,开发了一款新的看图软件 :Folio
其实代码都是 AI 写的,所以也就顺带开源了: GitHub - Folio
Folio 能做什么
Folio 目前主要围绕几个核心场景:
多图并列浏览
这是 Folio 的核心功能之一。最多可以同时打开四张图片并排看,说是用来对比构图、细节、色彩、版本差异。其实就是为了 快速找图集中的 AWESOME 图片 。

Exif 擦除
Folio 内置 Exif 信息查看与擦除功能,擦除支持指定分类。
为什么有人会把信息写到 ImageUnique ID 里啊,Folio 可以擦除它,同时保留其他信息。
批量重命名
支持按规则批量重命名,内置了一些简单的规则,比如加序号、替换字段、按模板生成文件名等。执行前会有预览,避免一键把文件夹搞乱。
格式转换
可以把图片转换成 JPEG、PNG、WebP、AVIF、TIFF 等格式。
支持拖拽
直接拖拽图片到文件夹、上传控件中。
开发框架 Electron
Folio 是用 Electron 做的。
好处很明显:跨平台、开发效率高、UI 能做得比较自由,很多现代桌面交互实现起来也舒服,花了周五加一个周末就做出了 MVP 版本,用学 AI 起 MVP ,首选 Electron 。
坏处也很明显:内存一下就起飞了,打开一个充满 40MB 的大图相册,内存直奔 2GB 。
现在的状态
Folio 目前已经完成了主要 MVP 功能,包括基础看图、多图并列、Exif 查看与擦除、批量重命名、格式转换、缓存、预览图、设置持久化和打包验证。
踩坑的地方
macOS 15 的图标
在 macOS 25 上,使用纯白色背景的图片使用下面命令就可以创建图标
1
| pnpx electron-icon-builder --input=resources/icon.png --output=resources --flatten
|
但是在 macOS 15 上面,装完发现是大大的直角方块,考虑到 Apple 的生态,15 的占有率应该很低了,本来没打算处理的,但是 Claude 给了我一个脚本就解决了。
mkicon.cjs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 用项目现成的 `sharp` 生成 macOS 形状的 1024 PNG。脚本(`mkicon.cjs`):
```js const sharp = require('sharp') const SRC = 'resources/icons/1024x1024.png' const OUT = process.argv[2] const C = 1024 // canvas const TILE = 952 // white squircle body (fills out near the edge) const OFF = (C - TILE) / 2 // 36 const R = Math.round(TILE * 0.2237) // ≈ 213
;(async () => { // 1) rounded mask for the tile const mask = Buffer.from( `<svg xmlns="http://www.w3.org/2000/svg" width="${TILE}" height="${TILE}"><rect x="0" y="0" width="${TILE}" height="${TILE}" rx="${R}" ry="${R}" fill="#fff"/></svg>`, ) const maskPng = await sharp(mask).png().toBuffer()
// 2) artwork resized to TILE and clipped to the rounded mask const tile = await sharp(SRC) .resize(TILE, TILE, { fit: 'cover' }) .composite([{ input: maskPng, blend: 'dest-in' }]) .png() .toBuffer()
// 3) soft drop shadow: a black rounded rect, shifted down, blurred const shadowSvg = Buffer.from( `<svg xmlns="http://www.w3.org/2000/svg" width="${C}" height="${C}"><rect x="${OFF}" y="${OFF + 8}" width="${TILE}" height="${TILE}" rx="${R}" ry="${R}" fill="rgba(0,0,0,0.32)"/></svg>`, ) const shadow = await sharp(shadowSvg).blur(13).png().toBuffer()
// 4) compose: transparent canvas -> shadow -> tile await sharp({ create: { width: C, height: C, channels: 4, background: { r: 0, g: 0, b: 0, alpha: 0 } } }) .composite([ { input: shadow, left: 0, top: 0 }, { input: tile, left: OFF, top: OFF }, ]) .png() .toFile(OUT) console.log('wrote', OUT) })().catch((e) => { console.error(e); process.exit(1) })
|
使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| cd apps/desktop
NODE_PATH="$(pwd)/node_modules:$(pwd)/../../node_modules" \ node /path/to/mkicon.cjs /tmp/icon-mac-1024.png
ISET=/tmp/Folio.iconset rm -rf "$ISET" && mkdir -p "$ISET" mk(){ sips -z "$2" "$2" /tmp/icon-mac-1024.png --out "$ISET/$1" >/dev/null; } mk icon_16x16.png 16 mk [email protected] 32 mk icon_32x32.png 32 mk [email protected] 64 mk icon_128x128.png 128 mk [email protected] 256 mk icon_256x256.png 256 mk [email protected] 512 mk icon_512x512.png 512 mk [email protected] 1024
iconutil -c icns "$ISET" -o resources/icons/icon.icns
|
HEIC、HEIF 与 JXL
APP 基于图片的支持能力很大程度上直接取决于 Chromium,在 macOS 上 HEIC、HEIF 与 JXL 走了 sips/imageIO 可以完成浏览, Windows 上目前还不支持。
JXL Chrome 已经恢复支持了,只是目前需要通过 chrome://flags 开启,但是 Electron 还不支持,我觉得可能等等就可以不需要使用第三方库,正常图片也是比较少的。
而 HEIF 的分发需要版权费,目前对于我自己的需求来说倒是暂时用不上。
先不考虑支持。
总结
Folio 是我给自己,也给有类似需求的人做的一款看图软件,界面。
它关注的不是“管理一整个照片库”,而是更直接的日常图片工作流:打开、浏览、对比、查看信息、清理隐私、重命名、转换格式。
如果你经常需要处理一堆图片,尤其是经常要对比多张图,Folio 应该会是一个挺顺手的工具。
已知问题
TODO
评论