Skip to content

Instantly share code, notes, and snippets.

@kujirahand
Created August 1, 2020 10:10
Show Gist options
  • Save kujirahand/75fb8af64c494abc089fbb96e6eb2774 to your computer and use it in GitHub Desktop.
Save kujirahand/75fb8af64c494abc089fbb96e6eb2774 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/binary"
"io"
"io/ioutil"
)
// 手軽にnバイト読み込む関数を定義
func readN(r io.Reader, n int) []byte {
buf := make([]byte, n)
cnt, err := r.Read(buf)
if err != nil || n != cnt {
return []byte{}
}
return buf
}
// 4byte整数を読む関数を定義
func readInt32(r io.Reader) int {
return int(binary.BigEndian.Uint32(readN(r, 4)))
}
func main() {
// ファイルを全部メモリに読み込む --- (*1)
buf, err := ioutil.ReadFile("tea.png")
if err != nil {
return
}
// 先頭のPNGシグネチャを取り込む --- (*2)
r := bytes.NewReader(buf)
if !bytes.Equal(readN(r, 8), []byte("\x89PNG\r\n\x1a\n")) {
println("PNGファイルではありません")
return
}
// 複数のチャンクを繰り返し読む --- (*3)
for {
// サイズ、タイプ、データ、CRCを順に読む --- (*4)
chunkLen := readInt32(r)
chunkType := string(readN(r, 4))
data := readN(r, chunkLen)
_ = readInt32(r) // CRC32
println("[CHUNK]", chunkType)
// IHDRチャンクの時 --- (*5)
if chunkType == "IHDR" {
rd := bytes.NewReader(data)
width := readInt32(rd)
height := readInt32(rd)
println("width=", width)
println("height=", height)
} else if chunkType == "IEND" {
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment