Image Map Image Map
Results 1 to 8 of 8

Thread: EGA/VGA 16 color dithering

  1. #1

    Default EGA/VGA 16 color dithering

    About 30 years ago I wrote a few Windows display drivers for various HW platforms. In doing so, one algorithm I always defaulted to the Microsoft implementation was the RGB dithered brush generation. Always short on time and the sample code from MS, either x86 assembly or even the C code, was enough to make a grown man cry, I never got around to implementing my own. Playing around with VGA code last week I decided to revisit the dithered brush code. After a little investigation, I settled on a very simple approach that has me wishing I'd spent the time on it back in the day. I put a github project together here: https://github.com/dschmenk/DITHER16

    Here are some samples:
    compaqs.jpg
    racecar.jpg

    Edit:
    The forum shrunk the images to the point of in distinguishing the dither. Better images are on GitHub.
    Last edited by resman; March 7th, 2019 at 04:10 PM.

  2. #2

    Default

    That dithering pattern looks extremely similar to the Chromagraphics dithering pattern used by the Futura 100 on color wax thermal printers

    The patterns allowed 300 dpi printers to have cleaner more color accurate results with a similar look to a 600dpu laser.

    Good job.

  3. #3

    Default

    Yeah, this looks good. I think Atkinson will always be my favorite dither algorithm (there's a phrase I never imagined I'd find myself writing,) but this is a nice-looking ordered dither.

    Never realized that the dither algorithm itself was a part of the display driver. Now I'm kinda curious if various manufacturers ever rolled their own, and what you'd get if you tried displaying the same image on various drivers...
    Computers: Amiga 1200, DEC VAXStation 4000/60, DEC MicroPDP-11/73
    Synthesizers: Roland JX-10/SH-09/MT-32/D-50, Yamaha DX7-II/V50/TX7/TG33/FB-01, Korg MS-20 Mini/ARP Odyssey/DW-8000/X5DR, Ensoniq SQ-80, E-mu Proteus/2, Moog Satellite, Oberheim SEM
    "'Legacy code' often differs from its suggested alternative by actually working and scaling." - Bjarne Stroustrup

  4. #4

    Default

    Quote Originally Posted by rmay635703 View Post
    That dithering pattern looks extremely similar to the Chromagraphics dithering pattern used by the Futura 100 on color wax thermal printers

    The patterns allowed 300 dpi printers to have cleaner more color accurate results with a similar look to a 600dpu laser.

    Good job.
    Thanks. The pattern itself is a standard 4x4, but the epiphany was to break the algorithm into two halves, 0%-50% brightness and 50%-100% brightness. With only 8 colors, the algorithm is quite straight forward.

  5. #5

    Default

    Quote Originally Posted by commodorejohn View Post
    Yeah, this looks good. I think Atkinson will always be my favorite dither algorithm (there's a phrase I never imagined I'd find myself writing,) but this is a nice-looking ordered dither.

    Never realized that the dither algorithm itself was a part of the display driver. Now I'm kinda curious if various manufacturers ever rolled their own, and what you'd get if you tried displaying the same image on various drivers...
    The VGA Windows driver does a full 8x8 pattern, but I don't think it really buys you much. I doubt anyone bothered implementing their own algorithm and I'm sure all the SVGA drivers implemented the same code. I don't think the benchmarks were affected by the dithering code which would have been the real reason to spend effort on it.

  6. #6

    Default

    The patterns are nice but the colour reproduction isn't very accurate. It doesn't look like you're doing any kind of gamma correction, which may be part of this. It also looks like you're not taking into account the specific RGB values in the target colour palette. This is particularly noticeable on the yellow bar of "Color Bars #2" - the dithered bar is brown rather than matching the yellow in the source image. There's a really good, in-depth article at https://bisqwit.iki.fi/story/howto/dither/jy/ which covers these issues. I will be interested to see if this inspires you to make some improvements!

    Another problem you might find is that the standard EGA 200-line RGBI palette does not completely cover the sRGB gamut. Consider completely saturated red (255,0,0). The closest RGBI colours (255,85,85) and (170,0,0) don't protrude right into that corner, and no combination of those with other colours will ever make a more saturated red. So you may find that colour accuracy and detail reproduction suffer. Avoiding this is, I think, mostly a matter of choosing source images carefully. Though it is possible that a clever pre-processing step could subtly regrade the images so that they look nice and lie within the RGBI gamut. I'd be really interested to hear about any developments along those lines, as I may want to steal them for my own (error-diffused based) image converter.

    For VGA and 350-line EGA, you can reprogram the palette to include the 8 corners of the sRGB cube which will enable you to reproduce all colours. It'd be an interesting exercise to try to figure out which other 8 colours (for EGA and for VGA) enable the best possible dithered reproduction of images. Windows uses 2 shades of grey and dark versions of the 6 saturated corner colours - I'm not convinced that this is optimal, though (and it is also really ugly compared to the RGBI colours). That's another thing I'd be interested to hear about if anyone does some playing around with it!

  7. #7

    Default

    Thank for the link, reenigne, I hadn't seen that one before.

    So just to clarify, this is an algorithm to dither to an idealized RGBI palette. There is no question the default colors for the VGA mode 12h are far from idealized. That mess of a color for yellow is abysmal. I really should have reprogrammed the colors for a better match. However, the code would really have been used for generating a brush for filling in large areas of the screen, not creating a dithered representation of an RGB image. Doing so was just a way to validate the speed and relative accuracy of the algorithm. An RGBI palette does present some interesting challenges to get decent results, i.e. the Windows driver doesn't use 2 shades of grey when dithering, as including the darker grey is rather difficult. It does provide the dark grey as a "closest match", though.

    For dithering an RGB image, there are much better approaches than building a 4x4 brush, then extracting the pixel from the brush like I did here. I tried some other approaches that sub-divided the RGB cube into sections based on the RGBI values, but I couldn't get a consistent brush pattern. It might have been a better approach for converting an RGB image with error diffusion. Rethinking the color matches using different color models might provide better results, too. That's where building a dithered brush to the RGBI palette was greatly simplified by using the HSV cone model.

  8. #8

    Default

    Went back to the dither code to address a few issues. First, reprogrammed the palette registers so that yellow looks like yellow. Then tweak the dither matrices to get rid of the flat spot in the middle of the transition from dim to bright colors. Finally, add code to include the dark grey color to the available dither colors.

    To improve the quality of the displayed image, i added a gamma value to adjust the RGB colors in the sample application. It really helped out my cheap, washed out LCD panel. The DOSBox screen capture doesn't really do the updates justice (added to the GitHub page).

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •