i_color_set
i_color_info
- i_img_empty
- i_img_empty_ch
- i_img_exorcise
- i_img_destroy
-
i_img_info
i_img_setmask
if ($ex_version < 5.57) {
@ISA = qw(Exporter);
}
- $VERSION = '0.85_02';
- eval {
- require XSLoader;
- XSLoader::load(Imager => $VERSION);
- 1;
- } or do {
- require DynaLoader;
- push @ISA, 'DynaLoader';
- bootstrap Imager $VERSION;
- }
+ $VERSION = '0.92';
+ require XSLoader;
+ XSLoader::load(Imager => $VERSION);
}
my %formats_low;
}
sub _valid_image {
- my ($self) = @_;
+ my ($self, $method) = @_;
$self->{IMG} and return 1;
- $self->_set_error('empty input image');
+ my $msg = 'empty input image';
+ $msg = "$method: $msg" if $method;
+ $self->_set_error($msg);
return;
}
$self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
}
else {
- $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
- $hsh{'channels'});
+ $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
+ $hsh{'channels'});
}
unless ($self->{IMG}) {
return $result;
}
+sub make_palette {
+ my ($class, $quant, @images) = @_;
+
+ unless (@images) {
+ Imager->_set_error("make_palette: supply at least one image");
+ return;
+ }
+ my $index = 1;
+ for my $img (@images) {
+ unless ($img->{IMG}) {
+ Imager->_set_error("make_palette: image $index is empty");
+ return;
+ }
+ ++$index;
+ }
+
+ return i_img_make_palette($quant, map $_->{IMG}, @images);
+}
+
# convert a paletted (or any image) to an 8-bit/channel RGB image
sub to_rgb8 {
my $self = shift;
$type = i_test_format_probe($IO, -1);
}
+ if ($input{file} && !$type) {
+ # guess the type
+ $type = $FORMATGUESS->($input{file});
+ }
+
unless ($type) {
- $self->_set_error('type parameter missing and not possible to guess from extension');
+ my $msg = "type parameter missing and it couldn't be determined from the file contents";
+ $input{file} and $msg .= " or file name";
+ $self->_set_error($msg);
return undef;
}
$self->{DEBUG} && print "loading a bmp file\n";
}
- if ( $type eq 'gif' ) {
- if ($input{colors} && !ref($input{colors})) {
- # must be a reference to a scalar that accepts the colour map
- $self->{ERRSTR} = "option 'colors' must be a scalar reference";
- return undef;
- }
- if ($input{'gif_consolidate'}) {
- if ($input{colors}) {
- my $colors;
- ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
- if ($colors) {
- ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
- }
- }
- else {
- $self->{IMG} =i_readgif_wiol( $IO );
- }
- }
- else {
- my $page = $input{'page'};
- defined $page or $page = 0;
- $self->{IMG} = i_readgif_single_wiol( $IO, $page );
- if ($self->{IMG} && $input{colors}) {
- ${ $input{colors} } =
- [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
- }
- }
-
- if ( !defined($self->{IMG}) ) {
- $self->{ERRSTR}=$self->_error_as_msg();
- return undef;
- }
- $self->{DEBUG} && print "loading a gif file\n";
- }
-
if ( $type eq 'tga' ) {
$self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
if ( !defined($self->{IMG}) ) {
return 1;
}
else {
- my $work = $@ || "Unknown error loading $file";
+ my $work = $@ || "Unknown error";
chomp $work;
$work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
$work =~ s/\n/\\n/g;
+ $work =~ s/\s*\.?\z/ loading $file/;
$file_load_errors{$file} = $work;
$$error = $work;
return 0;
}
unless ($type) {
- $ERRSTR = "No type parameter supplied and it couldn't be guessed";
+ my $msg = "type parameter missing and it couldn't be determined from the file contents";
+ $opts{file} and $msg .= " or file name";
+ Imager->_set_error($msg);
return;
}
}
}
elsif (defined $opts{radians} || defined $opts{degrees}) {
- my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
+ my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
my $back = $opts{back};
my $result = Imager->new;
sub setpixel {
my ($self, %opts) = @_;
+ $self->_valid_image("setpixel")
+ or return;
+
my $color = $opts{color};
unless (defined $color) {
$color = $self->{fg};
}
unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
- $color = _color($color)
- or return undef;
+ unless ($color = _color($color, 'setpixel')) {
+ $self->_set_error("setpixel: " . Imager->errstr);
+ return;
+ }
}
unless (exists $opts{'x'} && exists $opts{'y'}) {
- $self->{ERRSTR} = 'missing x and y parameters';
- return undef;
+ $self->_set_error('setpixel: missing x or y parameter');
+ return;
}
my $x = $opts{'x'};
my $y = $opts{'y'};
- if (ref $x && ref $y) {
- unless (@$x == @$y) {
- $self->{ERRSTR} = 'length of x and y mismatch';
+ if (ref $x || ref $y) {
+ $x = ref $x ? $x : [ $x ];
+ $y = ref $y ? $y : [ $y ];
+ unless (@$x) {
+ $self->_set_error("setpixel: x is a reference to an empty array");
return;
}
+ unless (@$y) {
+ $self->_set_error("setpixel: y is a reference to an empty array");
+ return;
+ }
+
+ # make both the same length, replicating the last element
+ if (@$x < @$y) {
+ $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
+ }
+ elsif (@$y < @$x) {
+ $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
+ }
+
my $set = 0;
if ($color->isa('Imager::Color')) {
- for my $i (0..$#{$opts{'x'}}) {
+ for my $i (0..$#$x) {
i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
or ++$set;
}
}
else {
- for my $i (0..$#{$opts{'x'}}) {
+ for my $i (0..$#$x) {
i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
or ++$set;
}
}
- $set or return;
+
return $set;
}
else {
}
}
- $self;
+ return $self;
}
sub getpixel {
my %opts = ( "type"=>'8bit', @_);
+ $self->_valid_image("getpixel")
+ or return;
+
unless (exists $opts{'x'} && exists $opts{'y'}) {
- $self->{ERRSTR} = 'missing x and y parameters';
- return undef;
+ $self->_set_error('getpixel: missing x or y parameter');
+ return;
}
my $x = $opts{'x'};
my $y = $opts{'y'};
- if (ref $x && ref $y) {
- unless (@$x == @$y) {
- $self->{ERRSTR} = 'length of x and y mismatch';
- return undef;
+ my $type = $opts{'type'};
+ if (ref $x || ref $y) {
+ $x = ref $x ? $x : [ $x ];
+ $y = ref $y ? $y : [ $y ];
+ unless (@$x) {
+ $self->_set_error("getpixel: x is a reference to an empty array");
+ return;
+ }
+ unless (@$y) {
+ $self->_set_error("getpixel: y is a reference to an empty array");
+ return;
+ }
+
+ # make both the same length, replicating the last element
+ if (@$x < @$y) {
+ $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
+ }
+ elsif (@$y < @$x) {
+ $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
}
+
my @result;
- if ($opts{"type"} eq '8bit') {
- for my $i (0..$#{$opts{'x'}}) {
+ if ($type eq '8bit') {
+ for my $i (0..$#$x) {
push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
}
}
- else {
- for my $i (0..$#{$opts{'x'}}) {
+ elsif ($type eq 'float' || $type eq 'double') {
+ for my $i (0..$#$x) {
push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
}
}
+ else {
+ $self->_set_error("getpixel: type must be '8bit' or 'float'");
+ return;
+ }
return wantarray ? @result : \@result;
}
else {
- if ($opts{"type"} eq '8bit') {
+ if ($type eq '8bit') {
return i_get_pixel($self->{IMG}, $x, $y);
}
- else {
+ elsif ($type eq 'float' || $type eq 'double') {
return i_gpixf($self->{IMG}, $x, $y);
}
+ else {
+ $self->_set_error("getpixel: type must be '8bit' or 'float'");
+ return;
+ }
}
-
- $self;
}
sub getscanline {
return;
}
- unless ($opts{channels}) {
- $opts{channels} = [ 0 .. $self->getchannels()-1 ];
- }
-
if ($opts{target}) {
my $target = $opts{target};
my $offset = $opts{offset};
if ($opts{type} eq '8bit') {
my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
- $opts{y}, @{$opts{channels}})
+ $opts{y}, $opts{channels})
or return;
- @{$target}{$offset .. $offset + @samples - 1} = @samples;
+ @{$target}[$offset .. $offset + @samples - 1] = @samples;
return scalar(@samples);
}
elsif ($opts{type} eq 'float') {
my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
- $opts{y}, @{$opts{channels}});
- @{$target}{$offset .. $offset + @samples - 1} = @samples;
+ $opts{y}, $opts{channels});
+ @{$target}[$offset .. $offset + @samples - 1] = @samples;
return scalar(@samples);
}
elsif ($opts{type} =~ /^(\d+)bit$/) {
my @data;
my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
$opts{y}, $bits, $target,
- $offset, @{$opts{channels}});
+ $offset, $opts{channels});
unless (defined $count) {
$self->_set_error(Imager->_error_as_msg);
return;
else {
if ($opts{type} eq '8bit') {
return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
- $opts{y}, @{$opts{channels}});
+ $opts{y}, $opts{channels});
}
elsif ($opts{type} eq 'float') {
return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
- $opts{y}, @{$opts{channels}});
+ $opts{y}, $opts{channels});
}
elsif ($opts{type} =~ /^(\d+)bit$/) {
my $bits = $1;
my @data;
i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
- $opts{y}, $bits, \@data, 0, @{$opts{channels}})
+ $opts{y}, $bits, \@data, 0, $opts{channels})
or return;
return @data;
}
return;
}
- unless(defined $opts{data} && ref $opts{data}) {
- $self->_set_error('setsamples: data parameter missing or invalid');
+ my $data = $opts{data};
+ unless(defined $data) {
+ $self->_set_error('setsamples: data parameter missing');
return;
}
- unless ($opts{channels}) {
- $opts{channels} = [ 0 .. $self->getchannels()-1 ];
- }
+ my $type = $opts{type};
+ defined $type or $type = '8bit';
- unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
- $self->_set_error('setsamples: type parameter missing or invalid');
- return;
+ my $width = defined $opts{width} ? $opts{width}
+ : $self->getwidth() - $opts{x};
+
+ my $count;
+ if ($type eq '8bit') {
+ $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
+ $data, $opts{offset}, $width);
}
- my $bits = $1;
+ elsif ($type eq 'float') {
+ $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
+ $data, $opts{offset}, $width);
+ }
+ elsif ($type =~ /^([0-9]+)bit$/) {
+ my $bits = $1;
+
+ unless (ref $data) {
+ $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
+ return;
+ }
- unless (defined $opts{width}) {
- $opts{width} = $self->getwidth() - $opts{x};
+ $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
+ $opts{channels}, $data, $opts{offset},
+ $width);
+ }
+ else {
+ $self->_set_error('setsamples: type parameter invalid');
+ return;
}
- my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
- $opts{channels}, $opts{data}, $opts{offset},
- $opts{width});
unless (defined $count) {
$self->_set_error(Imager->_error_as_msg);
return;
i_get_image_file_limits();
}
+my @check_args = qw(width height channels sample_size);
+
+sub check_file_limits {
+ my $class = shift;
+
+ my %opts =
+ (
+ channels => 3,
+ sample_size => 1,
+ @_,
+ );
+
+ if ($opts{sample_size} && $opts{sample_size} eq 'float') {
+ $opts{sample_size} = length(pack("d", 0));
+ }
+
+ for my $name (@check_args) {
+ unless (defined $opts{$name}) {
+ $class->_set_error("check_file_limits: $name must be defined");
+ return;
+ }
+ unless ($opts{$name} == int($opts{$name})) {
+ $class->_set_error("check_file_limits: $name must be a positive integer");
+ return;
+ }
+ }
+
+ my $result = i_int_check_image_file_limits(@opts{@check_args});
+ unless ($result) {
+ $class->_set_error($class->_error_as_msg());
+ }
+
+ return $result;
+}
+
# Shortcuts that can be exported
sub newcolor { Imager::Color->new(@_); }
# Default guess for the type of an image from extension
+my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps);
+
+my %ext_types =
+ (
+ ( map { $_ => $_ } @simple_types ),
+ tiff => "tiff",
+ tif => "tiff",
+ pbm => "pnm",
+ pgm => "pnm",
+ ppm => "pnm",
+ pnm => "pnm", # technically wrong, but historically it works in Imager
+ jpeg => "jpeg",
+ jpg => "jpeg",
+ bmp => "bmp",
+ dib => "bmp",
+ rgb => "sgi",
+ bw => "sgi",
+ sgi => "sgi",
+ fit => "fits",
+ fits => "fits",
+ rle => "utah",
+ );
+
sub def_guess_type {
my $name=lc(shift);
- my $ext;
- $ext=($name =~ m/\.([^\.]+)$/)[0];
- return 'tiff' if ($ext =~ m/^tiff?$/);
- return 'jpeg' if ($ext =~ m/^jpe?g$/);
- return 'pnm' if ($ext =~ m/^p[pgb]m$/);
- return 'png' if ($ext eq "png");
- return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
- return 'tga' if ($ext eq "tga");
- return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
- return 'gif' if ($ext eq "gif");
- return 'raw' if ($ext eq "raw");
- return lc $ext; # best guess
- return ();
+
+ my ($ext) = $name =~ /\.([^.]+)$/
+ or return;
+
+ my $type = $ext_types{$ext}
+ or return;
+
+ return $type;
}
sub combines {
sub preload {
# this serves two purposes:
- # - a class method to load the file support modules included with Image
+ # - a class method to load the file support modules included with Imager
# (or were included, once the library dependent modules are split out)
# - something for Module::ScanDeps to analyze
# https://rt.cpan.org/Ticket/Display.html?id=6566
L<Imager::ExtUtils> - tools to get access to Imager's C API.
+=item *
+
+L<Imager::Security> - brief security notes.
+
+=item *
+
+L<Imager::Threads> - brief information on working with threads.
+
=back
=head2 Basic Overview
box() - L<Imager::Draw/box()> - draw a filled or outline box.
+check_file_limits() - L<Imager::Files/check_file_limits()>
+
circle() - L<Imager::Draw/circle()> - draw a filled circle
close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash()>
-get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
+get_file_limits() - L<Imager::Files/get_file_limits()>
getheight() - L<Imager::ImageTypes/getheight()> - height of the image in
pixels
log() - L<Imager::ImageTypes/log()> - send a message to the debugging
log.
-map() - L<Imager::Transformations/"Color Mappings"> - remap color
+make_palette() - L<Imager::ImageTypes/make_palette()> - produce a
+color palette from one or more input images.
+
+map() - L<Imager::Transformations/map()> - remap color
channel values
masked() - L<Imager::ImageTypes/masked()> - make a masked image
NF() - L<Imager::Handy/NF()>
-open() - L<Imager::Files> - an alias for read()
+open() - L<Imager::Files/read()> - an alias for read()
open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
setcolors() - L<Imager::ImageTypes/setcolors()> - set palette colors
in a paletted image
-set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
+set_file_limits() - L<Imager::Files/set_file_limits()>
setmask() - L<Imager::ImageTypes/setmask()>
scaling - L<Imager::Transformations/scale()>
+security - L<Imager::Security>
+
SGI files - L<Imager::Files/"SGI (RGB, BW)">
sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
+threads - L<Imager::Threads>
+
tiles, color - L<Imager::Filters/mosaic>
transparent images - L<Imager::ImageTypes>,
writing an image to a file - L<Imager::Files>
-=head1 THREADS
-
-Imager doesn't support perl threads.
-
-Imager has limited code to prevent double frees if you create images,
-colors etc, and then create a thread, but has no code to prevent two
-threads entering Imager's error handling code, and none is likely to
-be added.
-
=head1 SUPPORT
The best place to get help with Imager is the mailing list.
=for stopwords
makeblendedfont Fontforge
-A test font, FT2/fontfiles/MMOne.pfb, contains a Postscript operator
-definition copyrighted by Adobe. See F<adobe.txt> in the source for
-license information.
+A test font, generated by the Debian packaged Fontforge,
+F<FT2/fontfiles/MMOne.pfb>, contains a Postscript operator definition
+copyrighted by Adobe. See F<adobe.txt> in the source for license
+information.
=head1 SEE ALSO
Other perl imaging modules include:
-L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).
+L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
+L<Prima::Image>, L<IPA>.
+
+If you're trying to use Imager for array processing, you should
+probably using L<PDL>.
=cut