在我的一个项目中,我需要为服务器上的图像生成一些占位符,以嵌入到 json 文件中提供给客户端。这些占位符稍后将被作为常规图像文件单独下载的实际对应部分替换。
该设置限制我将占位符嵌入 json 中的 Base64 编码。 占位符必须为 RGB,并且与要替换的实际图像具有相同的尺寸。这些尺寸范围最大约为 8192x8192 像素。相同大小的两个不同图片的占位符必须不同(至少base64编码的字符串必须不同)。它们还必须可由任何浏览器读取。
我怀疑一定存在一种图像编码形式,它几乎可以归结为:
这应该会导致少于 100 个 base64 字符。
但我就是找不到一种方法来实现这种压缩,或者至少改进我所拥有的。
目前,我使用 Sharp 通过以下代码生成这些占位符:
async function placeHolderFor(width: number, height: number, index: number) : Promise<Buffer> {
const v = 255 - index;
const buf = await sharp({
create: {
width: width,
height: height,
channels: 4,
background: { r: v, g: v, b: v, alpha: 1 }
}
})
.avif({ quality: 1 })
.toBuffer();
return buf;
}
然后将缓冲区转换为 base64 :
const buf = placeHolderFor(2048, 2048, 1);
const base64 = 'data:image/avif;base64,' + buf.toString('base64');
我对编码的格式和选项进行了很多修改,主要使用 2048x2048 作为尺寸进行测试。
到目前为止,我想出的最好的方法是质量最差的 avif 编码,它为我提供了 528 个八位字节缓冲区,转换为 727 个字符的 Base64 字符串。
事实证明我那天谷歌搜索非常糟糕。
在这里找到答案:https://cloudinary.com/blog/a_one_color_image_is_worth_two_thousand_words
迄今为止,最广泛支持的纯色图像格式是无损 webp,在使用 Sharp 生成压缩 2048x2048 图像后,它为我提供了一个 340px base64 字符串:
const buf = await sharp({
create: {
width: 2048,
height: 2048,
channels: 4,
background: { r: 255, g: 255, b: 255, alpha: 1 }
}
})
.webp({ lossless: true })
.toBuffer();
const base64 = 'data:image/webp;base64,' + buf.toString('base64');
console.log(base64);
此外,无论图像大小如何,FLIF 似乎都是编码前输出 19 字节的首选格式。浏览器不支持此格式。不过,根据 caniuse.com 的说法:
[它已]被 JPEG XL 取代,后者正在浏览器中实现