go-exif: github.com/dsoprea/go-exif/v3/common Index | Examples | Files

package exifcommon

import "github.com/dsoprea/go-exif/v3/common"

Index

Examples

Package Files

ifd.go parser.go testing_common.go type.go utility.go value_context.go value_encoder.go

Variables

var (
    // IfdStandardIfdIdentity represents the IFD path for IFD0.
    IfdStandardIfdIdentity = NewIfdIdentity(rootStandardIfd, IfdIdentityPart{"IFD", 0})

    // IfdExifStandardIfdIdentity represents the IFD path for IFD0/Exif0.
    IfdExifStandardIfdIdentity = IfdStandardIfdIdentity.NewChild(exifStandardIfd, 0)

    // IfdExifIopStandardIfdIdentity represents the IFD path for IFD0/Exif0/Iop0.
    IfdExifIopStandardIfdIdentity = IfdExifStandardIfdIdentity.NewChild(iopStandardIfd, 0)

    // IfdGPSInfoStandardIfdIdentity represents the IFD path for IFD0/GPSInfo0.
    IfdGpsInfoStandardIfdIdentity = IfdStandardIfdIdentity.NewChild(gpsInfoStandardIfd, 0)

    // Ifd1StandardIfdIdentity represents the IFD path for IFD1.
    Ifd1StandardIfdIdentity = NewIfdIdentity(rootStandardIfd, IfdIdentityPart{"IFD", 1})
)
var (

    // EncodeDefaultByteOrder is the default byte-order for encoding operations.
    EncodeDefaultByteOrder = binary.BigEndian

    // Default byte order for tests.
    TestDefaultByteOrder = binary.BigEndian
)
var (
    // ErrNotEnoughData is used when there isn't enough data to accommodate what
    // we're trying to parse (sizeof(type) * unit_count).
    ErrNotEnoughData = errors.New("not enough data for type")

    // ErrWrongType is used when we try to parse anything other than the
    // current type.
    ErrWrongType = errors.New("wrong type, can not parse")

    // ErrUnhandledUndefinedTypedTag is used when we try to parse a tag that's
    // recorded as an "unknown" type but not a documented tag (therefore
    // leaving us not knowning how to read it).
    ErrUnhandledUndefinedTypedTag = errors.New("not a standard unknown-typed tag")
)
var (
    ErrChildIfdNotMapped = errors.New("no child-IFD for that tag-ID under parent")
)
var (
    // ErrNotFarValue indicates that an offset-based lookup was attempted for a
    // non-offset-based (embedded) value.
    ErrNotFarValue = errors.New("not a far value")
)
var (
    // TODO(dustin): Rename TypeNames() to typeNames() and add getter.
    TypeNames = map[TagTypePrimitive]string{
        TypeByte:           "BYTE",
        TypeAscii:          "ASCII",
        TypeShort:          "SHORT",
        TypeLong:           "LONG",
        TypeRational:       "RATIONAL",
        TypeUndefined:      "UNDEFINED",
        TypeSignedLong:     "SLONG",
        TypeSignedRational: "SRATIONAL",

        TypeAsciiNoNul: "_ASCII_NO_NUL",
    }
)

func DumpBytes Uses

func DumpBytes(data []byte)

DumpBytes prints a list of hex-encoded bytes.

func DumpBytesClause Uses

func DumpBytesClause(data []byte)

DumpBytesClause prints a list like DumpBytes(), but encapsulated in "[]byte { ... }".

func DumpBytesClauseToString Uses

func DumpBytesClauseToString(data []byte) string

DumpBytesClauseToString returns a comma-separated list of hex-encoded bytes.

func DumpBytesToString Uses

func DumpBytesToString(data []byte) string

DumpBytesToString returns a stringified list of hex-encoded bytes.

func ExifFullTimestampString Uses

func ExifFullTimestampString(t time.Time) (fullTimestampPhrase string)

ExifFullTimestampString produces a string like "2018:11:30 13:01:49" from a `time.Time` struct. It will attempt to convert to UTC first.

Code:

originalPhrase := "2018:11:30 13:01:49"

