Tempest

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

2009.10.05
        Added full support for Graphics::Magick.  Some minor but important
        changes from the ImageMagick adapter (notably the lack of Fx or Clut
        operators, meaning a manual color lookup implementation)

2009.07.15
        Added has_image_lib method, as specified in API version 2009.07.15.
        Added tests for this and all other public static methods.

2009.07.03
        Fixed dubious dependancy tests (for GD and Image::Magick) bundled with
        the distribution.  *Now* this should fix the failures in the CPAN
        testers matrix.

2009.07.02
        In ImageMagick adapter, now checking if Clut method is supported and,
        if it's not, use the Fx operator instead.  This should fix the failures
        in the CPAN testers matrix.

2009.06.28
        Completely rewrote colorization to be simpler & produce more precise

lib/Tempest.pm  view on Meta::CPAN

    # Generate and write heatmap image
    $heatmap->render();

=head1 CONSTANTS

These constants can be assigned to the C<image_lib> property to specify use
of a given image library for all image manipulations.

=head3 C<LIB_MAGICK>

For forcing use of L<Image::Magick|Image::Magick> support.

=head3 C<LIB_GMAGICK>

For forcing use of L<Graphics::Magick|Graphics::Magick> support.

=head3 C<LIB_GD>

For forcing use of L<GD|GD> support.

=cut

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,

lib/Tempest.pm  view on Meta::CPAN

}

=head2 Setters

Each setter method assigns a new value to its respective property.
The setters also return the current class instance, so they can be 'chained'.

For example, if we wanted to change the C<image_lib> used for image processing,
and immediately render the resulting heatmap:

    # render heatmap with Image::Magick support
    $heatmap ->set_image_lib( Tempest::LIB_MAGICK ) ->render();

=head2 Getters

Each getter method returns the current value of its respective property.

For example, if we wanted to retrieve the C<coordinates> to be rendered and
immediately output them with the L<Data::Dumper|Data::Dumper> module:

    use Data::Dumper;

lib/Tempest/Imagemagick.pm  view on Meta::CPAN

=head1 NAME

Tempest::Imagemagick - PerlMagick adapter for Tempest heat-map generator

=head1 DESCRIPTION

Implements L<Tempest|Tempest> image operations using the
L<Image::Magick|Image::Magick> module.

=head1 COPYRIGHT & LICENSE

Copyright 2009 Evan Kaufman, all rights reserved.

This program is released under the MIT license.

L<http://www.opensource.org/licenses/mit-license.php>

=head1 ADDITIONAL LINKS

lib/Tempest/Imagemagick.pm  view on Meta::CPAN

=back

=cut

package Tempest::Imagemagick;

use strict;
use warnings;

use Carp;
use Image::Magick;

sub render {
    my $parent = shift;
    
    # load source image (in order to get dimensions)
    my $input_file = Image::Magick->new;
    $input_file->Read($parent->get_input_file());
    
    # create object for destination image
    my $output_file = Image::Magick->new;
    $output_file->Set( 'size' => join('x', $input_file->Get('width', 'height')) );
    $output_file->ReadImage('xc:white');
    
    # do any necessary preprocessing & transformation of the coordinates
    my $coordinates = $parent->get_coordinates();
    my $max_rep = 0;
    my %normal;
    for my $pair (@{$coordinates}) {
        # normalize repeated coordinate pairs
        my $pair_key = $pair->[0] . 'x' . $pair->[1];

lib/Tempest/Imagemagick.pm  view on Meta::CPAN

        }
        # get the max repitition count of any single coord set in the data
        if($normal{$pair_key}->[2] > $max_rep) {
            $max_rep = $normal{$pair_key}->[2];
        }
    }
    $coordinates = [ values(%normal) ];
    undef %normal;
    
    # load plot image (presumably greyscale)
    my $plot_file = Image::Magick->new;
    $plot_file->Read($parent->get_plot_file());
    
    # calculate coord correction based on plot image size
    my @plot_correct = ( ($plot_file->Get('width') / 2), ($plot_file->Get('height') / 2) );
    
    # colorize opacity for how many times at most a point will be repeated
    my $colorize_percent = 100 - int(99 / $max_rep);
    if($colorize_percent > 99) { $colorize_percent = 99; }
    $plot_file->Colorize('fill' => 'white', 'opacity' => $colorize_percent . '%');
    

lib/Tempest/Imagemagick.pm  view on Meta::CPAN

            # paste plot, centered on given coords
            $output_file->Composite('image' => $plot_file, 'compose' => 'Multiply', 'x' => $x, 'y' => $y );
        }
    }
    
    # destroy plot file, as we don't need it anymore
    undef $plot_file;
    
    # apply color lookup table with clut method if available
    if($output_file->can('Clut')) {
        my $color_file = Image::Magick->new;
        $color_file->Read($parent->get_color_file());
        $output_file->Clut('image' => $color_file);
    }
    # for older IM versions (anything before 6.3.5-7), use fx operator
    else {
        $output_file->Read($parent->get_color_file());
        my $fx = $output_file->Fx('expression' => 'v.p{0,u*v.h}');
        undef $output_file;
        $output_file = $fx;
    }

t/01-api.t  view on Meta::CPAN

    'image_lib',
);

foreach $propname (@props) {
    eval("ok( defined(&Tempest::get_$propname), '$propname getter');");
    eval("ok( defined(&Tempest::set_$propname), '$propname setter');");
}

## check that constants exist and that they have the expected values
%consts = (
    'LIB_MAGICK' => 'Image::Magick',
    'LIB_GMAGICK' => 'Graphics::Magick',
    'LIB_GD' => 'GD',
);

foreach $constname (keys(%consts)) {
    eval("ok( defined(&Tempest::$constname), '$constname constant' );");
    if(eval("defined(&Tempest::$constname)")) {
        eval("is(Tempest::$constname, '$consts{$constname}', '$constname constant value');");
    }
}

t/imagemagick.t  view on Meta::CPAN


use Test::More tests => 7;
use File::Basename;
use Cwd 'abs_path';

BEGIN {
    use_ok( 'Tempest' );
}

SKIP: {
    # skip entire test file if Image::Magick module is not available
    eval { require Image::Magick };
    skip "Image::Magick module not installed", 6 if $@;
    diag("Testing Image::Magick $Image::Magick::VERSION");
    
    # remove output file if it exists
    if(-f dirname(__FILE__) . '/data/output_imagemagick.png') {
        unlink(dirname(__FILE__) . '/data/output_imagemagick.png');
    }
    
    $instance = new Tempest(
        'input_file' => dirname(__FILE__) . '/data/screenshot.png',
        'output_file' => dirname(__FILE__) . '/data/output_imagemagick.png',
        'coordinates' => [



( run in 1.326 second using v1.01-cache-2.11-cpan-beeb90c9504 )