[post external=”true” cid=”” title=”一个在线生成指定大小、尺寸图片的工具” url=”https://zhuanlan.zhihu.com/p/592145905″ cover=”https://s1.ax1x.com/2023/05/08/p9wweo9.png” /]
在测试一些上传功能时需要几张满足边界值的图片方便我们测试,但主流方案要么不满足要求,要么生成图片步骤麻烦,其实原生 JavaScript
就能实现生成指定大小、尺寸的图片,代码也非常简单,使用 canvas
配合 ArrayBuffer
就能实现。
之前在写一个上传功能,要求上传的图片宽高必须小于 600×600,同时大小必须小于 5MB,那么我们就需要有这样几个用例来覆盖
1、宽高为 500×500,大小为 4MB。测试通过
2、宽高为 800×800,大小为 4MB。测试失败,且提示图片宽高超出限制
3、宽高为 500×500,大小为 6MB,测试失败,且提示图片大小超出限制
4、宽高为 800×800,大小为 6MB,测试失败,且提示图片宽高超出限制、大小超出限制
5、宽高为 500×800,大小为 4MB,测试失败,且提示图片高度超出限制
…
要覆盖全部的场景大概需要八九张图片,有些同学可能会想到 dummyimage,只需要一个链接就能得到指定宽高的图片,例如 http://dummyimage.com/300 将会返回一张 300×300 的图片,下载到本地就可以进行测试了,缺点是无法指定大小,无法满足上述要求。
另外还能搜索到的方案是先使用 ps 或一些工具生成指定尺寸的图片,再使用 linux
下 dd
命令,生成一个「目标大小减去图片大小」的空文件,再使用 cat
命令将空文件追加到图片文件中。
dd if=/dev/zero of=result bs=5189934 count=1
cat empty >> image.jpeg
上面两行命令,第一行是生成 5189934 字节的空文件,因为第一步使用 ps 创建的图片大小是 52946 字节,目标大小是 5MB,(52946 + 5189934) / 1024 / 1024 === 5;第二行是将空文件追加到图片中,不影响图片展示的同时,大小变为目标大小。
这种方法能够实现,但比较麻烦。
其实在网页上使用 JavaScript
就能实现需求
1、先渲染一个指定宽高的 canvas
2、获取到 canvas 节点,调用 toBlob
拿到该宽高图片的二进制数据
3、计算大小还需要补多少
4、使用 ArrayBuffer 生成指定大小的二进制数据
5、拼接图片的二进制与指定大小的二进制
6、下载即可
function createImage(targetSize, $canvas) {
$canvas.toBlob((blob) => {
if (blob === null) {
return;
}
const { size } = blob;
const target = targetSize;
const remaining = target - size;
if (remaining < 0) {
return;
}
// 2、获取到 canvas 二进制数据
blob.arrayBuffer().then((buf) => {
// 4、生成指定大小的二进制数据
const padding = new ArrayBuffer(remaining);
const longInt8View = new Uint8Array(padding);
for (var i = 0; i < longInt8View.length; i++) {
longInt8View[i] = i % 255;
}
// 5、拼接图片与空文件
const file = new Blob([buf, padding]);
// 6、下载
const url = URL.createObjectURL(file);
const $a = document.createElement("a");
$a.download = 'filename.jpg';
$a.href = url;
$a.click();
});
});
}