timestamp, err := ParseExifFullTimestamp(originalPhrase)
log.PanicIf(err)

restoredPhrase := ExifFullTimestampString(timestamp)
fmt.Printf("To EXIF timestamp: [%s]\n", restoredPhrase)

Output:

To EXIF timestamp: [2018:11:30 13:01:49]

func FormatFromBytes Uses

func FormatFromBytes(rawBytes []byte, tagType TagTypePrimitive, justFirst bool, byteOrder binary.ByteOrder) (phrase string, err error)

Format returns a stringified value for the given encoding. Automatically parses. Automatically calculates count based on type size.

func FormatFromType Uses

func FormatFromType(value interface{}, justFirst bool) (phrase string, err error)

Format returns a stringified value for the given encoding. Automatically parses. Automatically calculates count based on type size. This function also supports undefined-type values (the ones that we support, anyway) by way of the String() method that they all require. We can't be more specific because we're a base package and we can't refer to it.

func GetModuleRootPath Uses

func GetModuleRootPath() string

func GetTestAssetsPath Uses

func GetTestAssetsPath() string

func IsTime Uses

func IsTime(v interface{}) bool

IsTime returns true if the value is a `time.Time`.

func LoadStandardIfds Uses

func LoadStandardIfds(im *IfdMapping) (err error)

LoadStandardIfds loads the standard IFDs into the mapping.

func ParseExifFullTimestamp Uses

func ParseExifFullTimestamp(fullTimestampPhrase string) (timestamp time.Time, err error)

ParseExifFullTimestamp parses dates like "2018:11:30 13:01:49" into a UTC `time.Time` struct.

Code:

originalPhrase := "2018:11:30 13:01:49"

timestamp, err := ParseExifFullTimestamp(originalPhrase)
log.PanicIf(err)

fmt.Printf("To Go timestamp: [%s]\n", timestamp.Format(time.RFC3339))

Output:

To Go timestamp: [2018-11-30T13:01:49Z]

func TranslateStringToType Uses

func TranslateStringToType(tagType TagTypePrimitive, valueString string) (value interface{}, err error)

TranslateStringToType converts user-provided strings to properly-typed values. If a string, returns a string. Else, assumes that it's a single number. If a list needs to be processed, it is the caller's responsibility to split it (according to whichever convention has been established).

type BasicTag Uses

type BasicTag struct {
    // FqIfdPath is the fully-qualified IFD-path.
    FqIfdPath string

    // IfdPath is the unindexed IFD-path.
    IfdPath string

    // TagId is the tag-ID.
    TagId uint16
}

BasicTag describes a single tag for any purpose.

type EncodedData Uses

type EncodedData struct {
    Type    TagTypePrimitive
    Encoded []byte

    // TODO(dustin): Is this really necessary? We might have this just to correlate to the incoming stream format (raw bytes and a unit-count both for incoming and outgoing).
    UnitCount uint32
}

EncodedData encapsulates the compound output of an encoding operation.

type IfdIdentity Uses

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

IfdIdentity represents a single IFD path and provides access to various information and representations.

Only global instances can be used for equality checks.

func NewIfdIdentity Uses

func NewIfdIdentity(ifdTag IfdTag, parts ...IfdIdentityPart) (ii *IfdIdentity)

NewIfdIdentity returns a new IfdIdentity struct.

func NewIfdIdentityFromString Uses

func NewIfdIdentityFromString(im *IfdMapping, fqIfdPath string) (ii *IfdIdentity, err error)

NewIfdIdentityFromString parses a string like "IFD/Exif" or "IFD1" or something more exotic with custom IFDs ("SomeIFD4/SomeChildIFD6"). Note that this will valid the unindexed IFD structure (because the standard tags from the specification are unindexed), but not, obviously, any indices (e.g. the numbers in "IFD0", "IFD1", "SomeIFD4/SomeChildIFD6"). It is required for the caller to check whether these specific instances were actually parsed out of the stream.

func (*IfdIdentity) Equals Uses

func (ii *IfdIdentity) Equals(ii2 *IfdIdentity) bool

Equals returns true if the two IfdIdentity instances are effectively identical.

