gpt4 book ai didi

swift - 无法读取 PNG 文件的 IHDR block

转载 作者:行者123 更新时间:2023-11-30 10:49:49 24 4
gpt4 key购买 nike

我已经阅读了 PNG 文件规范,并了解到在 PNG 签名的前 8 个字节之后,我们有 IHDR block 。该图像表明我们的 IHDR 长度为 13(0x0000000D) 字节。 enter image description here

我已经用 swift 编写了一段代码来读取相同的 png 文件并打印字节,但这些字节不会为我提供长度等于 PNG 签名后 block 的前 4 个字节的 13 个字节的 IHDR。控制台中代码的输出是

PNG Signature Bytes: 89 50 4E 47 0D 0A 1A 0A 
File offset: 8
IHDR length bytes: 00 00 00 04
File offset: 12
IHDR Chunktype bytes: 43 67 42 49
File offset: 16
IHDR Data byte: 50 00 20 02
File offset: 20
pngImageWidth: 1342185474
pngImageWidth: 20480
pngImageHeight: 8194

我是否在这里遗漏了某些内容,或者我阅读的规范已过时?

前 8 个字节实际上是 PNG 签名字节。 IHDR 字节是我没有获得预期长度和 block 类型的地方(IHDR 的宽度、高度和其他字节对于不同的文件是可变的,但长度和 block 类型应该与我的阅读相同)。

读取 png 文件的代码很简单,如下所示:

enum PNGFileAnatomyConstants {
static let pngSignatureLength = 8
static let ihdrLength = 4
static let chunkTypeLength = 4
static let chunkCRCLength = 4
static let imageWidthLength = 4
static let imageHeigthLength = 4
}

func anatomyOfPNGFile() {
let bundle = Bundle.main

guard let pngFileUrl = bundle.url(forResource: "PNGFileSignature", withExtension: "png") else { fatalError() }

do {
// Signature start------------------------------------------------------------------------------------------

let readFileHandle = try FileHandle(forReadingFrom: pngFileUrl)
defer {
readFileHandle.closeFile()
}
let pngSignatureData = readFileHandle.readData(ofLength: PNGFileAnatomyConstants.pngSignatureLength)
let signatureString = pngSignatureData.hexEncodedString(options: [Data.HexEncodingOptions.upperCase])
if signatureString != "89 50 4E 47 0D 0A 1A 0A " {
fatalError(" Not a png")
}
print("PNG Signature Bytes: \(signatureString)")
print("File offset: \(readFileHandle.offsetInFile)")
// Signature ebd------------------------------------------------------------------------------------------




// IHDR Length start------------------------------------------------------------------------------------------
let ihdrLengthDataBigEndian = readFileHandle.readData(ofLength: PNGFileAnatomyConstants.ihdrLength)

let ihdrLength: UInt32
if PlatformEndianess.isLittleEndian {
ihdrLength = Data(ihdrLengthDataBigEndian.reversed()).withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt32>) -> UInt32 in
return unsafePointer.pointee
})
} else {
ihdrLength = ihdrLengthDataBigEndian.withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt32>) -> UInt32 in
return unsafePointer.pointee
})
}

let ihdrLengthDataBigEndianString = ihdrLengthDataBigEndian.hexEncodedString(options: [.upperCase])
print("IHDR length bytes: \(ihdrLengthDataBigEndianString)")
print("File offset: \(readFileHandle.offsetInFile)")
// IHDR Length end------------------------------------------------------------------------------------------





// IHDR chunk type start------------------------------------------------------------------------------------------
let ihdrChunkTypeData = readFileHandle.readData(ofLength: PNGFileAnatomyConstants.chunkTypeLength)
let ihdrChunkTypeDataString = ihdrChunkTypeData.hexEncodedString(options: [Data.HexEncodingOptions.upperCase])
print("IHDR Chunktype bytes: \(ihdrChunkTypeDataString)")
print("File offset: \(readFileHandle.offsetInFile)")
// IHDR chunk type end------------------------------------------------------------------------------------------



// IHDR data byte start------------------------------------------------------------------------------------------
let ihdrData = readFileHandle.readData(ofLength: Int(ihdrLength))
let ihdrDataString = ihdrData.hexEncodedString(options: [.upperCase])
print("IHDR Data byte: \(ihdrDataString)")
print("File offset: \(readFileHandle.offsetInFile)")
// IHDR data byte end------------------------------------------------------------------------------------------

do {
let pngImageWidth: UInt32
if PlatformEndianess.isLittleEndian {
pngImageWidth = Data(ihdrData.reversed()).withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt32>) -> UInt32 in
return unsafePointer.pointee
})
} else {
pngImageWidth = ihdrData.withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt32>) -> UInt32 in
return unsafePointer.pointee
})
}

