jpegstructure

package module
v2.0.0-...-d89a106 Latest Latest
Warning

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

Go to latest
Published: Mar 21, 2022 License: MIT Imports: 21 Imported by: 2

README

Build Status codecov Go Report Card GoDoc

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.

Documentation

Index

Examples

Constants

View Source
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
)

Variables

View Source
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")
)

Functions

func DumpBytes

func DumpBytes(data []byte)

DumpBytes prints the hex for a given byte-slice.

func DumpBytesClause

func DumpBytesClause(data []byte)

DumpBytesClause prints a Go-formatted byte-slice expression.

func DumpBytesClauseToString

func DumpBytesClauseToString(data []byte) string

DumpBytesClauseToString returns a string of Go-formatted byte values.

func DumpBytesToString

func DumpBytesToString(data []byte) string

DumpBytesToString returns a string of hex-encoded bytes.

func FormatXml

func FormatXml(raw string) (formatted string, err error)

FormatXml prettifies XML data.

func GetModuleRootPath

func GetModuleRootPath() string

GetModuleRootPath returns the root-path of the module.

func GetTestAssetsPath

func GetTestAssetsPath() string

GetTestAssetsPath returns the path of the test-assets.

func GetTestImageFilepath

func GetTestImageFilepath() string

GetTestImageFilepath returns the file-path of the common test-image.

func SortStringStringMap

func SortStringStringMap(data map[string]string) (sorted [][2]string)

SortStringStringMap sorts a string-string dictionary and returns it as a list of 2-tuples.

Types

type JpegMediaParser

type JpegMediaParser struct {
}

JpegMediaParser is a `riimage.MediaParser` that knows how to parse JPEG images.

func NewJpegMediaParser

func NewJpegMediaParser() *JpegMediaParser

NewJpegMediaParser returns a new JpegMediaParser.

func (*JpegMediaParser) GetImage

func (jmp *JpegMediaParser) GetImage(r io.Reader) (img image.Image, err error)

GetImage returns an image.Image-compatible struct.

func (*JpegMediaParser) LooksLikeFormat

func (jmp *JpegMediaParser) LooksLikeFormat(data []byte) bool

LooksLikeFormat indicates whether the data looks like a JPEG image.

func (*JpegMediaParser) Parse

func (jmp *JpegMediaParser) Parse(rs io.ReadSeeker, size int) (ec riimage.MediaContext, err error)

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 (*JpegMediaParser) ParseBytes

func (jmp *JpegMediaParser) ParseBytes(data []byte) (ec riimage.MediaContext, err error)

ParseBytes parses a JPEG byte-slice. Even if it fails, it will return the list of segments encountered prior to the failure.

func (*JpegMediaParser) ParseFile

func (jmp *JpegMediaParser) ParseFile(filepath string) (ec riimage.MediaContext, err error)

ParseFile parses a JPEG file. Even if it fails, it will return the list of segments encountered prior to the failure.

type JpegSplitter

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

JpegSplitter uses the Go stream splitter to divide the JPEG stream into segments.

func NewJpegSplitter

func NewJpegSplitter(visitor interface{}) *JpegSplitter

NewJpegSplitter returns a new JpegSplitter.

func (*JpegSplitter) Counter

func (js *JpegSplitter) Counter() int

Counter returns the number of processed segments.

func (*JpegSplitter) IsScanData

func (js *JpegSplitter) IsScanData() bool

IsScanData returns whether the last processed segment was scan-data.

func (*JpegSplitter) MarkerId

func (js *JpegSplitter) MarkerId() byte

MarkerId returns the ID of the last processed marker.

func (*JpegSplitter) MarkerName

func (js *JpegSplitter) MarkerName() string

MarkerName returns the name of the last-processed marker.

func (*JpegSplitter) Segments

func (js *JpegSplitter) Segments() *SegmentList

Segments returns all found segments.

func (*JpegSplitter) Split

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

Split is the base splitting function that satisfies `bufio.SplitFunc`.

type Segment

type Segment struct {
	MarkerId   byte
	MarkerName string
	Offset     int
	Data       []byte
	// contains filtered or unexported fields
}

Segment describes a single segment.

func (*Segment) EmbeddedString

func (s *Segment) EmbeddedString() string

EmbeddedString returns a string of properties that can be embedded into an longer string of properties.

func (*Segment) Exif

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

Exif returns an `exif.Ifd` instance for the EXIF data we currently have.

func (*Segment) FlatExif

func (s *Segment) FlatExif() (exifTags []exif.ExifTag, err error)

FlatExif parses the EXIF data and just returns a list of tags.

func (*Segment) FormattedXmp

func (s *Segment) FormattedXmp() (formatted string, err error)

FormattedXmp returns a formatted XML string. This only makes sense for a segment comprised of XML data (like XMP).

func (*Segment) Iptc

func (s *Segment) Iptc() (tags map[iptc.StreamTagKey][]iptc.TagData, err error)

Iptc parses Photoshop info (if present) and then parses the IPTC info inside it (if present).

func (*Segment) IsExif

func (s *Segment) IsExif() bool

IsExif returns true if EXIF data.

func (*Segment) IsIptc

func (s *Segment) IsIptc() bool

IsIptc returns true if XMP data.

func (*Segment) IsXmp

func (s *Segment) IsXmp() bool

IsXmp returns true if XMP data.

func (*Segment) SetExif

func (s *Segment) SetExif(ib *exif.IfdBuilder) (err error)

SetExif encodes and sets EXIF data into this segment.

