Picset/文章中心/AI玩法
AI玩法

大尺寸 PNG 不等于好图:用 CRC 检查结构,不替内容评分

大尺寸 PNG 可以先接受块结构与 CRC 检查,但检查通过不证明画面清楚、文字准确或商品真实。下面用 Node.js 验证签名、块边界、CRC 与 IEND 收尾,让截断和部分字节变化可追踪。它是结构检查示例,不是完整 PNG 解码器,更不是图像质量评分器。

Picset 内容研究组 · 发布/核验于 2026年10月9日 · 约 3 分钟阅读
大尺寸 PNG 不等于好图:用 CRC 检查结构,不替内容评分
简要回答

大尺寸 PNG 可以先接受块结构与 CRC 检查,但检查通过不证明画面清楚、文字准确或商品真实。下面用 Node.js 验证签名、块边界、CRC 与 IEND 收尾,让截断和部分字节变化可追踪。它是结构检查示例,不是完整 PNG 解码器,更不是图像质量评分器。

  大尺寸 PNG 可以先接受块结构与 CRC 检查,但检查通过不证明画面清楚、文字准确或商品真实。下面用 Node.js 验证签名、块边界、CRC 与 IEND 收尾,让截断和部分字节变化可追踪。它是结构检查示例,不是完整 PNG 解码器,更不是图像质量评分器。

  PNG 文件以签名和多个块组织,宽高信息只占其中一部分。若只读取头部,一个尺寸看起来很大的文件仍可能在后面损坏。因此交付检查应分别记录声明尺寸、结构状态、实际解码与内容审核,不使用一个合格布尔值覆盖所有不同层次。[1]

逐块检查,不根据像素数猜质量

  示例读取每块长度,先确认块不会越过文件边界,再对类型与数据计算 CRC。首块需要是长度13的 IHDR,最后需要空 IEND,且后面不能有额外字节。代码保存为 png-chunks.mjs,导入 checkPngChunks,将读到的 Buffer 传入;程序只返回检查结果,不修改原文件。

大尺寸 PNG 不等于好图:用 CRC 检查结构,不替内容评分:块边界、CRC校验、内容边界示意
块边界 · CRC校验 · 内容边界
function crc32(bytes) {
  let crc=0xffffffff;
  for (const byte of bytes) {
    crc ^= byte;
    for (let i=0;i<8;i++) crc=(crc>>>1)^((crc&1)?0xedb88320:0);
  }
  return (crc^0xffffffff)>>>0;
}
export function checkPngChunks(b) {
  const sig=Buffer.from([137,80,78,71,13,10,26,10]);
  if (b.length<8 || !b.subarray(0,8).equals(sig)) throw Error('signature');
  let offset=8, count=0, ended=false;
  while (offset<b.length) {
    if (b.length-offset<12) throw Error('truncated chunk');
    const length=b.readUInt32BE(offset), end=offset+12+length;
    if (end>b.length) throw Error('chunk outside file');
    const type=b.toString('ascii',offset+4,offset+8);
    if (count===0 && (type!=='IHDR'||length!==13)) throw Error('first chunk');
    const actual=crc32(b.subarray(offset+4,end-4));
    if (actual!==b.readUInt32BE(end-4)) throw Error('CRC mismatch: '+type);
    count++; offset=end;
    if (type==='IEND') { if(length!==0) throw Error('IEND length'); ended=true; break; }
  }
  if (!ended || offset!==b.length) throw Error('missing IEND or trailing bytes');
  return { chunks:count, crcValid:true };
}

  CRC 计算针对字节,不理解图片内容。它有助于发现传输或存储变化,却不能防止攻击者重新计算 CRC,也不能说明数据符合所有 PNG 规则。示例没有校验色彩类型、位深组合、IDAT顺序、解压上限或完整块语义,不能将 crcValid 改名成 pngFullyValid。

运行正常、修改与截断样例

  本次用 Pillow 生成一张纯色 PNG,并在 Node.js v24.16.0 下检查。正常文件通过;修改头部内一个字节而不更新 CRC,返回 CRC mismatch;截断到未完成的块被拒绝;IEND之后增加额外字节也被拒绝。这些测试覆盖指定边界,不包含所有恶意或极端 PNG。

  代码对全文件逐字节计算,适合说明算法,不用于证明大型文件性能。实际服务应在读入前限制字节数,解码时限制资源使用,并选可靠库处理格式。超大声明尺寸和压缩数据可能带来额外风险,不能因为 CRC 正确就省略安全解码层。

  通过结构检查后,还要打开图像看实际细节。生成标签的错字、重复纹理和主体变化不会让 CRC 报错;它们在文件层面完全正常。反过来,一个结构错误也不需要先请审核者判断商品颜色,程序可以将其作为文件异常交给下载或输出环节处理。

  Picset 等图像制作工作流可以把这类只读检查放在导出之后,[2] 本文没有验证特定工具输出,也不声称 CRC 是其内置能力。对不同格式要使用对应解析,不通过改后缀让 JPEG 或 WebP 进入 PNG 流程。文件清单与商品身份同样需要可靠业务对应。

  最终交付记录宜写明结构检查范围,再接实际解码、商品事实和渠道预览。这样一张大图不会因为像素多被自动放行,也不会因为技术字段通过就被称为真实实拍。代码负责发现它能解释的错误,内容判断继续由可靠材料与审核过程承担。

参考资料