Files
2019-10-30 19:41:13 +03:00

100 lines
2.6 KiB
Go

// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"os"
"runtime"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("run with a PNG file")
return
}
// this is not the best way
// it's better only to read the first 24 bytes
// this reads the whole file into memory
img, err := ioutil.ReadFile(args[0])
if err != nil {
fmt.Println(err)
return
}
report()
img = append([]byte(nil), img[:24]...)
// img = img[:24:24] // unnecessary
report()
// s.PrintBacking = true
// s.MaxPerLine = 8
// s.MaxElements = 24
// s.PrintBytesHex = true
// s.Show("first 24 bytes", img)
var (
pngHeader = [...]byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}
ihdrChunkType = [...]byte{0x49, 0x48, 0x44, 0x52}
)
// ------------------------------------------
// Read the PNG header
// https://www.w3.org/TR/2003/REC-PNG-20031110/#5PNG-file-signature
// ------------------------------------------
lpng := len(pngHeader)
if !bytes.Equal(img[:lpng], pngHeader[:]) {
fmt.Println("missing PNG header")
return
}
// skip the png header
img = img[lpng:]
// ------------------------------------------
// Read the IHDR chunk header
// The IHDR chunk shall be the first chunk in the PNG datastream.
// https://www.w3.org/TR/2003/REC-PNG-20031110/#11IHDR
// ------------------------------------------
header := img[:8] // get the length and chunk type
// ensure that the chunk type is IHDR
if !bytes.Equal(header[4:8], ihdrChunkType[:]) {
fmt.Println("missing IHDR chunk")
return
}
// ------------------------------------------
// Read the IHDR Chunk Data
// ------------------------------------------
img = img[len(header):] // skip the IHDR chunk header data
ihdr := img[:8] // read the width&height from the ihdr chunk
// All integers that require more than one byte shall be in:
// network byte order = Big Endian
// https://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order
fmt.Printf("dimensions: %dx%d\n",
// read the first 4 bytes (width)
binary.BigEndian.Uint32(ihdr[:4]),
// read the next 4 bytes (height)
binary.BigEndian.Uint32(ihdr[4:8]))
}
func report() {
var m runtime.MemStats
runtime.GC()
runtime.ReadMemStats(&m)
fmt.Printf(" > Memory Usage: %v KB\n", m.Alloc/1024)
}