| 
									
										
										
										
											2019-01-28 14:23:59 +03:00
										 |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"encoding/binary" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2019-01-29 19:43:12 +03:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2019-01-28 14:23:59 +03:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-05 23:32:32 +03:00
										 |  |  | 	report() | 
					
						
							| 
									
										
										
										
											2019-01-29 19:43:12 +03:00
										 |  |  | 	img = append([]byte(nil), img[:24]...) | 
					
						
							| 
									
										
										
										
											2019-03-05 23:32:32 +03:00
										 |  |  | 	// img = img[:24:24] // unnecessary | 
					
						
							|  |  |  | 	report() | 
					
						
							| 
									
										
										
										
											2019-01-29 19:43:12 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// 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} | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-01-28 14:23:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// ------------------------------------------ | 
					
						
							|  |  |  | 	// 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])) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-29 19:43:12 +03:00
										 |  |  | func report() { | 
					
						
							|  |  |  | 	var m runtime.MemStats | 
					
						
							|  |  |  | 	runtime.GC() | 
					
						
							|  |  |  | 	runtime.ReadMemStats(&m) | 
					
						
							|  |  |  | 	fmt.Printf(" > Memory Usage: %v KB\n", m.Alloc/1024) | 
					
						
							| 
									
										
										
										
											2019-01-28 14:23:59 +03:00
										 |  |  | } |