我正在使用 NSURLRequest 下载 jpg 和 png。这工作正常,但有时文件已损坏。我已经看到了捕捉错误:损坏的 JPEG 数据:数据段的过早结束,并且这适用于 jpgs。有谁知道对pngs做同样的事情的方法?即以编程方式检查png数据是否有效......
问问题
2240 次
3 回答
7
PNG 格式有几个内置检查。每个“块”都有一个 CRC32 检查,但要检查您是否需要阅读完整的文件。
更基本的检查(当然不是万无一失的)是读取文件的开头和结尾。
前 8 个字节应始终是以下(十进制)值{ 137, 80, 78, 71, 13, 10, 26, 10 }
(ref)。特别是,第二到第四个字节对应于 ASCII 字符串“PNG”。
十六进制:
89 50 4e 47 0d 0a 1a 0a
.. P N G ...........
您还可以检查文件的最后 12 个字节(IEND 块)。中间 4 个字节应对应 ASCII 字符串“IEND”。更具体地说,最后 12 个字节应该是(以十六进制表示):
00 00 00 00 49 45 4e 44 ae 42 60 82
........... I E N D ...........
(严格来说,PNG 文件以这 12 个字节结束并不是必须的,IEND 块本身表示 PNG 流的结束,因此文件原则上可以有额外的尾随字节,PNG 阅读器会忽略这些字节。在实践中,这是极不可能的)。
于 2012-05-11T16:16:10.550 回答
2
正如捕捉错误:损坏的 JPEG 数据:数据段的过早结束这里是 PNG 的代码片段:
- (BOOL)dataIsValidPNG:(NSData *)data
{
if (!data || data.length < 12)
{
return NO;
}
NSInteger totalBytes = data.length;
const char *bytes = (const char *)[data bytes];
return (bytes[0] == (char)0x89 && // PNG
bytes[1] == (char)0x50 &&
bytes[2] == (char)0x4e &&
bytes[3] == (char)0x47 &&
bytes[4] == (char)0x0d &&
bytes[5] == (char)0x0a &&
bytes[6] == (char)0x1a &&
bytes[7] == (char)0x0a &&
bytes[totalBytes - 12] == (char)0x00 && // IEND
bytes[totalBytes - 11] == (char)0x00 &&
bytes[totalBytes - 10] == (char)0x00 &&
bytes[totalBytes - 9] == (char)0x00 &&
bytes[totalBytes - 8] == (char)0x49 &&
bytes[totalBytes - 7] == (char)0x45 &&
bytes[totalBytes - 6] == (char)0x4e &&
bytes[totalBytes - 5] == (char)0x44 &&
bytes[totalBytes - 4] == (char)0xae &&
bytes[totalBytes - 3] == (char)0x42 &&
bytes[totalBytes - 2] == (char)0x60 &&
bytes[totalBytes - 1] == (char)0x82);
}
于 2012-10-04T11:42:29.763 回答
0
更好的 dataIsValidPNG 版本:
BOOL dataIsValidPNG(NSData *data) {
if (!data) {
return NO;
}
const NSInteger totalBytes = data.length;
const char *bytes = (const char *)[data bytes];
const char start[] = { '\x89', 'P', 'N', 'G', '\r', '\n', '\x1a', '\n' };
const char end[] = { '\0', '\0', '\0', '\0', 'I', 'E', 'N', 'D', '\xAE', 'B', '`', '\x82' };
if (totalBytes < (sizeof(start) + sizeof(end))) {
return NO;
}
return (memcmp(bytes, start, sizeof(start)) == 0) &&
(memcmp(bytes + (totalBytes - sizeof(end)), end, sizeof(end)) == 0);
}
于 2015-10-06T23:52:00.763 回答