PDF-API2
view release on metacpan or search on metacpan
lib/PDF/API2/Resource/XObject/Image/PNM.pm view on Meta::CPAN
$info{'fullheader'} = $in;
return \%info;
}
sub read_pnm {
my ($self, $pdf, $file) = @_;
my ($buf, $t, $scale, $line);
my $bpc;
my $cs;
my $fh;
if (ref($file)) {
$fh = $file;
}
else {
open $fh, '<', $file or die "$!: $file";
}
binmode($fh, ':raw');
$fh->seek(0, 0);
my $info = _read_header($fh);
if ($info->{'type'} == 1) { # ASCII PBM
$bpc = 1;
$cs = 'DeviceGray';
$self->{'Decode'} = PDFArray(PDFNum(1), PDFNum(0));
# Read the remainder of the file
local $/ = undef;
my $plain = <$fh>;
# Discard everything other than ASCII 1 and 0
$plain =~ s/[^01]+//g;
# Check length
my $size = $info->{'width'} * $info->{'height'};
croak "Incomplete ASCII PBM" if length($plain) < $size;
# Discard any additional bits
$plain = substr($plain, 0, $size) if length($plain) > $size;
# Pad with zeroes
$plain .= '0' x (8 - (length($plain) % 8));
# Convert to binary
$self->{' stream'} = pack('B*', $plain);
}
elsif ($info->{'type'} == 2) { # ASCII PGM
$cs = 'DeviceGray';
# Read the remainder of the file
local $/ = undef;
my $plain = <$fh>;
# Discard everything other than digits and whitespace
$plain =~ s/[^\d\s]+//gs;
$plain =~ s/^\s+//;
# Convert to an array of integers
my @raster = split m/\s+/, $plain;
# Check length
my $size = $info->{'width'} * $info->{'height'};
croak "Incomplete ASCII PGM" if scalar(@raster) < $size;
# Discard any additional integers
splice @raster, $size if scalar(@raster) > $size;
# Scale
$scale = 1;
if ($info->{'max'} <= 255) {
$bpc = 8;
$scale = 255 / $info->{'max'} unless $info->{'max'} == 255;
}
else {
$bpc = 16;
$scale = 65535 / $info->{'max'} unless $info->{'max'} == 65535;
}
@raster = map { $_ * $scale } @raster;
# Convert to bytes
if ($bpc == 8) {
$self->{' stream'} = pack('C*', @raster);
}
else {
$self->{' stream'} = pack('S*', @raster);
}
}
elsif ($info->{'type'} == 3) { # ASCII PPM
$cs = 'DeviceRGB';
# Read the remainder of the file
local $/ = undef;
my $plain = <$fh>;
# Discard everything other than digits and whitespace
$plain =~ s/[^\d\s]+//gs;
$plain =~ s/^\s+//;
# Convert to an array of integers
my @raster = split m/\s+/, $plain;
# Check length
my $size = $info->{'width'} * $info->{'height'};
croak "Incomplete ASCII PGM" if scalar(@raster) < $size * 3;
# Discard any additional integers
splice @raster, $size if scalar(@raster) > $size * 3;
# Scale
$scale = 1;
if ($info->{'max'} <= 255) {
$bpc = 8;
$scale = 255 / $info->{'max'} unless $info->{'max'} == 255;
}
else {
$bpc = 16;
$scale = 65535 / $info->{'max'} unless $info->{'max'} == 65535;
}
@raster = map { $_ * $scale } @raster;
# Convert to bytes
if ($bpc == 8) {
$self->{' stream'} = pack('C*', @raster);
}
else {
$self->{' stream'} = pack('S*', @raster);
}
}
elsif ($info->{'type'} == 4) { # Raw PBM
$cs = 'DeviceGray';
$bpc = 1;
$self->{'Decode'} = PDFArray(PDFNum(1), PDFNum(0));
read($fh, $self->{' stream'}, ($info->{'width'} * $info->{'height'} / 8));
}
elsif ($info->{'type'} == 5) { # Raw PGM
$cs = 'DeviceGray';
$bpc = $info->{'max'} <= 255 ? 8 : 16;
if ($info->{'max'} == 255 or $info->{'max'} == 65535) {
$scale = 1;
}
else {
$scale = ($bpc == 8 ? 255 : 65535) / $info->{'max'};
}
my $size = $info->{'width'} * $info->{'height'};
if ($scale == 1) {
read($fh, $self->{' stream'}, $size * ($bpc / 8));
}
else {
for (1 .. $size) {
read($fh, $buf, $bpc / 8);
if ($bpc == 8) {
$self->{' stream'} .= pack('C', (unpack('C', $buf) * $scale));
}
else {
$self->{' stream'} .= pack('S', (unpack('S', $buf) * $scale));
}
}
}
( run in 0.682 second using v1.01-cache-2.11-cpan-71847e10f99 )