确定base64字符串或缓冲区是否包含没有元数据的JPEG或PNG?可能吗?

问题描述 投票:0回答:3

有没有办法使用节点来做到这一点,无论是本地还是通过插件?

我想要完成的是根据输入类型选择无损或有损图像压缩。大型 JPEG 的无损存储是一场存储灾难。

javascript node.js image ecmascript-6 base64
3个回答
14
投票

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 标记后面的内容而变化。


1
投票

@MarkSetcell 的上面的答案在理论上是正确的。 然而,实际上,它不适用于 JPG!

确实

head -c2 test.jpg | base64
会产生
/9g

但是

head -c3 test.jpg | base64`
/9j/

因此,如果您想“确定 Base64 字符串或缓冲区是否包含 JPEG”,您需要测试它是否以

/9j
开头,而不是
/9g


0
投票

检查幻数标题不会检查图像是否已损坏。

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));
});
© www.soinside.com 2019 - 2024. All rights reserved.