print("pngImageWidth: \(pngImageWidth)")
}

do {
let pngImageWidth: UInt16
let widthData = Data(bytes: [ihdrData[0], ihdrData[1]])
if PlatformEndianess.isLittleEndian {

pngImageWidth = Data(widthData.reversed()).withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt16>) -> UInt16 in
return unsafePointer.pointee
})
} else {
pngImageWidth = widthData.withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt16>) -> UInt16 in
return unsafePointer.pointee
})
}

print("pngImageWidth: \(pngImageWidth)")//20480

let pngImageHeight: UInt16
let heightData = Data(bytes: [ihdrData[2], ihdrData[3]])
if PlatformEndianess.isLittleEndian {

pngImageHeight = Data(heightData.reversed()).withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt16>) -> UInt16 in
return unsafePointer.pointee
})
} else {
pngImageHeight = heightData.withUnsafeBytes({ (unsafePointer: UnsafePointer<UInt16>) -> UInt16 in
return unsafePointer.pointee
})
}

print("pngImageHeight: \(pngImageHeight)")//20480
}

} catch {
fatalError(error.localizedDescription)
}
}

extension Data {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}

func hexEncodedString(options: HexEncodingOptions = []) -> String {
let hexDigits = Array((options.contains(.upperCase) ? "0123456789ABCDEF " : "0123456789abcdef ").utf16)
var chars: [unichar] = []
chars.reserveCapacity(3 * count)
for byte in self {
chars.append(hexDigits[Int(byte / 16)])
chars.append(hexDigits[Int(byte % 16)])
chars.append(hexDigits.last!)
}
return String(utf16CodeUnits: chars, count: chars.count)
}
}

class PlatformEndianess {
static var isLittleEndian: Bool = {
var integer: UInt16 = 0x0001
return withUnsafeBytes(of: &integer, { (rawBufferPointer) -> Bool in
return rawBufferPointer.first == 0x01
})
}()
}

最佳答案

正如 MartinR 所指出的PNG 文件存在一个名为 CgBI 的扩展名。

普通 PNG 文件的结构是 PNG 签名后跟 IHDR block 。

下面是普通 PNG 文件的十六进制表示形式的字节示例( xx 是具有变量值的占位符字节):

PNG Signature(8 bytes): 89 50 4E 47 0D 0A 1A 0A
=======Chunk start=======
IHDR Chunk:
IHDR chunk length(4 bytes): 00 00 00 0D
IHDR chunk type(Identifies chunk type to be IHDR): 49 48 44 52
Image width in pixels(variable 4): xx xx xx xx
Image height in pixels(variable 4): xx xx xx xx
Flags in the chunk(variable 5 bytes): xx xx xx xx xx
CRC checksum(variable 4 bytes): xx xx xx xx
=======Chunk end=======

具有 CgBI 扩展名的 PNG 文件具有这样的结构:PNG 签名后跟 CgBI block ,然后是 IHDR block 。

当我说扩展名时,请不要将其与“filename.png、filename.cgbi”混淆。它实际上是 PNG 文件结构方式的扩展。

下面是带有 CgBI 扩展名的 PNG 文件的十六进制表示字节示例(xx 是具有变量值的占位符字节):

PNG Signature(8 bytes): 89 50 4E 47 0D 0A 1A 0A
=======Chunk start=======
CgBI Chunk:
CgBI chunk length(4 bytes): 00 00 00 04
CgBI chunk type(Identifies chunk type to be CgBI): 43 67 42 49
CgBI info flags(4 bytes): xx xx xx xx
CRC checksum(variable 4 bytes): xx xx xx xx
=======Chunk end=======
=======Chunk start=======
IHDR Chunk:
IHDR chunk length(4 bytes): 00 00 00 0D
IHDR chunk type(Identifies chunk type to be IHDR): 49 48 44 52
Image width in pixels(variable 4): xx xx xx xx
Image height in pixels(variable 4): xx xx xx xx
Flags in the chunk(variable 5 bytes): xx xx xx xx xx
CRC checksum(variable 4 bytes): xx xx xx xx
=======Chunk end=======

虽然 PNG 文件可以在所有图像查看器上呈现,但扩展名 CgBI 可能会也可能不会在所有图像查看器上呈现,具体取决于它们为此类文件提供的支持。

MacOS 预览可以显示此类图像,iOS 上的 UIImageView 也可以显示我的示例图像集中的文件(带有 CgBI 扩展名的 PNG)。

关于swift - 无法读取 PNG 文件的 IHDR block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54845745/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com