From 9e572207fcc057123425e3b8d5a7202d9a9d1dd9 Mon Sep 17 00:00:00 2001 From: Mats Date: Tue, 4 Aug 2026 23:59:58 +0200 Subject: [PATCH 1/2] fix: use per-file config in Linear Output batch export The batch path was using the current frame's rgbscan, stitch, flatfield, and process config for every file. Now resolves each file's own config via _batch_params_for, matching the print export pattern. Co-Authored-By: Claude Opus 4.6 --- negpy/desktop/controller.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/negpy/desktop/controller.py b/negpy/desktop/controller.py index 5005dcfd..7104dfd7 100644 --- a/negpy/desktop/controller.py +++ b/negpy/desktop/controller.py @@ -3362,12 +3362,10 @@ def request_linear_output_export(self, files: list[dict] | None = None) -> None: return exported = 0 - cfg = self.state.config - geometry = cfg.geometry expansion = self.state.linear_expansion - rgbscan = cfg.rgbscan - stitch = cfg.stitch if cfg.stitch.stitch_enabled else None for f in supported: + params = self._batch_params_for(f) + stitch = params.stitch if params.stitch.stitch_enabled else None stem = os.path.splitext(os.path.basename(f["path"]))[0] out_path = os.path.join(export_path, f"{stem}_linear.tiff") counter = 2 @@ -3378,12 +3376,12 @@ def request_linear_output_export(self, files: list[dict] | None = None) -> None: export_linear_output( f["path"], out_path, - geometry=geometry, + geometry=params.geometry, expansion=expansion, - rgbscan=rgbscan, + rgbscan=params.rgbscan, stitch=stitch, - flatfield=cfg.flatfield, - process=cfg.process, + flatfield=params.flatfield, + process=params.process, apply_wb=self.state.linear_apply_wb, apply_flatfield=self.state.linear_apply_flatfield, apply_sensor=self.state.linear_apply_sensor, From 5e79c1c2615aa080d06596eca3ee4a3dcfa3ed7b Mon Sep 17 00:00:00 2001 From: Mats Date: Wed, 5 Aug 2026 01:06:47 +0200 Subject: [PATCH 2/2] Add dc:title to Linear Output XMP, drop RAW-WB when WB is applied Bridge shows XMP dc:description (the RAW-WB line) instead of the TIFF ImageDescription tag. Add dc:title with the full description so Bridge displays it. Drop the RAW-WB gains from dc:description when WB has been baked in to avoid double-correction by downstream tools like ColorPerfect. Co-Authored-By: Claude Opus 4.6 --- negpy/services/export/linear_output.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/negpy/services/export/linear_output.py b/negpy/services/export/linear_output.py index f0d11e5e..f5034620 100644 --- a/negpy/services/export/linear_output.py +++ b/negpy/services/export/linear_output.py @@ -451,9 +451,21 @@ def _normalize_wb_rgb(wb: tuple[float, float, float, float]) -> tuple[float, flo return (wb[0] / g, 1.0, wb[2] / g) -def _build_xmp(source_path: str, wb: _CameraWB) -> bytes: - r, g, b = _normalize_wb_rgb(wb.as_shot) +def _build_xmp(source_path: str, wb: _CameraWB, title: str = "", wb_applied: bool = False) -> bytes: raw_name = os.path.basename(source_path) + title_block = "" + if title: + title_block = f" \n \n {title}\n \n \n" + desc_block = "" + if not wb_applied: + r, g, b = _normalize_wb_rgb(wb.as_shot) + desc_block = ( + " \n" + " \n" + f" RAW-WB: {r:.6f} {g:.6f} {b:.6f}\n" + " \n" + " \n" + ) xmp = ( "\n" "\n" @@ -464,11 +476,8 @@ def _build_xmp(source_path: str, wb: _CameraWB) -> bytes: " \n" " \n" - " \n" - " \n" - f" RAW-WB: {r:.6f} {g:.6f} {b:.6f}\n" - " \n" - " \n" + f"{title_block}" + f"{desc_block}" " \n" "\n" "\n" @@ -546,7 +555,7 @@ def _write_tiff( extratags: list[tuple] = [] if camera_wb is not None and source_path is not None: - xmp_bytes = _build_xmp(source_path, camera_wb) + xmp_bytes = _build_xmp(source_path, camera_wb, title=description, wb_applied=wb_applied) extratags.append((700, 1, len(xmp_bytes), xmp_bytes, True)) if source_meta is not None: