What's Changed
- Reuse filled-shape effect maps while moving styled groups by @kotulsky in #8993
- fix(ui-egui): a click on the bottom layer's Smart Filters selects them again (#8764) by @drunkeninja42 in #8974
- security(paint): cap spaced steps and procedural primitives by @dylanmtaylor in #8957
- i18n(zh-hans): translate status messages and preview labels by @IgnatAi401 in #8872
- perf(liquify): reuse interpolation taps and bound render buffers by @yongjip in #8855
- perf(mcp): move command list rows instead of cloning by @yongjip in #8844
- Codecs: warn when DPX or Cineon saves drop bits by @przemyslvw in #8793
- fix(type): type.edit with new text keeps the styles of unchanged text by @FinnNk in #8766
- perf(text): rasterise each text colour only over its own glyphs by @FinnNk in #8716
- fix(engine): refuse partial Color Balance and Hue/Saturation ATN exports by @FinnNk in #8701
- fix(geom): reject non-finite affine inverses by @Lucenx9 in #8651
- Crop default mode: moving the image under the box snaps (#8580) by @wanikhawar in #8622
- fix(engine): select files correctly in Windows Explorer by @ZFzuofeng in #8518
- Fix EngineData format_real emitting a bare trailing dot by @Silvertree2010 in #8486
- fix(app): no unused screen picker code on FreeBSD by @zuujiscom in #8469
- fix(ui): restore extras when showing the grid by @skylartaylor in #8962
- fix(text): lay out a variable font's named instance from its PostScri… by @jturnbach in #8909
- Fix XCF import with short linked-layer property lengths by @wanikhawar in #8865
- Soft Light: dark backdrops follow Photoshop's W3C curve (#8804) by @switch87 in #8817
- fix(actions): a recorded Layers-panel drag keeps its drop target by name by @FinnNk in #8781
- fix(gpu): rebuild the GPU canvas after an out-of-memory error by @FinnNk in #8774
- Layers: show effect row names through tl! by @hai5656a in #8754
- Black & White: keep 32-bit superwhites (#8537) by @HEOJUNFO in #8748
- feat(guides): New Guide Layout takes lengths with units by @FinnNk in #8719
- Write the Levels and Curves composite channel as Chnl.Cmps in .atn export by @mercuryVM in #8686
- fix(cms): reject malformed hex data in .look LUTs by @Lucenx9 in #8657
- Accept all-caps possessives in spell check by @Silvertree2010 in #8628
- Reject non-hex characters in engine hex color parser by @Silvertree2010 in #8541
- test(panic_hunt): give the panic-counting self-test its own deadline by @zuujiscom in #8473
- Puppet Warp pins go where they are dragged, without snapping by @paulou-jpg in #8217
- test(liquify): expand freeze-boundary regression coverage by @yongjip in #8082
- fix(layers): keep blend mode, Opacity, locks and Fill visible but greyed with no layer selected (#8880) by @MarekSpodBiedry in #8904
- fix(curves): 32-bit Curves continue past 0..1 like Photoshop by @FinnNk in #8782
- fix(codecs): WebP export keeps the resolution by @FinnNk in #8775
- PSD: write pattern transparency where Photoshop keeps it (#8054) by @Higgs32584 in #8756
- fix(ui): cap text fields and oversized text events by @FinnNk in #8722
- fix(export): report skipped layers in doc_export_layers (#8491) by @bommerts in #8713
- Slice tool: Style offers Fixed Ratio and Fixed Size (#8360) by @MatRanc in #8638
- Lost window device: quitting goes through while recovery can't be saved by @MatRanc in #8620
- Fix pasted shape group bounds and effects across documents by @kotulsky in #8992
- fix(io): preserve custom-domain Color Lookup LUTs by @ronibalthazar in #8879
- i18n(tr): fix mistranslations, inconsistencies and untranslated rows by @batuhangozegu in #8871
- IPP: preserve printer metadata across attribute groups by @ronibalthazar in #8828
- Levels, Curves and the other adjustments: ⌥ plus the shortcut opens the dialog at its last settings (#8900) by @marcoarnulfo in #8969
- fix(atn): keep Photoshop's other transform interpolation modes on import by @FinnNk in #8698
- fix(contributors): drop a duplicate people.toml table by @echelon in #9009
- Curves: the graph grows with the Properties panel and a resizable dialog (#8984) by @switch87 in #8998
- Perspective Crop: the swap button swaps W and H (#7059) by @davidmann4 in #7060
- Keep shape fill and stroke alpha through PSD round-trip (#6180) by @vbasky in #6868
- Color pickers: pick on press and follow small drags (#7793) by @hodd1444 in #7822
- fix(actions): match Selective Color ATN export to command parsing by @PerchAnton in #7681
- Auto-Align: a locked layer becomes the reference instead of being moved (#7080) by @davidmann4 in #7081
- Paste: keep the pasted image on the canvas (#6759) by @marmitoTH in #6798
- PSD smart filters: Sharpen, Dust & Scratches and Hue/Saturation stay editable (#6267) by @Higgs32584 in #6401
- Isolate live distortion tools per document (#5115) by @vbasky in #5447
- fix(format): report a failed directory flush after a save instead of ignoring it by @FinnNk in #5420
- fix(automation): release idle headless TCP server ports by @Ni-zav in #3914
- Crop: Delete Cropped Pixels keeps type and smart objects whole (#7116) by @davidmann4 in #7117
- PSD: keep Photoshop 2026 Light adjustment layers verbatim and warn (#6542) by @Higgs32584 in #6815
- perf: skip redundant smart object resamples and per-pixel reads by @osaidahmed in #6406
- New Document: category tabs and preset cards show a pointer, not a text cursor by @SiFuMax09 in #3647
- Make magnetic lasso edge direction polarity-independent by @imSlicedBread in #3415
- Integration batch: 44 PRs on main by @davidmann4 in #8663
- perf(camera-raw): exposure with all scopes under its 10 ms budget (P36), same output by @nicolasfalesy in #8465
- fix(atn): export Black & White adjustment layers with Photoshop's BanW class (#8481) by @Arian100 in #8527
- perf(gpu): layer pages that just miss the budget borrow the effect-map share, P60/P61 10× faster on integrated GPUs by @nicolasfalesy in #8547
- feat(styles): import and export .asl layer style libraries (#1051) by @echelon in #4049
- Options bar: the same tool options in every theme (#4178) by @DeWarePeb in #4221
- Keep adjustment clipping visible in compact Properties panels by @bommerts in #5248
- PSD: Distort smart filters and Invert open and save like Photoshop by @abc2cb in #5249
- fix(gpu): catch validation errors in watched compositor work by @geduful in #5370
- UI: split shape options and gradient stop helpers into reusable pieces (no behaviour change) by @Skyfuller1303 in #5452
- Add opt-out startup release checks and manual update status by @ZhuanTou33212 in #5485
- Plug-ins: wire Enable Generator (Image Assets needs it) by @reynold-hu in #5598
- PSD smart objects: keep Photoshop's Cylinder warp when re-rendered (#4112) by @alvarohn in #5769
- perf(doc): share the XMP packet, Duotone PSD data and unsupported adjustment bytes between snapshots by @FinnNk in #5815
- Color: a picked colour recolours the selected type and shapes by @bazmarth in #5842
- Preferences: old settings files take Shift-to-switch-tools on (#5647) by @Higgs32584 in #5878
- fix(compose): prevent outside stroke from bleeding into opaque character interior (#5861) by @seotarek in #5937
- Raw: charge the retained tile intermediates together (#4959) by @saad-mughal435 in #6041
- Color panel: Photoshop's panel-menu modes, the same in every theme (#6000) by @wanikhawar in #6055
- Fix legacy PSD point-text placement after font resolution by @bogusyogi in #6094
- feat(type): area type, text that wraps inside a closed path or shape by @SillySilk in #6230
- Selection: ⇧ mid-drag locks a selection-tool move to the axis (#6231) by @mroxso in #6254
- fix(engine): honor lock all on layer mask commands by @osaidahmed in #6352
- fix(ui): confirm opening damaged PSD/PSB documents by @DavidBonnier in #6658
- perf(canvas): skip occluded checker on CPU textures by @hogawish in #6966
- Eyedropper: a large sampling ring that reads on any colour (#6973) by @mroxso in #7021
- fix(atn): import a recorded Save As with its destination (#7102) by @ijasonwhite in #7202
- Gradient Overlay: add Method selector and retain editable source stops by @oRE-o in #7335
- photocraft-cli run: refuse an --out that is the input file unless --in-place (#7437) by @wanikhawar in #7455
- gpu, docs: fix timing test skip guard and document Windows ARM64 build on RTX Spark by @mweinbach in #7840
- Menu bar: a held Alt's auto-repeat doesn't re-arm the Alt tap by @Cl4VD3 in #7849
- CLI: reject ignored or conflicting mcp/serve launch options by @wanikhawar in #8035
- GPU compositor: build its pipelines in parallel; DX12 startup 13.2 s -> 7.3 s (part of #6419) by @00xJS in #8118
- fix(automation): doc.replaceSmartObject replaces Smart Object contents from the read root (#8061) by @VishnuByrraju in #8150
- fix(actions): strict .atn export keeps Apply Image's flat source fields (#7197) by @VishnuByrraju in #8180
- Image Assets: optionally keep a transparent artboard's full size by @IbrahimOezhan in #8254
- Keep the CPU canvas sharp at 100% zoom by @bommerts in #8354
- fix(ui-egui): expand layer visibility eye hitbox and render sunken well (#8467) by @kobaltgit in #8496
- fix(actions): accept Photoshop stringID blend modes (#8454) by @justinjohn0306 in #8502
- security(io): charge sparse layers, shape caches and shared decodes by @dylanmtaylor in #8955
- CMYK: Dissolve and post-adjustment rounding match the RGB compositor (#9033) by @davidmann4 in #9035
- security(engine): bound script, batch, adjustment, import and export work by @dylanmtaylor in #8954
- Make Crystallize 4x and Pointillize 3x faster on 24 MP layers by @excited-raccoon in #6200
- perf(retouch): releasing a Blur/Smudge/Dodge stroke takes its live pixels by @wanikhawar in #7281
- perf(seam): the shrink proxy drops its original-column map, same pixels (−15 % at 24 MP) by @ebosido444-ai in #8526
- PSD export: embed a linked file only when it is an image PhotoCraft can open by @davidmann4 in #9161
- CLI integration batch: clap for photocraft-cli and the desktop app (#7071) by @aiongg in #9167
- refactor(cli): split photocraft-cli into modules, no behaviour change (#7071) by @1Git2Clone in #8295
- refactor(cli): typed errors with thiserror instead of String (#7071) by @1Git2Clone in #8213
- Segmentation: anti-aliasing the full-resolution mask skips runs far from its edge by @xsvm in #8554
- fix(cli): help after a mistake, and mcp/serve option notes in --help (#7071) by @1Git2Clone in #9194
- fix(ui): keep repeated Tab presses in text editing by @denstu473 in #9030
- ui: highlight menu rows while dragging with the button held by @bfenty in #9112
- fix(ui): centre size-changing filter previews on the CPU canvas by @FinnNk in #8994
- fix(ui): show a filter dialog's preview on the CPU canvas by @FinnNk in #8978
- raster: translated surfaces share one rebuilt tile however many threads build it by @aiongg in #9230
- JPEG: open 12-bit and arithmetic-coded files through craft-jpeg (#4934, #5003) by @aiongg in #9195
- security(affinity): charge archive names, failed reads, corner arrays, attachments, pages and font names by @dylanmtaylor in #9257
- fix(ui): Liquify, Content-Aware Fill, Filter Gallery and Adaptive Wide Angle are modal, like Camera Raw by @wanikhawar in #9061
- Autosave: a recovery listing judges each key once, so an autosave in progress isn't listed twice by @aiongg in #9324
New Contributors
- @drunkeninja42 made their first contribution in #8974
- @IgnatAi401 made their first contribution in #8872
- @ZFzuofeng made their first contribution in #8518
- @hai5656a made their first contribution in #8754
- @paulou-jpg made their first contribution in #8217
- @MatRanc made their first contribution in #8638
- @ronibalthazar made their first contribution in #8879
- @batuhangozegu made their first contribution in #8871
- @marmitoTH made their first contribution in #6798
- @SiFuMax09 made their first contribution in #3647
- @Arian100 made their first contribution in #8527
- @geduful made their first contribution in #5370
- @ZhuanTou33212 made their first contribution in #5485
- @alvarohn made their first contribution in #5769
- @bogusyogi made their first contribution in #6094
- @SillySilk made their first contribution in #6230
- @DavidBonnier made their first contribution in #6658
- @hogawish made their first contribution in #6966
- @ijasonwhite made their first contribution in #7202
- @oRE-o made their first contribution in #7335
- @mweinbach made their first contribution in #7840
- @IbrahimOezhan made their first contribution in #8254
- @kobaltgit made their first contribution in #8496
- @justinjohn0306 made their first contribution in #8502
Full Changelog: v0.15.1...v0.16.0