Since there's no way to get a specific fully-qualified IFD path without a certain slice of parts and all other fields are also derived from this, checking that the fully-qualified IFD path is equals is sufficient.

func (*IfdIdentity) IfdTag Uses

func (ii *IfdIdentity) IfdTag() IfdTag

IfdTag returns the tag struct behind this IFD.

func (*IfdIdentity) Index Uses

func (ii *IfdIdentity) Index() int

Index returns the index of this IFD (more then one IFD under a parent IFD will be numbered [0..n]).

func (*IfdIdentity) LeafPathPart Uses

func (ii *IfdIdentity) LeafPathPart() IfdIdentityPart

LeafPathPart returns the last right-most path-part, which represents the current IFD.

func (*IfdIdentity) Name Uses

func (ii *IfdIdentity) Name() string

Name returns the simple name of this IFD.

func (*IfdIdentity) NewChild Uses

func (ii *IfdIdentity) NewChild(childIfdTag IfdTag, index int) (iiChild *IfdIdentity)

NewChild creates an IfdIdentity for an IFD that is a child of the current IFD.

func (*IfdIdentity) NewSibling Uses

func (ii *IfdIdentity) NewSibling(index int) (iiSibling *IfdIdentity)

NewSibling creates an IfdIdentity for an IFD that is a sibling to the current one.

func (*IfdIdentity) String Uses

func (ii *IfdIdentity) String() string

String returns a fully-qualified IFD path.

func (*IfdIdentity) TagId Uses

func (ii *IfdIdentity) TagId() uint16

TagId returns the tag-ID of the IFD.

func (*IfdIdentity) UnindexedString Uses

func (ii *IfdIdentity) UnindexedString() string

UnindexedString returns a non-fully-qualified IFD path.

type IfdIdentityPart Uses

type IfdIdentityPart struct {
    Name  string
    Index int
}

IfdIdentityPart represents one component in an IFD path.

func (IfdIdentityPart) String Uses

func (iip IfdIdentityPart) String() string

String returns a fully-qualified IFD path.

func (IfdIdentityPart) UnindexedString Uses

func (iip IfdIdentityPart) UnindexedString() string

UnindexedString returned a non-fully-qualified IFD path.

type IfdMapping Uses

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

IfdMapping describes all of the IFDs that we currently recognize.

func NewIfdMapping Uses

func NewIfdMapping() (ifdMapping *IfdMapping)

NewIfdMapping returns a new IfdMapping struct.

func NewIfdMappingWithStandard Uses

func NewIfdMappingWithStandard() (ifdMapping *IfdMapping, err error)

NewIfdMappingWithStandard retruns a new IfdMapping struct preloaded with the standard IFDs.

func (*IfdMapping) Add Uses

func (im *IfdMapping) Add(parentPlacement []uint16, tagId uint16, name string) (err error)

Add puts the given IFD at the given position of the tree. The position of the tree is referred to as the placement and is represented by a set of tag-IDs, where the leftmost is the root tag and the tags going to the right are progressive descendants.

func (*IfdMapping) DumpLineages Uses

func (im *IfdMapping) DumpLineages() (output []string, err error)

DumpLineages returns a slice of strings representing all mappings.

func (*IfdMapping) FqPathPhraseFromLineage Uses

func (im *IfdMapping) FqPathPhraseFromLineage(lineage []IfdTagIdAndIndex) (fqPathPhrase string)

FqPathPhraseFromLineage returns the fully-qualified IFD path from the slice.

func (*IfdMapping) Get Uses

func (im *IfdMapping) Get(parentPlacement []uint16) (childIfd *MappedIfd, err error)

Get returns the node given the path slice.

func (*IfdMapping) GetChild Uses

func (im *IfdMapping) GetChild(parentPathPhrase string, tagId uint16) (mi *MappedIfd, err error)

GetChild is a convenience function to get the child path for a given parent placement and child tag-ID.

func (*IfdMapping) GetWithPath Uses

func (im *IfdMapping) GetWithPath(pathPhrase string) (mi *MappedIfd, err error)

GetWithPath returns the node given the path string.

func (*IfdMapping) PathPhraseFromLineage Uses

func (im *IfdMapping) PathPhraseFromLineage(lineage []IfdTagIdAndIndex) (pathPhrase string)

PathPhraseFromLineage returns the non-fully-qualified IFD path from the slice.

func (*IfdMapping) ResolvePath Uses

func (im *IfdMapping) ResolvePath(pathPhrase string) (lineage []IfdTagIdAndIndex, err error)

ResolvePath takes a list of names, which can also be suffixed with indices (to identify the second, third, etc.. sibling IFD) and returns a list of tag-IDs and those indices.

Example:

- IFD/Exif/Iop - IFD0/Exif/Iop

This is the only call that supports adding the numeric indices.

func (*IfdMapping) StripPathPhraseIndices Uses

func (im *IfdMapping) StripPathPhraseIndices(pathPhrase string) (strippedPathPhrase string, err error)

StripPathPhraseIndices returns a non-fully-qualified path-phrase (no indices).

type IfdTag Uses

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

IfdTag describes a single IFD tag and its parent (if any).

func NewIfdTag Uses

func NewIfdTag(parentIfdTag *IfdTag, tagId uint16, name string) IfdTag

func (IfdTag) Name Uses

func (it IfdTag) Name() string

Name returns the simple name of this IFD.

func (IfdTag) ParentIfd Uses

func (it IfdTag) ParentIfd() *IfdTag

ParentIfd returns the IfdTag of this IFD's parent.

func (IfdTag) String Uses

func (it IfdTag) String() string

String returns a descriptive string.

func (IfdTag) TagId Uses

func (it IfdTag) TagId() uint16

TagId returns the tag-ID of this IFD.

type IfdTagIdAndIndex Uses

type IfdTagIdAndIndex struct {
    Name  string
    TagId uint16
    Index int
}

IfdTagIdAndIndex represents a specific part of the IFD path.

This is a legacy type.

func (IfdTagIdAndIndex) String Uses

func (itii IfdTagIdAndIndex) String() string

String returns a descriptive string.

type MappedIfd Uses

type MappedIfd struct {
    ParentTagId uint16
    Placement   []uint16
    Path        []string

    Name     string
    TagId    uint16
    Children map[uint16]*MappedIfd
}

MappedIfd is one node in the IFD-mapping.

func (*MappedIfd) PathPhrase Uses

func (mi *MappedIfd) PathPhrase() string

PathPhrase returns a non-fully-qualified IFD path.

func (*MappedIfd) String Uses

func (mi *MappedIfd) String() string

String returns a descriptive string.

type Parser Uses

type Parser struct {
}

Parser knows how to parse all well-defined, encoded EXIF types.

func (*Parser) ParseAscii Uses

func (p *Parser) ParseAscii(data []byte, unitCount uint32) (value string, err error)

ParseAscii returns a string and auto-strips the trailing NUL character that should be at the end of the encoding.

func (*Parser) ParseAsciiNoNul Uses

func (p *Parser) ParseAsciiNoNul(data []byte, unitCount uint32) (value string, err error)

ParseAsciiNoNul returns a string without any consideration for a trailing NUL character.

func (*Parser) ParseBytes Uses

func (p *Parser) ParseBytes(data []byte, unitCount uint32) (value []uint8, err error)

ParseBytesknows how to parse a byte-type value.

func (*Parser) ParseLongs Uses

func (p *Parser) ParseLongs(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []uint32, err error)

ParseLongs knows how to encode an encoded list of unsigned longs.

func (*Parser) ParseRationals Uses

func (p *Parser) ParseRationals(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []Rational, err error)

ParseRationals knows how to parse an encoded list of unsigned rationals.

func (*Parser) ParseShorts Uses

func (p *Parser) ParseShorts(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []uint16, err error)

ParseShorts knows how to parse an encoded list of shorts.

func (*Parser) ParseSignedLongs Uses

func (p *Parser) ParseSignedLongs(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []int32, err error)

ParseSignedLongs knows how to parse an encoded list of signed longs.

func (*Parser) ParseSignedRationals Uses

