Commit Graph
297 Commits
Author SHA1 Message Date
David Mann 32ce08364b Merge pull request #9991 from ljkx/feat/raw-xmp-crop
Camera Raw sidecars: apply the crop, stop reporting RawFileName (#9985)
2026-11-08 16:55:43 +01:00
Triwarr 2d16a609ea Merge remote-tracking branch 'origin/main' into pdf
# Conflicts:
#	docs/scorecard.md
2026-11-08 03:48:47 +01:00
David Mann 9da3cda6a7 Merge origin/main into feat/raw-xmp-crop
# Conflicts:
#	docs/file-format-parity.md
2026-11-08 02:56:35 +01:00
David Mann 100997baaa Merge origin/main into feat/raw-xmp-crop
# Conflicts:
#	crates/ui-egui/src/dialogs/camera_raw_ui/open.rs
#	crates/ui-egui/src/dialogs/camera_raw_ui/sidecar.rs
#	docs/file-format-parity.md
2026-11-08 01:36:16 +01:00
50b877645f Merge origin/main into feat/cli-metadata-option (#9975)
Conflicts with main's --no-maximize-compatibility (#8064) in the CLI
export args, output mapping and dev-dependencies, and in the
file-format parity status line and revision history: both sides kept.

Co-Authored-By: ljkx <ljkx@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 01:26:47 +01:00
Triwarr 0525197133 Merge remote-tracking branch 'origin/main' into pdf
# Conflicts:
#	docs/scorecard.md
2026-11-08 01:09:29 +01:00
Triwarr d297dd3a2d PDF: validate --pdf-dpi, band the raster conversion, complete the notices
- --pdf-dpi now rejects zero, negative, NaN and infinite values at parse time (unit-tested) instead of silently falling back to 300 DPI.
- The RGBA8 raster is converted and written in 256-row bands with a cancellation check per band, so the f32 buffer no longer duplicates a whole page; the pixel-memory estimate charges the retained raster instead of that buffer.
- docs/file-format-parity.md: the 2026-11-07 revision row is inside the revision table.
- NOTICE now reproduces the Hayro MIT notice, the Foxit/PDFium BSD-3-Clause text, Adobe's CMaps BSD-3-Clause text and the CC0 statement for the ICC profile; package.ps1 ships NOTICE and ATTRIBUTION.md in both installers.
2026-11-07 20:12:46 +01:00
Triwarr ca92d936c0 PDF: import raster pages through craft-pdf instead of PDFium
- craft-pdf (the shared Rust/Hayro reader in craft-libs, rev c5a1cbf) renders each page; no shared library is loaded or shipped, and every desktop platform works.
- Raster pages only: editable text/vector import and the pdf_text/pdf_vectors options are removed (they can return later through craft-pdf's interpret device). Page geometry, artboards, page range, budgets, cancellation and warnings are kept; the effective DPI now respects craft-pdf's 8192 px side and 64M px page limits.
- Drops pdfium-render, the PDFium download in CI, the build-script copy and the packaging/licence staging; records the Hayro/fonts/CMaps/ICC assets in ATTRIBUTION.md and NOTICE.
- \.ai\ files starting with %PDF- now take the PDF importer, matching the comment.
- Attribution, architecture and file-format-parity docs updated.
2026-11-07 19:41:22 +01:00
ba3ea95007 raw: honour ActiveArea in Hasselblad 3FR/FFF (PR #9058)
The decoder set the active area and the crop to the whole plane and never
read ActiveArea, so a file with masked borders and no DefaultCrop developed
with the borders in. Read ActiveArea like the DNG path, use it as the
initial crop, and place DefaultCrop relative to it as DNG does. Also give
3FR/FFF its own row in the camera raw table instead of "embedded preview
only".

Co-Authored-By: Gotya-OFFCIAL <Gotya-OFFCIAL@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 19:39:30 +01:00
David Mann b8b539c845 Merge origin/main into PR #9058 (raw: Hasselblad 3FR/FFF) 2026-11-07 19:37:23 +01:00
David Mann f98218cbe8 Merge pull request #10529 from luben93/raw/nef-lossy-after-split-v2
raw: decode Nikon "lossy after split" NEFs
2026-11-07 16:06:23 +01:00
Cristi RaduandClaude Opus 5.5 a1bb9f003f Saves take maximizeCompatibility for a PSD/PSB's merged image (#8064)
Photoshop's Maximize Compatibility checkbox, for one save: `maximizeCompatibility`
(true or false) on Save, Save As, Save a Copy, `app.save`, serve `doc.save`, MCP
`doc_save`/`doc_export`, Batch, Image Processor and Layers to Files decides the
merged image over Preferences > File Handling > Maximize PSD and PSB File
Compatibility; unset, the preference decides. Anything but a boolean is refused
before anything is written. The CLI takes `--no-maximize-compatibility`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 21:07:10 +02:00
Gotya-OFFCIAL e7241d2e26 raw: decode Hasselblad 3FR/FFF (X2D II 100C, uncompressed)
The X2D II 100C's 3FR files develop at full sensor resolution instead of
falling back to the camera's embedded JPEG preview. A 3FR is a TIFF whose
IFD0 holds the camera's JPEG and whose CFA image sits in a SubIFD with
DNG-style tags but no DNGVersion and no CFA-pattern tag (neither the
TIFF/EP pair nor the EXIF one), which is why the generic TIFF/EP path
reported "CFA pattern not recorded". The new decoder reuses the shared
strip reader, takes BlackLevel, WhiteLevel, DefaultCropOrigin/Size and
AsShotNeutral from the file, and takes the Bayer phase from a measured
per-body table (the X2D II 100C: RGGB at the data origin, measured
against the camera's own embedded JPEG; unmeasured bodies warn).
Lossless-JPEG 3FR stays preview-only, like uncompressed-only ORF and RAF
before it.

Clean-room: the TIFF 6.0 and DNG specifications, the sample file's bytes
and its embedded JPEG; no code or tables from dcraw, LibRaw, rawspeed,
rawler or darktable.

Adds round-trip and hostile tests through a mirrored synthetic builder
(tests/it/hasselblad.rs, testgen::Hasselblad3frSpec) and updates the
support matrix (file-format-parity, gaps G14, target-app-parity).
2026-11-06 12:05:10 +08:00
yoriswind 7763e2578f Merge main into recorded Shear mapping 2026-11-03 12:11:27 -08:00
ljkxandClaude Opus 5.5 864cf84067 Merge origin/main into feat/raw-xmp-crop
Resolve the parity-doc conflict: keep main's status line and entries, re-add this PR's entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 20:39:43 +01:00
ljkxandClaude Opus 5.5 79b8073a8d Merge origin/main into feat/cli-metadata-option
Resolve docs/file-format-parity.md: keep main's new revision-history rows and this PR's row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 20:38:24 +01:00
yoriswind 0edb29a18c Merge upstream main into Shear action mapping 2026-11-03 09:32:21 -08:00
ljkxandClaude Opus 5.5 516c70073e Merge origin/main into feat/cli-metadata-option
Resolve apps/photocraft-cli/src/args.rs: keep both ValueError variants (Metadata and main's OnOff).
Resolve docs/file-format-parity.md: keep main's entries and re-add this PR's status entry, table notes and history row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:03:15 +01:00
ljkxandClaude Opus 5.5 01aef54239 Merge origin/main into feat/raw-xmp-crop
Resolve the parity-doc conflict: keep main's status line and entries, prepend this PR's entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:49:39 +01:00
David Mann 559d3fe0f4 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/engine/src/cmd/file_cmds.rs
#	crates/ui-egui/src/app/files.rs
#	crates/ui-egui/src/dialogs/tiff_options_ui.rs
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/ui-parity.md
2026-11-03 17:11:53 +01:00
Yuki-init e3a84b628d TIFF Options: compression, image pyramid and Save Transparency (#8827) (#10932)
Offer TIFF compression, image pyramid and transparency options on Save As and Save a Copy, with matching CLI and automation parameters.

Follow-up: preserve the unsaved state when a copy discards layers over the document's own file, and check the other export formats for the same issue.

Closes #8827.
2026-11-03 15:39:15 +01:00
ljkx a99e8696fc CLI --metadata: qualify the docs per format, test text and ICC (#9466)
Review follow-up on #9975. The help text and the CLI book page said the
XMP and free-form text are kept in every flat export and the ICC profile,
EXIF and resolution "either way". Not every format holds them: JPEG and
WebP have no place for free-form text, TIFF writes only its named text
tags, and an Indexed Color document's palette PNG carries no XMP, text,
ICC or EXIF at all, only its resolution. The texts (and the parity-doc
revision row) now say the XMP and text are kept where the format holds
them and that the option leaves everything else as it is without it.

The test fixture gains a free-form text entry and a Display P3 profile
(from photocraft-cms, now a dev-dependency; no profile file committed),
so it checks the text is gone with `none` and kept by a default PNG, and
that the default export keeps a real ICC profile that `none` matches,
instead of comparing None with None.
2026-11-03 11:44:55 +01:00
ljkx b5770e4283 CLI: --metadata none|all for convert, run --out and batch (#9466)
Since #733 a flat export from the CLI keeps the document's whole XMP
packet and free-form text, as Save As does; only Export As starts at
Metadata: None. Batch exports of Photoshop masters therefore carry the
full DocumentAncestors list (and the text of every type layer), which
can be many times larger than the image, with no way to leave it out.

`--metadata` is a new export option shared by `convert`, `run --out`
and `batch`. `none` sets ExportOptions::xmp to XmpEmbed::None, the same
path Export As's Metadata: None and Quick Export use, so the XMP packet
and free-form text are dropped while the ICC profile, EXIF and
resolution are written as before; PSD, PSB and .pcraft keep the XMP
either way. `all` is the default, so existing scripts write the same
files. Any other value is a usage error (exit 2) naming the flag,
before anything is read or written.

Tested through the binary for PNG, WebP, JPEG and TIFF from all three
subcommands (packet present by default and with `all`, absent with
`none`; pixels, ICC and resolution unchanged), layered saves, and bad
values. Documented in the CLI book page and file-format parity doc.
2026-11-03 11:44:39 +01:00
yoriswind 8e17f90c06 Bound Shear action curves and preserve native precision 2026-11-02 18:26:17 -08:00
yoriswind c9fc8458b4 Map recorded Shear actions with measured curve settings 2026-11-02 16:40:07 -08:00
ljkxandClaude Opus 5.5 40a0928948 Merge origin/main into feat/raw-xmp-crop
Resolve docs/file-format-parity.md: keep main's entries and re-add this PR's status entry, table notes and revision-history row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 01:00:19 +01:00
David Mann eb3c2044d4 Merge #10755: Support newer recorded Action events
# Conflicts:
#	crates/engine/src/cmd/artboard_cmds.rs
#	crates/engine/src/cmd/atn_cmds.rs
#	crates/engine/src/cmd/atn_cmds/events.rs
#	crates/engine/src/cmd/atn_cmds/steps_make.rs
#	crates/engine/tests/it/main.rs
#	docs/atn.md
#	docs/development.md
#	docs/file-format-parity.md
2026-11-03 00:44:15 +01:00
David Mann b0aa230ae8 Merge #10765: Actions: support direct Gradient Map and Lab-range Replace Color
# Conflicts:
#	crates/engine/src/cmd/atn_cmds.rs
#	crates/engine/src/cmd/atn_cmds/events.rs
#	crates/engine/tests/it/main.rs
#	docs/atn.md
#	docs/development.md
#	docs/file-format-parity.md
2026-11-03 00:38:44 +01:00
David Mann 673bfb4d9c Merge remote-tracking branch 'origin/main' into integration-batch-12
# Conflicts:
#	docs/file-format-parity.md
2026-11-02 20:15:23 +01:00
ljkxandClaude Opus 5.5 7eb54124ea Merge origin/main into feat/raw-xmp-crop
Conflict only in docs/file-format-parity.md: main's status line with this PR's Camera Raw crop entry first (Last updated 2026-11-02), and both revision-history rows, this PR's redated to 2026-11-02 above main's 2026-10-30 YCbCr TIFF row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 19:59:27 +01:00
9034223c4b TIFF: open YCbCr images as RGB (#10316) (#10319)
* TIFF: open YCbCr images as RGB (#10316)

Scanners often write JPEG-compressed YCbCr TIFFs with 2x2 chroma
subsampling. The tiff crate decodes and upsamples them but returns raw
YCbCr samples, which the decoder rejected with "colour type YCbCr(8)".

The new tiff/ycbcr.rs converts them to RGB after decoding: JPEG data
uses the JFIF full-range BT.601 conversion (as libtiff does), other
compressions honour ReferenceBlackWhite and YCbCrCoefficients with the
TIFF defaults as fallback. 8 and 16-bit. YCbCr with extra samples, or
in other sample formats, fails with a clear unsupported error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Contributors: add Yuki-init's display name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* TIFF YCbCr: test that YCbCrCoefficients set the luma weights

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* TIFF: YCbCr tags with the wrong value count use the defaults

tag_f64s now returns None unless the tag holds exactly n values, so a
YCbCrCoefficients or ReferenceBlackWhite tag with extra values falls
back to the TIFF defaults instead of being truncated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lrgj5pnShYtsSnrsZq5iRn

* TIFF YCbCr: tests for tiled JPEG with ICC, big-endian 16-bit and planar

Covers the layouts the review asked for: a tiled 4:2:0 JPEG file with an
embedded profile (checked against an independent JPEG decoder), a
big-endian 16-bit file, and planar data in both byte orders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lrgj5pnShYtsSnrsZq5iRn

* TIFF YCbCr: cite the formula sources and pin the green-channel choice

Documents where the conversion comes from: TIFF 6.0 Section 21
(YCbCrCoefficients, pp. 90-91) and libtiff's tif_color.c
(TIFFYCbCrToRGBInit, TIFFYCbCrtoRGB). Red and blue follow the spec;
green follows libtiff and adds Y unscaled, which matches the spec only
when the luma weights sum to 1. The module doc records this as a
deliberate compatibility choice, and a new test pins it: with weights
0.25/0.25/0.25, mid gray stays (128, 128, 128).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lrgj5pnShYtsSnrsZq5iRn

* Codecs README: YCbCr TIFFs with three 8- or 16-bit samples decode to RGB

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lrgj5pnShYtsSnrsZq5iRn

* Format tiff_ycbcr tests with rustfmt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(tiff): compare grouped YCbCr decoding and update support notes

* style(tiff): align grouped decode call with test formatting

* style(tiff): apply repository rustfmt to grouped YCbCr regression

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-02 19:31:22 +01:00
David MannandClaude Opus 5.5 f79a169651 Integration: one Actions row and the batch's event total in the file format parity page
The doc merge left five Actions rows that disagreed (version 12 unsupported vs read; 120 vs
127 events). Found by CodeRabbit on #10776.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 16:42:36 +01:00
David Mann 79a2a4e15f Merge PR #10632: Actions: map all 47 Filter Gallery effects (#10592)
With our fix-up 023e2662d7 on top of the author's head. Conflicts resolved item by item (Rust), docs as unions.
2026-11-02 03:18:45 +01:00
ljkx ec5a2bcaed Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	docs/file-format-parity.md
2026-11-02 03:17:35 +01:00
David Mann 520a996b30 Merge PR #10630: Actions: map Photoshop's Split Channels, Merge Spot Channel, Trap and Match Color steps (#10609)
With our fix-up a299bf9f6c on top of the author's head. Conflicts resolved item by item (Rust), docs as unions.
2026-11-02 03:15:28 +01:00
David Mann 496d9f3623 Merge PR #10618: Map Stylize and Pixelate action events
With our fix-up 52cc86351b on top of the author's head. Conflicts resolved item by item (Rust), docs as unions; docs/atn.md regenerated at the end.
2026-11-02 03:10:21 +01:00
David Mann 5d6041c1cd Merge PR #10628: Map selection, clipboard and layer-operation ATN events
With our fix-up 0e41091687 on top of the author's head. Conflicts resolved item by item (Rust), docs as unions; docs/atn.md regenerated at the end.
2026-11-02 02:55:08 +01:00
David Mann 4f899196cb Merge PR #10702: Actions: preserve settings in mapped ATN events
With our fix-up 78cf0cf91f on top of the author's head. Conflicts resolved item by item (Rust), docs as unions; docs/atn.md regenerated at the end.
2026-11-02 02:55:02 +01:00
yoriswind 7b0d68c8e3 Fix Artboard action round trips and singleton links 2026-11-01 17:48:22 -08:00
David Mann d570b77abb Merge PR #10753: Support recorded layer, document and layer comp references
With our fix-up ea4112a4ce on top of the author's head 686f08c884. docs/atn.md kept from the batch (regenerated at the end); development.md and parity doc rows as unions.
2026-11-02 02:40:55 +01:00
David Mann 48b0e221cd Merge PR #10627: Actions: map Photoshop's newer-feature steps (Oil Paint, Smart Sharpen, Focus Area, Sky, Remove Background) (#10610)
With our fix-up 6ab24508d8 on top of the author's head 8988b6bfd0. Conflicts resolved: import lists as unions (bare_from/bare_to taken from steps_other, #10631), event table, tests and parity doc rows as unions.
2026-11-02 02:16:45 +01:00
David Mann 5bc852379a Merge PR #10743: Read Photoshop Actions version 12 descriptors
With our fix-up 1f524c378b on top of the author's head 713aa92ba5. Resolved with main: the version check sits in main's parse_layout (it merged cleanly); doc comments combined; atn_contract no longer expects version 12 to be refused and pins that an empty version 12 set parses; one ATTRIBUTION row for all ATN fixtures; the fixture README states which files were encoded how; development.md no longer counts the fixtures.
2026-11-02 02:13:56 +01:00
6ab24508d8 Integration: .atn Oil Paint/Smart Sharpen clamp on import, Smart Sharpen maps the Gaussian form (#10627)
Out-of-range Oil Paint and Smart Sharpen settings kept the step as a
Photoshop step; the reference application clamps them when the step
plays, so the import now clamps (stylization 10.5 -> 10, Amnt 500.5 % ->
500, Rds 0.05 px -> 0.1). Export still refuses out-of-range params.

Oil Paint's light direction (LghD) had no range: LghD 500 mapped and
saved back as 500. It now clamps to the command's -180..180 on import
(500 -> 180) and export refuses {"angle": 181}.

Smart Sharpen mapped the legacy Lens Blur form, which the command's
Gaussian sharpen does not play, and wrote every step as legacy Lens
Blur. It now follows the PSD smart-filter mapping (photocraft-io
smart_map): only useLegacy false + blur GsnB maps (noiseReduction ->
reduceNoise); the reference default (useLegacy true, lensBlur), Motion
Blur and legacy steps stay Photoshop steps; export writes useLegacy
false, Amnt, Rds, noiseReduction, blur GsnB.

Co-authored-by: hectorviov <1501713+hectorviov@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 02:13:01 +01:00
David Mann cafaabcf04 Merge PR #10631: Actions: map Photoshop's De-Interlace, NTSC, HSB/HSL, Custom, Average and matting steps (#10607)
With our fix-up 632a62b554 on top of the author's head 4ed3f5b591. Conflicts resolved as unions (module list, event table, tests, parity doc rows).
2026-11-02 02:03:24 +01:00
David Mann 2d332d3ba5 Merge PR #10629: Actions: map Photoshop's Distort filter steps (Pinch, Polar Coordinates, Spherize, Twirl, Wave, ZigZag) (#10605)
With our fix-up 363e0f5e89 on top of the author's head 244082fb2c. Conflicts with main resolved as unions (new tests next to main's; parity doc revision rows).
2026-11-02 02:02:03 +01:00
yoriswind 8b2cd1a70a Merge original ATN reference documentation from #10603
Preserve the original reference history and measurements, then document the 22 newly supported forms and their strict mapping boundaries. Artboard from Group remains kept; the Crop Photos parent does not cover generated helper recordings.
2026-11-01 14:07:21 -08:00
yoriswind 0fb31eb63d docs: document supported direct adjustment forms and limits 2026-11-01 14:04:20 -08:00
yoriswind 35850ca7db Merge original ATN reference documentation from #10603 2026-11-01 13:23:37 -08:00
yoriswind 21b6546907 Resolve recorded Action reference forms at playback 2026-11-01 12:55:02 -08:00
yoriswind 7ca16e9eba Read Photoshop Actions version 12 descriptors 2026-11-01 11:45:32 -08:00