You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
5 years ago
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"hash/crc32"
|
||
|
"log"
|
||
|
"os"
|
||
|
)
|
||
|
|
||
|
type ChunkData struct {
|
||
|
length uint32
|
||
|
name string
|
||
|
data []byte
|
||
|
crc uint32
|
||
|
raw []byte
|
||
|
}
|
||
|
|
||
|
|
||
|
// validates the png by reading the header of the file
|
||
|
func ValidatePng(f *os.File) (bool, []byte) {
|
||
|
headerBytes := make([]byte, 8)
|
||
|
_, err := f.Read(headerBytes)
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
firstByteMatch := headerBytes[0] == 0x89
|
||
|
pngAsciiMatch := string(headerBytes[1:4]) == "PNG"
|
||
|
dosCRLF := headerBytes[4] == 0x0d && headerBytes[5] == 0x0a
|
||
|
dosEof := headerBytes[6] == 0x1a
|
||
|
unixLF := headerBytes[7] == 0x0a
|
||
|
return firstByteMatch && pngAsciiMatch && dosCRLF && dosEof && unixLF, headerBytes
|
||
|
}
|
||
|
|
||
|
// reads the data of one chunk
|
||
|
// it is assumed that the file reader is at the beginning of the chunk when reading
|
||
|
func ReadChunk(f *os.File) (ChunkData, error) {
|
||
|
lengthRaw := make([]byte, 4)
|
||
|
_, err := f.Read(lengthRaw)
|
||
|
length := binary.BigEndian.Uint32(lengthRaw)
|
||
|
crcRaw := make([]byte, 4)
|
||
|
nameRaw := make([]byte, 4)
|
||
|
_, _ = f.Read(nameRaw)
|
||
|
name := string(nameRaw)
|
||
|
data := make([]byte, length)
|
||
|
_, err = f.Read(data)
|
||
|
_, err = f.Read(crcRaw)
|
||
|
crc := binary.BigEndian.Uint32(crcRaw)
|
||
|
fullData := make([]byte, 0)
|
||
|
fullData = append(fullData, lengthRaw...)
|
||
|
fullData = append(fullData, nameRaw...)
|
||
|
fullData = append(fullData, data...)
|
||
|
fullData = append(fullData, crcRaw...)
|
||
|
return ChunkData{
|
||
|
length: length,
|
||
|
name: name,
|
||
|
data: data,
|
||
|
crc: crc,
|
||
|
raw: fullData,
|
||
|
}, err
|
||
|
}
|
||
|
|
||
|
// creates a chunk with the given data and name
|
||
|
func CreateChunk(data []byte, name string) ChunkData {
|
||
|
rawLength := make([]byte, 4)
|
||
|
binary.BigEndian.PutUint32(rawLength, uint32(len(data)))
|
||
|
rawName := []byte(name)
|
||
|
dataAndName := make([]byte, 0)
|
||
|
dataAndName = append(dataAndName, rawName...)
|
||
|
dataAndName = append(dataAndName, data...)
|
||
|
crc := crc32.ChecksumIEEE(dataAndName)
|
||
|
rawCrc := make([]byte, 4)
|
||
|
binary.BigEndian.PutUint32(rawCrc, crc)
|
||
|
fullData := make([]byte, 0)
|
||
|
fullData = append(fullData, rawLength...)
|
||
|
fullData = append(fullData, dataAndName...)
|
||
|
fullData = append(fullData, rawCrc...)
|
||
|
return ChunkData{
|
||
|
length: uint32(len(data)),
|
||
|
name: name,
|
||
|
data: data,
|
||
|
crc: crc,
|
||
|
raw: fullData,
|
||
|
}
|
||
|
}
|
||
|
|