Color-TupleEncode

 view release on metacpan or  search on metacpan

lib/Color/TupleEncode/2Way.pm  view on Meta::CPAN

For example, if C<orient = 1> and C<hzero = 180> (cyan), 

         hue  color    r = x/y
     
           0  red      0
          45  orange   0.25
          90  lime     0.5
         135  green    0.75
  hzero  180  cyan     1
         240  blue     1.5
         270  violet   2
         300  purple   3
         315  purple   4
           0  red      INF, NaN (y=0)

=head2 Saturation

The saturation is calculated using the size of the 2-tuple, C<r = sqrt( x**2 + y**2 )>. Depending on the value of C<power>, 

    r = sqrt ( x**2 + y **2 )

                      -r/power
    saturation = 1 - 2           if power > 0

    saturation = 1               if power = 0

The default limits on saturation are C<s = 1> at C<r = 0> and C<s = 0>
at C<r = INF>. The default rate of decrease is C<power = 1>. Thus, for
every unit change in C<r>, saturation is decreased by 50%. Use the
C<power> option to change the rate of change. In general, saturation
will change by a factor of C<2> for every C<power> units of C<r>. That
is,

    r    saturation
         power = 1    power = 2   power = 3
    0    1            1           1
    1    0.5          0.707       0.794
    2    0.25         0.5         0.63
    3    0.125        0.354       0.5
    4    0.063        0.25        0.397
    
If C<power = 0>, saturation will be assigned the value it would have at C<r = 0> if C<power E<gt> 0>.
However, keep in mind the effect of C<rmin>, described below.

Saturation can be interpolated within C<[min,max]> by setting the C<-min> and C<-max> options.

  $convert->set_options(-saturation=>{min=>0.8,max=>0.2})

In this example, saturation will be C<0.8> at C<r E<lt>= 0> and will start decreasing at C<r = 0> towards C<0.2> at C<r = INF>.

You can set the minimum value of the tuple component at which saturation begins to change. Use C<rmin> option,

  $convert->set_options(-saturation=>{min=>0.8,max=>0.2,rmin=>1})

In this example, saturation will be C<0.8> at C<r E<lt>= 1>, will start decreasing at C<r = 1> towards C<0.2> at C<r = INF>.

If C<rmin> is set and C<power = 0>, then saturation will be C<min> for C<r E<lt>= rmin> and C<max> for C<r E<gt> rmin>.

=head2 Value

The value is calculated using the same formula as for saturation. 

By setting different C<rmin> values for saturation and value components, you can control the range of C<r> over which the encoding acts. For example, 

  $convert->set_options(-saturation=>{rmin=>0},-value=>{rmin=>1})

will result in saturation changing for C<r E<gt> 0> and value only for
C<r E<gt> 1>. For C<r E<lt>= 1>, value will be at its C<min> setting.

=head1 EXPORT

Exports nothing.

Use L<Color::TupleEncode> and set the encoding method to
C<"Color::TupleEncode::2Way"> to use this module.

=cut 

Readonly::Scalar our $TUPLE_SIZE      => 2;
Readonly::Array  our @OPTIONS_OK      => (qw(-orientation -hzero -saturation -value));
Readonly::Hash   our %OPTIONS_DEFAULT => (-hzero=>180,
					  -orientation=>1,
					  -saturation => {power=>1,min=>1,max=>0,rmin=>0},
					  -value      => {power=>2,min=>1,max=>0,rmin=>1});

sub _component_power_scale {
  my ($value,$options,$component_name,$min,$max,$power) = @_;
  $min = $options->{min} if defined $options->{min};
  $max = $options->{max} if defined $options->{max};
  confess "Option for $component_name minimum must be between [0,1] (saw $min), e.g. use -$component_name=>{rmin=>0.25}." if $min < 0;
  confess "Option for $component_name maximum must be between [0,1] (saw $max), e.g. use -$component_name=>{compmax=>0.75}." if $max > 1;
  $power = defined $options->{power} ? $options->{power} : $power;
  confess "Power for $component_name must be non-negative (saw $power), e.g. use -$component_name=>{power=>1}" if $power < 0;
  my $rmin = defined $options->{rmin} ? $options->{rmin} : 0;
  my $component;
  if(! defined $power) {
    confess "The option -power is not defined for $component_name. It is required to compute the value. Try -$component_name=>{power=>3}.";
  } elsif ($power == 0) {
    if($value <= $rmin) {
      $component = $min;
    } else {
      $component = $max;
    }
  } else {
    ### $component_name
    ### $value
    ### $rmin
    if($value < $rmin) {
      ### below rmin
      $component = $min;
    } else {
      my $f = 1 - 2 ** ( - ($value-$rmin) / $power );
      ### $value
      ### $f
      $component = _interpolate($f,$min,$max);
    }
    ### $component
  }
  $component = 0 if $component < 0;
  $component = 1 if $component > 1;
  return $component;



( run in 1.093 second using v1.01-cache-2.11-cpan-5a3173703d6 )