Yohan Chalier Blog RSS

Halftone Palette

Content

I recently stumbled upon an — old — article about the generation of halftone QR codes. It is a very impressive technique where a QR code is locally distorted to recreate an input image while maintaining its data encoding properties. I found the idea really clever, and the black and white images it involves have a really nice feel. It confirmed that the halftone effect, where an image is only composed of either black or white pixels, was something I liked a lot. So I decided to dig further.

3 examples of halftone QR codes
Examples of halftone QR codes, from the teaser of Chu, H. K., Chang, C. S., Lee, R. R., & Mitra, N. J. (2013). Halftone QR codes. ACM Transactions on Graphics (TOG), 32(6), 1-8

Black and White Halftoning

Basically, it was originally developped for printing images. The idea is that, given an input grey-scale image, you can reproduce it with black ink on white paper by projecting little dots everywhere, with a high density in darker regions and a low density in brighter ones. You simply divide the original image into a grid, compute the brightness of each cell, and replace it with a dot with a proportional area. If the grid is small enough, the blurring property of the human eye averages patches of black and white dots into grey areas of varying intensities.

Linear black and white gradient Halftone version of the linear black and white gradient Halftone version of the linear black and white gradient
Left: original image; middle: coarse halftone version with the dividing grid visible; right: Finer halftone version of the linear gradient

From that, many variations are possible to make the result less tabular. Most important ones are tilting the grid, and interlacing the rows, ie. horizontally translating one row out of two by half of the cell size.

Coarse  interlaced and tilted halftone gradient Fine interlaced and tilted halftone gradient
Coarse (left) and fine (right) interlaced and tilted halftone images

Also, the dot shape can change:

Dot shape Rendering
Circle Halftone linear gradient with circular dots
Ellipse Halftone linear gradient with elliptical dots
Horizontal line Halftone linear gradient with horizontal lines
Vertical line Halftone linear gradient with verical lines
Triangle Halftone linear gradient with triangles
Square Halftone linear gradient with squares
Hexagon Halftone linear gradient with hexagons
Octagon Halftone linear gradient with octagons
Euclidean Halftone linear gradient with euclidean dots

The euclidean dot is an interesting one. It looks like there is a switch from black dots on white paper to white dots on black paper after 50% darkness. Actually, the grid pattern is maintained, but the dots are allowed to leak outside their cells. In the words of Kodak, the excess ink injected in one cell bridges between the dots. It is particularly suited to high and low key images.

One thing that lured me into halftoning images is the generation of pixelated images. In the above examples, dots look smooth, as we would see in paper printing: they were generated in a JavaScript canvas which, by default, applies anti-aliasing, which re-introduces grey pixels in the image. For an exactly black and white image, we want to turn that off.

Anti-aliased halftone image Aliased halftone image
Anti-aliased (left) and aliased (right) halftone images

Colored Halftoning

Black density can be used to reproduce grey levels. Colors can also be reproduced by varying intensities of a few primary colors, either by using additive (as in a LED screen) or subtractive (as in painting) color mixing.

Again, the idea is simple. An image is decomposed into several color channels. The basic additive basis is RGB (red, green & blue), while the basic subtractive basis is CMY (cyan, magenta & yellow). For printing, the CMYK (cyan, magenta, yellow & black) basis is often used to offer richer black tones.

For each channel, an halftone layer (often called screen) is generated. All layers are then mixed together according to some rule. In additive mixing, RGB values are simply added together. In subtractive mixing, RGB values are inversed and subtracted to the first layer, usually white.

Also, each screen is tilted differently, to avoid Moiré patterns. As we only have a 90° range, a group of CMY screens is tilted at 30°, 60° and 75°. Yellow is a brighter color, hence it is less important if it is not tilted enough.

Colored circles Halftone colored circles
Orignal image (left) and colored halftone version (right)

Getting Creative

I really wanted to play with all this but failed at finding a good software for it. I have not searched a lot, so I might have missed something, but a lot of existing solutions are either very basic, do not offer a lot of customization or asking you for money. Therefore, I created my own: Halftone Palette!

Screenshot of my online halftone palette

It allows for everything (and a little more) detailed in this article; for instance, illustration images were generated with it. You'll find the code — and the possibility to contribute too! — on GitHub. It is far from perfect, but it allows for playing around. Here are some of the images I was able to generate:

A forestry coast with three colors subtractive mix
A forestry coast with three colors subtractive mix
Window frame, with a coarse grained screen on top of a finer one
Window frame, with a coarse grained screen on top of a finer one
Plane in the sky, with a two color additive mix
Plane in the sky, with a two color additive mix
Building, boosted contrast and euclidean dots
Building, boosted contrast and euclidean dots
Interlaced hills, with a two tone subtractive mix
Interlaced hills, with a two tone subtractive mix
Cloudy bridge, small dots
Cloudy bridge, small dots
Cliff, two colors
Cliff, two colors
Building, vertical lines
Building, vertical lines
Waves, vertical lines and blue background
Waves, vertical lines and blue background
Large input noise
Large input noise
Lighthouse near a cliff, animated by offsetting the grid, with a Bayer-like pattern