func (*Segment) String

func (s *Segment) String() string

String returns a descriptive string.

type SegmentList

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

SegmentList contains a slice of segments.

func NewSegmentList

func NewSegmentList(segments []*Segment) (sl *SegmentList)

NewSegmentList returns a new SegmentList struct.

func (*SegmentList) Add

func (sl *SegmentList) Add(s *Segment)

Add adds another segment.

func (*SegmentList) ConstructExifBuilder

func (sl *SegmentList) ConstructExifBuilder() (rootIb *exif.IfdBuilder, err error)

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

func (*SegmentList) DropExif

func (sl *SegmentList) DropExif() (wasDropped bool, err error)

DropExif will drop the EXIF data if present.

func (*SegmentList) DumpExif

func (sl *SegmentList) DumpExif() (segmentIndex int, segment *Segment, exifTags []exif.ExifTag, err error)

DumpExif returns an unstructured list of tags (useful when just reviewing).

func (*SegmentList) Exif

func (sl *SegmentList) Exif() (rootIfd *exif.Ifd, rawExif []byte, err error)

Exif returns an `exif.Ifd` instance for the EXIF data we currently have.

func (*SegmentList) FindExif

func (sl *SegmentList) FindExif() (index int, segment *Segment, err error)

FindExif returns the the segment that hosts the EXIF data (if present).

func (*SegmentList) FindIptc

func (sl *SegmentList) FindIptc() (index int, segment *Segment, err error)

FindIptc returns the the segment that hosts the IPTC data (if present).

func (*SegmentList) FindXmp

func (sl *SegmentList) FindXmp() (index int, segment *Segment, err error)

FindXmp returns the the segment that hosts the XMP data (if present).

func (*SegmentList) Iptc

func (sl *SegmentList) Iptc() (tags map[iptc.StreamTagKey][]iptc.TagData, err error)

Iptc returns embedded IPTC data if present.

func (*SegmentList) OffsetsEqual

func (sl *SegmentList) OffsetsEqual(o *SegmentList) bool

OffsetsEqual returns true is all segments have the same marker-IDs and were found at the same offsets.

func (*SegmentList) Print

func (sl *SegmentList) Print()

Print prints segment info.

func (*SegmentList) Segments

func (sl *SegmentList) Segments() []*Segment

Segments returns the underlying slice of segments.

func (*SegmentList) SetExif

func (sl *SegmentList) SetExif(ib *exif.IfdBuilder) (err error)

SetExif encodes and sets EXIF data into the given segment. If `index` is -1, append a new segment.

Example

ExampleSegmentList_SetExif shows how to construct a chain of `IfdBuilder` structs for the existing IFDs, identify the builder for the IFD that we know hosts the tag we want to change, and how to change it.

filepath := GetTestImageFilepath()

// Parse the image.

jmp := NewJpegMediaParser()

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

sl := intfc.(*SegmentList)

// Update the CameraOwnerName tag.

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

ifdPath := "IFD/Exif"

ifdIb, err := exif.GetOrCreateIbFromRootIb(rootIb, ifdPath)
log.PanicIf(err)

err = ifdIb.SetStandardWithName("CameraOwnerName", "TestOwner")
log.PanicIf(err)

// Update the exif segment.

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

b := new(bytes.Buffer)

err = sl.Write(b)
log.PanicIf(err)

// Validate.

d := b.Bytes()

intfc, err = jmp.ParseBytes(d)
log.PanicIf(err)

sl = intfc.(*SegmentList)

_, _, exifTags, err := sl.DumpExif()
log.PanicIf(err)

for _, et := range exifTags {
	if et.IfdPath == "IFD/Exif" && et.TagName == "CameraOwnerName" {
		fmt.Printf("Value: [%s]\n", et.FormattedFirst)
		break
	}
}
Output:

Value: [TestOwner]
Example (Unknowntype)
filepath := GetTestImageFilepath()

// Parse the image.

jmp := NewJpegMediaParser()

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

sl := intfc.(*SegmentList)

// Update the UserComment tag.

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

ifdPath := "IFD/Exif"

exifIb, err := exif.GetOrCreateIbFromRootIb(rootIb, ifdPath)
log.PanicIf(err)

uc := exifundefined.Tag9286UserComment{
	EncodingType:  exifundefined.TagUndefinedType_9286_UserComment_Encoding_ASCII,
	EncodingBytes: []byte("TEST COMMENT"),
}

err = exifIb.SetStandardWithName("UserComment", uc)
log.PanicIf(err)

// Update the exif segment.

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

b := new(bytes.Buffer)

err = sl.Write(b)
log.PanicIf(err)
Output:

func (*SegmentList) Validate

func (sl *SegmentList) Validate(data []byte) (err error)

Validate checks that all of the markers are actually located at all of the recorded offsets.

func (*SegmentList) Write

func (sl *SegmentList) Write(w io.Writer) (err error)

Write writes the segment data to the given `io.Writer`.

type SegmentVisitor

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
}

SegmentVisitor describes a segment-visitor struct.

type SofSegment

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
}

SofSegment has info read from a SOF segment.

func (SofSegment) String

func (ss SofSegment) String() string

String returns a string representation of the SOF segment.

type SofSegmentVisitor

type SofSegmentVisitor interface {
	// HandleSof is called for each encountered SOF segment.
	HandleSof(sof *SofSegment) error
}

SofSegmentVisitor describes a visitor that is only called for each SOF segment.

Jump to

Keyboard shortcuts

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