iOS 上的 PNG 验证
使用 OpenStreetMap 图块在 iOS 上编写地图应用程序。 地图切片图像异步下载并存储在字典中,或保留在 SQLite DB 中。
有时,无论出于何种原因,在尝试渲染地图图块图像时,我都会收到以下错误:ImageIO:<错误> PNG无效距离太远
这会导致我的地图上出现令人讨厌的黑色方块。
这是发生这种情况的代码片段:
NSData *imageData = [TileDownloader RetrieveDataAtTileX:(int)tilex Y:(int)tiley Zoom:(int)zoomLevel];
if (imageData != nil) {
NSLog(@"Obtained image data\n");
UIImage *img = [[UIImage imageWithData:imageData] retain];
// Perform the image render on the current UI context.
// ERROR OCCURS BETWEEN PUSH AND POP
UIGraphicsPushContext(context);
[img drawInRect:[self rectForMapRect:mapRect] blendMode:kCGBlendModeNormal alpha:1.0f];
UIGraphicsPopContext();
[img release];
}
现在,我正在寻找一种方法来确保在尝试将 png 渲染到我的地图之前它是有效的。
编辑:系统偶尔也会抛出此错误:ImageIO:<错误> PNGIDAT:CRC 错误
Writing a mapping application on iOS, making use of OpenStreetMap tiles.
Map tile images are downloaded asynchronously and stored in a dictionary, or persisted in a SQLite DB.
Occasionally, for whatever reason, while attempting to render a map tile image, I get the following error:ImageIO: <ERROR> PNGinvalid distance too far back
This causes nasty black squares to appear over my map.
This is the piece of code in which this occurs:
NSData *imageData = [TileDownloader RetrieveDataAtTileX:(int)tilex Y:(int)tiley Zoom:(int)zoomLevel];
if (imageData != nil) {
NSLog(@"Obtained image data\n");
UIImage *img = [[UIImage imageWithData:imageData] retain];
// Perform the image render on the current UI context.
// ERROR OCCURS BETWEEN PUSH AND POP
UIGraphicsPushContext(context);
[img drawInRect:[self rectForMapRect:mapRect] blendMode:kCGBlendModeNormal alpha:1.0f];
UIGraphicsPopContext();
[img release];
}
Now, what I'm looking for is a way to ensure a png is valid before attempting to render it to my map.
Edit: The system also occasionally throws this error:ImageIO: <ERROR> PNGIDAT: CRC error
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我在其他问题中发现了这一点,并将为我解决问题的内容放在一起。希望您觉得这有帮助。
PNG 格式有几个内置检查。每个“块”都有 CRC32 检查,但要检查您需要读取完整文件。
更基本的检查(当然不是万无一失的)是读取文件的开头和结尾。
前 8 个字节应始终为以下(十进制)值 { 137, 80, 78, 71, 13, 10, 26, 10 } (参考)。特别地,第二到第四字节对应于ASCII字符串“PNG”。
以十六进制表示:
您还可以检查文件的最后 12 个字节(IEND 块)。中间 4 个字节应对应于 ASCII 字符串“IEND”。更具体地说,最后 12 个字节应该是(十六进制):(
严格来说,PNG 文件并不一定必须以这 12 个字节结尾,IEND 块本身表示 PNG 流的结束,因此文件原则上可以有额外的尾随字节,PNG 阅读器会忽略这些字节,但实际上,这是极不可能的)。
这是一个实现:
I found this in other question and put together what solved the issue for me. Hope you find this helpful.
The PNG format has several built in checks. Each "chunk" has a CRC32 check, but to check that you'd need to read the full file.
A more basic check (not foolproof, of course) would be to read the start and ending of the file.
The first 8 bytes should always be the following (decimal) values { 137, 80, 78, 71, 13, 10, 26, 10 } (ref). In particular, the bytes second-to-fourth correspond to the ASCII string "PNG".
In hexadecimal:
You can also check the last 12 bytes of the file (IEND chunk). The middle 4 bytes should correspond to the ASCII string "IEND". More specifically the last 12 bytes should be (in hexa):
(Strictly speaking, it's not really obligatory for a PNG file to end with those 12 bytes, the IEND chunk itself signals the end of the PNG stream and so a file could in principle have extra trailing bytes which would be ignored by the PNG reader. In practice, this is extremely improbable).
Here is an implementation:
我知道这是一个超级旧的线程,但我一直在寻找一个 NSData 扩展,它实际上验证了 PNG 数据块中的 crc32。由于没有找到,我从其他来源改编了一个。
这实际上会标记坏的 PNG CRC,大多数图像库都没有这样做(令人震惊)
I know this is a super old thread, but I was looking around for an NSData extension that actually validated the crc32's in the PNG data chunks. Having not found one, I adapted one from some other source.
This will actually flag bad PNG CRC's, which isn't done (shockingly) by most image libraries
从我自己的异步下载队列管理器切换到 All Seeing I 实现。问题变成了一个有争议的问题。
Switched from my own Asynchronous Download Queue Manager to the All Seeing I implementation. Problem became a moot point.