gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

media_parser.go (2389B)


      1 package pngstructure
      2 
      3 import (
      4 	"bufio"
      5 	"bytes"
      6 	"image"
      7 	"io"
      8 	"os"
      9 
     10 	"image/png"
     11 
     12 	"github.com/dsoprea/go-logging"
     13 	"github.com/dsoprea/go-utility/v2/image"
     14 )
     15 
     16 // PngMediaParser knows how to parse a PNG stream.
     17 type PngMediaParser struct {
     18 }
     19 
     20 // NewPngMediaParser returns a new `PngMediaParser` struct.
     21 func NewPngMediaParser() *PngMediaParser {
     22 
     23 	// TODO(dustin): Add test
     24 
     25 	return new(PngMediaParser)
     26 }
     27 
     28 // Parse parses a PNG stream given a `io.ReadSeeker`.
     29 func (pmp *PngMediaParser) Parse(rs io.ReadSeeker, size int) (mc riimage.MediaContext, err error) {
     30 	defer func() {
     31 		if state := recover(); state != nil {
     32 			err = log.Wrap(state.(error))
     33 		}
     34 	}()
     35 
     36 	// TODO(dustin): Add test
     37 
     38 	ps := NewPngSplitter()
     39 
     40 	err = ps.readHeader(rs)
     41 	log.PanicIf(err)
     42 
     43 	s := bufio.NewScanner(rs)
     44 
     45 	// Since each segment can be any size, our buffer must be allowed to grow
     46 	// as large as the file.
     47 	buffer := []byte{}
     48 	s.Buffer(buffer, size)
     49 	s.Split(ps.Split)
     50 
     51 	for s.Scan() != false {
     52 	}
     53 
     54 	log.PanicIf(s.Err())
     55 
     56 	return ps.Chunks(), nil
     57 }
     58 
     59 // ParseFile parses a PNG stream given a file-path.
     60 func (pmp *PngMediaParser) ParseFile(filepath string) (mc riimage.MediaContext, err error) {
     61 	defer func() {
     62 		if state := recover(); state != nil {
     63 			err = log.Wrap(state.(error))
     64 		}
     65 	}()
     66 
     67 	f, err := os.Open(filepath)
     68 	log.PanicIf(err)
     69 
     70 	defer f.Close()
     71 
     72 	stat, err := f.Stat()
     73 	log.PanicIf(err)
     74 
     75 	size := stat.Size()
     76 
     77 	chunks, err := pmp.Parse(f, int(size))
     78 	log.PanicIf(err)
     79 
     80 	return chunks, nil
     81 }
     82 
     83 // ParseBytes parses a PNG stream given a byte-slice.
     84 func (pmp *PngMediaParser) ParseBytes(data []byte) (mc riimage.MediaContext, err error) {
     85 	defer func() {
     86 		if state := recover(); state != nil {
     87 			err = log.Wrap(state.(error))
     88 		}
     89 	}()
     90 
     91 	// TODO(dustin): Add test
     92 
     93 	br := bytes.NewReader(data)
     94 
     95 	chunks, err := pmp.Parse(br, len(data))
     96 	log.PanicIf(err)
     97 
     98 	return chunks, nil
     99 }
    100 
    101 // LooksLikeFormat returns a boolean indicating whether the stream looks like a
    102 // PNG image.
    103 func (pmp *PngMediaParser) LooksLikeFormat(data []byte) bool {
    104 	return bytes.Compare(data[:len(PngSignature)], PngSignature[:]) == 0
    105 }
    106 
    107 // GetImage returns an image.Image-compatible struct.
    108 func (pmp *PngMediaParser) GetImage(r io.Reader) (img image.Image, err error) {
    109 	img, err = png.Decode(r)
    110 	log.PanicIf(err)
    111 
    112 	return img, nil
    113 }
    114 
    115 var (
    116 	// Enforce interface conformance.
    117 	_ riimage.MediaParser = new(PngMediaParser)
    118 )