Tempest
view release on metacpan or search on metacpan
lib/Tempest.pm view on Meta::CPAN
use constant LIB_MAGICK => 'Image::Magick';
use constant LIB_GMAGICK => 'Graphics::Magick';
use constant LIB_GD => 'GD';
=head1 PROPERTIES
=head2 Required Properties
=head3 C<input_file>
The generated heatmap will share the same dimensions as this image,
and - if indicated - will be overlaid onto this image with a given
opacity.
=cut
my %input_file;
=head3 C<output_file>
The generated heatmap will be written to this path, replacing any
existing file without warning.
=cut
my %output_file;
=head3 C<coordinates>
The contained x,y coordinates will mark the center of all plotted data
points in the heatmap. Coordinates can - and in many cases are
expected to - be repeated.
=cut
my %coordinates;
=head2 Optional Properties
=head3 C<plot_file>
This image, expected to be greyscale, is used to plot data points for
each of the given coordinates. Defaults to a bundled image, if none
is provided.
=cut
my %plot_file;
=head3 C<color_file>
This image, expected to be a true color vertical gradient, is used as a
color lookup table and is applied to the generated heatmap. Defaults
to a bundled image, if none is provided.
=cut
my %color_file;
=head3 C<overlay>
If true, the heatmap is overlaid onto the input image with a given
opacity before being written to the filesystem. Defaults to B<True>.
=cut
my %overlay;
=head3 C<opacity>
Indicates with what percentage of opaqueness to overlay the heatmap
onto the input image. If 0, the heatmap will not be visible; if 100,
the input image will not be visible. Defaults to b<50>.
=cut
my %opacity;
=head3 C<image_lib>
Indicates which supported image manipulation library should be used
for rendering operations. Defaults to the first available from the
following:
=cut
my %image_lib;
my @_required = ('input_file', 'output_file', 'coordinates');
my @_optional = ('plot_file', 'color_file', 'overlay', 'opacity', 'image_lib');
=head1 METHODS
=head2 C<new>
Class constructor, accepts a hash of named arguments corresponding to
the class' own getter and setter methods.
$heatmap = new Tempest(
'input_file' => 'screenshot.png',
'output_file' => 'heatmap.png',
'coordinates' => [ [0,10], [2,14], [2,14] ],
);
=cut
sub new {
my $class = shift;
croak('Bad parameter list, should be a hash') if @_ % 2;
my %params = @_;
# inside-out object model
my $self = bless \(my $dummy), $class;
# set defaults
$plot_file{$self} = dirname(__FILE__) . '/Tempest/data/plot.png';
$color_file{$self} = dirname(__FILE__) . '/Tempest/data/clut.png';
$overlay{$self} = 1;
$opacity{$self} = 50;
$image_lib{$self} = $self->_calc_image_lib();
# for all required parameters..
for my $param_name (@_required) {
# ..ensure they were provided
if(!exists $params{$param_name}) {
croak("Missing required parameter '$param_name'");
}
# ..and call each of their setters
eval('$self->set_' . $param_name . '($params{$param_name})');
}
# for all optional parameters..
for my $param_name (@_optional) {
# ..if they were provided..
if(exists $params{$param_name}) {
# ..call their setters
eval('$self->set_' . $param_name . '($params{$param_name})');
}
}
return $self;
}
=head2 C<render>
Initiates processing of provided arguments, and writes a heatmap image
to the filesystem. Returns B<True> on success.
die('Rendering failed') if ! $heatmap->render();
=cut
sub render {
my $self = shift;
my $lib_name = ucfirst(lc($image_lib{$self}));
$lib_name =~ s/\W//g;
my $result = eval('require Tempest::'.$lib_name.'; return Tempest::'.$lib_name.'::render($self);');
croak($@) if $@;
return $result;
}
=head2 C<version>
Returns the version number of the current release.
die('Outdated') if $heatmap->version() lt '2009.06.15';
=cut
sub version {
return $VERSION;
}
=head2 C<api_version>
lib/Tempest.pm view on Meta::CPAN
if(ref($coordinates) ne 'ARRAY') {
croak('Bad coordinates: not an array reference');
}
for my $pair (@{$coordinates}) {
if(ref($pair) ne 'ARRAY' || scalar(@{$pair}) != 2) {
croak('Bad coordinate pair: ' . join(',', @{$pair}));
}
}
$coordinates{$self} = $coordinates;
return $self;
}
sub get_coordinates {
my $self = shift;
return $coordinates{$self};
}
sub set_plot_file {
my $self = shift;
my $plot_file = shift;
if(-r $plot_file) {
$plot_file{$self} = $plot_file;
}
else {
croak("Image '$plot_file' is not readable");
}
return $self;
}
sub get_plot_file {
my $self = shift;
return $plot_file{$self};
}
sub set_color_file {
my $self = shift;
my $color_file = shift;
if(-r $color_file) {
$color_file{$self} = $color_file;
}
else {
croak("Image '$color_file' is not readable");
}
return $self;
}
sub get_color_file {
my $self = shift;
return $color_file{$self};
}
sub set_overlay {
my $self = shift;
my $overlay = shift;
$overlay{$self} = $overlay ? 1 : 0;
return $self;
}
sub get_overlay {
my $self = shift;
return $overlay{$self};
}
sub set_opacity {
my $self = shift;
my $opacity = shift;
if($opacity >=0 && $opacity <= 100) {
$opacity{$self} = $opacity;
}
else {
croak("'$opacity' is not a valid percentage (integer from 0 to 100)");
}
return $self;
}
sub get_opacity {
my $self = shift;
return $opacity{$self};
}
sub set_image_lib {
my $self = shift;
my $image_lib = shift;
if($self->has_image_lib($image_lib)) {
$image_lib{$self} = $image_lib;
}
else {
croak("Image library '$image_lib' could not be found");
}
return $self;
}
sub get_image_lib {
my $self = shift;
return $image_lib{$self};
}
=head2 C<has_image_lib>
Returns true value if the given image library is available.
die('GD is unavailable') if ! $heatmap->has_image_lib(Tempest::LIB_GD);
=cut
sub has_image_lib {
my $self = shift;
my $image_lib = shift;
# work as instance method or static method
if(ref($self) ne 'Tempest') {
$image_lib = $self;
undef $self;
}
( run in 2.121 seconds using v1.01-cache-2.11-cpan-7fcb06a456a )