The Art of Orderly Rendering and Disorderly Dithering
This document provides an overview of converting BMP files to Apple II Double Hi-Res (DHGR) Monochrome and Color files using Bmp2DHR’s Cross-Hatched rendering filter.
Cross-Hatched rendering uses a 2 x 2 alternating paired pixel pattern (2 pixels x 2 rasters) based on a user definable threshold which alternates (by default) between a high and low range of the RGB values of the input image’s original pixel color.
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered and Cross-Hatched |
Cross-Hatched rendering can be used by itself or to modify the appearance of Bmp2DHR’s monochrome or color error-diffusion dithering. Because of its regular 2 x 2 pattern, the output from Bmp2DHR’s cross-hatch filter has some resemblance to 2 x 2 positioned (ordered) dithering.
All the DHGR images shown in this document were converted from BMP files by Bmp2DHR, the best DHGR converter on The Planet.
Bmp2DHR’s Buckels Dither (d9) was used for Bmp2DHR’s error-diffused dithered output. The Buckels dither is a full color bleed dither weighted like Floyd-Steinberg but loosely based on Atkinson’s dithering pattern. The example monochrome dithering uses a reduced color bleed of 25% which provides results similar to Atkinson. The color palette is a variation of the Wikipedia palette with a “light grey” added like on the IIgs.
Original Image – 256 Colors |
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered Only |
Bmp2DHR Dithered and Cross-Hatched |
The GIMP – Floyd Steinberg Dithering |
The Gimp – Positioned (ordered) Dithering |
Apple II Double Hi-Res (DHGR) color graphics have only 15 fixed colors (both DHGR greys are the same on the Apple II composite display). Arbitrary palettes cannot be built like they can on an Apple IIgs in Super Hi-Res mode, because DHGR colors are fixed.
On the other hand, DHGR colors are saturated so bit-mapped graphics from more capable displays can be dithered and rendered effectively but the coarse resolution of 140 x 192 generally results in a large amount of detail loss when converting complex large modern images like photos and illustrations. DHGR monochrome has a finer resolution of 560 x 192 which is quite good for dithering but not very colorful.
Bmp2DHR provides the following rendering options:
Cross-Hatching is not ordered dithering. In fact Bmp2DHR likes to think of cross-hatching as an “Art Form” (Bmp2DHR likes to think of everything it does as an “Art Form”). But Cross-Hatching is only a “special effect” to render an image somewhat as if it had been created or edited by hand in an old paint program.
Combining cross-hatched rendering with error diffusion dithering provides more interesting and disorderly results than cross-hatching alone; somewhat like Art imitating Reality imitating Art. The example images in this document have been clustered to provide an equivalent comparison between cross-hatched rendering and dithering.
Ordered Dithering is not directly supported by Bmp2DHR (thus far). Right now, Bmp2DHR thinks ordered dithering looks kind-of crappy in DHGR mode.
For conversion to DHGR using Bmp2DHR’s Direct Pixel Mapping, graphics editors like The GIMP that support unlocked scaling and image conversion to BMP with indexed palettes and Ordered Dithering can be used to:
Original Image
Sax384.bmp (24-bit) |
B2d sax384 x1 d9 vrgb |
B2d sax384 x2 d9 vrgb |
B2d sax384 x3 d9 vrgb |
Original Image
Sax384.bmp (24-bit) |
B2d sax384 x1 d9
r25 mono v |
B2d sax384 x2 d9
r25 mono v |
B2d sax384 x3 d9
r25 mono v |
The DHGR images above are examples of combining cross-hatching and dithering. The Bmp2DHR conversion command is noted above each image. The two DHGR images below are converted to DHGR using error diffusion dithering alone:
Dithered only B2d sax384 d9 vrgb |
Dithered only B2d sax384 d9 r25
mono v |
Bmp2DHR is not alone in the world of graphics utilities that provide DHGR rendering.
“][gif” – DHGR
rendering |
|
Today some programs like the GIMP provide ordered (positional) dithering of DHGR-ready output along-side their other dithering options:
The GIMP –
positioned dithering |
|
The whole idea behind cross-hatching is to alternate dots in a regular paired pattern between two linear RGB ranges using an optionally definable high and low threshold to deviate the mean color error from the real color. The closest “wrong color” creates the pattern when the threshold drives the real color into the “wrong color’s” range.
Command option “X” (Cross-Hatch Pattern) can be used in conjunction with command option “Z” (Threshold Percentage Value). When “Z” is not used the default value of “Z25” is provided as a threshold.
Command |
Description |
Pattern |
X |
Cross-Hatch Pattern |
2 x 2 Alternating |
Usage |
Follow “X” with
numeric value 1-3 |
|
X1 |
Darkens lighter colors by demotion |
Low, med Med, low |
X, X2 |
Default Cross-Hatch |
High, low Low, high |
X3 |
Lightens darker colors by promotion |
High, med Med, high |
Command |
Description |
|
Z |
High, low threshold for Cross-Hatch colors |
1% to 50% (Default 25%) |
Usage |
Follow “Z” with
numeric value 1-50 |
|
Bmp2DHR provides 3 Cross-Hatched (Cross-Hatched) patterns.
The x2 default pattern alternates using high color and a low color in a threshold range which reverses between odd and even lines. The Cross-Hatch threshold is user definable from 1% to 50% in both the high and the low levels.
Original Image |
X2 Cross-Hatched and Dithered |
The x1 and x3 Cross-Hatches alternate every second pixel with an unadjusted palette color starting from the first pixel on every even line and every second pixel on every odd line.
X1 Cross-Hatched and Dithered |
X3 Cross-Hatched and Dithered |
Since every second pixel in X1 and X3 cross-hatching is in the unadjusted palette color, the actual hue of the image will be closer to the original than in the default X2 cross-hatched equivalent which rotates around the unadjusted palette color. Psycho-visually all 3 patterns will be “off” by about the same amount. Verbatim colors pass-through unadjusted which allows pure black and pure white to plot in solid blocks.
Command Option “X” is also affected by Command Option “P” (Palette Selection) since the color distance varies from palette to palette so has different mean values.
X2 - Palette 5 – todhr-like conversion |
X2 - Palette 0 – Kegs32-like conversion |
http://www.appleoldies.ca/cc65/programs/dhgr/bmp2dhr.zip
The following are additional examples of Bmp2DHR output comparing Cross-Hatched output to other output. Bmp2DHR outputs native DHGR files in standard Apple II format
.
Original Image – 24 Bit Color |
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered Only |
Bmp2DHR Dithered and Cross-Hatched |
The GIMP – Floyd Steinberg Dithering |
The Gimp – Positioned (ordered) Dithering |
Original Image – 24 Bit Color |
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered Only Monochrome Equivalent |
Bmp2DHR Dithered and Cross-Hatched Monochrome Equivalent |
The GIMP – Floyd Steinberg Dithering Monochrome Equivalent |
The Gimp – Positioned (ordered) Dithering Monochrome Equivalent |
Original Image – 24 Bit Color |
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered Only Monochrome Equivalent |
Bmp2DHR Dithered and Cross-Hatched Monochrome Equivalent |
Bmp2DHR is only concerned with displaying high-end graphics on the low-end Apple II DHGR display so sees no need to sacrifice vertical excellence for the “bells and whistles” that general graphics editors like The GIMP offer.
As far as The GIMP goes, dithering for DHGR (or anything else) is not a really strong feature. Bmp2DHR is not “picking-on” The GIMP or any other Paint Program; you need them for “big-hammer” type-things like scaling images. But consider The GIMP’s dithering and indexed conversion options in the context of DHGR conversion compared to Bmp2DHR’s more robust equivalents:
GIMP Indexed
Conversion Options |
Purpose |
None |
Color Reduction, Direct Pixel Mapping |
Floyd-Steinberg Normal |
High End Color Graphics, Low-End Display |
Floyd-Steinberg Reduced Color Bleeding |
Monochrome Display, Print Media |
Positioned |
Hard to Say, Looks like Hell! |
Using a bigger hammer like the GIMP to hit a small nail like DHGR makes little sense.
Bmp2DHR adapts “psycho visual” color matching routines from Joel Yliluoma's arbitrary-palette positional dithering algorithm:
http://bisqwit.iki.fi/story/howto/dither/jy/
Rendering and dithering programs are only as good as the color mapping routines that they provide. Better psycho visual color mapping results in better dithering:
The GIMP –Wikipedia Palette “None” (Direct Pixel Mapping) |
Bmp2DHR – Wikipedia Palette Direct Pixel Mapping |
Bmp2DHR thinks it sees color the way the Apple II sees color. The GIMP apparently sees color somewhat differently.
Bmp2DHR also offers a variety of error diffusion options (9 built in “classically designed” dithers and the capability for user definable dithers in the “classic” style of many more than can be counted on your toes).
Like the Apple II, Bmp2DHR’s dithers are forever and not just something to put on a menu.
Bmp2DHR is a little “old-fashioned” and believes that seeing color from the eyes of the Apple II user, and providing simple options that benefit rendering on the DHGR color and monochrome displays, is more desirable than neatly organized menus in a general purpose modern paint program.
Original Image – 24 Bit Color |
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered Only |
Bmp2DHR Dithered and Cross-Hatched |
The GIMP – Floyd Steinberg Dithering |
The Gimp – Positioned (ordered) Dithering |
Perception was all we had on the Apple II. Bmp2DHR remembers that. Rendering was terribly important. Display resolution was precious in those days and artful rendering was appreciated more, but unfortunately was not applied backwards as better displays than DHGR became available. “Progress” made dithering less important in the wake of more capable displays. Modern users barely use dithering if at all.
Today it seems obvious that “quality rendering” is not so important even though it is also obvious from Bmp2DHR’s output that the “standard parts” are now available to make this happen simply and elegantly.
So how does this apply to Bmp2DHR’s monochrome rendering and dithering? Well, exactly the same way. Color perception in Bmp2DHR controls monochrome output. It’s very Highfalutin. Doing some kind of half-tone of that is good enough for a modern user didn’t appeal to Bmp2DHR just because it was published somewhere. Bill Atkinson’s early work with the Macintosh and reduced color bleed was inspiring and offered a clear direction forwards instead of backwards to Floyd-Steinberg. He was in fact inspired by photography… an analog skill (like perception).
It was immediately obvious to Bmp2DHR that Atkinson dithering applied to DHGR’s monochrome mode and needed a long-overdue update based on color perception rather than on putting a menu together with some words that modern users like to see in paint programs; hence both the simple Buckels Dither and Bmp2DHR’s user-definable classic error diffusion patterns were devised, augmented by cross-hatched rendering which was also inspired not by commands on menus but by DHGR and the Apple II itself.
Bmp2DHR (25% reduced color bleed) |
Bmp2DHR Dithered and Cross-Hatched |
The GIMP – Floyd Steinberg Reduced |
The Gimp – Positioned (ordered) Dithering |
It was also obvious that some modern user’s notion of “water-board” positional dithering was just regurgitation for those uninitiated in less capable displays like the Apple II’s DHGR. We never cared so much about printing a dither as seeing something artful on our Apple II displays, IIRC (and I do). And I have no idea where this notion that positional dithering looked any good came from. Compared to Bmp2DHR’s simple rendering and dithering, the GIMP’s monochrome output looks like hell when displayed on the Apple II’s DHGR display. My short lifetime prevents me from searching for anything better; it was just simpler to do DHGR properly, and write Bmp2DHR!
Original Image – 24 bit Color |
Bmp2DHR Cross-Hatched Only |
Bmp2DHR Dithered Only |
Bmp2DHR Dithered and Cross-Hatched |
Monochrome Equivalent |
Momochrome Equivalent |
Many explanations about dithering and computer graphics in general are just “noise” to the average person, even a technical person, but a picture is worth a thousand words. Even if you didn’t understand some of the atrocious simplifications in this overview I am sure you get the picture because your eyes don’t lie. Bmp2DHR’s source code is available for the techies anyway, so why get hung-up on theory? Just use the thing.
“Turnabout” is fair-play. A few years back I met a fellow programmer by the name of Jack Crenshaw on usenet. He was learning about websites and using a Microsoft full-blown product as a starting point and wasn’t getting the results that he wanted. I suggested to Jack that he ignore the “bells and whistles” and start with learning HTML instead which he could just “hand-bomb” in a text editor and go from there. Crenshaw is a pretty smart fellow, so results were no problem. He’s also been around a little longer than DHGR so I have some faith in Jack’s advice:
Crenshaw’s First Law says, “There is a myriad of ways to take a simple problem and make it seem complex. Only a handful of ways to take a complex problem and make it seem simple.”
There’s also only a handful of ways to render an image in a fixed palette of 15 colors. But unbelievable as it may seem when it comes to DHGR rendering even today, at least one of the graphics programs accused of “heavy lifting” seems to be almost as empty-handed as “][gif” was “back in the day”.
But despite its relative simplicity, Bmp2DHR’s hands are full.
So fill your hand! Download Bmp2DHR at the following links:
Win32 and latest version complete with source:
http://www.appleoldies.ca/cc65/programs/dhgr/bmp2hr.zip
MS-DOS: http://www.appleoldies.ca/cc65/programs/dhgr/bmp2dhrMSDOS.zip
Other: (Linux, OSX): http://hoop-la.ca/apple2/appleoldies/bmp2dhr/
And remember, Bmp2DHR comes with a “money-back” guarantee. It is absolutely free. If you are not 100% satisfied with the results you get when converting to DHGR with Bmp2DHR or if you find something better, then good for you! I didn’t.
All the best,
Bill Buckels
October 2014
The Apple II DHGR display does not have square pixels like the original Macintosh or modern computers. It has rectangular pixels. So dithering on the DHGR display has a very different appearance than what most modern users see on their modern square pixeled displays. Today’s computers use the same square-pixeled display to represent color and monochrome, but it was not so with DHGR.
Dithering DHGR in color is relatively twice as coarse in the horizontal axis than on a square pixel display. Dithering DHGR in monochrome is relatively twice as fine in the horizontal axis than on a square pixel display. Therefore dithering DHGR in color is relatively 4 times as coarse as dithering DHGR in monochrome (just the opposite).
That’s a generalization and doesn’t consider aspect ratio but for the purposes of perception the significance is adequate for discussion or observation purposes.
Introducing a 2 pixel x 2 raster patterned “overlay filter” like cross-hatching provides Monochrome DHGR with twice the relative resolution of a 2 x 2 dither on a square-pixeled display but, mainly because of the alternating arrangement of the horizontal pattern, Color DHGR still gets a 2 x 2 dither effect (sort of) especially for areas of the same original color.
This whole idea is a lot more robust for DHGR rendering than a checker-board pattern fill that one might use in a paint program. (That’s an assumption based on my current experience. Someone who knows what they are doing might disagree.) It’s also not 2 x 2 positioned dithering; it’s 2 x 2 positioned rendering with a user definable threshold.
Cross-hatching offers 3 patterns as noted earlier in this document. How thresholding displays is based on these patterns as demonstrated earlier.
See the source code for more information.