fix: align PNG export crop with displayed frequency axis

The spectrogram image spans the full Nyquist axis, but sel.freq* are
fractions of the displayed axis (capped at EffectiveMaxFreqHz). ExportPNG
mapped the selection straight onto the full image height, so when the
display max frequency was below Nyquist the export grabbed a band higher
in frequency than the box-select. Scale by DisplayFreqFraction() to match
the on-screen texture sub-sampling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 14:56:27 -07:00
parent c0f61d0472
commit 81bab18ddd
+8 -3
View File
@@ -266,11 +266,16 @@ void ExportPNG(const SpectrogramApp* spa, const char* dirPath)
int imgW = spa->spectrogramImage.width;
int imgH = spa->spectrogramImage.height;
// Selection region in image-pixel coordinates
// Selection region in image-pixel coordinates. The image spans the full
// Nyquist axis, but sel.freq* are fractions of the *displayed* axis (capped
// at EffectiveMaxFreqHz), so scale by DisplayFreqFraction() the same way the
// on-screen texture sub-sampling does — otherwise the export grabs a band
// higher in frequency than what was box-selected.
float cropFrac = DisplayFreqFraction();
int selX0 = (int)(spa->sel.timeStart * imgW);
int selX1 = (int)(spa->sel.timeEnd * imgW);
int selY0 = (int)((1.0f - spa->sel.freqEnd) * imgH);
int selY1 = (int)((1.0f - spa->sel.freqStart) * imgH);
int selY0 = (int)((1.0f - spa->sel.freqEnd * cropFrac) * imgH);
int selY1 = (int)((1.0f - spa->sel.freqStart * cropFrac) * imgH);
// Clamp to image bounds
selX0 = Clamp(selX0, 0, imgW);