Photo2Mac

A native macOS image editor with a fully non-destructive workflow. Your edits live on a stack saved as XMP metadata inside the image.

~1.7 MB · macOS 14+ · Apple Silicon · GPL-2.0

Why Photo2Mac?

Most Mac image editors either commit pixels on every adjustment (Preview, most free apps) or hide your edits inside a proprietary library (Photos, Lightroom). Photo2Mac sits in the gap: every edit is just an entry on an EditStack that Core Image renders live. Nothing is written until you Save, and when you do, the stack travels inside the saved file as XMP — so re-opening the same file in Photo2Mac restores the edits and lets you keep tuning, indefinitely.

Other apps just see the rendered pixels. Photo2Mac is the only one that knows the recipe.

Features

Install

  1. Download the latest .dmg from the releases page.
  2. Open the .dmg, drag Photo2Mac.app to the Applications shortcut.
  3. Because the bundle is ad-hoc signed (no paid Apple Developer ID yet), Gatekeeper will refuse to open it on first launch. Clear the quarantine flag once:
    xattr -dr com.apple.quarantine /Applications/Photo2Mac.app
  4. Open Photo2Mac.app from /Applications and use ⌘O to open an image, or drop one onto the window.
No Homebrew required. The .dmg is about 1.7 MB and links only to Apple system frameworks. Build-from-source details are on GitHub.

The XMP edit stack

Photo2Mac is non-destructive: every adjustment lives on an EditStack rendered live by Core Image. When you Save, Photo2Mac writes the rendered pixels and embeds the EditStack as XMP metadata inside the image. Re-opening that file in Photo2Mac restores the stack so you can keep editing; other apps just see the rendered pixels.

This is the on-disk format, so external tools can read or even produce one.

Namespace

The same property is written into JPEG (APP1), PNG (iTXt XML:com.adobe.xmp), HEIC (meta box) and TIFF (tag 700) via Apple's ImageIO.

EditStack JSON

{
  "rotateDegrees": 0,        // clockwise, supports 0.01° increments
  "flipHorizontal": false,
  "flipVertical": false,
  "crop": null,              // or { x, y, width, height } normalized 0..1
  "adjustments": {
    "brightness": 0.0,       // -1 .. 1   -> CI -0.5 .. 0.5
    "contrast":   0.0,       // -1 .. 1   -> CI  0.5 .. 1.5
    "saturation": 0.0,       // -1 .. 1   -> CI  0.0 .. 2.0
    "exposure":   0.0        // -3 .. 3 EV stops (CIExposureAdjust)
  }
}

Render order is fixed and applied in this sequence: flipH → flipV → rotate → crop → adjustments — geometry first (so crop always operates on the rotated frame the user actually sees), pixel adjustments last.

Also written: standard tags

So that any XMP viewer — Preview's Inspector, Metapho, Adobe Bridge, exiftool, mdls, macOS Get Info — can see what happened to the file, three well-known tags are written alongside p2m:editStack:

These three values are always English regardless of Photo2Mac's UI language — file metadata is read by tools and people anywhere, so it stays locale-independent.

Example: rotate + crop

A 2.5° counter-clockwise straighten, then crop to the central 90%×80%:

{
  "rotateDegrees": -2.5,
  "flipHorizontal": false,
  "flipVertical": false,
  "crop": { "x": 0.05, "y": 0.10, "width": 0.90, "height": 0.80 },
  "adjustments": {
    "brightness": 0, "contrast": 0, "saturation": 0, "exposure": 0
  }
}

The matching tiff:ImageDescription:

Photo2Mac 0.1.0 — rotate -2.50°, crop 90%×80% at (5%, 10%)

Inspecting a Photo2Mac file from the command line

With exiftool:

# Every XMP field, including the p2m one
exiftool -XMP:all -G photo.jpg

# Just the edit stack JSON
exiftool -XMP-p2m:editStack -b photo.jpg | jq

# Human-readable summary
exiftool -ImageDescription -CreatorTool photo.jpg

Full reference, including the stability policy (the 1.0/ in the namespace URI is the schema version): docs/XMP.md in the repo.

Changelog

Mirrors the GitHub releases exactly. Newest first.

