(c) 2006-2017 Martin Krzywinski | mkweb.bcgsc.ca
TupleEncode - encoding a tuple into HSV color.

Documentation for the implementation of color encoding schemes. The Color::TupleEncode Perl module is available on CPAN).

main module


encoding implementations




example scripts






Color::TupleEncode - Encode a tuple (vector) into a color - useful for generating color representation of a comparison of multiple values.


Version 0.11


Given a tuple (e.g. three numbers) , apply color-coding method to encode the tuple by a color in HSV (hue, saturation, value) space. For a visual tour of the results, see mkweb.bcgsc.ca

  use Color::TupleEncode;

  # By default the encoding method Color::TupleEncode::Baran will be used

  # initialize and define in one step
  $encoder = Color::TupleEncode->new(tuple=>[$a,$b,$c]);

  # pass in some options understood by the encoding implementation
  %options = {-ha=>30, -saturation=>{dmin=>0.2,dmax=>0.8}};
  $encoder = Color::TupleEncode->new(tuple=>[$a,$b,$c],options=>\%options);

  # initialize tuple directly

  # obtain RGB (0 <= R,G,B <= 1) values
  ($r,$g,$b) = $encoder->as_RGB;

  # obtain RGB (0 <= R,G,B <= 255) values
  ($r255,$g255,$b255) = $encoder->as_RGB255;

  # obtain RGB hex (e.g. FF00FF - note no leading #)
  $hex = $encoder->as_RGBhex;

  # obtain HSV (0 <= H < 360, 0 <= S,V <= 1) values
  ($h,$s,$v) = $encoder->as_HSV;

  # change the encoding method

  # see how many values this method accepts ($tuple_size = 2)
  $tuple_size = $encoder->get_tuple_size();

  # set the tuple with the new method and encode

  ($r,$g,$b) = $encoder->as_RGB;

Use %options to define implementation and any parameters that control the encoding.

  %options = (-method=>"Color::TupleEncode::Baran");

  %options = (-method=>"Color::TupleEncode::Baran",

A non-OO interface is also supported.

  # import functions explicitly
  use Color::TupleEncode qw(tuple_asRGB tuple_asRGB255 tuple_asHSV tuple_asRGBhex);

  # or import them all automatically
  use Color::TupleEncode qw(:all);

  # pass tuple and options just like with new()
  ($r,$g,$b) = tuple_asRGB(tuple=>[$a,$b,$c]);

  # specify options
  ($r,$g,$b) = tuple_asRGB(tuple=>[$a,$b,$c],options=>\%options)

  # specify method directly - note that ::2Way takes two values
  ($r,$g,$b) = tuple_asRGB(tuple=>[$a,$b],method=>"Color::TupleEncode::2Way");

  # tuple_asRGB255, tuple_asHSV and tuple_asRGBhex work analogously


Default Encoding

The default encoding method is due to Baran et al. (see "COLOR ENCODINGS"). This method encodes a 3-tuple (x,y,z) by first assigning a characteristic hue to each variable and then calculating a color based on the relative relationship of the values. The encoding is designed to emphasize the variable that is most different.

The default encoding is implemented in Color::TupleEncode::Baran.


This encoding converts a 2-tuple (x,y) to color. It is implemented in the module Color::TupleEncode::2Way.

If you would like to implement your own encoding, I suggest editing and extend this module. See "IMPLEMENTING AN ENCODING CLASS" for more details.

Other Encodings

Color::TupleEncode is designed to derive encoding functionality from utility modules, such as Color::TupleEncode::Baran. The utility modules implement the specifics of the tuple-to-color conversion and Color::TupleEncode does the housekeeping.

You can change the class by using -method in the %options hash passed to new()

  %options = (-method=>"Color::TupleEncode::2Way");

set the option directly


or pass the method name to new()


Note that when using the options hash, option names are prefixed by -. When passing arguments to new(), however, the - is not used.


Quick encoding

To encode a tuple with the default encoding scheme (Color::TupleEncode::Baran):

  use Color::TupleEncode qw(as_HSV as_RGBhex);

  my @tuple = (0.2,0.5,0.9);

  my @hsv = as_HSV(tuple=>\@tuple);    #  291 0.7 1.0
  my @rgb = as_RGB255(tuple=>\@tuple); #  230  77 255
  my $hex = as_RGBhex(tuple=>\@tuple); #  E64DFF

Encoding with options

Options control how individual encodings work. The Color::TupleEncode::Baran method supports changing the characteristic hues of each variable, min/max ranges for saturation and value and min/max ranges for the largest variable difference for saturation and value components.

  # change the characteristic hues
  my @hsv = as_HSV(tuple=>\@tuple,options=>{-ha=>60,-hb=>180,-hc=>300}); # 351 0.7 1.0

Using another implementation

  use Color::TupleEncode qw(as_HSV as_RGBhex);

  my @tuple = (0.2,0.5,0.9);

  my $method = "Color::TupleEncode::2Way";
  my @hsv   = tuple_asHSV(tuple=>\@tuple,method=>$method);    # 255 0.6 1.0
  my @rgb   = tuple_asRGB255(tuple=>\@tuple,method=>$method); # 102 140 255
  my @rgb   = tuple_asRGBhex(tuple=>\@tuple,method=>$method); # 668Cff


This is one of the example scripts in the examples/ directory. It shows how to use the 3-tuple encoding implemented by Color::TupleEncode::Baran

The example-3way takes a 3-tuple (or uses a random one) and reports its HSV, RGB and hex colors.

  # use a random tuple
  > examples/example-3way
  The 3-tuple 0.787 0.608 0.795 encodes as follows

  hue 125 saturation 0.186 value 1.000
  R 207 G 255 B 211
  hex CFFFD3

  # use a 3-tuple specified with -tuple
  > examples/example-3way -tuple 0.2,0.3,0.9
  The 3-tuple 0.200 0.300 0.900 encodes as follows

  hue 257 saturation 0.700 value 1.000
  R 128 G 77 B 255
  hex 804DFF


This is one of the example scripts in the examples/ directory. It shows how to use the 2-tuple encoding implemented by Color::TupleEncode::2Way

The example-2way takes a 2-tuple (or uses a random one) and reports its HSV, RGB and hex colors.

  # use a random 2-tuple
  > examples/example-2way
  The 2-tuple 0.786 0.524 encodes as follows

  hue 240 saturation 0.440 value 0.126
  R 18 G 18 B 32
  hex 121220

  # use a 2-tuple specified with -tuple
  > examples/example-2way -tuple 0.2,0.9
  The 2-tuple 0.200 0.900 encodes as follows

  hue 40 saturation 0.167 value 0.422
  R 108 G 102 B 90
  hex 6C665A


This script is much more flexible. It can read tuples from a file, or generate a matrix of tuples that span a given range. You can specify the implementation and options on the command line.

The script can also generate a PNG color chart of the kind seen at mkweb.bcgsc.ca

By default tuple2color uses the 3-tuple encoding.

  # generate a matrix of tuples and report RGB, HSV and hex values
  > examples/tuple2color 
  abc 0 0 0 rgb 255 255 255 hsv 0 0 1 hex FFFFFF
  abc 0.2 0 0 rgb 255 204 204 hsv 0 0.2 1 hex FFCCCC
  abc 0.4 0 0 rgb 255 153 153 hsv 0 0.4 1 hex FF9999
  abc 0.6 0 0 rgb 255 102 102 hsv 0 0.6 1 hex FF6666
  abc 0.8 0 0 rgb 255 51 51 hsv 0 0.8 1 hex FF3333

  # specify range of matrix values (default is min=0, max=1, step=(max-min)/10)
  tuple2color -min 0 -max 1 -step 0.1

  # you can overwrite one or more matrix settings
  tuple2color -step 0.2

  # instead of using an automatically generated matrix, 
  # specify input data (tuples)
  tuple2color -data matrix_data.txt

  # specify how matrix entries should be sorted (default no sort)
  tuple2color -data matrix_data.txt -sortby a,b,c
  tuple2color -data matrix_data.txt -sortby b,c,a
  tuple2color -data matrix_data.txt -sortby c,a,b

  # specify implementation
  tuple2color -data matrix_data.txt -method Color::TupleEncode::Baran

  # specify options for Color::Threeway
  draw_color_char ... -options "-saturation=>{dmin=>0,dmax=>1}"

In addition, generate a PNG image of values and corresponding encoded colors.

  # draw color patch matrix using default settings
  tuple2color -draw

  # specify output image size
  tuple2color ... -width 500 -height 500

  # specify output file
  tuple2color ... -outfile somematrix.png

The 2-way and 3-way encoding color charts are bundled with this module, at examples/color-chart-*.png.

These charts were generated using examples/tuple2color as follows.

A large 2-tuple encoding chart with [a,b] in the range [0,2] sampling every 0.15.

  ./tuple2color -method "Color::TupleEncode::2Way"  \
                -min 0 -max 2 -step 0.15            \
                -outfile color-chart-2way.png       \
                -width 600 -height 1360             \

A small 2-tuple encoding chart with [a,b] in the range [0,2] sampling every 0.3.

  ./tuple2color -method "Color::TupleEncode::2Way"  \
                -min 0 -max 2 -step 0.3             \
                -outfile color-chart-2way-small.png \
                -width 600 -height 430              \

A large 3-tuple encoding chart with [a,b,c] in the range [0,1] sampling every 0.2.

  ./tuple2color -step 0.2                           \
                -outfile color-chart-3way.png       \
                -width 650 -height 1450             \

A large 2-tuple encoding chart with [a,b,c] in the range [0,1] sampling every 1/3.

  ./tuple2color -step 0.33333333333                 \
                -outfile color-chart-3way-small.png \
                -width 650 -height 450              \



new( tuple => [ $a,$b,$c ] )

new( tuple => [ $a,$b,$c ], options => \%options)

new( tuple => [ $a,$b,$c ], method => $class_name)

new( tuple => [ $a,$b,$c ], method => $class_name, options => \%options)

Initializes the encoder object. You can immediately pass in a tuple, options and/or an encoding method. The method can be part of the option hash (as -method).

Options are passed in as a hash reference and the encoding method as the name of the module that implements the encoding. Two methods are available (Color::TupleEncode::Baran (default encoding) and Color::TupleEncode::2Way).

At any time if you try to pass in incorrectly formatted input (e.g. the wrong number of elements in a tuple, an option that is not understood by the encoding method), the module dies using confess.

You can write your own encoding method - see "IMPLEMENTING AN ENCODING CLASS" for details.

set_options( %options )

Define options that control how encoding is done. Each encoding method has its own set of options. For details, see "COLOR ENCODINGS".

Options are passed in as a hash and option names are prefixed with -.


$ok = has_option( $option_name )

Tests whether the current encoding scheme supports (and has set) the option $option_name.

If the method does not support the option, undef is returned.

If the method supports the option, but it is not set, 0 is returned.

If the method supports the option, and the option is set, 1 is returned.

%options = get_options()

$option_value = get_options( "-saturation" )

($option_value_1,$option_value_2) = get_options( qw(-saturation -value) )

Retrieve one or more (or all) option values. Options control how color encoding is done and are set by set_options() or during initialization.

If no option names are passed, a hash of all defined options (hash keys) and their values (hash values) is returned.

If one or more option names is passed, a list of corresponding values is returned.

set_tuple( @tuple )

set_tuple( \@tuple )

Define the tuple to encode to a color. Retrieve with get_tuple().

The tuple size must be compatible with the encoding method. You can check the required size with get_tuple_size().

@tuple = get_tuple()

Retrieve the current tuple, defind by set_tuple(@tuple).

$size = get_tuple_size()

Retrieve the size of the tuple for the current implementation. For example, the method by Baran et al. (see "COLOR ENCODINGS") uses three values as input, thus $size=3.

$method = get_method()

Retrieve the current encoding method. By default, this is Color::TupleEncode::Baran.

set_method( "Color::TupleEncode::2Way" )

Set the encoding method. By default, the method is Color::TupleEncode::Baran.

You can also set the method as an option


or at initialization



Note that when using the options hash, option names are prefixed by -. When passing arguments to new(), however, the - is not used.

($r,$g,$b) = as_RGB()

Retrieve the RGB encoding of the current tuple. The tuple is set by either set_tuple() or at initialization.

Each of the returned RGB component values are in the range [0,1].

If the tuple is not defined, then as_RGB(), this and other as_* methods return nothing (evaluates to false in all contexts).


Analogous to as_RGB() but each of the returned RGB component values are in the range [0,255].

$hex = as_RGBhex()

Analogous to as_RGB() but returned is the hex encoding (e.g. FF01AB) of the RGB color.

Note that the hex encoding does not have a leading #.

($h,$s,$v) = as_HSV()

Retrieve the HSV encoding of the current tuple. The tuple is set by either set_tuple() or at initialization.

Hue $h is in the range [0,360) and saturation $s and value $v in the range [0,1].


In addition to the object oriented interface, you can call these functions directly to obtain the color encoding. Note that any encoding options must be passed in each call.

($r,$g,$b) = tuple_asRGB( tuple => [$a,$b,$c])

($r,$g,$b) = tuple_asRGB( tuple => [$a,$b,$c], options => %options)

($r,$g,$b) = tuple_asRGB( tuple => [$a,$b,$c], method => $class_name)

($r,$g,$b) = tuple_asRGB( tuple => [$a,$b,$c], method => $class_name, options => %options)

($r,$g,$b) = tuple_asRGB255()

$hex = tuple_asRGBhex()

($h,$s,$v) = tuple_asHSV()

These functions work just like tuple_asRGB, but return the color in a different color space (e.g. RGB, HSV) or form (component or hex).


Required Functions

It is assumed that the encoding utility class will implement the following functions.

Encodings must be done from a tuple to HSV color space. HSV is a natural choice because it is possible to visually identify individual H,S,V components of a color (e.g. orage saturated dark). On the other hand, doing so in RGB is very difficult (what is the R,G,B decomposition of a dark desaturated orange?).

Each of these functions should be implemented as follows. For example, _get_saturation

  sub _get_saturation {
    # obtain the Color::TupleEncode object
    my $self = shift;
    # extract data tuple
    my (@tuple) = $self->get_tuple;
    my $saturation;
    ... now use @tuple to define $saturation
    return $saturation;

This function returns the size of the tuple used by the encoding. You can implement this as follows,

  Readonly::Scalar our $TUPLE_SIZE => 3;

  sub _get_tuple_size {
    return $TUPLE_SIZE;

You must define a package variable @OPTIONS_OK, which lists all acceptable options for this encoding. Any options you wish to be set by default when this method is initially set should be in %OPTIONS_DEFAULT.

For example,

  Readonly::Array our @OPTIONS_OK      => 
      (qw(-ha -hb -hc -saturation -value));
  Readonly::Hash  our %OPTIONS_DEFAULT => 

Two functions provice access to these variables

  sub _get_ok_options {
    return @OPTIONS_OK; 

  sub _get_default_options {
    return %OPTIONS_DEFAULT;

Using Your Implementation

See the example files with this distribution

  # uses Color::TupleEncode::2Way
  > examples/example-2way

  # uses Color::TupleEncode::Baran
  > examples/example-3way

of how to go about using your implementation.

For example, if you have created Color::TupleEncode::4Way, which encodes 4-tuples, then you would use it thus

  use Color::TupleEncode;
  use Color::TupleEncode::4Way;

  # set the method to your implementation
  $encoder = Color::TupleEncode->new(method=>"Color::TupleEncode::4Way");

  # set any options for your implementation

  # encode
  ($h,$s,$v) = $encoder->as_HSV(1,2,3,4);


Martin Krzywinski, <martin.krzywinski at gmail.com>


Please report any bugs or feature requests to bug-color-tupleencode at rt.cpan.org, or through the web interface at rt.cpan.org I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Color::TupleEncode

You can also look for information at:


Color::GraphicsObject for converting colors between color spaces.

Color::TupleEncode::Baran for the 3-tuple encoding (by Baran et al.).

Color::TupleEncode::2Way for the 2-tuple encoding (by Author).


For details about the color encoding, see


Copyright 2010 Martin Krzywinski.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See dev.perl.org for more information.

(c) 2006-2017 Martin Krzywinski mkweb.bcgsc.ca