diff options
Diffstat (limited to 'vendor/github.com/superseriousbusiness')
17 files changed, 0 insertions, 2463 deletions
diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/.MODULE_ROOT b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/.MODULE_ROOT deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/.MODULE_ROOT +++ /dev/null diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/LICENSE b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/LICENSE deleted file mode 100644 index 163291ed6..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT LICENSE - -Copyright 2020 Dustin Oprea - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/README.md b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/README.md deleted file mode 100644 index bf60ef504..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/README.md +++ /dev/null @@ -1,10 +0,0 @@ -[](https://travis-ci.org/dsoprea/go-jpeg-image-structure/v2) -[](https://codecov.io/gh/dsoprea/go-jpeg-image-structure) -[](https://goreportcard.com/report/github.com/dsoprea/go-jpeg-image-structure/v2) -[](https://godoc.org/github.com/dsoprea/go-jpeg-image-structure/v2) - -## Overview - -Parse raw JPEG data into individual segments of data. You can print or export this data, including hash digests for each. You can also parse/modify the EXIF data and write an updated image. - -EXIF, XMP, and IPTC data can also be extracted. The provided CLI tool can print this data as well. diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/markers.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/markers.go deleted file mode 100644 index a12171bd8..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/markers.go +++ /dev/null @@ -1,212 +0,0 @@ -package jpegstructure - -import ( - "github.com/dsoprea/go-logging" -) - -const ( - // MARKER_SOI marker - MARKER_SOI = 0xd8 - - // MARKER_EOI marker - MARKER_EOI = 0xd9 - - // MARKER_SOS marker - MARKER_SOS = 0xda - - // MARKER_SOD marker - MARKER_SOD = 0x93 - - // MARKER_DQT marker - MARKER_DQT = 0xdb - - // MARKER_APP0 marker - MARKER_APP0 = 0xe0 - - // MARKER_APP1 marker - MARKER_APP1 = 0xe1 - - // MARKER_APP2 marker - MARKER_APP2 = 0xe2 - - // MARKER_APP3 marker - MARKER_APP3 = 0xe3 - - // MARKER_APP4 marker - MARKER_APP4 = 0xe4 - - // MARKER_APP5 marker - MARKER_APP5 = 0xe5 - - // MARKER_APP6 marker - MARKER_APP6 = 0xe6 - - // MARKER_APP7 marker - MARKER_APP7 = 0xe7 - - // MARKER_APP8 marker - MARKER_APP8 = 0xe8 - - // MARKER_APP10 marker - MARKER_APP10 = 0xea - - // MARKER_APP12 marker - MARKER_APP12 = 0xec - - // MARKER_APP13 marker - MARKER_APP13 = 0xed - - // MARKER_APP14 marker - MARKER_APP14 = 0xee - - // MARKER_APP15 marker - MARKER_APP15 = 0xef - - // MARKER_COM marker - MARKER_COM = 0xfe - - // MARKER_CME marker - MARKER_CME = 0x64 - - // MARKER_SIZ marker - MARKER_SIZ = 0x51 - - // MARKER_DHT marker - MARKER_DHT = 0xc4 - - // MARKER_JPG marker - MARKER_JPG = 0xc8 - - // MARKER_DAC marker - MARKER_DAC = 0xcc - - // MARKER_SOF0 marker - MARKER_SOF0 = 0xc0 - - // MARKER_SOF1 marker - MARKER_SOF1 = 0xc1 - - // MARKER_SOF2 marker - MARKER_SOF2 = 0xc2 - - // MARKER_SOF3 marker - MARKER_SOF3 = 0xc3 - - // MARKER_SOF5 marker - MARKER_SOF5 = 0xc5 - - // MARKER_SOF6 marker - MARKER_SOF6 = 0xc6 - - // MARKER_SOF7 marker - MARKER_SOF7 = 0xc7 - - // MARKER_SOF9 marker - MARKER_SOF9 = 0xc9 - - // MARKER_SOF10 marker - MARKER_SOF10 = 0xca - - // MARKER_SOF11 marker - MARKER_SOF11 = 0xcb - - // MARKER_SOF13 marker - MARKER_SOF13 = 0xcd - - // MARKER_SOF14 marker - MARKER_SOF14 = 0xce - - // MARKER_SOF15 marker - MARKER_SOF15 = 0xcf -) - -var ( - jpegLogger = log.NewLogger("jpegstructure.jpeg") - jpegMagicStandard = []byte{0xff, MARKER_SOI, 0xff} - jpegMagic2000 = []byte{0xff, 0x4f, 0xff} - - markerLen = map[byte]int{ - 0x00: 0, - 0x01: 0, - 0xd0: 0, - 0xd1: 0, - 0xd2: 0, - 0xd3: 0, - 0xd4: 0, - 0xd5: 0, - 0xd6: 0, - 0xd7: 0, - 0xd8: 0, - 0xd9: 0, - 0xda: 0, - - // J2C - 0x30: 0, - 0x31: 0, - 0x32: 0, - 0x33: 0, - 0x34: 0, - 0x35: 0, - 0x36: 0, - 0x37: 0, - 0x38: 0, - 0x39: 0, - 0x3a: 0, - 0x3b: 0, - 0x3c: 0, - 0x3d: 0, - 0x3e: 0, - 0x3f: 0, - 0x4f: 0, - 0x92: 0, - 0x93: 0, - - // J2C extensions - 0x74: 4, - 0x75: 4, - 0x77: 4, - } - - markerNames = map[byte]string{ - MARKER_SOI: "SOI", - MARKER_EOI: "EOI", - MARKER_SOS: "SOS", - MARKER_SOD: "SOD", - MARKER_DQT: "DQT", - MARKER_APP0: "APP0", - MARKER_APP1: "APP1", - MARKER_APP2: "APP2", - MARKER_APP3: "APP3", - MARKER_APP4: "APP4", - MARKER_APP5: "APP5", - MARKER_APP6: "APP6", - MARKER_APP7: "APP7", - MARKER_APP8: "APP8", - MARKER_APP10: "APP10", - MARKER_APP12: "APP12", - MARKER_APP13: "APP13", - MARKER_APP14: "APP14", - MARKER_APP15: "APP15", - MARKER_COM: "COM", - MARKER_CME: "CME", - MARKER_SIZ: "SIZ", - - MARKER_DHT: "DHT", - MARKER_JPG: "JPG", - MARKER_DAC: "DAC", - - MARKER_SOF0: "SOF0", - MARKER_SOF1: "SOF1", - MARKER_SOF2: "SOF2", - MARKER_SOF3: "SOF3", - MARKER_SOF5: "SOF5", - MARKER_SOF6: "SOF6", - MARKER_SOF7: "SOF7", - MARKER_SOF9: "SOF9", - MARKER_SOF10: "SOF10", - MARKER_SOF11: "SOF11", - MARKER_SOF13: "SOF13", - MARKER_SOF14: "SOF14", - MARKER_SOF15: "SOF15", - } -) diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/media_parser.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/media_parser.go deleted file mode 100644 index e6fc60bc4..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/media_parser.go +++ /dev/null @@ -1,139 +0,0 @@ -package jpegstructure - -import ( - "bufio" - "bytes" - "image" - "io" - "os" - - "image/jpeg" - - "github.com/dsoprea/go-logging" - "github.com/dsoprea/go-utility/v2/image" -) - -// JpegMediaParser is a `riimage.MediaParser` that knows how to parse JPEG -// images. -type JpegMediaParser struct { -} - -// NewJpegMediaParser returns a new JpegMediaParser. -func NewJpegMediaParser() *JpegMediaParser { - - // TODO(dustin): Add test - - return new(JpegMediaParser) -} - -// Parse parses a JPEG uses an `io.ReadSeeker`. Even if it fails, it will return -// the list of segments encountered prior to the failure. -func (jmp *JpegMediaParser) Parse(rs io.ReadSeeker, size int) (ec riimage.MediaContext, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - s := bufio.NewScanner(rs) - - // Since each segment can be any size, our buffer must allowed to grow as - // large as the file. - buffer := []byte{} - s.Buffer(buffer, size) - - js := NewJpegSplitter(nil) - s.Split(js.Split) - - for s.Scan() != false { - } - - // Always return the segments that were parsed, at least until there was an - // error. - ec = js.Segments() - - log.PanicIf(s.Err()) - - return ec, nil -} - -// ParseFile parses a JPEG file. Even if it fails, it will return the list of -// segments encountered prior to the failure. -func (jmp *JpegMediaParser) ParseFile(filepath string) (ec riimage.MediaContext, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // TODO(dustin): Add test - - f, err := os.Open(filepath) - log.PanicIf(err) - - defer f.Close() - - stat, err := f.Stat() - log.PanicIf(err) - - size := stat.Size() - - sl, err := jmp.Parse(f, int(size)) - - // Always return the segments that were parsed, at least until there was an - // error. - ec = sl - - log.PanicIf(err) - - return ec, nil -} - -// ParseBytes parses a JPEG byte-slice. Even if it fails, it will return the -// list of segments encountered prior to the failure. -func (jmp *JpegMediaParser) ParseBytes(data []byte) (ec riimage.MediaContext, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - br := bytes.NewReader(data) - - sl, err := jmp.Parse(br, len(data)) - - // Always return the segments that were parsed, at least until there was an - // error. - ec = sl - - log.PanicIf(err) - - return ec, nil -} - -// LooksLikeFormat indicates whether the data looks like a JPEG image. -func (jmp *JpegMediaParser) LooksLikeFormat(data []byte) bool { - if len(data) < 4 { - return false - } - - l := len(data) - if data[0] != 0xff || data[1] != MARKER_SOI || data[l-2] != 0xff || data[l-1] != MARKER_EOI { - return false - } - - return true -} - -// GetImage returns an image.Image-compatible struct. -func (jmp *JpegMediaParser) GetImage(r io.Reader) (img image.Image, err error) { - img, err = jpeg.Decode(r) - log.PanicIf(err) - - return img, nil -} - -var ( - // Enforce interface conformance. - _ riimage.MediaParser = new(JpegMediaParser) -) diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/segment.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/segment.go deleted file mode 100644 index 6b433bf1f..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/segment.go +++ /dev/null @@ -1,352 +0,0 @@ -package jpegstructure - -import ( - "bytes" - "errors" - "fmt" - - "crypto/sha1" - "encoding/hex" - - "github.com/dsoprea/go-exif/v3" - "github.com/dsoprea/go-exif/v3/common" - "github.com/dsoprea/go-iptc" - "github.com/dsoprea/go-logging" - "github.com/dsoprea/go-photoshop-info-format" - "github.com/dsoprea/go-utility/v2/image" -) - -const ( - pirIptcImageResourceId = uint16(0x0404) -) - -var ( - // exifPrefix is the prefix found at the top of an EXIF slice. This is JPEG- - // specific. - exifPrefix = []byte{'E', 'x', 'i', 'f', 0, 0} - - xmpPrefix = []byte("http://ns.adobe.com/xap/1.0/\000") - - ps30Prefix = []byte("Photoshop 3.0\000") -) - -var ( - // ErrNoXmp is returned if XMP data was requested but not found. - ErrNoXmp = errors.New("no XMP data") - - // ErrNoIptc is returned if IPTC data was requested but not found. - ErrNoIptc = errors.New("no IPTC data") - - // ErrNoPhotoshopData is returned if Photoshop info was requested but not - // found. - ErrNoPhotoshopData = errors.New("no photoshop data") -) - -// SofSegment has info read from a SOF segment. -type SofSegment struct { - // BitsPerSample is the bits-per-sample. - BitsPerSample byte - - // Width is the image width. - Width uint16 - - // Height is the image height. - Height uint16 - - // ComponentCount is the number of color components. - ComponentCount byte -} - -// String returns a string representation of the SOF segment. -func (ss SofSegment) String() string { - - // TODO(dustin): Add test - - return fmt.Sprintf("SOF<BitsPerSample=(%d) Width=(%d) Height=(%d) ComponentCount=(%d)>", ss.BitsPerSample, ss.Width, ss.Height, ss.ComponentCount) -} - -// SegmentVisitor describes a segment-visitor struct. -type SegmentVisitor interface { - // HandleSegment is triggered for each segment encountered as well as the - // scan-data. - HandleSegment(markerId byte, markerName string, counter int, lastIsScanData bool) error -} - -// SofSegmentVisitor describes a visitor that is only called for each SOF -// segment. -type SofSegmentVisitor interface { - // HandleSof is called for each encountered SOF segment. - HandleSof(sof *SofSegment) error -} - -// Segment describes a single segment. -type Segment struct { - MarkerId byte - MarkerName string - Offset int - Data []byte - - photoshopInfo map[uint16]photoshopinfo.Photoshop30InfoRecord - iptcTags map[iptc.StreamTagKey][]iptc.TagData -} - -// SetExif encodes and sets EXIF data into this segment. -func (s *Segment) SetExif(ib *exif.IfdBuilder) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - ibe := exif.NewIfdByteEncoder() - - exifData, err := ibe.EncodeToExif(ib) - log.PanicIf(err) - - l := len(exifPrefix) - - s.Data = make([]byte, l+len(exifData)) - copy(s.Data[0:], exifPrefix) - copy(s.Data[l:], exifData) - - return nil -} - -// Exif returns an `exif.Ifd` instance for the EXIF data we currently have. -func (s *Segment) Exif() (rootIfd *exif.Ifd, data []byte, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - l := len(exifPrefix) - - rawExif := s.Data[l:] - - jpegLogger.Debugf(nil, "Attempting to parse (%d) byte EXIF blob (Exif).", len(rawExif)) - - im, err := exifcommon.NewIfdMappingWithStandard() - log.PanicIf(err) - - ti := exif.NewTagIndex() - - _, index, err := exif.Collect(im, ti, rawExif) - log.PanicIf(err) - - return index.RootIfd, rawExif, nil -} - -// FlatExif parses the EXIF data and just returns a list of tags. -func (s *Segment) FlatExif() (exifTags []exif.ExifTag, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // TODO(dustin): Add test - - l := len(exifPrefix) - - rawExif := s.Data[l:] - - jpegLogger.Debugf(nil, "Attempting to parse (%d) byte EXIF blob (FlatExif).", len(rawExif)) - - exifTags, _, err = exif.GetFlatExifData(rawExif, nil) - log.PanicIf(err) - - return exifTags, nil -} - -// EmbeddedString returns a string of properties that can be embedded into an -// longer string of properties. -func (s *Segment) EmbeddedString() string { - h := sha1.New() - h.Write(s.Data) - - // TODO(dustin): Add test - - digestString := hex.EncodeToString(h.Sum(nil)) - - return fmt.Sprintf("OFFSET=(0x%08x %10d) ID=(0x%02x) NAME=[%-5s] SIZE=(%10d) SHA1=[%s]", s.Offset, s.Offset, s.MarkerId, markerNames[s.MarkerId], len(s.Data), digestString) -} - -// String returns a descriptive string. -func (s *Segment) String() string { - - // TODO(dustin): Add test - - return fmt.Sprintf("Segment<%s>", s.EmbeddedString()) -} - -// IsExif returns true if EXIF data. -func (s *Segment) IsExif() bool { - if s.MarkerId != MARKER_APP1 { - return false - } - - // TODO(dustin): Add test - - l := len(exifPrefix) - - if len(s.Data) < l { - return false - } - - if bytes.Equal(s.Data[:l], exifPrefix) == false { - return false - } - - return true -} - -// IsXmp returns true if XMP data. -func (s *Segment) IsXmp() bool { - if s.MarkerId != MARKER_APP1 { - return false - } - - // TODO(dustin): Add test - - l := len(xmpPrefix) - - if len(s.Data) < l { - return false - } - - if bytes.Equal(s.Data[:l], xmpPrefix) == false { - return false - } - - return true -} - -// FormattedXmp returns a formatted XML string. This only makes sense for a -// segment comprised of XML data (like XMP). -func (s *Segment) FormattedXmp() (formatted string, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // TODO(dustin): Add test - - if s.IsXmp() != true { - log.Panicf("not an XMP segment") - } - - l := len(xmpPrefix) - - raw := string(s.Data[l:]) - - formatted, err = FormatXml(raw) - log.PanicIf(err) - - return formatted, nil -} - -func (s *Segment) parsePhotoshopInfo() (photoshopInfo map[uint16]photoshopinfo.Photoshop30InfoRecord, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - if s.photoshopInfo != nil { - return s.photoshopInfo, nil - } - - if s.MarkerId != MARKER_APP13 { - return nil, ErrNoPhotoshopData - } - - l := len(ps30Prefix) - - if len(s.Data) < l { - return nil, ErrNoPhotoshopData - } - - if bytes.Equal(s.Data[:l], ps30Prefix) == false { - return nil, ErrNoPhotoshopData - } - - data := s.Data[l:] - b := bytes.NewBuffer(data) - - // Parse it. - - pirIndex, err := photoshopinfo.ReadPhotoshop30Info(b) - log.PanicIf(err) - - s.photoshopInfo = pirIndex - - return s.photoshopInfo, nil -} - -// IsIptc returns true if XMP data. -func (s *Segment) IsIptc() bool { - // TODO(dustin): Add test - - // There's a cost to determining if there's IPTC data, so we won't do it - // more than once. - if s.iptcTags != nil { - return true - } - - photoshopInfo, err := s.parsePhotoshopInfo() - if err != nil { - if err == ErrNoPhotoshopData { - return false - } - - log.Panic(err) - } - - // Bail if the Photoshop info doesn't have IPTC data. - - _, found := photoshopInfo[pirIptcImageResourceId] - if found == false { - return false - } - - return true -} - -// Iptc parses Photoshop info (if present) and then parses the IPTC info inside -// it (if present). -func (s *Segment) Iptc() (tags map[iptc.StreamTagKey][]iptc.TagData, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // Cache the parse. - if s.iptcTags != nil { - return s.iptcTags, nil - } - - photoshopInfo, err := s.parsePhotoshopInfo() - log.PanicIf(err) - - iptcPir, found := photoshopInfo[pirIptcImageResourceId] - if found == false { - return nil, ErrNoIptc - } - - b := bytes.NewBuffer(iptcPir.Data) - - tags, err = iptc.ParseStream(b) - log.PanicIf(err) - - s.iptcTags = tags - - return tags, nil -} - -var ( - // Enforce interface conformance. - _ riimage.MediaContext = new(Segment) -) diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/segment_list.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/segment_list.go deleted file mode 100644 index b4f4d5810..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/segment_list.go +++ /dev/null @@ -1,416 +0,0 @@ -package jpegstructure - -import ( - "bytes" - "fmt" - "io" - - "crypto/sha1" - "encoding/binary" - - "github.com/dsoprea/go-exif/v3" - "github.com/dsoprea/go-exif/v3/common" - "github.com/dsoprea/go-iptc" - "github.com/dsoprea/go-logging" -) - -// SegmentList contains a slice of segments. -type SegmentList struct { - segments []*Segment -} - -// NewSegmentList returns a new SegmentList struct. -func NewSegmentList(segments []*Segment) (sl *SegmentList) { - if segments == nil { - segments = make([]*Segment, 0) - } - - return &SegmentList{ - segments: segments, - } -} - -// OffsetsEqual returns true is all segments have the same marker-IDs and were -// found at the same offsets. -func (sl *SegmentList) OffsetsEqual(o *SegmentList) bool { - if len(o.segments) != len(sl.segments) { - return false - } - - for i, s := range o.segments { - if s.MarkerId != sl.segments[i].MarkerId || s.Offset != sl.segments[i].Offset { - return false - } - } - - return true -} - -// Segments returns the underlying slice of segments. -func (sl *SegmentList) Segments() []*Segment { - return sl.segments -} - -// Add adds another segment. -func (sl *SegmentList) Add(s *Segment) { - sl.segments = append(sl.segments, s) -} - -// Print prints segment info. -func (sl *SegmentList) Print() { - if len(sl.segments) == 0 { - fmt.Printf("No segments.\n") - } else { - exifIndex, _, err := sl.FindExif() - if err != nil { - if err == exif.ErrNoExif { - exifIndex = -1 - } else { - log.Panic(err) - } - } - - xmpIndex, _, err := sl.FindXmp() - if err != nil { - if err == ErrNoXmp { - xmpIndex = -1 - } else { - log.Panic(err) - } - } - - iptcIndex, _, err := sl.FindIptc() - if err != nil { - if err == ErrNoIptc { - iptcIndex = -1 - } else { - log.Panic(err) - } - } - - for i, s := range sl.segments { - fmt.Printf("%2d: %s", i, s.EmbeddedString()) - - if i == exifIndex { - fmt.Printf(" [EXIF]") - } else if i == xmpIndex { - fmt.Printf(" [XMP]") - } else if i == iptcIndex { - fmt.Printf(" [IPTC]") - } - - fmt.Printf("\n") - } - } -} - -// Validate checks that all of the markers are actually located at all of the -// recorded offsets. -func (sl *SegmentList) Validate(data []byte) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - if len(sl.segments) < 2 { - log.Panicf("minimum segments not found") - } - - if sl.segments[0].MarkerId != MARKER_SOI { - log.Panicf("first segment not SOI") - } else if sl.segments[len(sl.segments)-1].MarkerId != MARKER_EOI { - log.Panicf("last segment not EOI") - } - - lastOffset := 0 - for i, s := range sl.segments { - if lastOffset != 0 && s.Offset <= lastOffset { - log.Panicf("segment offset not greater than the last: SEGMENT=(%d) (0x%08x) <= (0x%08x)", i, s.Offset, lastOffset) - } - - // The scan-data doesn't start with a marker. - if s.MarkerId == 0x0 { - continue - } - - o := s.Offset - if bytes.Compare(data[o:o+2], []byte{0xff, s.MarkerId}) != 0 { - log.Panicf("segment offset does not point to the start of a segment: SEGMENT=(%d) (0x%08x)", i, s.Offset) - } - - lastOffset = o - } - - return nil -} - -// FindExif returns the the segment that hosts the EXIF data (if present). -func (sl *SegmentList) FindExif() (index int, segment *Segment, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - for i, s := range sl.segments { - if s.IsExif() == true { - return i, s, nil - } - } - - return -1, nil, exif.ErrNoExif -} - -// FindXmp returns the the segment that hosts the XMP data (if present). -func (sl *SegmentList) FindXmp() (index int, segment *Segment, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - for i, s := range sl.segments { - if s.IsXmp() == true { - return i, s, nil - } - } - - return -1, nil, ErrNoXmp -} - -// FindIptc returns the the segment that hosts the IPTC data (if present). -func (sl *SegmentList) FindIptc() (index int, segment *Segment, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - for i, s := range sl.segments { - if s.IsIptc() == true { - return i, s, nil - } - } - - return -1, nil, ErrNoIptc -} - -// Exif returns an `exif.Ifd` instance for the EXIF data we currently have. -func (sl *SegmentList) Exif() (rootIfd *exif.Ifd, rawExif []byte, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - _, s, err := sl.FindExif() - log.PanicIf(err) - - rootIfd, rawExif, err = s.Exif() - log.PanicIf(err) - - return rootIfd, rawExif, nil -} - -// Iptc returns embedded IPTC data if present. -func (sl *SegmentList) Iptc() (tags map[iptc.StreamTagKey][]iptc.TagData, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // TODO(dustin): Add comment and return data. - - _, s, err := sl.FindIptc() - log.PanicIf(err) - - tags, err = s.Iptc() - log.PanicIf(err) - - return tags, nil -} - -// ConstructExifBuilder returns an `exif.IfdBuilder` instance (needed for -// modifying) preloaded with all existing tags. -func (sl *SegmentList) ConstructExifBuilder() (rootIb *exif.IfdBuilder, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - rootIfd, _, err := sl.Exif() - if log.Is(err, exif.ErrNoExif) == true { - // No EXIF. Just create a boilerplate builder. - - im := exifcommon.NewIfdMapping() - - err := exifcommon.LoadStandardIfds(im) - log.PanicIf(err) - - ti := exif.NewTagIndex() - - rootIb := - exif.NewIfdBuilder( - im, - ti, - exifcommon.IfdStandardIfdIdentity, - exifcommon.EncodeDefaultByteOrder) - - return rootIb, nil - } else if err != nil { - log.Panic(err) - } - - rootIb = exif.NewIfdBuilderFromExistingChain(rootIfd) - - return rootIb, nil -} - -// DumpExif returns an unstructured list of tags (useful when just reviewing). -func (sl *SegmentList) DumpExif() (segmentIndex int, segment *Segment, exifTags []exif.ExifTag, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - segmentIndex, s, err := sl.FindExif() - if err != nil { - if err == exif.ErrNoExif { - return 0, nil, nil, err - } - - log.Panic(err) - } - - exifTags, err = s.FlatExif() - log.PanicIf(err) - - return segmentIndex, s, exifTags, nil -} - -func makeEmptyExifSegment() (s *Segment) { - - // TODO(dustin): Add test - - return &Segment{ - MarkerId: MARKER_APP1, - } -} - -// SetExif encodes and sets EXIF data into the given segment. If `index` is -1, -// append a new segment. -func (sl *SegmentList) SetExif(ib *exif.IfdBuilder) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - _, s, err := sl.FindExif() - if err != nil { - if log.Is(err, exif.ErrNoExif) == false { - log.Panic(err) - } - - s = makeEmptyExifSegment() - - prefix := sl.segments[:1] - - // Install it near the beginning where we know it's safe. We can't - // insert it after the EOI segment, and there might be more than one - // depending on implementation and/or lax adherence to the standard. - tail := append([]*Segment{s}, sl.segments[1:]...) - - sl.segments = append(prefix, tail...) - } - - err = s.SetExif(ib) - log.PanicIf(err) - - return nil -} - -// DropExif will drop the EXIF data if present. -func (sl *SegmentList) DropExif() (wasDropped bool, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // TODO(dustin): Add test - - i, _, err := sl.FindExif() - if err == nil { - // Found. - sl.segments = append(sl.segments[:i], sl.segments[i+1:]...) - - return true, nil - } else if log.Is(err, exif.ErrNoExif) == false { - log.Panic(err) - } - - // Not found. - return false, nil -} - -// Write writes the segment data to the given `io.Writer`. -func (sl *SegmentList) Write(w io.Writer) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - offset := 0 - - for i, s := range sl.segments { - h := sha1.New() - h.Write(s.Data) - - // The scan-data will have a marker-ID of (0) because it doesn't have a - // marker-ID or length. - if s.MarkerId != 0 { - _, err := w.Write([]byte{0xff}) - log.PanicIf(err) - - offset++ - - _, err = w.Write([]byte{s.MarkerId}) - log.PanicIf(err) - - offset++ - - sizeLen, found := markerLen[s.MarkerId] - if found == false || sizeLen == 2 { - sizeLen = 2 - l := uint16(len(s.Data) + sizeLen) - - err = binary.Write(w, binary.BigEndian, &l) - log.PanicIf(err) - - offset += 2 - } else if sizeLen == 4 { - l := uint32(len(s.Data) + sizeLen) - - err = binary.Write(w, binary.BigEndian, &l) - log.PanicIf(err) - - offset += 4 - } else if sizeLen != 0 { - log.Panicf("not a supported marker-size: SEGMENT-INDEX=(%d) MARKER-ID=(0x%02x) MARKER-SIZE-LEN=(%d)", i, s.MarkerId, sizeLen) - } - } - - _, err := w.Write(s.Data) - log.PanicIf(err) - - offset += len(s.Data) - } - - return nil -} diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/splitter.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/splitter.go deleted file mode 100644 index 1856beddf..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/splitter.go +++ /dev/null @@ -1,437 +0,0 @@ -package jpegstructure - -import ( - "bufio" - "bytes" - "io" - - "encoding/binary" - - "github.com/dsoprea/go-logging" -) - -// JpegSplitter uses the Go stream splitter to divide the JPEG stream into -// segments. -type JpegSplitter struct { - lastMarkerId byte - lastMarkerName string - counter int - lastIsScanData bool - visitor interface{} - - currentOffset int - segments *SegmentList - - scandataOffset int -} - -// NewJpegSplitter returns a new JpegSplitter. -func NewJpegSplitter(visitor interface{}) *JpegSplitter { - return &JpegSplitter{ - segments: NewSegmentList(nil), - visitor: visitor, - } -} - -// Segments returns all found segments. -func (js *JpegSplitter) Segments() *SegmentList { - return js.segments -} - -// MarkerId returns the ID of the last processed marker. -func (js *JpegSplitter) MarkerId() byte { - return js.lastMarkerId -} - -// MarkerName returns the name of the last-processed marker. -func (js *JpegSplitter) MarkerName() string { - return js.lastMarkerName -} - -// Counter returns the number of processed segments. -func (js *JpegSplitter) Counter() int { - return js.counter -} - -// IsScanData returns whether the last processed segment was scan-data. -func (js *JpegSplitter) IsScanData() bool { - return js.lastIsScanData -} - -func (js *JpegSplitter) processScanData(data []byte) (advanceBytes int, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - // Search through the segment, past all 0xff's therein, until we encounter - // the EOI segment. - - dataLength := -1 - for i := js.scandataOffset; i < len(data); i++ { - thisByte := data[i] - - if i == 0 { - continue - } - - lastByte := data[i-1] - if lastByte != 0xff { - continue - } - - if thisByte == 0x00 || thisByte >= 0xd0 && thisByte <= 0xd8 { - continue - } - - // After all of the other checks, this means that we're on the EOF - // segment. - if thisByte != MARKER_EOI { - continue - } - - dataLength = i - 1 - break - } - - if dataLength == -1 { - // On the next pass, start on the last byte of this pass, just in case - // the first byte of the two-byte sequence is here. - js.scandataOffset = len(data) - 1 - - jpegLogger.Debugf(nil, "Scan-data not fully available (%d).", len(data)) - return 0, nil - } - - js.lastIsScanData = true - js.lastMarkerId = 0 - js.lastMarkerName = "" - - // Note that we don't increment the counter since this isn't an actual - // segment. - - jpegLogger.Debugf(nil, "End of scan-data.") - - err = js.handleSegment(0x0, "!SCANDATA", 0x0, data[:dataLength]) - log.PanicIf(err) - - return dataLength, nil -} - -func (js *JpegSplitter) readSegment(data []byte) (count int, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - if js.counter == 0 { - // Verify magic bytes. - - if len(data) < 3 { - jpegLogger.Debugf(nil, "Not enough (1)") - return 0, nil - } - - if data[0] == jpegMagic2000[0] && data[1] == jpegMagic2000[1] && data[2] == jpegMagic2000[2] { - // TODO(dustin): Revisit JPEG2000 support. - log.Panicf("JPEG2000 not supported") - } - - if data[0] != jpegMagicStandard[0] || data[1] != jpegMagicStandard[1] || data[2] != jpegMagicStandard[2] { - log.Panicf("file does not look like a JPEG: (%02x) (%02x) (%02x)", data[0], data[1], data[2]) - } - } - - chunkLength := len(data) - - jpegLogger.Debugf(nil, "SPLIT: LEN=(%d) COUNTER=(%d)", chunkLength, js.counter) - - if js.scanDataIsNext() == true { - // If the last segment was the SOS, we're currently sitting on scan data. - // Search for the EOI marker afterward in order to know how much data - // there is. Return this as its own token. - // - // REF: https://stackoverflow.com/questions/26715684/parsing-jpeg-sos-marker - - advanceBytes, err := js.processScanData(data) - log.PanicIf(err) - - // This will either return 0 and implicitly request that we need more - // data and then need to run again or will return an actual byte count - // to progress by. - - return advanceBytes, nil - } else if js.lastMarkerId == MARKER_EOI { - // We have more data following the EOI, which is unexpected. There - // might be non-standard cruft at the end of the file. Terminate the - // parse because the file-structure is, technically, complete at this - // point. - - return 0, io.EOF - } else { - js.lastIsScanData = false - } - - // If we're here, we're supposed to be sitting on the 0xff bytes at the - // beginning of a segment (just before the marker). - - if data[0] != 0xff { - log.Panicf("not on new segment marker @ (%d): (%02X)", js.currentOffset, data[0]) - } - - i := 0 - found := false - for ; i < chunkLength; i++ { - jpegLogger.Debugf(nil, "Prefix check: (%d) %02X", i, data[i]) - - if data[i] != 0xff { - found = true - break - } - } - - jpegLogger.Debugf(nil, "Skipped over leading 0xFF bytes: (%d)", i) - - if found == false || i >= chunkLength { - jpegLogger.Debugf(nil, "Not enough (3)") - return 0, nil - } - - markerId := data[i] - - js.lastMarkerName = markerNames[markerId] - - sizeLen, found := markerLen[markerId] - jpegLogger.Debugf(nil, "MARKER-ID=%x SIZELEN=%v FOUND=%v", markerId, sizeLen, found) - - i++ - - b := bytes.NewBuffer(data[i:]) - payloadLength := 0 - - // marker-ID + size => 2 + <dynamic> - headerSize := 2 + sizeLen - - if found == false { - - // It's not one of the static-length markers. Read the length. - // - // The length is an unsigned 16-bit network/big-endian. - - // marker-ID + size => 2 + 2 - headerSize = 2 + 2 - - if i+2 >= chunkLength { - jpegLogger.Debugf(nil, "Not enough (4)") - return 0, nil - } - - l := uint16(0) - err = binary.Read(b, binary.BigEndian, &l) - log.PanicIf(err) - - if l < 2 { - log.Panicf("length of size read for non-special marker (%02x) is unexpectedly less than two.", markerId) - } - - // (l includes the bytes of the length itself.) - payloadLength = int(l) - 2 - jpegLogger.Debugf(nil, "DataLength (dynamically-sized segment): (%d)", payloadLength) - - i += 2 - } else if sizeLen > 0 { - - // Accommodates the non-zero markers in our marker index, which only - // represent J2C extensions. - // - // The length is an unsigned 32-bit network/big-endian. - - // TODO(dustin): !! This needs to be tested, but we need an image. - - if sizeLen != 4 { - log.Panicf("known non-zero marker is not four bytes, which is not currently handled: M=(%x)", markerId) - } - - if i+4 >= chunkLength { - jpegLogger.Debugf(nil, "Not enough (5)") - return 0, nil - } - - l := uint32(0) - err = binary.Read(b, binary.BigEndian, &l) - log.PanicIf(err) - - payloadLength = int(l) - 4 - jpegLogger.Debugf(nil, "DataLength (four-byte-length segment): (%u)", l) - - i += 4 - } - - jpegLogger.Debugf(nil, "PAYLOAD-LENGTH: %d", payloadLength) - - payload := data[i:] - - if payloadLength < 0 { - log.Panicf("payload length less than zero: (%d)", payloadLength) - } - - i += int(payloadLength) - - if i > chunkLength { - jpegLogger.Debugf(nil, "Not enough (6)") - return 0, nil - } - - jpegLogger.Debugf(nil, "Found whole segment.") - - js.lastMarkerId = markerId - - payloadWindow := payload[:payloadLength] - err = js.handleSegment(markerId, js.lastMarkerName, headerSize, payloadWindow) - log.PanicIf(err) - - js.counter++ - - jpegLogger.Debugf(nil, "Returning advance of (%d)", i) - - return i, nil -} - -func (js *JpegSplitter) scanDataIsNext() bool { - return js.lastMarkerId == MARKER_SOS -} - -// Split is the base splitting function that satisfies `bufio.SplitFunc`. -func (js *JpegSplitter) Split(data []byte, atEOF bool) (advance int, token []byte, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - for len(data) > 0 { - currentAdvance, err := js.readSegment(data) - if err != nil { - if err == io.EOF { - // We've encountered an EOI marker. - return 0, nil, err - } - - log.Panic(err) - } - - if currentAdvance == 0 { - if len(data) > 0 && atEOF == true { - // Provide a little context in the error message. - - if js.scanDataIsNext() == true { - // Yes, we've ran into this. - - log.Panicf("scan-data is unbounded; EOI not encountered before EOF") - } else { - log.Panicf("partial segment data encountered before scan-data") - } - } - - // We don't have enough data for another segment. - break - } - - data = data[currentAdvance:] - advance += currentAdvance - } - - return advance, nil, nil -} - -func (js *JpegSplitter) parseSof(data []byte) (sof *SofSegment, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - stream := bytes.NewBuffer(data) - buffer := bufio.NewReader(stream) - - bitsPerSample, err := buffer.ReadByte() - log.PanicIf(err) - - height := uint16(0) - err = binary.Read(buffer, binary.BigEndian, &height) - log.PanicIf(err) - - width := uint16(0) - err = binary.Read(buffer, binary.BigEndian, &width) - log.PanicIf(err) - - componentCount, err := buffer.ReadByte() - log.PanicIf(err) - - sof = &SofSegment{ - BitsPerSample: bitsPerSample, - Width: width, - Height: height, - ComponentCount: componentCount, - } - - return sof, nil -} - -func (js *JpegSplitter) parseAppData(markerId byte, data []byte) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - return nil -} - -func (js *JpegSplitter) handleSegment(markerId byte, markerName string, headerSize int, payload []byte) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - cloned := make([]byte, len(payload)) - copy(cloned, payload) - - s := &Segment{ - MarkerId: markerId, - MarkerName: markerName, - Offset: js.currentOffset, - Data: cloned, - } - - jpegLogger.Debugf(nil, "Encountered marker (0x%02x) [%s] at offset (%d)", markerId, markerName, js.currentOffset) - - js.currentOffset += headerSize + len(payload) - - js.segments.Add(s) - - sv, ok := js.visitor.(SegmentVisitor) - if ok == true { - err = sv.HandleSegment(js.lastMarkerId, js.lastMarkerName, js.counter, js.lastIsScanData) - log.PanicIf(err) - } - - if markerId >= MARKER_SOF0 && markerId <= MARKER_SOF15 { - ssv, ok := js.visitor.(SofSegmentVisitor) - if ok == true { - sof, err := js.parseSof(payload) - log.PanicIf(err) - - err = ssv.HandleSof(sof) - log.PanicIf(err) - } - } else if markerId >= MARKER_APP0 && markerId <= MARKER_APP15 { - err := js.parseAppData(markerId, payload) - log.PanicIf(err) - } - - return nil -} diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/testing_common.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/testing_common.go deleted file mode 100644 index e7169c2f0..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/testing_common.go +++ /dev/null @@ -1,73 +0,0 @@ -package jpegstructure - -import ( - "os" - "path" - - "github.com/dsoprea/go-logging" -) - -var ( - testImageRelFilepath = "NDM_8901.jpg" -) - -var ( - moduleRootPath = "" - assetsPath = "" -) - -// GetModuleRootPath returns the root-path of the module. -func GetModuleRootPath() string { - if moduleRootPath == "" { - moduleRootPath = os.Getenv("JPEG_MODULE_ROOT_PATH") - if moduleRootPath != "" { - return moduleRootPath - } - - currentWd, err := os.Getwd() - log.PanicIf(err) - - currentPath := currentWd - visited := make([]string, 0) - - for { - tryStampFilepath := path.Join(currentPath, ".MODULE_ROOT") - - _, err := os.Stat(tryStampFilepath) - if err != nil && os.IsNotExist(err) != true { - log.Panic(err) - } else if err == nil { - break - } - - visited = append(visited, tryStampFilepath) - - currentPath = path.Dir(currentPath) - if currentPath == "/" { - log.Panicf("could not find module-root: %v", visited) - } - } - - moduleRootPath = currentPath - } - - return moduleRootPath -} - -// GetTestAssetsPath returns the path of the test-assets. -func GetTestAssetsPath() string { - if assetsPath == "" { - moduleRootPath := GetModuleRootPath() - assetsPath = path.Join(moduleRootPath, "assets") - } - - return assetsPath -} - -// GetTestImageFilepath returns the file-path of the common test-image. -func GetTestImageFilepath() string { - assetsPath := GetTestAssetsPath() - filepath := path.Join(assetsPath, testImageRelFilepath) - - return filepath -} diff --git a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/utility.go b/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/utility.go deleted file mode 100644 index 1c618ba6d..000000000 --- a/vendor/github.com/superseriousbusiness/go-jpeg-image-structure/v2/utility.go +++ /dev/null @@ -1,110 +0,0 @@ -package jpegstructure - -import ( - "bytes" - "fmt" - "sort" - "strings" - - "github.com/dsoprea/go-logging" - "github.com/go-xmlfmt/xmlfmt" -) - -// DumpBytes prints the hex for a given byte-slice. -func DumpBytes(data []byte) { - fmt.Printf("DUMP: ") - for _, x := range data { - fmt.Printf("%02x ", x) - } - - fmt.Printf("\n") -} - -// DumpBytesClause prints a Go-formatted byte-slice expression. -func DumpBytesClause(data []byte) { - fmt.Printf("DUMP: ") - - fmt.Printf("[]byte { ") - - for i, x := range data { - fmt.Printf("0x%02x", x) - - if i < len(data)-1 { - fmt.Printf(", ") - } - } - - fmt.Printf(" }\n") -} - -// DumpBytesToString returns a string of hex-encoded bytes. -func DumpBytesToString(data []byte) string { - b := new(bytes.Buffer) - - for i, x := range data { - _, err := b.WriteString(fmt.Sprintf("%02x", x)) - log.PanicIf(err) - - if i < len(data)-1 { - _, err := b.WriteRune(' ') - log.PanicIf(err) - } - } - - return b.String() -} - -// DumpBytesClauseToString returns a string of Go-formatted byte values. -func DumpBytesClauseToString(data []byte) string { - b := new(bytes.Buffer) - - for i, x := range data { - _, err := b.WriteString(fmt.Sprintf("0x%02x", x)) - log.PanicIf(err) - - if i < len(data)-1 { - _, err := b.WriteString(", ") - log.PanicIf(err) - } - } - - return b.String() -} - -// FormatXml prettifies XML data. -func FormatXml(raw string) (formatted string, err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - formatted = xmlfmt.FormatXML(raw, " ", " ") - formatted = strings.TrimSpace(formatted) - - return formatted, nil -} - -// SortStringStringMap sorts a string-string dictionary and returns it as a list -// of 2-tuples. -func SortStringStringMap(data map[string]string) (sorted [][2]string) { - // Sort keys. - - sortedKeys := make([]string, len(data)) - i := 0 - for key := range data { - sortedKeys[i] = key - i++ - } - - sort.Strings(sortedKeys) - - // Build result. - - sorted = make([][2]string, len(sortedKeys)) - for i, key := range sortedKeys { - sorted[i] = [2]string{key, data[key]} - } - - return sorted -} diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/.MODULE_ROOT b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/.MODULE_ROOT deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/.MODULE_ROOT +++ /dev/null diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/LICENSE b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/LICENSE deleted file mode 100644 index 163291ed6..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT LICENSE - -Copyright 2020 Dustin Oprea - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/chunk_decoder.go b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/chunk_decoder.go deleted file mode 100644 index 518bc91ad..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/chunk_decoder.go +++ /dev/null @@ -1,81 +0,0 @@ -package pngstructure - -import ( - "bytes" - "fmt" - - "encoding/binary" -) - -type ChunkDecoder struct { -} - -func NewChunkDecoder() *ChunkDecoder { - return new(ChunkDecoder) -} - -func (cd *ChunkDecoder) Decode(c *Chunk) (decoded interface{}, err error) { - switch c.Type { - case "IHDR": - return cd.decodeIHDR(c) - } - - // We don't decode this type. - return nil, nil -} - -type ChunkIHDR struct { - Width uint32 - Height uint32 - BitDepth uint8 - ColorType uint8 - CompressionMethod uint8 - FilterMethod uint8 - InterlaceMethod uint8 -} - -func (ihdr *ChunkIHDR) String() string { - return fmt.Sprintf("IHDR<WIDTH=(%d) HEIGHT=(%d) DEPTH=(%d) COLOR-TYPE=(%d) COMP-METHOD=(%d) FILTER-METHOD=(%d) INTRLC-METHOD=(%d)>", - ihdr.Width, ihdr.Height, ihdr.BitDepth, ihdr.ColorType, ihdr.CompressionMethod, ihdr.FilterMethod, ihdr.InterlaceMethod, - ) -} - -func (cd *ChunkDecoder) decodeIHDR(c *Chunk) (*ChunkIHDR, error) { - var ( - b = bytes.NewBuffer(c.Data) - ihdr = new(ChunkIHDR) - readf = func(data interface{}) error { - return binary.Read(b, binary.BigEndian, data) - } - ) - - if err := readf(&ihdr.Width); err != nil { - return nil, err - } - - if err := readf(&ihdr.Height); err != nil { - return nil, err - } - - if err := readf(&ihdr.BitDepth); err != nil { - return nil, err - } - - if err := readf(&ihdr.ColorType); err != nil { - return nil, err - } - - if err := readf(&ihdr.CompressionMethod); err != nil { - return nil, err - } - - if err := readf(&ihdr.FilterMethod); err != nil { - return nil, err - } - - if err := readf(&ihdr.InterlaceMethod); err != nil { - return nil, err - } - - return ihdr, nil -} diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/media_parser.go b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/media_parser.go deleted file mode 100644 index 4c8421905..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/media_parser.go +++ /dev/null @@ -1,85 +0,0 @@ -package pngstructure - -import ( - "bufio" - "bytes" - "image" - "io" - "os" - - "image/png" - - riimage "github.com/dsoprea/go-utility/v2/image" -) - -// PngMediaParser knows how to parse a PNG stream. -type PngMediaParser struct { -} - -// NewPngMediaParser returns a new `PngMediaParser`. -func NewPngMediaParser() riimage.MediaParser { - return new(PngMediaParser) -} - -// Parse parses a PNG stream given a `io.ReadSeeker`. -func (pmp *PngMediaParser) Parse( - rs io.ReadSeeker, - size int, -) (riimage.MediaContext, error) { - ps := NewPngSplitter() - if err := ps.readHeader(rs); err != nil { - return nil, err - } - - s := bufio.NewScanner(rs) - - // Since each segment can be any - // size, our buffer must be allowed - // to grow as large as the file. - buffer := []byte{} - s.Buffer(buffer, size) - s.Split(ps.Split) - - for s.Scan() { - } - - if err := s.Err(); err != nil { - return nil, err - } - - return ps.Chunks() -} - -// ParseFile parses a PNG stream given a file-path. -func (pmp *PngMediaParser) ParseFile(filepath string) (riimage.MediaContext, error) { - f, err := os.Open(filepath) - if err != nil { - return nil, err - } - defer f.Close() - - stat, err := f.Stat() - if err != nil { - return nil, err - } - - size := stat.Size() - return pmp.Parse(f, int(size)) -} - -// ParseBytes parses a PNG stream given a byte-slice. -func (pmp *PngMediaParser) ParseBytes(data []byte) (riimage.MediaContext, error) { - br := bytes.NewReader(data) - return pmp.Parse(br, len(data)) -} - -// LooksLikeFormat returns a boolean indicating -// whether the stream looks like a PNG image. -func (pmp *PngMediaParser) LooksLikeFormat(data []byte) bool { - return bytes.Equal(data[:len(PngSignature)], PngSignature[:]) -} - -// GetImage returns an image.Image-compatible struct. -func (pmp *PngMediaParser) GetImage(r io.Reader) (img image.Image, err error) { - return png.Decode(r) -} diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/png.go b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/png.go deleted file mode 100644 index dfe773b71..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/png.go +++ /dev/null @@ -1,386 +0,0 @@ -package pngstructure - -import ( - "bytes" - "errors" - "fmt" - "io" - - "encoding/binary" - "hash/crc32" - - "github.com/dsoprea/go-exif/v3" - exifcommon "github.com/dsoprea/go-exif/v3/common" - riimage "github.com/dsoprea/go-utility/v2/image" -) - -var ( - PngSignature = [8]byte{137, 'P', 'N', 'G', '\r', '\n', 26, '\n'} - EXifChunkType = "eXIf" - IHDRChunkType = "IHDR" -) - -var ( - ErrNotPng = errors.New("not png data") - ErrCrcFailure = errors.New("crc failure") -) - -// ChunkSlice encapsulates a slice of chunks. -type ChunkSlice struct { - chunks []*Chunk -} - -func NewChunkSlice(chunks []*Chunk) (*ChunkSlice, error) { - if len(chunks) == 0 { - err := errors.New("ChunkSlice must be initialized with at least one chunk (IHDR)") - return nil, err - } else if chunks[0].Type != IHDRChunkType { - err := errors.New("first chunk in any ChunkSlice must be an IHDR") - return nil, err - } - - return &ChunkSlice{chunks}, nil -} - -func NewPngChunkSlice() (*ChunkSlice, error) { - ihdrChunk := &Chunk{ - Type: IHDRChunkType, - } - - ihdrChunk.UpdateCrc32() - - return NewChunkSlice([]*Chunk{ihdrChunk}) -} - -func (cs *ChunkSlice) String() string { - return fmt.Sprintf("ChunkSlize<LEN=(%d)>", len(cs.chunks)) -} - -// Chunks exposes the actual slice. -func (cs *ChunkSlice) Chunks() []*Chunk { - return cs.chunks -} - -// Write encodes and writes all chunks. -func (cs *ChunkSlice) WriteTo(w io.Writer) error { - if _, err := w.Write(PngSignature[:]); err != nil { - return err - } - - // TODO(dustin): !! This should respect - // the safe-to-copy characteristic. - for _, c := range cs.chunks { - if _, err := c.WriteTo(w); err != nil { - return err - } - } - - return nil -} - -// Index returns a map of chunk types to chunk slices, grouping all like chunks. -func (cs *ChunkSlice) Index() (index map[string][]*Chunk) { - index = make(map[string][]*Chunk) - for _, c := range cs.chunks { - if grouped, found := index[c.Type]; found { - index[c.Type] = append(grouped, c) - } else { - index[c.Type] = []*Chunk{c} - } - } - - return index -} - -// FindExif returns the the segment that hosts the EXIF data. -func (cs *ChunkSlice) FindExif() (chunk *Chunk, err error) { - index := cs.Index() - if chunks, found := index[EXifChunkType]; found { - return chunks[0], nil - } - - return nil, exif.ErrNoExif -} - -// Exif returns an `exif.Ifd` instance with the existing tags. -func (cs *ChunkSlice) Exif() (*exif.Ifd, []byte, error) { - chunk, err := cs.FindExif() - if err != nil { - return nil, nil, err - } - - im, err := exifcommon.NewIfdMappingWithStandard() - if err != nil { - return nil, nil, err - } - - ti := exif.NewTagIndex() - - _, index, err := exif.Collect(im, ti, chunk.Data) - if err != nil { - return nil, nil, err - } - - return index.RootIfd, chunk.Data, nil -} - -// ConstructExifBuilder returns an `exif.IfdBuilder` instance -// (needed for modifying) preloaded with all existing tags. -func (cs *ChunkSlice) ConstructExifBuilder() (*exif.IfdBuilder, error) { - rootIfd, _, err := cs.Exif() - if err != nil { - return nil, err - } - - return exif.NewIfdBuilderFromExistingChain(rootIfd), nil -} - -// SetExif encodes and sets EXIF data into this segment. -func (cs *ChunkSlice) SetExif(ib *exif.IfdBuilder) error { - // Encode. - - ibe := exif.NewIfdByteEncoder() - - exifData, err := ibe.EncodeToExif(ib) - if err != nil { - return err - } - - // Set. - - exifChunk, err := cs.FindExif() - - switch { - case err == nil: - // EXIF chunk already exists. - exifChunk.Data = exifData - exifChunk.Length = uint32(len(exifData)) - - case errors.Is(err, exif.ErrNoExif): - // Add a EXIF chunk for the first time. - exifChunk = &Chunk{ - Type: EXifChunkType, - Data: exifData, - Length: uint32(len(exifData)), - } - - // Insert exif after the IHDR chunk; it's - // a reliably appropriate place to put it. - cs.chunks = append( - cs.chunks[:1], - append( - []*Chunk{exifChunk}, - cs.chunks[1:]..., - )..., - ) - - default: - return err - } - - exifChunk.UpdateCrc32() - return nil -} - -// PngSplitter hosts the princpal `Split()` -// method uses by `bufio.Scanner`. -type PngSplitter struct { - chunks []*Chunk - currentOffset int - - doCheckCrc bool - crcErrors []string -} - -func (ps *PngSplitter) Chunks() (*ChunkSlice, error) { - return NewChunkSlice(ps.chunks) -} - -func (ps *PngSplitter) DoCheckCrc(doCheck bool) { - ps.doCheckCrc = doCheck -} - -func (ps *PngSplitter) CrcErrors() []string { - return ps.crcErrors -} - -func NewPngSplitter() *PngSplitter { - return &PngSplitter{ - chunks: make([]*Chunk, 0), - doCheckCrc: true, - crcErrors: make([]string, 0), - } -} - -// Chunk describes a single chunk. -type Chunk struct { - Offset int - Length uint32 - Type string - Data []byte - Crc uint32 -} - -func (c *Chunk) String() string { - return fmt.Sprintf("Chunk<OFFSET=(%d) LENGTH=(%d) TYPE=[%s] CRC=(%d)>", c.Offset, c.Length, c.Type, c.Crc) -} - -func calculateCrc32(chunk *Chunk) uint32 { - c := crc32.NewIEEE() - - c.Write([]byte(chunk.Type)) - c.Write(chunk.Data) - - return c.Sum32() -} - -func (c *Chunk) UpdateCrc32() { - c.Crc = calculateCrc32(c) -} - -func (c *Chunk) CheckCrc32() bool { - expected := calculateCrc32(c) - return c.Crc == expected -} - -// Bytes encodes and returns the bytes for this chunk. -func (c *Chunk) Bytes() ([]byte, error) { - if len(c.Data) != int(c.Length) { - return nil, errors.New("length of data not correct") - } - b := make([]byte, 0, 4+4+c.Length+4) - b = binary.BigEndian.AppendUint32(b, c.Length) - b = append(b, c.Type...) - b = append(b, c.Data...) - b = binary.BigEndian.AppendUint32(b, c.Crc) - return b, nil -} - -// Write encodes and writes the bytes for this chunk. -func (c *Chunk) WriteTo(w io.Writer) (int, error) { - if len(c.Data) != int(c.Length) { - return 0, errors.New("length of data not correct") - } - - var n int - - b := make([]byte, 4) // uint32 buf - - binary.BigEndian.PutUint32(b, c.Length) - if nn, err := w.Write(b); err != nil { - return n + nn, err - } - - n += len(b) - - if nn, err := io.WriteString(w, c.Type); err != nil { - return n + nn, err - } - - n += len(c.Type) - - if nn, err := w.Write(c.Data); err != nil { - return n + nn, err - } - - n += len(c.Data) - - binary.BigEndian.PutUint32(b, c.Crc) - if nn, err := w.Write(b); err != nil { - return n + nn, err - } - - n += len(b) - - return n, nil -} - -// readHeader verifies that the PNG header bytes appear next. -func (ps *PngSplitter) readHeader(r io.Reader) error { - var ( - sigLen = len(PngSignature) - header = make([]byte, sigLen) - ) - - if _, err := r.Read(header); err != nil { - return err - } - - ps.currentOffset += sigLen - if !bytes.Equal(header, PngSignature[:]) { - return ErrNotPng - } - - return nil -} - -// Split fulfills the `bufio.SplitFunc` -// function definition for `bufio.Scanner`. -func (ps *PngSplitter) Split( - data []byte, - atEOF bool, -) ( - advance int, - token []byte, - err error, -) { - // We might have more than one chunk's worth, and, - // if `atEOF` is true, we won't be called again. - // We'll repeatedly try to read additional chunks, - // but, when we run out of the data we were given - // then we'll return the number of bytes for the - // chunks we've already completely read. Then, we'll - // be called again from the end ofthose bytes, at - // which point we'll indicate that we don't yet have - // enough for another chunk, and we should be then - // called with more. - for { - len_ := len(data) - if len_ < 8 { - return advance, nil, nil - } - - length := binary.BigEndian.Uint32(data[:4]) - type_ := string(data[4:8]) - chunkSize := (8 + int(length) + 4) - - if len_ < chunkSize { - return advance, nil, nil - } - - crcIndex := 8 + length - crc := binary.BigEndian.Uint32(data[crcIndex : crcIndex+4]) - - content := make([]byte, length) - copy(content, data[8:8+length]) - - c := &Chunk{ - Length: length, - Type: type_, - Data: content, - Crc: crc, - Offset: ps.currentOffset, - } - - ps.chunks = append(ps.chunks, c) - - if !c.CheckCrc32() { - ps.crcErrors = append(ps.crcErrors, type_) - - if ps.doCheckCrc { - err = ErrCrcFailure - return - } - } - - advance += chunkSize - ps.currentOffset += chunkSize - - data = data[chunkSize:] - } -} - -var ( - // Enforce interface conformance. - _ riimage.MediaContext = new(ChunkSlice) -) diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/testing_common.go b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/testing_common.go deleted file mode 100644 index 42f28d282..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/testing_common.go +++ /dev/null @@ -1,77 +0,0 @@ -package pngstructure - -import ( - "fmt" - "os" - "path" -) - -var ( - assetsPath = "assets" -) - -func getModuleRootPath() (string, error) { - moduleRootPath := os.Getenv("PNG_MODULE_ROOT_PATH") - if moduleRootPath != "" { - return moduleRootPath, nil - } - - currentWd, err := os.Getwd() - if err != nil { - return "", err - } - - currentPath := currentWd - visited := make([]string, 0) - - for { - tryStampFilepath := path.Join(currentPath, ".MODULE_ROOT") - - _, err := os.Stat(tryStampFilepath) - if err != nil && !os.IsNotExist(err) { - return "", err - } else if err == nil { - break - } - - visited = append(visited, tryStampFilepath) - - currentPath = path.Dir(currentPath) - if currentPath == "/" { - return "", fmt.Errorf("could not find module-root: %v", visited) - } - } - - return currentPath, nil -} - -func getTestAssetsPath() (string, error) { - if assetsPath == "" { - moduleRootPath, err := getModuleRootPath() - if err != nil { - return "", err - } - - assetsPath = path.Join(moduleRootPath, "assets") - } - - return assetsPath, nil -} - -func getTestBasicImageFilepath() (string, error) { - assetsPath, err := getTestAssetsPath() - if err != nil { - return "", err - } - - return path.Join(assetsPath, "libpng.png"), nil -} - -func getTestExifImageFilepath() (string, error) { - assetsPath, err := getTestAssetsPath() - if err != nil { - return "", err - } - - return path.Join(assetsPath, "exif.png"), nil -} diff --git a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/utility.go b/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/utility.go deleted file mode 100644 index cac6020f2..000000000 --- a/vendor/github.com/superseriousbusiness/go-png-image-structure/v2/utility.go +++ /dev/null @@ -1,67 +0,0 @@ -package pngstructure - -import ( - "bytes" - "fmt" -) - -func DumpBytes(data []byte) { - fmt.Printf("DUMP: ") - for _, x := range data { - fmt.Printf("%02x ", x) - } - - fmt.Printf("\n") -} - -func DumpBytesClause(data []byte) { - fmt.Printf("DUMP: ") - - fmt.Printf("[]byte { ") - - for i, x := range data { - fmt.Printf("0x%02x", x) - - if i < len(data)-1 { - fmt.Printf(", ") - } - } - - fmt.Printf(" }\n") -} - -func DumpBytesToString(data []byte) (string, error) { - b := new(bytes.Buffer) - - for i, x := range data { - if _, err := b.WriteString(fmt.Sprintf("%02x", x)); err != nil { - return "", err - } - - if i < len(data)-1 { - if _, err := b.WriteRune(' '); err != nil { - return "", err - } - } - } - - return b.String(), nil -} - -func DumpBytesClauseToString(data []byte) (string, error) { - b := new(bytes.Buffer) - - for i, x := range data { - if _, err := b.WriteString(fmt.Sprintf("0x%02x", x)); err != nil { - return "", err - } - - if i < len(data)-1 { - if _, err := b.WriteString(", "); err != nil { - return "", err - } - } - } - - return b.String(), nil -} |