Tree-Cladogram

 view release on metacpan or  search on metacpan

lib/Tree/Cladogram/ImageMagick.pm  view on Meta::CPAN

package Tree::Cladogram::ImageMagick;

use parent 'Tree::Cladogram';

use Image::Magick;

use Moo;

use Types::Standard qw/Int/;

has title_x =>
(
	default  => sub{return 0},
	is       => 'rw',
	isa      => Int,
	required => 0,
);

has title_y =>
(
	default  => sub{return 0},
	is       => 'rw',
	isa      => Int,
	required => 0,
);

our $VERSION = '1.04';

# ------------------------------------------------

sub _calculate_leaf_name_bounds
{
	my($self)			= @_;
	my($image)			= Image::Magick -> new(size => '1 x 1');
	my($result)			= $image -> Read('canvas:white');
	my($leaf_font_size)	= $self -> leaf_font_size;
	my($x_step)			= $self -> x_step;

	my($attributes);
	my(@metrics);
	my($x);
	my($y);

	$self -> root -> walk_down
	({
		callback =>
		sub
		{
			my($node)		= @_;
			my(@metrics)	= $image -> QueryFontMetrics
								(
									font		=> $self -> leaf_font_file,
									pointsize	=> $self -> leaf_font_size,
									text		=> $node -> name,
									x			=> 0,
									y			=> 0,
								);
			$attributes				= $node -> attributes;
			$x						= $$attributes{x} + $x_step + 4;
			$y						= $$attributes{y} + int($leaf_font_size / 2);
			$$attributes{bounds}	= [$x, $y, $x + $metrics[11] + 1, $y + $metrics[5]];

			$node -> attributes($attributes);

			return 1; # Keep walking.
		},
		_depth	=> 0,
	});

} # End of _calculate_leaf_name_bounds.

# ------------------------------------------------

sub _calculate_title_metrics
{
	my($self, $image, $maximum_x, $maximum_y) = @_;
	my(@metrics) = $image -> QueryFontMetrics
					(
						font		=> $self -> title_font_file,
						pointsize	=> $self -> title_font_size,
						text		=> $self -> title,
						x			=> 0,
						y			=> 0,
					);

	$self -> title_width($metrics[11] + 1);
	$self -> title_x(int( ($maximum_x - $metrics[11]) / 2) );
	$self -> title_y($maximum_y - $self -> leaf_font_size);

} # End of _calculate_title_metrics.

# ------------------------------------------------

sub create_image
{
	my($self, $maximum_x, $maximum_y) = @_;
	my($image) = Image::Magick -> new(size => "$maximum_x x $maximum_y");

	$image -> Read('canvas:white');
	$self -> _calculate_title_metrics($image, $maximum_x, $maximum_y) if (length($self -> title) );

	if ($self -> draw_frame)
	{
		# The advantage of Draw over Border is that the former
		# draws /on/ the image, thereby not making it larger.

		my(@x) = (0, ($maximum_x - 1), ($maximum_x - 1), 0);
		my(@y) = (0, 0, ($maximum_y - 1), ($maximum_y - 1) );

		$image -> Draw
			(
				fill		=> 'none',
				primitive	=> 'polyline',
				points		=> "$x[0],$y[0] $x[1],$y[1] $x[2],$y[2] $x[3],$y[3] $x[0],$y[0]",
				stroke		=> $self -> frame_color,
				strokewidth	=> 1,
			);
	}

	return $image;

} # End of create_image.

# ------------------------------------------------

sub draw_horizontal_branch
{
	my($self, $image, $middle_attributes, $daughter_attributes, $final_offset) = @_;
	my($branch_width)	= $self -> branch_width - 1;
	my($x_step)			= $self -> x_step;
	my(@x)				= ($$middle_attributes{x}, $$daughter_attributes{x} + $x_step + $final_offset);
	my(@y)				= ($$daughter_attributes{y}, $$daughter_attributes{y} + $branch_width);
	my($result)			= $image -> Draw
							(
								fill		=> $self -> branch_color,
								method		=> 'replace',
								points		=> "$x[0],$y[0] $x[1],$y[1]",
								primitive	=> 'rectangle',
							);

} # End of draw_horizontal_branch.

