pngstructure

package module
v0.0.0-...-29b889a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2021 License: MIT Imports: 12 Imported by: 10

README

Build Status codecov Go Report Card GoDoc

Overview

Parse raw PNG data into individual chunks. Parse/modify EXIF data and write an updated image.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	PngSignature  = [8]byte{137, 'P', 'N', 'G', '\r', '\n', 26, '\n'}
	EXifChunkType = "eXIf"
	IHDRChunkType = "IHDR"
)
View Source
var (
	ErrNotPng     = errors.New("not png data")
	ErrNoExif     = errors.New("file does not have EXIF")
	ErrCrcFailure = errors.New("crc failure")
)

Functions

func DumpBytes

func DumpBytes(data []byte)

func DumpBytesClause

func DumpBytesClause(data []byte)

func DumpBytesClauseToString

func DumpBytesClauseToString(data []byte) string

func DumpBytesToString

func DumpBytesToString(data []byte) string

Types

type Chunk

type Chunk struct {
	Offset int
	Length uint32
	Type   string
	Data   []byte
	Crc    uint32
}

Chunk describes a single chunk.

func (*Chunk) Bytes

func (c *Chunk) Bytes() []byte

Bytes encodes and returns the bytes for this chunk.

Example
c := Chunk{
	Offset: 0,
	Length: 5,
	Type:   "ABCD",
	Data:   []byte{0x11, 0x22, 0x33, 0x44, 0x55},
	Crc:    0x5678,
}

data := c.Bytes()
data = data
Output:

func (*Chunk) CheckCrc32

func (c *Chunk) CheckCrc32() bool

func (*Chunk) String

func (c *Chunk) String() string

func (*Chunk) UpdateCrc32

func (c *Chunk) UpdateCrc32()

func (*Chunk) WriteTo

func (c *Chunk) WriteTo(w io.Writer) (count int, err error)

Write encodes and writes the bytes for this chunk.

type ChunkDecoder

type ChunkDecoder struct {
}

func NewChunkDecoder

func NewChunkDecoder() *ChunkDecoder

func (*ChunkDecoder) Decode

func (cd *ChunkDecoder) Decode(c *Chunk) (decoded interface{}, err error)
Example
filepath := path.Join(assetsPath, "Selection_058.png")

pmp := NewPngMediaParser()

intfc, err := pmp.ParseFile(filepath)
log.PanicIf(err)

cs := intfc.(*ChunkSlice)

index := cs.Index()
ihdrRawSlice, found := index["IHDR"]

if found != true {
	log.Panicf("IHDR chunk not found")
}

cd := NewChunkDecoder()

ihdrRaw, err := cd.Decode(ihdrRawSlice[0])
log.PanicIf(err)

ihdr := ihdrRaw.(*ChunkIHDR)
ihdr = ihdr
Output:

type ChunkIHDR

type ChunkIHDR struct {
	Width             uint32
	Height            uint32
	BitDepth          uint8
	ColorType         uint8
	CompressionMethod uint8
	FilterMethod      uint8
	InterlaceMethod   uint8
}

func (*ChunkIHDR) String

func (ihdr *ChunkIHDR) String() string

type ChunkSlice

type ChunkSlice struct {
	// contains filtered or unexported fields
}

ChunkSlice encapsulates a slice of chunks.

func NewChunkSlice

func NewChunkSlice(chunks []*Chunk) *ChunkSlice

func NewPngChunkSlice

func NewPngChunkSlice() *ChunkSlice

func (*ChunkSlice) Chunks

func (cs *ChunkSlice) Chunks() []*Chunk

Chunks exposes the actual slice.

func (*ChunkSlice) ConstructExifBuilder

func (cs *ChunkSlice) ConstructExifBuilder() (rootIb *exif.IfdBuilder, err error)

ConstructExifBuilder returns an `exif.IfdBuilder` instance (needed for modifying) preloaded with all existing tags.

Example
testExifFilepath := getTestExifImageFilepath()

pmp := NewPngMediaParser()

intfc, err := pmp.ParseFile(testExifFilepath)
log.PanicIf(err)

cs := intfc.(*ChunkSlice)

// Add a new tag to the additional EXIF.

rootIb, err := cs.ConstructExifBuilder()
log.PanicIf(err)

err = rootIb.SetStandardWithName("ImageLength", []uint32{44})
log.PanicIf(err)

err = rootIb.AddStandardWithName("BitsPerSample", []uint16{33})
log.PanicIf(err)

// Update the image.

err = cs.SetExif(rootIb)
log.PanicIf(err)

b := new(bytes.Buffer)

err = cs.WriteTo(b)
log.PanicIf(err)

updatedImageData := b.Bytes()

// Re-parse.

pmp = NewPngMediaParser()

intfc, err = pmp.ParseBytes(updatedImageData)
log.PanicIf(err)

cs = intfc.(*ChunkSlice)

rootIfd, _, err := cs.Exif()
log.PanicIf(err)

for i, ite := range rootIfd.Entries {
	value, err := ite.Value()
	log.PanicIf(err)

	fmt.Printf("%d: (0x%04x) %v\n", i, ite.TagId(), value)
}
Output:

