File Coverage

blib/lib/Imager/Heatmap.pm
Criterion Covered Total %
statement 92 92 100.0
branch 31 34 91.1
condition 8 9 88.8
subroutine 18 18 100.0
pod 9 9 100.0
total 158 162 97.5


line stmt bran cond sub pod time code
1             package Imager::Heatmap;
2 5     5   347824 use 5.008000;
  5         17  
  5         198  
3 5     5   27 use strict;
  5         9  
  5         158  
4 5     5   33 use warnings;
  5         20  
  5         136  
5 5     5   15961 use utf8;
  5         145  
  5         29  
6 5     5   185 use XSLoader;
  5         13  
  5         110  
7 5     5   26 use Carp;
  5         8  
  5         1059  
8 5     5   5818 use Imager;
  5         331742  
  5         40  
9 5     5   492 use List::Util qw/ max /;
  5         11  
  5         11231  
10              
11             our $VERSION = '0.03';
12             our %DEFAULTS = (
13             xsigma => 1,
14             ysigma => 1,
15             correlation => 0.0,
16             );
17              
18             XSLoader::load __PACKAGE__, $VERSION;
19              
20             sub new {
21 15     15 1 53461 my ($class, %args) = @_;
22              
23 15         68 my $self = bless {}, $class;
24              
25 15 100 100     145 unless (exists $args{xsize} && exists $args{ysize}) {
26 2         42 croak "You need to specify xsize and ysize";
27             }
28 13         73 $self->xsize(delete $args{xsize});
29 13         60 $self->ysize(delete $args{ysize});
30              
31 13 50       91 $self->xsigma ((exists $args{xsigma}) ? delete $args{xsigma} : $DEFAULTS{xsigma});
32 13 50       72 $self->ysigma ((exists $args{ysigma}) ? delete $args{ysigma} : $DEFAULTS{ysigma});
33 13 50       259 $self->correlation((exists $args{correlation}) ? delete $args{correlation} : $DEFAULTS{correlation});
34              
35 13 100       53 if (keys %args) {
36 1         23 croak "You did specify some unkown options: " . join ',', keys %args;
37             }
38              
39 12         45 return $self;
40             }
41              
42             sub xsize {
43 46     46 1 2761 my $self = shift;
44              
45 46 100       151 if (@_) {
46 16 100       59 if ($_[0] < 0) { croak "xsize must be a positive number" }
  1         64  
47 15         63 $self->{xsize} = $_[0];
48              
49 15         145 $self->_invalidate_matrix;
50             }
51 45         326 return $self->{xsize};
52             }
53              
54             sub ysize {
55 45     45 1 878 my $self = shift;
56              
57 45 100       136 if (@_) {
58 16 100       47 if ($_[0] < 0) { croak "ysize must be a positive number" }
  1         24  
59 15         39 $self->{ysize} = $_[0];
60              
61 15         37 $self->_invalidate_matrix;
62             }
63 44         68053 return $self->{ysize};
64             }
65              
66             sub xsigma {
67 26     26 1 1714 my $self = shift;
68              
69 26 100       78 if (@_) {
70 15 100       54 if ($_[0] < 0.0) { croak "xsigma should be a positive number" }
  1         27  
71 14         37 $self->{xsigma} = $_[0];
72             }
73 25         90 return $self->{xsigma}
74             }
75              
76             sub ysigma {
77 26     26 1 91 my $self = shift;
78              
79 26 100       75 if (@_) {
80 15 100       47 if ($_[0] < 0.0) { croak "ysigma should be a positive number" }
  1         14  
81 14         33 $self->{ysigma} = $_[0];
82             }
83 25         97 return $self->{ysigma}
84             }
85              
86             sub correlation {
87 29     29 1 3241 my $self = shift;
88              
89 29 100       74 if (@_) {
90 18 100 100     106 if ($_[0] < -1 || $_[0] > 1) {
91 2         28 croak "correlation should be a number between -1 and 1";
92             }
93 16         42 $self->{correlation} = $_[0];
94             }
95 27         1317369 return $self->{correlation}
96             }
97              
98             sub _invalidate_matrix {
99 30     30   130 (shift)->{matrix} = undef;
100             }
101              
102             sub matrix {
103 19     19 1 2690 my $self = shift;
104              
105             # Initialize array for size xsize * ysize and fill it by zero
106 19 100       82 unless (defined $self->{matrix}) {
107 11         39 $self->{matrix} = [ (0)x($self->xsize*$self->ysize) ];
108             }
109              
110 19         251 return $self->{matrix};
111             }
112              
113             sub insert_datas {
114 9     9 1 923472 my $self = shift;
115              
116 9         43 $self->{matrix} = xs_build_matrix(
117             $self->matrix, \@_, # Insert datas
118             $self->xsize, $self->ysize,
119             $self->xsigma, $self->ysigma, $self->correlation,
120             );
121             }
122              
123             sub draw {
124 3     3 1 168 my $self = shift;
125              
126 3         12 my $img = Imager->new(
127             xsize => $self->xsize,
128             ysize => $self->ysize,
129             channels => 4,
130             );
131              
132 3         1162 my $matrix = $self->matrix;
133              
134 3         15 my ($w, $h) = ($self->xsize, $self->ysize);
135 3         7 my $max = max(@{ $matrix });
  3         8445  
136              
137 3 100       20 unless ($max) {
138 2         119 carp "Nothing to be rendered";
139 2         1293 return $img;
140             }
141              
142 1         3 my %color_cache;
143 1         6 for (my $y = 0; $y < $h; $y++) {
144 90000         186405 my @linedata = map {
145 300         56994 my $hue = int((1 - $_/$max)*240);
146 90000         141555 my $alpha = int(sqrt($_/$max)*255);
147              
148 90000   66     309506 $color_cache{"$hue $alpha"} ||= Imager::Color->new(
149             hue => $hue,
150             saturation => 1.0,
151             value => 1.0,
152             alpha => $alpha,
153             );
154             } @$matrix[$y*$w..$y*$w+$w-1];
155              
156 300         8830 $img->setscanline('y' => $y, pixels => \@linedata);
157             }
158              
159 1         448 return $img;
160             }
161              
162             1;
163             __END__