Skip to content

Image export: choose screen-matched vs export-fit color mapping (palette window + equalization), with a preview in the save modal #52

Description

@rosslh

Context

The PNG export makes opinionated choices about how its color mapping is derived, with no user control:

  • Equalization table: with histogram coloring active, the export equalizes against its own escape-value distribution (export-fit, like the zoom animator's frames). Before c85de94 it inherited the map's viewport-global table (screen-matched), which miscolored aspect-expanded exports — but always matched what the user saw on screen.
  • Palette window: the export keeps the config's window — under auto-fit, the viewport's fitted min/max — even though the exported region (aspect-adjusted bounds) and resolution differ from the screen. A fully export-fit mapping would refit the window to the export's own values when auto-fit is on.

So the current behavior is a hybrid: screen-matched window, export-fit equalization. Both pure mappings are legitimate, and neither is right for everyone:

  • Screen-matched (viewport window + viewport table): the saved PNG reproduces exactly the view the user judged and decided to save — but content added by aspect-ratio bounds expansion is colored through a mapping it never entered.
  • Export-fit (window refit to the export under auto-fit + table fit to the export): the export is colored coherently as the image it is — but can differ from what was on screen at save time.

Proposal

Support both, as an option in the save-image modal, with a small live preview so the difference is visible before committing to a full-resolution render:

  • A control in saveImageModal choosing the mapping. Each choice applies as a coherent bundle (window + equalization together), not as independent toggles.
  • A preview thumbnail rendered at the requested aspect ratio through the worker pool (e.g. ~300 px wide via RegionRenderer.renderRegion + recolor), re-rendered when the mapping choice or dimensions change. The preview also incidentally shows the aspect-ratio bounds expansion, which is otherwise invisible until the file is saved.

Implementation notes

  • Screen-matched = config window + the map's paletteCdf (see MandelbrotMap.rebuildPaletteCdf).
  • Export-fit = fittedRangeForRender-style window refit over the stitched export values + fittedCdfForValues (see ImageSaver.exportCdf); ImageSaver.generateImageColumns already renders columns for values and recolors through a shared table, so the window refit slots into the same pass.
  • PNG/data-export metadata should keep pinning the window actually used (pinnedConfig), whichever mapping produced it.

Non-goals

  • The zoom animator's analogous choices (relative vs absolute manual window across depths, per-frame vs locked-to-target grading): previewing a whole zoom's coloring is expensive, and the animation flow deserves its own design if ever.
  • Making aspect-ratio handling configurable (expand vs center-crop): a geometry decision, separate axis from color mapping; the preview at least makes the current expansion behavior visible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions