timholy/Images.jl — pull request #135 by timholy (2014-07-28 03:58:39+00:00)
Title: WIP: broader use of ColorValues and getting rid of `limits` with fixed-point numbers

Currently this is waiting on a couple of other pull requests (https://github.com/JeffBezanson/FixedPoint.jl/pull/2 and https://github.com/JuliaLang/Color.jl/pull/51), but I thought I'd post it for general consideration. This has two aims:

## Get rid of array dimensions that correspond to color

This switches to ColorValue immutables for essentially all `imread` operations. (OK, not quite, but it's a major step in that direction.) Formerly, this was not possible without converting image pixel values to `Float64`, because `ColorValue` immutables were only supported for `Float64`. There are several reasons why forcing users to make such conversions would be undesirable. To overcome this barrier, one of my pending pull requests makes `ColorValue`s parametric, and this allows us to use them for other data types.

## Get rid of the limits property

Images has a fairly complicated infrastructure for scaling, which is primarily used for display by IJulia or ImageView. The default is that images stored in `Uint8` are scaled from `0x00` to `0xff`, whereas a `Float32` image is scaled from `0.0f0` to `1.0f0`. This causes a problem if you convert the underlying representation from `Uint8` to `Float32`, which can easily happen if you filter or otherwise transform the image. A related problem is how to scale `Uint16` images; if the scaling is always `0x0000` to `0xffff`, then images produced by a 10-bit camera will always render as near-black. Handling these two problems is the main reason for the existence of the `limits` property, to allow arithmetic operations/file-format readers/users to annotate the image so that appropriate contrast limits are chosen.

However, maintaining the `limits` property under arithmetic operations is annoying and error-prone, and in some cases there is no obviously-correct way to do it. Recently @StefanKarpinski [suggested](https://github.com/JuliaLang/Color.jl/issues/42#issuecomment-50103642) a different approach: "virtually" change the pixel values, remapping unsigned integers implicitly to the range `0.0` to `1.0`, but without changing the underlying (in-memory) representation. Hence my work on fixed-point numbers. I've implemented variants for all common bitdepth cameras.

I'm pretty excited that this will clean up a lot of stuff: once this gets merged, the default contrast limits can just be `0.0` to `1.0`, although of course the user will be able to manually override them. But going forward this would only need to be something passed to the display code, and not an image property. Nevertheless it should ensure that, for most images, display "just works." That it will do so while allowing us to zero-copy pass the data to ImageView (and someday, OpenGL) is a big bonus.