What is a good algorithm to make halftone images (like this)? A quick google search brings up a bunch of papers on the subject, but it's difficult to judge which are good, efficient, etc. Is there a best choice to do this sort of thing?
- Filter down to the resolution you want the "dots" separated by.
- Get the average intensity of the pixel group in that area.
- Draw the dot such that the surface area of the dot is equal to the percent from white to Black of the average intensity.
Think of the Pixels groups as a hexagonal grid. Use a circle function to decide which pixels go into the group. You can tune the overlap of the circles to adjust the black/saturation of the output. This is really designed for hi-resolution output such as print. If you are doing this to display on screen as a visual effect make sure you use an anti-aliased circle drawing routine to compensate for the low-resolution of the display. (Compared to print, even HD isn't really that high.)
If you are doing this because you like the effect, that's cool. But if you just want to dither down to a black and white image consider using a "Floyd-Steinberg" dither. It provides high quality results and distributes the error across the image. http://en.wikipedia.org/wiki/Floyd-Steinberg_dithering
The easiest way to do this, is to go pixel by pixel and use randomness: for each pixel, probability of coloring it back = darkness of the original color.
That can give you a two-line dithering algorithm. It's not going to look as nice as Floyd-Steinberg (because that one keeps track of the errors), or as artistic as the "tile and then put disks in each tile so that fraction of black = average darkness in the original tile", but it works quite well in practice.
Halftoning is very efficient.
Single-level halftone: Input: Pixels from your image; preconstructed "screen" containing threshold values. At runtime: For each color channel, for each pixel, select one threshold value (index into threshold array modulo the array dimensions). One comparison between the pixel and the threshold determines whether the output value is on or off.
It generalizes to multi-level output as well, by using multiple screens.
The interesting part is construction of the screens (threshold arrays). There are many variations -- clustered dot (AM), stochastic (FM), many variations and hybrids including blue noise and green noise (AM/FM). And you usually want a different screen for each color channel. The traditional clustered dot screens lay their dots out in rectangular grids that can be described by their frequency (low frequency = big dots) and angle (typically 15° for Cyan, 75° for Magenta, 90° for Yellow and 45° for Black).
If you want to experiment, the Photoshop Bitmap with Halftone Screen Method (see this tutorial) has an internal screen generator and will screen a greyscale image into a bitmap just like your example.
The dithering methods suggested by others involve more per-pixel computation, and the output doesn't resemble your clustered dot screened halftone example.