gtsocial-umbx

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

media_parser.go (2964B)


      1 package jpegstructure
      2 
      3 import (
      4 	"bufio"
      5 	"bytes"
      6 	"image"
      7 	"io"
      8 	"os"
      9 
     10 	"image/jpeg"
     11 
     12 	"github.com/dsoprea/go-logging"
     13 	"github.com/dsoprea/go-utility/v2/image"
     14 )
     15 
     16 // JpegMediaParser is a `riimage.MediaParser` that knows how to parse JPEG
     17 // images.
     18 type JpegMediaParser struct {
     19 }
     20 
     21 // NewJpegMediaParser returns a new JpegMediaParser.
     22 func NewJpegMediaParser() *JpegMediaParser {
     23 
     24 	// TODO(dustin): Add test
     25 
     26 	return new(JpegMediaParser)
     27 }
     28 
     29 // Parse parses a JPEG uses an `io.ReadSeeker`. Even if it fails, it will return
     30 // the list of segments encountered prior to the failure.
     31 func (jmp *JpegMediaParser) Parse(rs io.ReadSeeker, size int) (ec riimage.MediaContext, err error) {
     32 	defer func() {
     33 		if state := recover(); state != nil {
     34 			err = log.Wrap(state.(error))
     35 		}
     36 	}()
     37 
     38 	s := bufio.NewScanner(rs)
     39 
     40 	// Since each segment can be any size, our buffer must allowed to grow as
     41 	// large as the file.
     42 	buffer := []byte{}
     43 	s.Buffer(buffer, size)
     44 
     45 	js := NewJpegSplitter(nil)
     46 	s.Split(js.Split)
     47 
     48 	for s.Scan() != false {
     49 	}
     50 
     51 	// Always return the segments that were parsed, at least until there was an
     52 	// error.
     53 	ec = js.Segments()
     54 
     55 	log.PanicIf(s.Err())
     56 
     57 	return ec, nil
     58 }
     59 
     60 // ParseFile parses a JPEG file. Even if it fails, it will return the list of
     61 // segments encountered prior to the failure.
     62 func (jmp *JpegMediaParser) ParseFile(filepath string) (ec riimage.MediaContext, err error) {
     63 	defer func() {
     64 		if state := recover(); state != nil {
     65 			err = log.Wrap(state.(error))
     66 		}
     67 	}()
     68 
     69 	// TODO(dustin): Add test
     70 
     71 	f, err := os.Open(filepath)
     72 	log.PanicIf(err)
     73 
     74 	defer f.Close()
     75 
     76 	stat, err := f.Stat()
     77 	log.PanicIf(err)
     78 
     79 	size := stat.Size()
     80 
     81 	sl, err := jmp.Parse(f, int(size))
     82 
     83 	// Always return the segments that were parsed, at least until there was an
     84 	// error.
     85 	ec = sl
     86 
     87 	log.PanicIf(err)
     88 
     89 	return ec, nil
     90 }
     91 
     92 // ParseBytes parses a JPEG byte-slice. Even if it fails, it will return the
     93 // list of segments encountered prior to the failure.
     94 func (jmp *JpegMediaParser) ParseBytes(data []byte) (ec riimage.MediaContext, err error) {
     95 	defer func() {
     96 		if state := recover(); state != nil {
     97 			err = log.Wrap(state.(error))
     98 		}
     99 	}()
    100 
    101 	br := bytes.NewReader(data)
    102 
    103 	sl, err := jmp.Parse(br, len(data))
    104 
    105 	// Always return the segments that were parsed, at least until there was an
    106 	// error.
    107 	ec = sl
    108 
    109 	log.PanicIf(err)
    110 
    111 	return ec, nil
    112 }
    113 
    114 // LooksLikeFormat indicates whether the data looks like a JPEG image.
    115 func (jmp *JpegMediaParser) LooksLikeFormat(data []byte) bool {
    116 	if len(data) < 4 {
    117 		return false
    118 	}
    119 
    120 	l := len(data)
    121 	if data[0] != 0xff || data[1] != MARKER_SOI || data[l-2] != 0xff || data[l-1] != MARKER_EOI {
    122 		return false
    123 	}
    124 
    125 	return true
    126 }
    127 
    128 // GetImage returns an image.Image-compatible struct.
    129 func (jmp *JpegMediaParser) GetImage(r io.Reader) (img image.Image, err error) {
    130 	img, err = jpeg.Decode(r)
    131 	log.PanicIf(err)
    132 
    133 	return img, nil
    134 }
    135 
    136 var (
    137 	// Enforce interface conformance.
    138 	_ riimage.MediaParser = new(JpegMediaParser)
    139 )