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.
Context
The PNG export makes opinionated choices about how its color mapping is derived, with no user control:
So the current behavior is a hybrid: screen-matched window, export-fit equalization. Both pure mappings are legitimate, and neither is right for everyone:
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:
saveImageModalchoosing the mapping. Each choice applies as a coherent bundle (window + equalization together), not as independent toggles.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
paletteCdf(seeMandelbrotMap.rebuildPaletteCdf).fittedRangeForRender-style window refit over the stitched export values +fittedCdfForValues(seeImageSaver.exportCdf);ImageSaver.generateImageColumnsalready renders columns for values and recolors through a shared table, so the window refit slots into the same pass.pinnedConfig), whichever mapping produced it.Non-goals