func (p *Parser) ParseSignedRationals(data []byte, unitCount uint32, byteOrder binary.ByteOrder) (value []SignedRational, err error)

ParseSignedRationals knows how to parse an encoded list of signed rationals.

type Rational Uses

type Rational struct {
    // Numerator is the numerator of the rational value.
    Numerator uint32

    // Denominator is the numerator of the rational value.
    Denominator uint32
}

Rational describes an unsigned rational value.

type SignedRational Uses

type SignedRational struct {
    // Numerator is the numerator of the rational value.
    Numerator int32

    // Denominator is the numerator of the rational value.
    Denominator int32
}

SignedRational describes a signed rational value.

type TagTypePrimitive Uses

type TagTypePrimitive uint16

TagTypePrimitive is a type-alias that let's us easily lookup type properties.

const (
    // TypeByte describes an encoded list of bytes.
    TypeByte TagTypePrimitive = 1

    // TypeAscii describes an encoded list of characters that is terminated
    // with a NUL in its encoded form.
    TypeAscii TagTypePrimitive = 2

    // TypeShort describes an encoded list of shorts.
    TypeShort TagTypePrimitive = 3

    // TypeLong describes an encoded list of longs.
    TypeLong TagTypePrimitive = 4

    // TypeRational describes an encoded list of rationals.
    TypeRational TagTypePrimitive = 5

    // TypeUndefined describes an encoded value that has a complex/non-clearcut
    // interpretation.
    TypeUndefined TagTypePrimitive = 7

    // TypeSignedLong describes an encoded list of signed longs.
    TypeSignedLong TagTypePrimitive = 9

    // TypeSignedRational describes an encoded list of signed rationals.
    TypeSignedRational TagTypePrimitive = 10

    // TypeAsciiNoNul is just a pseudo-type, for our own purposes.
    TypeAsciiNoNul TagTypePrimitive = 0xf0
)

func GetTypeByName Uses

func GetTypeByName(typeName string) (tagType TagTypePrimitive, found bool)

GetTypeByName returns the `TagTypePrimitive` for the given type name. Returns (0) if not valid.

func (TagTypePrimitive) IsValid Uses

func (tagType TagTypePrimitive) IsValid() bool

IsValid returns true if tagType is a valid type.

func (TagTypePrimitive) Size Uses

func (tagType TagTypePrimitive) Size() int

Size returns the size of one atomic unit of the type.

func (TagTypePrimitive) String Uses

func (typeType TagTypePrimitive) String() string

String returns the name of the type

type ValueContext Uses

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

ValueContext embeds all of the parameters required to find and extract the actual tag value.

func NewValueContext Uses

func NewValueContext(ifdPath string, tagId uint16, unitCount, valueOffset uint32, rawValueOffset []byte, rs io.ReadSeeker, tagType TagTypePrimitive, byteOrder binary.ByteOrder) *ValueContext

NewValueContext returns a new ValueContext struct.

func (*ValueContext) AddressableData Uses

func (vc *ValueContext) AddressableData() io.ReadSeeker

AddressableData returns the block of data that we can dereference into.

func (*ValueContext) ByteOrder Uses

func (vc *ValueContext) ByteOrder() binary.ByteOrder

ByteOrder returns the byte-order of numbers.

func (*ValueContext) Format Uses

func (vc *ValueContext) Format() (value string, err error)

Format returns a string representation for the value.

Where the type is not ASCII, `justFirst` indicates whether to just stringify the first item in the slice (or return an empty string if the slice is empty).

Since this method lacks the information to process undefined-type tags (e.g. byte-order, tag-ID, IFD type), it will return an error if attempted. See `Undefined()`.

func (*ValueContext) FormatFirst Uses

func (vc *ValueContext) FormatFirst() (value string, err error)

FormatFirst is similar to `Format` but only gets and stringifies the first item.

func (*ValueContext) GetFarOffset Uses

func (vc *ValueContext) GetFarOffset() (offset uint32, err error)

GetFarOffset returns the offset if the value is not embedded [within the pointer itself] or an error if an embedded value.

func (*ValueContext) IfdPath Uses

func (vc *ValueContext) IfdPath() string

