Metadata-Version: 2.4
Name: charmfix
Version: 0.1.0
Summary: Repair broken or missing EXIF metadata in Kodak Charmera (Generalplus) JPEGs without touching image data
Keywords: exif,jpeg,kodak,charmera,photos,metadata
Author: Václav Vinklát
Author-email: Václav Vinklát <vin@email.cz>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Graphics
Requires-Dist: piexif>=1.1.3
Requires-Python: >=3.11
Project-URL: Homepage, https://github.com/vinklat/charmfix
Project-URL: Source, https://github.com/vinklat/charmfix
Project-URL: Issues, https://github.com/vinklat/charmfix/issues
Project-URL: Documentation, https://github.com/vinklat/charmfix/blob/main/CLI.md
Description-Content-Type: text/markdown

# charmfix

Repair the EXIF metadata of Kodak Charmera photos so Apple Photos, and everything else, shows the
right date, size and camera. Only metadata changes: every byte of image data stays the same (→
[REPAIRS.md](https://github.com/vinklat/charmfix/blob/v0.1.0/REPAIRS.md#invariant)), and charmfix checks this before it writes each file (→
[REPAIRS.md](https://github.com/vinklat/charmfix/blob/v0.1.0/REPAIRS.md#verification)). Source files are never modified (→
[CLI.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLI.md#source-safety)). Repaired copies go to a separate folder.

## What is wrong with Charmera files

The Charmera uses a Generalplus chip; its JPEGs carry a `GPEncoder` comment. Most files have **no
EXIF at all**, so Photos falls back to the import or copy date. Other firmware writes broken EXIF:
dates like `2026:03:03:12:16:29`, a 640×480 size on a 1440×1080 image, or a MakerNote that points
outside the EXIF block. charmfix fixes all of these; the exact rules are in
[REPAIRS.md](https://github.com/vinklat/charmfix/blob/v0.1.0/REPAIRS.md).

## Install

Released versions are published to [PyPI](https://pypi.org/project/charmfix/). With
[uv](https://docs.astral.sh/uv/):

```sh
uv tool install charmfix   # puts `charmfix` on your PATH
uvx charmfix -h            # or run it without installing
```

`pipx install charmfix` works too. Before the first release, or to run unreleased changes, install
from a checkout of this repository (→ [DEVELOPMENT.md](https://github.com/vinklat/charmfix/blob/v0.1.0/DEVELOPMENT.md#quality-gates)):

```sh
uv tool install .
uvx --from . charmfix -h
```

Supported Python versions → [DEVELOPMENT.md](https://github.com/vinklat/charmfix/blob/v0.1.0/DEVELOPMENT.md#prerequisites-and-setup).

## Usage

```sh
charmfix /Volumes/CHARMERA                     # writes to ~/Pictures/Kodak Charmera Repaired
charmfix /Volumes/CHARMERA -o ~/Desktop/fixed --report ~/Desktop/charmfix-report.json
charmfix /Volumes/CHARMERA --dry-run -v        # show what would change, write nothing
```

Without `-o`, copies go to the default output folder → [CLI.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLI.md#options). All options, exit
codes and the report format are in [CLI.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLI.md). Each file gets a status →
[REPAIRS.md](https://github.com/vinklat/charmfix/blob/v0.1.0/REPAIRS.md#status). Running charmfix again on the same card skips files it has already
written → [CLI.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLI.md#output-files).

**Run it on the card itself.** When a file has no usable EXIF date (often no EXIF at all), the
capture date is the file's modification time, which the camera sets when it takes the photo
([rule 1a](https://github.com/vinklat/charmfix/blob/v0.1.0/REPAIRS.md#rules)). Use the mounted card, or a copy that kept the times (`cp -p`, Finder
copy). Downloaded or exported files usually carry the copy time instead.

**macOS blocks the card?** Follow the hint charmfix prints (→ [CLI.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLI.md#discovery)): allow the
app you run it from under System Settings → Privacy & Security → Files and Folders → Removable
Volumes (or Full Disk Access), then restart that app.

## Apple Photos workflow

1. Insert the card and run `charmfix /Volumes/<card> --report ~/charmfix-report.json`.
2. Check the summary and look at any `partial` or `failed` lines.
3. In Photos, choose **File → Import…** and pick the output folder.

## Documentation

| Location | Audience | Authority |
| -- | -- | -- |
| [CLI.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLI.md) | Users, developers and AI agents | Canonical contract |
| [REPAIRS.md](https://github.com/vinklat/charmfix/blob/v0.1.0/REPAIRS.md), [DEVELOPMENT.md](https://github.com/vinklat/charmfix/blob/v0.1.0/DEVELOPMENT.md), [TESTING.md](https://github.com/vinklat/charmfix/blob/v0.1.0/TESTING.md) | Developers and AI agents | Canonical contracts |
| [AGENTS.md](https://github.com/vinklat/charmfix/blob/v0.1.0/AGENTS.md), [CLAUDE.md](https://github.com/vinklat/charmfix/blob/v0.1.0/CLAUDE.md) (imports AGENTS.md) | AI agents | How to use the contracts |
| `README.md` | Users | Non-canonical user guide |

## License

MIT → [LICENSE](https://github.com/vinklat/charmfix/blob/v0.1.0/LICENSE).
