有没有办法使用节点来做到这一点,无论是本地还是通过插件?
我想要完成的是根据输入类型选择无损或有损图像压缩。大型 JPEG 的无损存储是一场存储灾难。
PNG 文件的前八个字节始终包含以下值 - 请参阅 PNG 规范:
(decimal) 137 80 78 71 13 10 26 10
(hexadecimal) 89 50 4e 47 0d 0a 1a 0a
(ASCII C notation) \211 P N G \r \n \032 \n
因此,如果我从任何 PNG 文件的开头取出 8 个字节并按如下方式对其进行 base64 编码,我会得到:
head -c8 test.png | base64
iVBORw0KGgo=
每个 JPEG 文件的前 2 个字节都包含十六进制的
ff
d8
- 请参阅 Wikipedia 条目中的 JPEG。因此,如果我采用任何 JPEG 文件并对前两个字节进行如下 base64 编码,我会得到:
head -c2 test.jpg | base64
/9g=
所以我的建议是查看你的base64编码文件的前几个(10个
PNG
和2个JPEG
,总是排除=
)字符,看看它们是否符合我的建议,然后使用它作为决定因素 - 如果您的字符串不匹配,请确保输出错误消息,以防测试由于某种原因不够彻底!
为什么 PNG 是 10 个字符?因为保证签名是8个字节,即64位,而base64一次分割成6位来生成一个字符,所以前10个字符是前60位。第 11 个字符将根据签名后面的内容而有所不同。
JPEG 的逻辑相同...2 个字节是 16 位,这意味着保证每个字符对应 6 位 2 个字符。第三个字符将根据 2 字节 SOI 标记后面的内容而变化。
@MarkSetcell 的上面的答案在理论上是正确的。 然而,实际上,它不适用于 JPG!
确实
head -c2 test.jpg | base64
会产生 /9g
但是
head -c3 test.jpg | base64`
/9j/
因此,如果您想“确定 Base64 字符串或缓冲区是否包含 JPEG”,您需要测试它是否以
/9j
开头,而不是 /9g
!
检查幻数标题不会检查图像是否已损坏。
Png 文件具有指定的内部结构,其中的块具有 crc 错误检查代码,因此您可以检查 png 文件是否损坏。我有一个很小的 npm 库可以在这里执行此操作:https://www.npmjs.com/package/png-validator
它检查所有内部标头和数据块是否有效。因此,如果您这样做,您可以非常确定您正在处理有效的 png 文件。
我发现的唯一对 jpg 进行深度扫描的 js 实现是:https://github.com/image-size/image-size/blob/main/lib/types/jpg.ts
我还没有尝试过适应它。
在浏览器中,您可以使用 Image 构造函数来加载图像,如果浏览器加载图像失败,则图像实例将发出错误事件,如果成功则发出 load 事件。
const image = new Image();
image.src = url;
const promise = Promise((resolve, reject) => {
image.addEventListener("error", () => resolve(false));
image.addEventListener("load", () => resolve(true));
});