go-exif

repository·master·Indexed 20 days ago

https://github.com/dsoprea/go-exif

A native Go library for parsing, updating, and adding raw EXIF data blocks. It is format-agnostic, focusing on the EXIF standard rather than specific image containers. The library provides tools for scanning raw EXIF byte-slices, heuristic search and extraction from media blobs via SearchAndExtractExif, and an IfdBuilder for constructing or modifying Image File Directories. It includes the exif-read-tool CLI for dumping EXIF data in text or JSON format and provides specialized types for handling GPS coordinates and S2 cell IDs.

Tokens
28.5K
Snippets
129
Records
158
Agent score
69%

What's inside go-exif

  1. Configure IFD mapping and Tag indices

    master

    The library is configuration-driven and does not have built-in knowledge of tags and IDs by default. To use it, you must provide:

    1. IFD mapping: Contains knowledge of the IFD hierarchies and their tag-IDs.
    2. Tag index: Contains knowledge of the tags that specific IFDs are allowed to host.

    While there are convenience functions to load standard TIFF information, you can also load custom IFDs and tags to support non-standard or proprietary EXIF implementations.

  2. Understand the scope of go-exif

    master

    The go-exif package is strictly concerned with parsing and encoding raw EXIF data. It does not understand specific file formats (like JPEG, PNG, or HEIC).

    Users are responsible for:

    1. Extracting the raw EXIF byte-slice from a media file.
    2. Writing the updated EXIF data back into the media file.

    If you need help with the file-format specific logic, the author provides companion projects:

    • go-jpeg-image-structure
    • go-png-image-structure
    • go-tiff-image-structure
    • go-heic-exif-extractor
  3. Install go-exif v3

    master

    To get the project and its dependencies, clone the repository and navigate to the v3 directory:

    $ git clone https://github.com/dsoprea/go-exif.git
    $ cd v3
  4. GpsDegrees data structure

    master

    The GpsDegrees struct represents high-level geographic data parsed from EXIF. It consists of:

    • Orientation: A byte describing the N/E/S/W direction.
    • Degrees: A float64 representing the degree component.
    • Minutes: A float64 representing the minute component.
    • Seconds: A float64 representing the second component.
  5. Understand the EncodedData structure

    master

    Every encoding operation returns an EncodedData struct, which contains the results of the encoding process:

    • Type: The TagTypePrimitive assigned to this data (e.g., TypeByte, TypeShort, etc.).
    • Encoded: The actual []byte slice containing the binary representation of the value.
    • UnitCount: A uint32 representing the number of units (elements) in the encoded data (e.g., for TypeShort, this is the number of uint16 elements).
  6. GpsInfo data structure

    master

    The GpsInfo struct is a container that encapsulates all geographic information extracted from EXIF data in one place. It includes:

    • Latitude: A GpsDegrees struct.
    • Longitude: A GpsDegrees struct.
    • Altitude: An int representing altitude.
    • Timestamp: A time.Time object representing when the data was recorded.
  7. Use IfdBuilder to create or update EXIF IFDs

    master

    The IfdBuilder is the primary structure for constructing or modifying Image File Directories (IFDs). It allows you to add, replace, or delete tags, and manage child IFDs. You can initialize it from scratch or by creating a builder from an existing Ifd structure.

    Key capabilities:

    • Adding/Setting Tags: Use SetStandard or SetStandardWithName for known EXIF tags, or Set for custom BuilderTag instances.
    • Managing Child IFDs: Use AddChildIb to create branches in the IFD tree.
    • Thumbnail Management: Use SetThumbnail to handle thumbnail data (this automatically manages offset and size tags).
    • Navigation: Use GetOrCreateIbFromRootIb to navigate to a specific path in the IFD tree, even if it doesn't exist yet.
    // Example: Creating a new IFD builder from an existing IFD
    // (Assuming 'existingIfd' is an *exif.Ifd instance)
    builder := exif.NewIfdBuilderWithExistingIfd(existingIfd)
    
    // Adding a standard tag by name
    err := builder.SetStandardWithName("DateTimeOriginal", time.Now())
    
    // Adding a child IFD
    childIb := exif.NewIfdBuilder(mapping, index, "EXIF/GPSInfo", byteOrder)
    err := builder.AddChildIb(childIb)
  8. How to use TagIndex for EXIF tag lookups

    master

    The TagIndex is a lookup facility used to find EXIF tag metadata (like name and supported data types) using either a Tag ID or a Tag Name within a specific IFD (Image File Directory) path.

    To use it, you typically initialize a new index with NewTagIndex(), populate it using LoadStandardTags(ti), and then perform lookups using Get (by ID) or GetWithName (by name).

    Note: Get and GetWithName require an exifcommon.IfdIdentity to specify the IFD context.

    // 1. Initialize
    ti := exif.NewTagIndex()
    
    // 2. Load standard tags
    err := exif.LoadStandardTags(ti)
    
    // 3. Lookup by ID
    // ii is an exifcommon.IfdIdentity representing the IFD path
    tag, err := ti.Get(ii, 0x0100)
    
    // 4. Lookup by Name
    tag, err := ti.GetWithName(ii, "Model")
  9. Debug encoding with the IfdByteEncoder journal

    master

    The IfdByteEncoder maintains an internal journal that records every step taken during the encoding process (e.g., entering a tag, allocating data, setting next IFD offsets). You can inspect this journal to understand the hierarchy and the decisions made by the encoder.

    To view the trace, call PrintJournal() on your encoder instance. The output uses symbols like > (enter), < (exit), and - (action) to show the encoding flow.

    encoder := exif.NewIfdByteEncoder()
    // ... perform encoding operations ...
    encoder.PrintJournal()
  10. Initialize an IFD mapping

    master

    To work with EXIF Image File Directories (IFDs), you should use the IfdMapping type. You can initialize a mapping with standard EXIF structures (like Exif, GPSInfo, and Iop) using NewIfdMappingWithStandard(), or start with an empty mapping using NewIfdMapping() and manually add nodes using Add().

    Standard IFD paths include:

    • IFD/Exif
    • IFD/Exif/Iop
    • IFD/GPSInfo
    import "github.com/dsoprea/dsoprea/dsoprea/go-exif"
    
    // Initialize with standard EXIF IFDs
    im := exif.NewIfdMappingWithStandard()
  11. Use the exif-read-tool CLI to dump EXIF data

    master

    The exif-read-tool is a command-line utility used to extract and display EXIF information from image files. It can output data in a human-readable format or as a structured JSON object. It also supports extracting embedded thumbnails to a specified file path.

    Basic Usage

    To dump EXIF tags to the console in a standard format:

    exif-read-tool -filepath <path-to-image>

    Output Formats

    • Standard Output: Prints tags with their IFD path, ID, name, count, type, and value.
    • JSON Output: Use the -j or --json flag to output the data as a structured JSON array of IfdEntry objects. This is ideal for programmatic processing.

    Extracting Thumbnails

    If the image contains an embedded thumbnail, you can save it to a file using the -t or --thumbnail-output-filepath flag.

    exif-read-tool -filepath <path-to-image> -t <output-thumbnail-path>
    exif-read-tool -filepath <file-path>
  12. Find EXIF data in media files using SearchAndExtractExif

    master

    If you do not want to manually parse the media container to find the EXIF offset, you can use heuristic search methods to find and decode EXIF information directly from a media blob.

    Use exif.SearchAndExtractExif (or exif.SearchFileAndExtractExif for files) to explore EXIF information in formats you might not yet have a specific parser for.