IfdPath returns the path of the IFD containing this tag.

func (*ValueContext) RawValueOffset Uses

func (vc *ValueContext) RawValueOffset() []byte

RawValueOffset returns the uninterpreted value-offset. This is used for embedded values (values small enough to fit within the offset bytes rather than needing to be stored elsewhere and referred to by an actual offset).

func (*ValueContext) ReadAscii Uses

func (vc *ValueContext) ReadAscii() (value string, err error)

ReadAscii parses the encoded NUL-terminated ASCII string from the value- context.

func (*ValueContext) ReadAsciiNoNul Uses

func (vc *ValueContext) ReadAsciiNoNul() (value string, err error)

ReadAsciiNoNul parses the non-NUL-terminated encoded ASCII string from the value-context.

func (*ValueContext) ReadBytes Uses

func (vc *ValueContext) ReadBytes() (value []byte, err error)

ReadBytes parses the encoded byte-array from the value-context.

func (*ValueContext) ReadLongs Uses

func (vc *ValueContext) ReadLongs() (value []uint32, err error)

ReadLongs parses the list of encoded, unsigned longs from the value-context.

func (*ValueContext) ReadRationals Uses

func (vc *ValueContext) ReadRationals() (value []Rational, err error)

ReadRationals parses the list of encoded, unsigned rationals from the value- context.

func (*ValueContext) ReadRawEncoded Uses

func (vc *ValueContext) ReadRawEncoded() (rawBytes []byte, err error)

ReadRawEncoded returns the encoded bytes for the value that we represent.

func (*ValueContext) ReadShorts Uses

func (vc *ValueContext) ReadShorts() (value []uint16, err error)

ReadShorts parses the list of encoded shorts from the value-context.

func (*ValueContext) ReadSignedLongs Uses

func (vc *ValueContext) ReadSignedLongs() (value []int32, err error)

ReadSignedLongs parses the list of encoded, signed longs from the value-context.

func (*ValueContext) ReadSignedRationals Uses

func (vc *ValueContext) ReadSignedRationals() (value []SignedRational, err error)

ReadSignedRationals parses the list of encoded, signed rationals from the value-context.

func (*ValueContext) SetUndefinedValueType Uses

func (vc *ValueContext) SetUndefinedValueType(tagType TagTypePrimitive)

SetUndefinedValueType sets the effective type if this is an unknown-type tag.

func (*ValueContext) SizeInBytes Uses

func (vc *ValueContext) SizeInBytes() int

SizeInBytes returns the number of bytes that this value requires. The underlying call will panic if the type is UNDEFINED. It is the responsibility of the caller to preemptively check that.

func (*ValueContext) TagId Uses

func (vc *ValueContext) TagId() uint16

TagId returns the ID of the tag that we represent.

func (*ValueContext) UnitCount Uses

func (vc *ValueContext) UnitCount() uint32

UnitCount returns the embedded unit-count.

func (*ValueContext) ValueOffset Uses

func (vc *ValueContext) ValueOffset() uint32

ValueOffset returns the value-offset decoded as a `uint32`.

func (*ValueContext) Values Uses

func (vc *ValueContext) Values() (values interface{}, err error)

Values knows how to resolve the given value. This value is always a list (undefined-values aside), so we're named accordingly.

Since this method lacks the information to process unknown-type tags (e.g. byte-order, tag-ID, IFD type), it will return an error if attempted. See `Undefined()`.

type ValueEncoder Uses

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

ValueEncoder knows how to encode values of every type to bytes.

func NewValueEncoder Uses

func NewValueEncoder(byteOrder binary.ByteOrder) *ValueEncoder

NewValueEncoder returns a new ValueEncoder.

func (*ValueEncoder) Encode Uses

func (ve *ValueEncoder) Encode(value interface{}) (ed EncodedData, err error)

Encode returns bytes for the given value, infering type from the actual value. This does not support `TypeAsciiNoNull` (all strings are encoded as `TypeAscii`).

Package exifcommon imports 14 packages (graph) and is imported by 6 packages. Updated 2020-09-15. Refresh now. Tools for package owners.