0: (0x0100) [11]
1: (0x0101) [44]
2: (0x0102) [33]

func (*ChunkSlice) Exif

func (cs *ChunkSlice) Exif() (rootIfd *exif.Ifd, data []byte, err error)

Exif returns an `exif.Ifd` instance with the existing tags.

Example
testExifFilepath := getTestExifImageFilepath()

pmp := NewPngMediaParser()

intfc, err := pmp.ParseFile(testExifFilepath)
log.PanicIf(err)

cs := intfc.(*ChunkSlice)

rootIfd, _, err := cs.Exif()
log.PanicIf(err)

rootIfd = rootIfd
Output:

func (*ChunkSlice) FindExif

func (cs *ChunkSlice) FindExif() (chunk *Chunk, err error)

FindExif returns the the segment that hosts the EXIF data.

Example
testBasicFilepath := getTestBasicImageFilepath()

pmp := NewPngMediaParser()

intfc, err := pmp.ParseFile(testBasicFilepath)
log.PanicIf(err)

cs := intfc.(*ChunkSlice)

exifChunk, err := cs.FindExif()
log.PanicIf(err)

exifChunk = exifChunk
Output:

func (*ChunkSlice) Index

func (cs *ChunkSlice) Index() (index map[string][]*Chunk)

Index returns a map of chunk types to chunk slices, grouping all like chunks.

Example
filepath := path.Join(assetsPath, "Selection_058.png")

pmp := NewPngMediaParser()

intfc, err := pmp.ParseFile(filepath)
log.PanicIf(err)

cs := intfc.(*ChunkSlice)

index := cs.Index()
index = index
Output:

func (*ChunkSlice) SetExif

func (cs *ChunkSlice) SetExif(ib *exif.IfdBuilder) (err error)

SetExif encodes and sets EXIF data into this segment.

Example
// Build EXIF.

testBasicFilepath := getTestBasicImageFilepath()

im := exif.NewIfdMappingWithStandard()
ti := exif.NewTagIndex()

ib := exif.NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)

err := ib.AddStandardWithName("ImageWidth", []uint32{11})
log.PanicIf(err)

err = ib.AddStandardWithName("ImageLength", []uint32{22})
log.PanicIf(err)

// Add/replace EXIF into PNG (overwrite existing).

pmp := NewPngMediaParser()

intfc, err := pmp.ParseFile(testBasicFilepath)
log.PanicIf(err)

cs := intfc.(*ChunkSlice)

err = cs.SetExif(ib)
log.PanicIf(err)

b := new(bytes.Buffer)

// Write to a `bytes.Buffer`.
err = cs.WriteTo(b)
log.PanicIf(err)
Output:

func (*ChunkSlice) String

func (cs *ChunkSlice) String() string

func (*ChunkSlice) WriteTo

func (cs *ChunkSlice) WriteTo(w io.Writer) (err error)

Write encodes and writes all chunks.

type PngMediaParser

type PngMediaParser struct {
}

PngMediaParser knows how to parse a PNG stream.

func NewPngMediaParser

func NewPngMediaParser() *PngMediaParser

NewPngMediaParser returns a new `PngMediaParser` struct.

func (*PngMediaParser) LooksLikeFormat

func (pmp *PngMediaParser) LooksLikeFormat(data []byte) bool

LooksLikeFormat returns a boolean indicating whether the stream looks like a PNG image.

Example
filepath := path.Join(assetsPath, "libpng.png")

data, err := ioutil.ReadFile(filepath)
log.PanicIf(err)

pmp := NewPngMediaParser()

isPng := pmp.LooksLikeFormat(data)
fmt.Printf("%v\n", isPng)
Output:

true

func (*PngMediaParser) Parse

func (pmp *PngMediaParser) Parse(rs io.ReadSeeker, size int) (mc riimage.MediaContext, err error)

Parse parses a PNG stream given a `io.ReadSeeker`.

func (*PngMediaParser) ParseBytes

func (pmp *PngMediaParser) ParseBytes(data []byte) (mc riimage.MediaContext, err error)

ParseBytes parses a PNG stream given a byte-slice.

func (*PngMediaParser) ParseFile

func (pmp *PngMediaParser) ParseFile(filepath string) (mc riimage.MediaContext, err error)

ParseFile parses a PNG stream given a file-path.

type PngSplitter

type PngSplitter struct {
	// contains filtered or unexported fields
}

PngSplitter hosts the princpal `Split()` method uses by `bufio.Scanner`.

func NewPngSplitter

func NewPngSplitter() *PngSplitter

func (*PngSplitter) Chunks

func (ps *PngSplitter) Chunks() *ChunkSlice

func (*PngSplitter) CrcErrors

func (ps *PngSplitter) CrcErrors() []string

func (*PngSplitter) DoCheckCrc

func (ps *PngSplitter) DoCheckCrc(doCheck bool)

func (*PngSplitter) Split

func (ps *PngSplitter) Split(data []byte, atEOF bool) (advance int, token []byte, err error)

Split fulfills the `bufio.SplitFunc` function definition for `bufio.Scanner`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL