From eee4110d59b39c3a226ee0b3d03a58f851c41083 Mon Sep 17 00:00:00 2001 From: Persune Date: Mon, 23 Oct 2023 02:13:29 +0800 Subject: [PATCH] Use standard RGB-YIQ matrix coefficients https://forums.nesdev.org/viewtopic.php?p=172817#p172817 Bisqwit originally intended to match a certain palette using different display primaries ("FCC D65"). This resulted in colors that looked off. The modification here is to more closely match Bisqwit's own palette generator, which uses a more standard RGB-YIQ matrix. at hue 0, saturation 1.0, contrast 1.0, brightness 1.0, gamma 2.2 https://bisqwit.iki.fi/utils/nespalette.php IQ component coefficients are derived from the NTSC base matrix of luminance and color-difference. with color reduction factors and an additional 33 degree rotation of each respective component. https://www.nesdev.org/wiki/NTSC_video#Converting_YUV_to_signal_RGB --- Core/NES/BisqwitNtscFilter.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Core/NES/BisqwitNtscFilter.cpp b/Core/NES/BisqwitNtscFilter.cpp index 7c7015ecf..6652d35f8 100644 --- a/Core/NES/BisqwitNtscFilter.cpp +++ b/Core/NES/BisqwitNtscFilter.cpp @@ -66,7 +66,7 @@ BisqwitNtscFilter::BisqwitNtscFilter(Emulator* emu) : BaseVideoFilter(emu) int scale = 8 / _resDivider; outputBuffer += frameInfo.Width * ((120 - GetOverscan().Top) * scale); - DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, GetVideoPhaseOffset() + 120*341*_signalsPerPixel); + DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, GetVideoPhaseOffset() + 120 * 341 * _signalsPerPixel); _workDone = true; } @@ -134,14 +134,28 @@ void BisqwitNtscFilter::OnBeforeApplyFilter() _y = contrast / _yWidth; - _ir = (int)(contrast * 1.994681e-6 * saturation / _iWidth); - _qr = (int)(contrast * 9.915742e-7 * saturation / _qWidth); + // https://forums.nesdev.org/viewtopic.php?p=172817#p172817 + // Bisqwit originally intended to match a certain palette using different + // display primaries ("FCC D65"). This resulted in colors that looked off. + // The modification here is to more closely match Bisqwit's own palette + // generator, which uses a more standard RGB-YIQ matrix. + // at hue 0, saturation 1.0, contrast 1.0, brightness 1.0, gamma 2.2 + // https://bisqwit.iki.fi/utils/nespalette.php - _ig = (int)(contrast * 9.151351e-8 * saturation / _iWidth); - _qg = (int)(contrast * -6.334805e-7 * saturation / _qWidth); + // ( * ) / (<_iWidth or _qWidth at 0> / 2000) + double saturationFactor = (167941.0 * 144044.0) / (12.0 * 2000.0); - _ib = (int)(contrast * -1.012984e-6 * saturation / _iWidth); - _qb = (int)(contrast * 1.667217e-6 * saturation / _qWidth); + // IQ coefficients are derived from the NTSC base matrix of luminance and color-difference + // with color reduction factors and an additional 33 degree rotation of each respective component. + // https://www.nesdev.org/wiki/NTSC_video#Converting_YUV_to_signal_RGB + _ir = (int)(contrast * ( 0.956084 / saturationFactor) * saturation / _iWidth); + _qr = (int)(contrast * ( 0.620888 / saturationFactor) * saturation / _qWidth); + + _ig = (int)(contrast * (-0.272281 / saturationFactor) * saturation / _iWidth); + _qg = (int)(contrast * (-0.646901 / saturationFactor) * saturation / _qWidth); + + _ib = (int)(contrast * (-1.105617 / saturationFactor) * saturation / _iWidth); + _qb = (int)(contrast * ( 1.702501 / saturationFactor) * saturation / _qWidth); } void BisqwitNtscFilter::RecursiveBlend(int iterationCount, uint64_t *output, uint64_t *currentLine, uint64_t *nextLine, int pixelsPerCycle, bool verticalBlend)