v0.2.0-alpha · 2026-05-28

Help window, About panel, XMP documentation, and file associations.

New

  • Custom About panel with author, copyright and clickable GitHub / Issues / email links.
  • Help window (⌘?) with sections for overview, getting started, tools, save/persistence, the XMP edit-stack format (namespace, JSON example, render order), shortcuts, tips, and current limitations. Opens at a readable 740×820 instead of macOS's default collapsed size.
  • XMP edit-stack documentation — full reference at docs/XMP.md: the p2m: namespace, EditStack JSON schema (rotateDegrees, flipH/V, crop, adjustments) with Core Image mapping, render order, the three standard tags also written (xmp:CreatorTool, tiff:ImageDescription, dc:description), examples, and exiftool snippets.
  • File associations in Settings — set Photo2Mac as the default editor for JPEG / PNG / HEIC / HEIF / TIFF, individually or all at once. Reads and writes the same LaunchServices DB Finder's Get Info > Open With > Change All... uses.

Fixes

  • Help window no longer opens collapsed to just the title bar on first launch.
v0.1.0-alpha · 2026-05-28 — First public release

First public release.

What works

  • Non-destructive pipeline with live Core Image rendering (Metal-backed).
  • Crop with 8 handles (corners + edges), aspect-ratio picker (Original, 1:1, 4:3, 3:2, 16:9, ..., Free), directional resize cursors on hover.
  • Rotate with ±90° presets, 0.01° slider, precise angle text field; Flip H / V.
  • Tune — brightness / contrast / saturation / exposure with a live histogram (Luminance / RGB / R / G / B).
  • Edits list popover in the toolbar with per-row revert.
  • Save (⌘S) overwrites the open file with rendered pixels + embedded XMP EditStack; Save As (⌘⇧S) prompts for a destination.
  • Invisible autosave under ~/Library/Application Support/Photo2Mac/ so unsaved edits survive a tab close.
  • Welcome screen with recent files; Metadata viewer with EXIF + Photo2Mac XMP status (raw JSON optional).
  • Bilingual UI (English default + Romanian), switchable in Settings; saved files always store English-only metadata.
  • Custom About panel + Help window (⌘?).
  • Tabs, Open Recent menu, Undo / Redo (⌘Z / ⌘⇧Z) with collapsed slider drags.

What's not yet there

Frequently asked questions

Is Photo2Mac free?

Yes. Photo2Mac is free and open source under the GPL-2.0-or-later license. There is no paid tier, no subscription, no telemetry. The source and the .dmg download are both on GitHub.

What does «non-destructive» actually mean here?

The original pixels of your file are never touched until you press Save. Every adjustment — crop, rotate, flip, brightness, contrast, saturation, exposure — lives on an EditStack that is rendered live by Core Image. When you Save, Photo2Mac writes the rendered pixels and embeds the EditStack as XMP metadata, so re-opening the same file restores the stack and lets you keep editing.

Which formats does Photo2Mac read and write?

JPEG, PNG, HEIC and TIFF. RAW support is on the roadmap. XMP metadata is embedded in all four output formats via ImageIO.

Does it work on Apple Silicon Macs?

Yes. The .dmg is built for Apple Silicon (arm64) and requires macOS 14 Sonoma or later. The codebase is universal and builds on Intel from source as well.

Why does macOS show a Gatekeeper warning the first time I open Photo2Mac?

Because the bundle is ad-hoc signed — there is no paid Apple Developer ID yet. Clear the quarantine flag once with:

xattr -dr com.apple.quarantine /Applications/Photo2Mac.app

Then open the app normally. Notarization (which removes the warning permanently) is planned once the project has a Developer ID.

Does Photo2Mac need Homebrew or any other dependency installed?

No. The .dmg is self-contained (about 1.7 MB) and links only to Apple system frameworks (Core Image, ImageIO, AppKit, SwiftUI). Drag to Applications and run.

License & credits

Photo2Mac is released under GPL-2.0-or-later. UI icons are a subset of the Phosphor icon set (MIT) via Iconify.

Feedback

Bugs and feature requests: issue tracker.
Direct contact: razvan@cremenescu.ro.