Personal tools

Colour

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
m
Line 68: Line 68:
 
== Getting colour coordinates out ==
 
== Getting colour coordinates out ==
   
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double<hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example
+
To retrieve the [http://en.wikipedia.org/wiki/SRGB sRGB] coordinates of a colour, use the functions found in the <hask>Data.Colour.SRGB</hask> module. To get coordinates as <hask>Double</hask>s (or whatever your internal representation is) use <hask>toSRGB</hask>. For example
   
 
<haskell>
 
<haskell>

Revision as of 05:34, 10 July 2009

This page provides a short introduction to using the colour package on hackage.

Contents

1 The Colour data type

The
Colour a
data type and its basic operations are found in the
Data.Colour
module. The type variable
a
is used to specify the numeric type used for the internal representation of the data. Typically one will use:
Colour Double

You may wish to make a type synonym for this type in your program if you will use it everywhere.

You can always use the
colourConvert
to change to a different internal representation type.

2 Creating colours

A collections of colours given by name can be found in the
Data.Colour.Names
module. There is also a
readColourName
to convert a string with one of these names into a colour. Be aware that the colour
tan
will conflict with the Prelude function unless you hide the Prelude function or import the module qualified. Another way to make a colour is by specifying an RGB triple. These functions can be found in the
Data.Colour.SRGB
library. For example, if you have three
Word8
s named
red
,
green
, and
blue
, then
sRGB24 red green blue

will create the colour with those sRGB colour coordinates.

If you have three
Double
s (or whatever you are using for your internal representation) named
red
,
green
, and
blue
, then
sRGB red green blue
will produce the colour with those colour coordinates. These
Double
should be in the range [0,1] otherwise the resulting colour would be out of gamut (a colour gamut is a collection of representable colours on a device, such as your monitor). Lastly,
sRGB24read
and
sRGB24reads
can create colour from string specifications of the form
"#00aaff"
or
"00aaff"
.

3 Manipulating Colours

The colour operations are found in the
Data.Colour
module. The most common operation on colours is
blend
. For example,

the function

blend 0.25 red green

will create a new colour that is 25% red, and 75% green. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result.

If you need to blend more than two colours, you can use multiple applications of
blend
, or you can use
affineCombo
. For example,
affineCombo [(0.25,red),(0.5,green)] violet

will create a new colour that is 25% red, 50% green, and 25% violet. Again the weights should all be non-negative and the sum of the weights should be no more than 1, otherwise an out of gamut colour could result.

Color intensity can be changed by using
darken
. For example,
darken 0.4 turquoise

will produce a turquoise that is only 40% of the intensity of normal turquoise. The weight parameter (the first parameter) should be between 0 and 1, otherwise an out of gamut colour could result. However if you know that the intensity is low enough, you may safe "darken" by values greater than 1 (which will actually lighten the colour).

Lastly, colours are instance of a Monoid so colours can be "added" by using
mappend
(and
mempty
is a quick way to get black). However, like spotlights, adding colours makes more intense colours. Adding colours could take you out of gamut. Unless you specifically know you want to be adding colours, you probably want to be using
blend
instead.

4 Getting colour coordinates out

To retrieve the sRGB coordinates of a colour, use the functions found in the
Data.Colour.SRGB
module. To get coordinates as
Double
s (or whatever your internal representation is) use
toSRGB
. For example
toSRGB chartreuse
will produce a value of type
RGB Double
.

4.1 RGB triples

The type
RGB
is special type of (strict) triple used to store colour coordinates. The functions
channelRed
,
channelGreen
, and
channelBlue
can be used to access the three fields. The constructor
RGB
will created a such a triple. For example,
RGB 0.5 0.4 0.6

You might find the functions

curryRGB :: (RGB a -> b) -> a -> a -> a -> b
uncurryRGB :: (a -> a -> a -> b) -> RGB a -> b

useful when working with functions that operate on RGB triples.

4.2 Back to colour coordinates

Recall that

toSRGB chartreuse
produces an
RGB Double
. The coordinates output by
toSRGB
will all be between 0 and 1 unless the colour is out of gamut. If you want to retrieve the colour coordinates as
Word8
s, use
toSRGB24
toSRGB24 khaki
will produce an
RGB Word8
. Out of gamut channels be clamped to either to the range 0 to 255. Lastly, the functions
sRGB24show
and
sRGB24shows
will produce colour strings of the form
"#00aaff"
.

5 Transparent Colour

Colours that are semi transparent are represented by the
AlphaColour a
type found in
Data.Colour
. Again the
a
type parameter represents the data type used for the internal representation and would typically be
Double
. Opaque AlphaColours are created from Colours using
opaque
. For example.
opaque goldenrod
creates an opaque goldenrod. Semi transparent colours can be made using
withOpacity
moccasin `withOpacity` 0.7

creates a colour that is 70% opaque and hence 30% transparent.

The value
transparent
is 100% transparent and
transparent == anyColour `withOpacity` 0
. Like regular colours, semi-transparent colours can be blended using
blend
and
affineCombo
. The function
darken
will darken a semi-transparent colour without affecting its opacity. To make an existing semi-transparent colour more transparent use
dissolve
. For example,
disolve 0.6 ac
will return a semi-transparent colour that is 60% of the opacity of
ac
. Note that One should avoid dissolving with weights (the first parameter) greater than 1, as you may create invalid "super-opaque" colours. If you know the opacity is less than
x
then you can safely use weights no more than
(recip x)
. Negative weights will also produce invalid "super-transparent" colours.
anyColour `withOpacity` opacity == disolve opacity (opaque anyColour)
Lastly, a the key operation on transparent colours is compositing. Given two semitransparent colours
acTop
and
acBottom
acTop `over` acBottom
will produce the semi-transparent colour resulting from acTop being composited over top of
acBottom
. The bottom layer,
acBottom
can be a non-transparent colour (of type
Colour
). In this case the result will also be a non-transparent colour. However, the top layer must be of semi-transparent type (although it could, of course, be opaque). Compositing is such important operation on semi-transparent colours, that it is the Monoid instance for
AlphaColour a
. The function
mappend
is
over
, and
mempty
is
transparent
.

5.1 Getting semi-transparent coordinates

The opacity of a semi-transparent colour can be retrieved by the
alphaChannel
function. The pure colour of a semi-transparent colour
ac
can be retrieved by first compositing the colour atop of black, the by darkening by the reciprocal of the alpha channel.
pureColour ac | a > 0 = darken (recip a) (ac `over` (mempty::Colour Double))
              | otherwise = error "transparent has no pure colour"
 where
  a = alphaChannel ac

Note however, that transparent has no pure colour, and this case needs to be handled specially.

This operation is not natively provided because it is an operation that should be avoided. It is only really useful for interfacing with libraries that require pure colour components. Ideally it would be these libraries that implement conversion to and from
Colour
. However, you may find it necessary to implement the conversion functions yourself, in which case you can use the above "trick" to write the conversion function.