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