BEGIN {
require Exporter;
- require DynaLoader;
-
- $VERSION = '0.47';
- @ISA = qw(Exporter DynaLoader);
- bootstrap Imager $VERSION;
+ @ISA = qw(Exporter);
+ $VERSION = '0.48';
+ eval {
+ require XSLoader;
+ XSLoader::load(Imager => $VERSION);
+ 1;
+ } or do {
+ require DynaLoader;
+ push @ISA, 'DynaLoader';
+ bootstrap Imager $VERSION;
+ }
}
BEGIN {
}
};
- $filters{nearest_color} ={
- callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
- defaults => { },
- callsub => sub { my %hsh=@_; i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, $hsh{colors}, $hsh{dist}); }
- };
+ $filters{nearest_color} =
+ {
+ callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
+ defaults => { },
+ callsub =>
+ sub {
+ my %hsh=@_;
+ # make sure the segments are specified with colors
+ my @colors;
+ for my $color (@{$hsh{colors}}) {
+ my $new_color = _color($color)
+ or die $Imager::ERRSTR."\n";
+ push @colors, $new_color;
+ }
+
+ i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
+ $hsh{dist})
+ or die Imager->_error_as_msg() . "\n";
+ },
+ };
$filters{gaussian} = {
callseq => [ 'image', 'stddev' ],
defaults => { },
i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
$hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
- $hsh{ssample_param}, \@segments);
+ $hsh{ssample_param}, \@segments)
+ or die Imager->_error_as_msg() . "\n";
},
};
$filters{unsharpmask} =
}
my $newcopy=Imager->new();
- $newcopy->{IMG}=i_img_new();
- i_copy($newcopy->{IMG},$self->{IMG});
+ $newcopy->{IMG} = i_copy($self->{IMG});
return $newcopy;
}
sub paste {
my $self = shift;
- unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
- my %input=(left=>0, top=>0, @_);
- unless($input{img}) {
- $self->{ERRSTR}="no source image";
+
+ unless ($self->{IMG}) {
+ $self->_set_error('empty input image');
+ return;
+ }
+ my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
+ my $src = $input{img} || $input{src};
+ unless($src) {
+ $self->_set_error("no source image");
return;
}
$input{left}=0 if $input{left} <= 0;
$input{top}=0 if $input{top} <= 0;
- my $src=$input{img};
+
my($r,$b)=i_img_info($src->{IMG});
+ my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
+ my ($src_right, $src_bottom);
+ if ($input{src_coords}) {
+ ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
+ }
+ else {
+ if (defined $input{src_maxx}) {
+ $src_right = $input{src_maxx};
+ }
+ elsif (defined $input{width}) {
+ if ($input{width} <= 0) {
+ $self->_set_error("paste: width must me positive");
+ return;
+ }
+ $src_right = $src_left + $input{width};
+ }
+ else {
+ $src_right = $r;
+ }
+ if (defined $input{src_maxx}) {
+ $src_bottom = $input{src_maxy};
+ }
+ elsif (defined $input{height}) {
+ if ($input{height} < 0) {
+ $self->_set_error("paste: height must be positive");
+ return;
+ }
+ $src_bottom = $src_top + $input{height};
+ }
+ else {
+ $src_bottom = $b;
+ }
+ }
+
+ $src_right > $r and $src_right = $r;
+ $src_bottom > $r and $src_bottom = $b;
+
+ if ($src_right <= $src_left
+ || $src_bottom < $src_top) {
+ $self->_set_error("nothing to paste");
+ return;
+ }
i_copyto($self->{IMG}, $src->{IMG},
- 0,0, $r, $b, $input{left}, $input{top});
+ $src_left, $src_top, $src_right, $src_bottom,
+ $input{left}, $input{top});
+
return $self; # What should go here??
}
if ( $input{'type'} eq 'pnm' ) {
$self->{IMG}=i_readpnm_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
if ( !defined($self->{IMG}) ) {
- $self->{ERRSTR}='unable to read pnm image: '._error_as_msg(); return undef;
+ $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
+ return undef;
}
$self->{DEBUG} && print "loading a pnm file\n";
return $self;
$params{storechannels},
$params{interleave});
if ( !defined($self->{IMG}) ) {
- $self->{ERRSTR}='unable to read raw image';
+ $self->{ERRSTR}=$self->_error_as_msg();
return undef;
}
$self->{DEBUG} && print "loading a raw file\n";
if (defined $input{class} && $input{class} eq 'fax') {
if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
- $self->{ERRSTR}='Could not write to buffer';
+ $self->{ERRSTR} = $self->_error_as_msg();
return undef;
}
} else {
if (!i_writetiff_wiol($self->{IMG}, $IO)) {
- $self->{ERRSTR}='Could not write to buffer';
+ $self->{ERRSTR} = $self->_error_as_msg();
return undef;
}
}
$self->_set_opts(\%input, "pnm_", $self)
or return undef;
if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
- $self->{ERRSTR}='unable to write pnm image';
+ $self->{ERRSTR} = $self->_error_as_msg();
return undef;
}
$self->{DEBUG} && print "writing a pnm file\n";
$self->_set_opts(\%input, "raw_", $self)
or return undef;
if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
- $self->{ERRSTR}='unable to write raw image';
+ $self->{ERRSTR} = $self->_error_as_msg();
return undef;
}
$self->{DEBUG} && print "writing a raw file\n";
}
}
if (defined($filters{$input{'type'}}{defaults})) {
- %hsh=('image',$self->{IMG},%{$filters{$input{'type'}}{defaults}},%input);
+ %hsh=( image => $self->{IMG},
+ imager => $self,
+ %{$filters{$input{'type'}}{defaults}},
+ %input );
} else {
- %hsh=('image',$self->{IMG},%input);
+ %hsh=( image => $self->{IMG},
+ imager => $self,
+ %input );
}
my @cs=@{$filters{$input{'type'}}{callseq}};
return $self;
}
+sub register_filter {
+ my $class = shift;
+ my %hsh = ( defaults => {}, @_ );
+
+ defined $hsh{type}
+ or die "register_filter() with no type\n";
+ defined $hsh{callsub}
+ or die "register_filter() with no callsub\n";
+ defined $hsh{callseq}
+ or die "register_filter() with no callseq\n";
+
+ exists $filters{$hsh{type}}
+ and return;
+
+ $filters{$hsh{type}} = \%hsh;
+
+ return 1;
+}
+
# Scale an image to requested size and return the scaled version
sub scale {
my $img = Imager->new();
my $tmp = Imager->new();
+ my $scalefactor = $opts{scalefactor};
+
unless (defined wantarray) {
my @caller = caller;
warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
return;
}
- unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
+ unless ($self->{IMG}) {
+ $self->_set_error('empty input image');
+ return undef;
+ }
+ # work out the scaling
if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
- my ($xpix,$ypix)=( $opts{xpixels}/$self->getwidth() , $opts{ypixels}/$self->getheight() );
- if ($opts{'type'} eq 'min') { $opts{scalefactor}=min($xpix,$ypix); }
- if ($opts{'type'} eq 'max') { $opts{scalefactor}=max($xpix,$ypix); }
- } elsif ($opts{xpixels}) { $opts{scalefactor}=$opts{xpixels}/$self->getwidth(); }
- elsif ($opts{ypixels}) { $opts{scalefactor}=$opts{ypixels}/$self->getheight(); }
+ my ($xpix, $ypix)=( $opts{xpixels} / $self->getwidth() ,
+ $opts{ypixels} / $self->getheight() );
+ if ($opts{'type'} eq 'min') {
+ $scalefactor = min($xpix,$ypix);
+ }
+ elsif ($opts{'type'} eq 'max') {
+ $scalefactor = max($xpix,$ypix);
+ }
+ else {
+ $self->_set_error('invalid value for type parameter');
+ return undef;
+ }
+ } elsif ($opts{xpixels}) {
+ $scalefactor = $opts{xpixels} / $self->getwidth();
+ }
+ elsif ($opts{ypixels}) {
+ $scalefactor = $opts{ypixels}/$self->getheight();
+ }
+ elsif ($opts{constrain} && ref $opts{constrain}
+ && $opts{constrain}->can('constrain')) {
+ # we've been passed an Image::Math::Constrain object or something
+ # that looks like one
+ (undef, undef, $scalefactor)
+ = $opts{constrain}->constrain($self->getwidth, $self->getheight);
+ unless ($scalefactor) {
+ $self->_set_error('constrain method failed on constrain parameter');
+ return undef;
+ }
+ }
if ($opts{qtype} eq 'normal') {
- $tmp->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
- if ( !defined($tmp->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
- $img->{IMG}=i_scaleaxis($tmp->{IMG},$opts{scalefactor},1);
- if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
+ $tmp->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
+ if ( !defined($tmp->{IMG}) ) {
+ $self->{ERRSTR} = 'unable to scale image';
+ return undef;
+ }
+ $img->{IMG}=i_scaleaxis($tmp->{IMG}, $scalefactor, 1);
+ if ( !defined($img->{IMG}) ) {
+ $self->{ERRSTR}='unable to scale image';
+ return undef;
+ }
+
return $img;
}
- if ($opts{'qtype'} eq 'preview') {
- $img->{IMG}=i_scale_nn($self->{IMG},$opts{'scalefactor'},$opts{'scalefactor'});
- if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
+ elsif ($opts{'qtype'} eq 'preview') {
+ $img->{IMG} = i_scale_nn($self->{IMG}, $scalefactor, $scalefactor);
+ if ( !defined($img->{IMG}) ) {
+ $self->{ERRSTR}='unable to scale image';
+ return undef;
+ }
return $img;
}
- $self->{ERRSTR}='scale: invalid value for qtype'; return undef;
+ else {
+ $self->_set_error('invalid value for qtype parameter');
+ return undef;
+ }
}
# Scales only along the X axis
sub scaleX {
- my $self=shift;
- my %opts=(scalefactor=>0.5,@_);
+ my $self = shift;
+ my %opts = ( scalefactor=>0.5, @_ );
unless (defined wantarray) {
my @caller = caller;
return;
}
- unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
+ unless ($self->{IMG}) {
+ $self->{ERRSTR} = 'empty input image';
+ return undef;
+ }
my $img = Imager->new();
- if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getwidth(); }
+ my $scalefactor = $opts{scalefactor};
- unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
- $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},0);
+ if ($opts{pixels}) {
+ $scalefactor = $opts{pixels} / $self->getwidth();
+ }
+
+ unless ($self->{IMG}) {
+ $self->{ERRSTR}='empty input image';
+ return undef;
+ }
+
+ $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
+
+ if ( !defined($img->{IMG}) ) {
+ $self->{ERRSTR} = 'unable to scale image';
+ return undef;
+ }
- if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
return $img;
}
# Scales only along the Y axis
sub scaleY {
- my $self=shift;
- my %opts=(scalefactor=>0.5,@_);
+ my $self = shift;
+ my %opts = ( scalefactor => 0.5, @_ );
unless (defined wantarray) {
my @caller = caller;
my $img = Imager->new();
- if ($opts{pixels}) { $opts{scalefactor}=$opts{pixels}/$self->getheight(); }
+ my $scalefactor = $opts{scalefactor};
- unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
- $img->{IMG}=i_scaleaxis($self->{IMG},$opts{scalefactor},1);
+ if ($opts{pixels}) {
+ $scalefactor = $opts{pixels} / $self->getheight();
+ }
+
+ unless ($self->{IMG}) {
+ $self->{ERRSTR} = 'empty input image';
+ return undef;
+ }
+ $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
+
+ if ( !defined($img->{IMG}) ) {
+ $self->{ERRSTR} = 'unable to scale image';
+ return undef;
+ }
- if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='unable to scale image'; return undef; }
return $img;
}
-
# Transform returns a spatial transformation of the input image
# this moves pixels to a new location in the returned image.
# NOTE - should make a utility function to check transforms for
my $self=shift;
my %opts=(tx => 0,ty => 0, @_);
- unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
- unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; }
+ unless ($self->{IMG}) {
+ $self->{ERRSTR}='empty input image';
+ return undef;
+ }
+ unless ($opts{src} && $opts{src}->{IMG}) {
+ $self->{ERRSTR}='empty input image for src';
+ return undef;
+ }
%opts = (src_minx => 0,
src_miny => 0,
%opts);
unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
- $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) {
- $self->{ERRSTR} = $self->_error_as_msg();
+ $opts{src_minx}, $opts{src_miny},
+ $opts{src_maxx}, $opts{src_maxy})) {
+ $self->_set_error($self->_error_as_msg());
return undef;
}
return $self;
elsif (defined $opts{radians} || defined $opts{degrees}) {
my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
+ my $back = $opts{back};
my $result = Imager->new;
- if ($opts{back}) {
- $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $opts{back});
+ if ($back) {
+ $back = _color($back);
+ unless ($back) {
+ $self->_set_error(Imager->errstr);
+ return undef;
+ }
+
+ $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
}
else {
$result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
}
-# Autoload methods go after =cut, and are processed by the autosplit program.
+sub Inline {
+ my ($lang) = @_;
+
+ $lang eq 'C'
+ or die "Only C language supported";
+
+ require Imager::ExtUtils;
+ return Imager::ExtUtils->inline_config;
+}
1;
__END__
L<Imager::Fountain> - Helper for making gradient profiles.
+=item *
+
+L<Imager::API> - using Imager's C API
+
+=item *
+
+L<Imager::APIRef> - API function reference
+
+=item *
+
+L<Imager::Inline> - using Imager's C API from Inline::C
+
+=item *
+
+L<Imager::ExtUtils> - tools to get access to Imager's C API.
+
=back
=head2 Basic Overview
masked() - L<Imager::ImageTypes/masked> - make a masked image
-matrix_transform() - L<Imager::Engines/"Matrix Transformations">
+matrix_transform() - L<Imager::Engines/matrix_transform>
maxcolors() - L<Imager::ImageTypes/maxcolors>
scale() - L<Imager::Transformations/scale>
-setscanline() - L<Imager::Draw/setscanline>
-
scaleX() - L<Imager::Transformations/scaleX>
scaleY() - L<Imager::Transformations/scaleY>
setpixel() - L<Imager::Draw/setpixel>
+setscanline() - L<Imager::Draw/setscanline>
+
+settag() - L<Imager::ImageTypes/settag>
+
set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
string() - L<Imager::Draw/string> - draw text on an image