Artwork by VileR
Decodes NTSC composite artifact color from CGA RGBI image data. This is not a full NTSC simulation.
CGA images are encoded into the output of the color generation circuit of the CGA based on the original schematic published in the IBM Personal Computer AT Technical Reference, First Edition (1984). That quasi-composite output is then sampled for luma and chroma signals.
Developed for my PC emulator, MartyPC: https://github.com/dbalsom/martypc
Programs that have a Composite output mode utilizing the CGA's high resolution monochrome mode with a foreground color of bright white have an RGBI image essentially congruent to their composite signal - they can be sampled for artifact color direcctly. This is because the CGA color clock generator for White is tied to +5V, so whenever a white pixel appears on the screen, a composite signal of full luminance is output. However, the story is different when color is involved, such as if the foreground color in high resolution mode is changed, or when games use a 320x200 4 color mode (See screenshot below), or text mode effects intended for composite displays such as the famous PC demo, 8088mph. Naive sampling of the RGBI image data directly for artifact color will not produce the correct result.
Screenshots of early Sierra titles showing the CGA's magenta and cyan palette are not correct for a composite display, so will produce erroneous colors. The video mode these games operated in for composite output was the CGA's monochrome 640x200 high resolution mode. These screenshots are usually created by emulating these games with an EGA or VGA card, which do not support the CGA's high resolution 640x200 mono mode, and will instead display a 320x200, 2-bit color image. The resulting colors do not result in an equivalent composite signal.
As of July 1, 2023 I've included a third method, 'Reenigne', which implements reenigne's chroma multiplexer algorithm in Rust. This produces superior results as it better models the analog behavior of the chroma multiplexer. This algorithm is also much faster, although much more difficult to comprehend.
You can see my results vs reenigne's:
Thank you to reenigne, xot and EMMIR
Decode 'war.png' to 'output.png' with specified hue, saturation and luminosity, using fast method
cga_artifact --input .\examples\war.png -h 1.5 -s 1.5 -l 1.0 --method fast
Decode 'king.png' to 'output.png' with specified hue, saturation and luminosity, using accurate method
cga_artifact --input .\examples\king.png -h 1.5 -s 1.5 -l 1.0 --method accurate