exifscalpel

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: MPL-2.0 Imports: 0 Imported by: 0

README

exifscalpel

exifscalpel is a small Go library of JPEG metadata write/edit primitives — byte-level parsing and surgical, minimal-diff editing of a JPEG's segments, its EXIF/TIFF block, and its XMP packet.

It exists to de-duplicate code currently copy-pasted between two CLIs and give them a shared, better-tested core:

  • tidy-exif — surgically empties Adobe software signatures (XMP CreatorTool, history softwareAgent, EXIF Software), preserving everything else.
  • lapis — privacy tool; strips identifying metadata (GPS, device IDs, thumbnails, IPTC) at three paranoia levels.

Both CLIs import exifscalpel as equal peers; the dependency flows one way (the library depends on neither tool). Policy stays in the CLIs — exifscalpel ships primitives only: no orchestration, flags, printing, or file walking.

Why this exists (and why not a library off the shelf)

The Go ecosystem's metadata libraries are read-only (bep/imagemeta states writing "is not supported, and never will"). The write-capable options either rebuild rather than minimally edit (dsoprea/go-exif) or reserialize the whole XMP packet via a model round-trip (trimmer-io/go-xmp) — the opposite of a length-preserving, leave-every-other-byte-identical edit. That gap is exifscalpel's reason to exist. Full survey in exifscalpel-HANDOFF.md §9.

Planned packages

Package Role Source of the engine
jpeg segment parse/write + identification lapis (canonical; identical in both repos)
exif TIFF/IFD parse + rebuild, tag edit lapis parseEXIF/buildEXIF
xmp XMP field-level surgery, length-preserving tidy-exif parseXMP/cleanXMP/marshalXMP

Primitives only; the high-level orchestration (InspectJPEG/CleanJPEG, lapis's Strip) stays in the consumers.

Status

Pre-code / planning. Repo is scaffolded; no Go yet. The build is fully specified in exifscalpel-HANDOFF.md — a cold-start guide (provenance, hard-won conclusions, package layout, API sketch, 7-phase migration, tests, decisions, prior-art). See STATUS.md.

One decision to make before Phase 2: the exif engine — lift lapis's lean, zero-dependency engine (recommended) vs depend on dsoprea/go-exif (handoff §7/§9).

License

Mozilla Public License 2.0 (MPL-2.0) — same as tidy-exif. lapis is MIT; MPL-2.0 is file-level copyleft and imports cleanly into MIT projects (only modifications to exifscalpel's own files stay MPL).

Documentation

Overview

Package exifscalpel is a small library of JPEG metadata write/edit primitives: byte-level parsing and surgical, minimal-diff editing of a JPEG's segments, its EXIF/TIFF block, and its XMP packet.

It exists to de-duplicate code shared between two sibling CLIs (tidy-exif, which empties Adobe software signatures, and lapis, a privacy stripper) and to give them a single, well-tested core. The dependency flows one way: both CLIs import exifscalpel; exifscalpel imports neither. It ships primitives only — no orchestration, flags, printing, or file walking. Policy (the Adobe-only gate, paranoia levels, output) stays in the consumers.

Packages

The library is three independent packages:

  • jpeg — JPEG segment parse/write plus segment identification (IsEXIF/IsXMP). Depends only on the standard library.
  • exif — TIFF/IFD parse and rebuild, with tag-level edit helpers.
  • xmp — XMP field-level surgery, length-preserving, plus read-only extraction of arbitrary XMP properties by namespace (ReadProperties).

exif and xmp take a segment payload ([]byte) and return bytes; they do not import jpeg, so each package stays independently usable and testable. Segment identification (the "Exif\x00\x00" and Adobe xap namespace signatures) lives in jpeg.

Invariants

These behaviors cost real debugging time in the predecessor tools and are baked into the code and tests here:

  1. XMP xmpMM:History stEvt:softwareAgent appears in ATTRIBUTE form (<rdf:li stEvt:softwareAgent="Adobe Photoshop CS6 (Windows)"/>), not only element form. The xmp package handles both on parse and clean; the attribute-form regression fixture is mandatory.

  2. Length-preserving edits avoid rewriting JPEG offsets. XMP pads the cleaned XML with whitespace inside <?xpacket?> so the APP1 segment keeps its byte length. The exif package can instead rebuild the payload (length may change) — correct when removing tags or IFDs. Both modes are available; neither is forced.

  3. EXIF value storage: a TIFF entry value of four bytes or fewer is stored inline; larger values live at an offset relative to the TIFF header (after "Exif\x00\x00"). The exif parser resolves every entry's value to actual bytes.

  4. JPEG parsing stops at SOS (0xFF 0xDA) and returns the compressed tail verbatim. Standalone markers (SOI, EOI, RST) carry no length; legal 0xFF padding before a marker is skipped.

Directories

Path Synopsis
Package exif parses and edits the EXIF/TIFF block carried in a JPEG APP1 segment.
Package exif parses and edits the EXIF/TIFF block carried in a JPEG APP1 segment.
Package iptc performs surgical edits on the IPTC-IIM metadata carried in a JPEG APP13 (Photoshop Image Resource) segment.
Package iptc performs surgical edits on the IPTC-IIM metadata carried in a JPEG APP13 (Photoshop Image Resource) segment.
Package jpeg parses and writes JPEG marker segments and identifies the EXIF and XMP APP1 segments.
Package jpeg parses and writes JPEG marker segments and identifies the EXIF and XMP APP1 segments.
Package xmp performs field-level surgery on the XMP packet carried in a JPEG APP1 segment.
Package xmp performs field-level surgery on the XMP packet carried in a JPEG APP1 segment.

Jump to

Keyboard shortcuts

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