App-Basis-ConvertText2
view release on metacpan or search on metacpan
lib/App/Basis/ConvertText2/Plugin/Chart.pm view on Meta::CPAN
=head1 NAME
App::Basis::ConvertText2::Plugin::Chart
=head1 SYNOPSIS
my $content = "apples,bananas,cake,cabbage,edam,fromage,tomatoes,chips
1,2,3,5,11,22,33,55
1,2,3,5,11,22,33,55
1,2,3,5,11,22,33,55
1,2,3,5,11,22,33,55
" ;
my $params = {
size => "600x480",
title => "chart1",
xaxis => 'things xways',
yaxis => 'Vertical things',
format => 'pie',
legends => 'a,b,c,d,e,f,g,h'
} ;
my $obj = App::Basis::ConvertText2::Plugin::Chart->new() ;
my $out = $obj->process( 'chart', $content, $params) ;
=head1 DESCRIPTION
Convert comma separated text strings into charts image PNG
=cut
# ----------------------------------------------------------------------------
package App::Basis::ConvertText2::Plugin::Chart;
$App::Basis::ConvertText2::Plugin::Chart::VERSION = '0.4';
use 5.10.0;
use strict;
use warnings;
# the different graph types
use GD::Graph::lines;
use GD::Graph::lines3d;
use GD::Graph::bars;
use GD::Graph::bars3d;
use GD::Graph::pie;
use GD::Graph::points;
use GD::Graph::linespoints;
use GD::Graph::area;
use GD::Graph::mixed;
use GD;
use Capture::Tiny qw(capture);
use Path::Tiny;
use Moo;
use App::Basis;
use App::Basis::ConvertText2::Support;
use namespace::autoclean;
has handles => (
is => 'ro',
init_arg => undef,
default => sub { [qw{chart}] }
);
# BEGIN {
# load up the X11 colour names
GD::Graph::colour::read_rgb("/etc/X11/rgb.txt");
# }
# ----------------------------------------------------------------------------
my %_chart_formats = (
mixed => 'GD::Graph::mixed',
area => 'GD::Graph::area',
lines => 'GD::Graph::lines',
points => 'GD::Graph::points',
linespoints => 'GD::Graph::linespoints',
bars => 'GD::Graph::bars',
lines3d => 'GD::Graph::lines3d',
pie => 'GD::Graph::pie'
);
# ----------------------------------------------------------------------------
sub chart_formats {
my @charts = sort keys %_chart_formats;
return @charts;
}
# ----------------------------------------------------------------------------
sub _split_csv_data {
my $data = shift;
my @d = ();
my $j = 0;
foreach my $line ( split( /\n/, $data ) ) {
last if ( !$line );
my @row = split( /,/, $line );
for ( my $i = 0; $i <= $#row; $i++ ) {
undef $row[$i] if ( $row[$i] eq 'undef' );
# dont' bother with any zero values either
undef $row[$i] if ( $row[$i] =~ /^0\.?0?$/ );
push @{ $d[$j] }, $row[$i];
}
$j++;
}
return @d;
}
# ----------------------------------------------------------------------------
=item chart
create a simple chart image, with some nice defaults
parameters
data - comma separated lines of chart data
filename - filename to save the created chart image as
hashref params of
size - size of image, default 400x300, widthxheight - optional
title - title for the chart
xaxis - label for x axis
yaxis - label for y axis
format - chart format mixed, area, lines, points, linespoints, bars, lines3d, pie
types - space separated list of types, in the same order as the data sets. Possible values are: lines bars points area linespoints
overwrite - If set to 0, bars of different data sets will be drawn next to each other. If set to 1, they will be drawn in front of each other. Default: 0.
legends - csv of legends for graph, these correspond to the data sets
=cut
sub process {
my $self = shift;
my ( $tag, $content, $params, $cachedir ) = @_;
my ( @data, $chart, $format );
my @types = ();
$params->{size} ||= "400x300";
my ( $x, $y ) = ( $params->{size} =~ /^\s*(\d+)\s*x\s*(\d+)\s*$/ );
# strip any ending linefeed
chomp $content;
return "" if ( !$content );
my $sig = create_sig( $content, $params );
my $filename = cachefile( $cachedir, "$sig.png" );
if ( !-f $filename ) {
# open the csv file, read contents, calc max, add into data array
@data = _split_csv_data($content);
$format = $params->{format} || "mixed";
$format = lc $format;
if ( !$y ) {
$x = 400;
$y = 300;
}
die "Unknown format type $format" if ( !$_chart_formats{$format} );
# get the name of the GD::Graph format class to instantiate and do it
$chart = $_chart_formats{$format}->new( $x, $y );
if ( $format eq "lines3d" ) {
# always assume stacked bars when using lines3d
$chart->set( bar_spacing => 6 );
}
if ( $params->{types} ) {
@types = split( /\s/, $params->{types} );
}
else {
$params->{types} = "points " x scalar(@data);
}
# set the types
$chart->set(
types => [@types],
default_type => $types[0] || "points",
bgclr => 'white',
fgclr => 'black',
boxclr => 'ivory',
accentclr => 'black',
valuesclr => 'black',
labelclr => 'black',
axislabelclr => 'black',
legendclr => 'black',
valuesclr => 'black',
textclr => 'black',
# shadow_depth => 2,
x_label => $params->{xaxis} || "",
y_label => $params->{yaxis} || "",
title => $params->{title} || "",
overwrite => $params->{overwrite} || 0,
bar_spacing => 6,
long_ticks => 1,
x_ticks => 1,
x_labels_vertical => 1,
legend_marker_width => 24,
line_width => 3,
marker_size => 5,
legend_placement => 'RC',
);
# set the colours for the charts
# white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow, yellow, dyellow,
# lgreen, green, dgreen, lred, red, dred, lpurple, purple, dpurple, lorange, orange,
# pink, dpink, marine, cyan, lbrown, dbrown.
$chart->set( dclrs => [qw(marine blue lred dgreen orange salmon lbrown gold lgreen yellow gray dred lpurple)] );
# set the font things
$chart->set_title_font(gdGiantFont);
# pie legends are written on the slices, so we don't have this method
if ( $format eq 'pie' ) {
$chart->set_value_font(gdMediumBoldFont);
}
else {
# legends comma seperated to allow spaces in descriptions
$chart->set_legend( split( /,/, $params->{legends} || "" ) );
$chart->set_legend_font(gdMediumBoldFont);
$chart->set_x_label_font(gdMediumBoldFont);
$chart->set_y_label_font(gdMediumBoldFont);
$chart->set_x_axis_font(gdMediumBoldFont);
$chart->set_y_axis_font(gdMediumBoldFont);
$chart->set_values_font(gdMediumBoldFont);
}
my ( $stdout, $stderr, $exit ) = capture {
my $gd = $chart->plot( \@data );
path($filename)->spew_raw( $gd->png ) if ($$gd);
};
}
my $out;
if ( -f $filename ) {
# create something suitable for the HTML
$out = create_img_src( $filename, $params->{title} );
}
return $out;
}
# ----------------------------------------------------------------------------
1;
( run in 1.732 second using v1.01-cache-2.11-cpan-39bf76dae61 )