...

Source file src/github.com/dsoprea/go-png-image-structure/v2/media_parser.go

Documentation: github.com/dsoprea/go-png-image-structure/v2

     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  )
   119  

View as plain text