# ------------------------------------------------

sub draw_leaf_name
{
	my($self, $image, $name, $daughter_attributes, $final_offset) = @_;

	if ( (length($name) > 0) && ($name !~ /^\d+$/) )
	{
		my($bounds)		= $$daughter_attributes{bounds};
		$$bounds[0]		+= $final_offset;
		$$bounds[2]		+= $final_offset;
		my($font_size)	= $self -> leaf_font_size;

		$image -> Annotate
		(

lib/Tree/Cladogram/ImageMagick.pm  view on Meta::CPAN

{
	my($self, $image, $maximum_x, $maximum_y) = @_;
	my($title) = $self -> title;

	if (length($title) > 0)
	{
		$image -> Annotate
		(
			antialias	=> 'false',
			font		=> $self -> title_font_file,
			gravity		=> 'forget',
			pointsize	=> $self -> title_font_size,
			stroke		=> $self -> title_font_color,
			strokewidth	=> 1,
			text		=> $title,
			x			=> $self -> title_x,
			y			=> $self -> title_y,
		);
	}

} # End of draw_title.

# ------------------------------------------------

sub draw_vertical_branch
{
	my($self, $image, $middle_attributes, $daughter_attributes) = @_;
	my($branch_width)	= $self -> branch_width - 1;
	my($x_step)			= $self -> x_step;
	my(@x)				= ($$middle_attributes{x}, $$middle_attributes{x} + $branch_width);
	my(@y)				= ($$middle_attributes{y}, $$daughter_attributes{y});
	my($result)			= $image -> Draw
							(
								fill		=> $self -> branch_color,
								method		=> 'replace',
								points		=> "$x[0],$y[0] $x[1],$y[1]",
								primitive	=> 'rectangle',
							);

} # End of draw_vertical_branch.

# ------------------------------------------------

sub write
{
	my($self, $image, $file_name) = @_;

	$image -> Write($file_name);
	$self -> log('Wrote ' . $file_name);

} # End of write.

# ------------------------------------------------

1;

=pod

=head1 NAME

C<Tree::Cladogram::ImageMagick> - Render a cladogram using Imager or Image::Magick

=head1 Synopsis

See L<Tree::Cladogram/Synopsis>.

=head1 Description

See L<Tree::Cladogram/Description>.

=head1 Distributions

See L<Tree::Cladogram/Distributions>.

=head1 Constructor and Initialization

See L<Tree::Cladogram/Constructor and Initialization>.

=head1 Methods

See L<Tree::Cladogram/Methods>.

=head1 FAQ

See L<Tree::Cladogram/FAQ>.

=head1 See Also

See L<Tree::Cladogram/See Also>.

=head1 Machine-Readable Change Log

The file Changes was converted into Changelog.ini by L<Module::Metadata::Changes>.

=head1 Version Numbers

Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.

=head1 Repository

L<https://github.com/ronsavage/Tree-Cladogram>

=head1 SUPPORT

Bugs should be reported via the CPAN bug tracker at

L<https://github.com/ronsavage/Tree-Cladogram/issues>

=head1 Author

L<Tree::Cladogram> was written by Ron Savage I<E<lt>ron@savage.net.auE<gt>> in 2015.

My homepage: L<http://savage.net.au/>

=head1 Copyright

Australian copyright (c) 2015, Ron Savage.

	All Programs of mine are 'OSI Certified Open Source Software';
	you can redistribute them and/or modify them under the terms of
	The Artistic License 2.0, a copy of which is available at:



( run in 0.526 second using v1.01-cache-2.11-cpan-39bf76dae61 )