继上次尝试用纯浏览器生成视频之后,我最近又做了一个新尝试,使用纯浏览器端处理图片并打包成ZIP,简单的图片处理并不是什么难题,关键是打包的实现,不过经过验证发现是完全可行的。

先简单看下成果

Image

Image

https://feathertools.top/number-images

功能介绍

这是一个批量为图片加数字/字母序号标注的在线工具,虽然是在线工具,但是文件并不会上传到服务器,只是加载到浏览器内存里面,后面的图片处理和打包下载也都是完全本地实现的,主打一个数据安全。

工具支持对选择的图片进行拖拽排序并对序号的类型,起始值,以及外观和位置做简单的自定义。

字母类型序号可以支持到 Excel 那种列名的形式 A, B, AA, AB, AC…,只要电脑内存够大,理论上是可以处理很多图片的,

想法来源

早在十几年前,当我媳妇还是女朋友的时候,我帮她给论文用的图片素材添加标号时,PS 了半天都没搞定,非常丢脸,后来用 Python PIL 实现了,才渡过了难关。

最近做工具站时,想到可能别人的女朋友也有类似的需求,又玩不转P图工具,没有趁手的软件,使用其它在线工具又担心自己的资料泄露。那狗哥我的工具就很适合了,这个功德我得做。

Image

https://www.anl.gg/post/134-draw-char-in-picture-using-pil/

技术细节

虽然部分代码是 AI 写的,但是我自己也是参与了技术细节的,这里简单分享一下。

1. 图片排序

最开始的拖拽排序是用 dragstart, dragenter, dragend 事件实现的,但是在移动端测试时,发现不工作,后来又加入了 touch 相关事件的支持,但是还是问题多多,后来查询资料后才发现可以使用 pointerdown, pointermove, pointerup 来替代 drag 和 touch 事件来兼容桌面端和移动端。

Image

2. 字母序号生成

为了支持 A, B, AC, AD, AAA 这样 Excel 风格的序号,写了一个简单的方法。

function numberToLetter(number) {
    if (number <= 0) return '';
    
    const remainder = number % 26 || 26;
    const letter = String.fromCharCode(64 + remainder);
    const quotient = Math.floor((number - 1) / 26);
    
    return numberToLetter(quotient) + letter;
}

3. 为图片生成 blob URL

因为可能涉及比较多数据或者比较大图片的处理,我又没有做上传的功能,为了方便图片显示,为图片生成了 Blob URL,类似下面的 URL,用于图片显示。

blob:https://feathertools.top/9d8ec45c-57ce-4685-b728-530a76e95918

function getBlob(canvas, quality = 0.9) {
    return new Promise((resolve) => {
        canvas.toBlob(resolve, 'image/png', quality);
    });
}

const processedBlob = await getBlob(canvas);
URL.createObjectURL(processedBlob);

按理说,生成了 Blob URL,应该在合适的时机销毁的,但是我目前还没有想到比较合适的时机,只能暂时寄希望于标签页关闭了。

URL.revokeObjectURL(objectURL)

4. 打包 ZIP

为了方便下载处理后的图片,需要将文件打包成 ZIP,这里使用了 JSZip 这个包。

const zip = new JSZip();
for (let i = 0; i < processedImages.length; i++) {
    const image = processedImages[i];
    zip.file(`image_${i + 1}_${image.name}`, image.processedBlob);
}

// Generate the zip file and trigger download
const content = await zip.generateAsync({ type: 'blob' });
downloadFile(content, 'processed_images.zip');

文章同步发表于微信公众号老狗拾光,欢迎关注。

微信公众号老狗拾光