our
$VERSION
=
'3.026'
;
our
$LAST_UPDATE
=
'3.026'
;
Hide Show 48 lines of Pod
sub
new {
my
(
$class
,
$pdf
,
$file
,
%opts
) =
@_
;
if
(
defined
$opts
{
'-name'
} && !
defined
$opts
{
'name'
}) {
$opts
{
'name'
} =
delete
(
$opts
{
'-name'
}); }
if
(
defined
$opts
{
'-compress'
} && !
defined
$opts
{
'compress'
}) {
$opts
{
'compress'
} =
delete
(
$opts
{
'-compress'
}); }
my
(
$name
,
$compress
);
if
(
exists
$opts
{
'name'
}) {
$name
=
$opts
{
'name'
}; }
if
(
exists
$opts
{
'compress'
}) {
$compress
=
$opts
{
'compress'
}; }
my
$self
;
$class
=
ref
(
$class
)
if
ref
(
$class
);
$self
=
$class
->SUPER::new(
$pdf
,
$name
||
'Nx'
.pdfkey());
$pdf
->new_obj(
$self
)
unless
$self
->is_obj(
$pdf
);
$self
->{
' apipdf'
} =
$pdf
;
weaken
$self
->{
' apipdf'
};
$self
->read_pnm(
$pdf
,
$file
);
if
(
defined
$compress
) {
$self
->filters(
'FlateDecode'
);
}
else
{
$self
->filters(
'ASCIIHexDecode'
);
}
return
$self
;
}
sub
readppmheader {
my
(
$gr
,
$buffer
) =
@_
;
my
%info
;
$info
{
'error'
} =
undef
;
my
(
$width
,
$height
,
$max
,
$comment
,
$content
);
(
$buffer
,
$comment
) = eat_whitespace(
$gr
,
$buffer
, 0);
(
$buffer
,
$content
) = read_content(
$gr
,
$buffer
);
if
(
length
(
$content
) != 2) {
$info
{
'error'
} =
'Read error or EOF'
;
return
(\
%info
,
$buffer
);
}
if
(
$content
=~ /^P([1-6])/) {
$info
{
'type'
} = $1;
if
(
$info
{
'type'
} > 3) {
$info
{
'raw'
} = 1;
}
else
{
$info
{
'raw'
} = 0;
}
}
else
{
$info
{
'error'
} =
'Unrecognized magic number, not 1..6'
;
return
(\
%info
,
$buffer
);
}
if
(
$info
{
'type'
} == 1 or
$info
{
'type'
} == 4) {
$max
= 1;
$info
{
'bgp'
} =
'b'
;
}
elsif
(
$info
{
'type'
} == 2 or
$info
{
'type'
} == 5) {
$info
{
'bgp'
} =
'g'
;
}
else
{
$info
{
'bgp'
} =
'p'
;
}
(
$buffer
,
$comment
) = eat_whitespace(
$gr
,
$buffer
, 0);
(
$buffer
,
$content
) = read_content(
$gr
,
$buffer
);
if
(
length
(
$content
) == 0) {
$info
{
'error'
} =
'Read error or EOF on width'
;
return
(\
%info
,
$buffer
);
}
if
(
$content
=~ m/(^\d+)$/) {
$width
= $1;
}
else
{
$info
{
'error'
} =
'Invalid width value '
.$1;
return
(\
%info
,
$buffer
);
}
if
(
$width
< 1) {
$info
{
'error'
} =
'Invalid width value '
.
$width
;
return
(\
%info
,
$buffer
);
}
(
$buffer
,
$comment
) = eat_whitespace(
$gr
,
$buffer
, 0);
(
$buffer
,
$content
) = read_content(
$gr
,
$buffer
);
if
(
length
(
$content
) == 0) {
$info
{
'error'
} =
'Read error or EOF on height'
;
return
(\
%info
,
$buffer
);
}
if
(
$content
=~ m/(^\d+)$/) {
$height
= $1;
}
else
{
$info
{
'error'
} =
'Invalid height value '
.$1;
return
(\
%info
,
$buffer
);
}
if
(
$height
< 1) {
$info
{
'error'
} =
'Invalid height value '
.
$height
;
return
(\
%info
,
$buffer
);
}
if
(
$info
{
'bgp'
} =~ m/^[gp]$/) {
(
$buffer
,
$comment
) = eat_whitespace(
$gr
,
$buffer
, 0);
(
$buffer
,
$content
) = read_content(
$gr
,
$buffer
);
if
(
length
(
$content
) == 0) {
$info
{
'error'
} =
'Read error or EOF on max'
;
return
(\
%info
,
$buffer
);
}
if
(
$content
=~ m/(^\d+)$/) {
$max
= $1;
}
else
{
$info
{
'error'
} =
'Invalid max value '
.$1;
return
(\
%info
,
$buffer
);
}
if
(
$max
< 1 ||
$max
> 65535) {
$info
{
'error'
} =
'Invalid max value '
.
$max
;
return
(\
%info
,
$buffer
);
}
}
$info
{
'width'
} =
$width
;
$info
{
'height'
} =
$height
;
$info
{
'max'
} =
$max
;
if
(
$info
{
'raw'
}) {
if
(
$buffer
=~ m/^\s/) {
$buffer
=
substr
(
$buffer
, 1);
}
else
{
$info
{
'error'
} =
'Expected single whitespace before raster data'
;
return
(\
%info
,
$buffer
);
}
}
else
{
(
$buffer
,
$comment
) = eat_whitespace(
$gr
,
$buffer
, 0);
}
return
(\
%info
,
$buffer
);
}
sub
eat_whitespace {
my
(
$gr
,
$buffer
,
$qflag
) =
@_
;
my
(
$count
,
$buf
,
@comment
);
my
$in_comment
= 0;
while
(1) {
if
(
length
(
$buffer
) == 0) {
$count
=
read
(
$gr
,
$buffer
, 50);
if
(
$count
== 0 && (!
$qflag
||
$in_comment
)) {
print
STDERR
"EOF or read error reading whitespace.\n"
;
return
(
$buffer
,
''
);
}
}
if
(!
$in_comment
) {
$buffer
=~ s/^\s+//; }
if
(
length
(
$buffer
) > 0) {
if
(
$buffer
=~ m/^
$in_comment
= 1;
if
(
$buffer
=~ s/^
$in_comment
= 0;
}
elsif
(
$buffer
=~ s/^
push
@comment
, $1;
$in_comment
= 0;
}
else
{
$count
=
read
(
$gr
,
$buf
, 50);
if
(
$count
== 0) {
print
STDERR
"EOF or read error reading whitespace in pixel data\n"
;
return
(
$buffer
,
''
);
}
$buffer
.=
$buf
;
next
;
}
}
else
{
$in_comment
= 0;
last
;
}
}
else
{
if
(
$qflag
&& !
$in_comment
) {
last
; }
next
;
}
}
my
$comments
=
''
;
if
(
scalar
(
@comment
) > 0) {
$comments
=
join
(
"\n"
,
@comment
); }
return
(
$buffer
,
$comments
);
}
sub
read_content {
my
(
$gr
,
$buffer
) =
@_
;
my
(
$count
,
$content
);
$content
=
''
;
while
(1) {
if
(
length
(
$buffer
) == 0) {
$count
=
read
(
$gr
,
$buffer
, 50);
if
(
$count
== 0) {
print
STDERR
"EOF or read error reading content in pixel data\n"
;
return
(
$buffer
,
''
);
}
}
$buffer
=~ s/^([^\s]+)//;
$content
.= $1;
if
(
length
(
$buffer
) == 0) {
next
; }
last
;
}
return
(
$buffer
,
$content
);
}
sub
read_pnm {
my
$self
=
shift
;
my
$pdf
=
shift
;
my
$file
=
shift
;
my
(
$rc
,
$buf
,
$buf2
,
$s
,
$pix
,
$max
);
my
(
$w
,
$h
,
$bpc
,
$cs
,
$img
,
@img
) = (0,0,
''
,
''
,
''
);
my
(
$info
,
$buffer
,
$content
,
$comment
,
$sample
,
$gr
);
my
$inf
;
if
(
ref
(
$file
)) {
$inf
=
$file
;
}
else
{
open
$inf
,
"<"
,
$file
or
die
"$!: $file"
;
}
binmode
(
$inf
,
':raw'
);
$inf
->
seek
(0, 0);
$buffer
=
''
;
(
$info
,
$buffer
) = readppmheader(
$inf
,
$buffer
);
if
(
defined
$info
->{
'error'
}) {
print
STDERR
"Error reported during PNM file header read:\n"
.(
$info
->{
'error'
}).
".\n"
;
return
$self
;
}
$w
=
$info
->{
'width'
};
$h
=
$info
->{
'height'
};
$max
=
$info
->{
'max'
};
my
$bytes_per_sample
= 1;
if
(
$max
> 255) {
$bytes_per_sample
= 2; }
if
(
$info
->{
'type'
} == 1) {
$bpc
= 1;
my
(
$row
,
$col
,
$bits
);
my
$qflag
;
$content
=
''
;
for
(
$row
= 0;
$row
<
$h
;
$row
++) {
$bits
=
''
;
for
(
$col
= 0;
$col
<
$w
;
$col
++) {
if
(
length
(
$content
) == 0) {
$qflag
= 0;
if
(
$row
==
$h
-1 &&
$col
==
$w
-1) {
$qflag
= 1; }
(
$buffer
,
$comment
) = eat_whitespace(
$inf
,
$buffer
,
$qflag
);
(
$buffer
,
$content
) = read_content(
$inf
,
$buffer
);
if
(
length
(
$content
) == 0) {
print
STDERR
"Unexpected EOF or read error reading pixel data.\n"
;
return
$self
;
}
}
$sample
=
substr
(
$content
, 0, 1);
$content
=
substr
(
$content
, 1);
if
(
$sample
ne
'0'
&&
$sample
ne
'1'
) {
print
STDERR
"Invalid bit value '$sample' in pixel data.\n"
;
return
$self
;
}
$bits
.=
$sample
;
if
(
length
(
$bits
) == 8) {
$self
->{
' stream'
} .=
pack
(
'B8'
,
$bits
);
$bits
=
''
;
}
}
if
(
$bits
ne
''
) {
while
(
length
(
$bits
) < 8) {
$bits
.=
'0'
;
}
$self
->{
' stream'
} .=
pack
(
'B8'
,
$bits
);
}
}
$cs
=
'DeviceGray'
;
$self
->{
'Decode'
} = PDFArray(PDFNum(1), PDFNum(0));
}
elsif
(
$info
->{
'type'
} == 2) {
if
(
$max
== 255 ||
$max
== 65535) {
$s
= 0;
}
elsif
(
$max
> 255) {
$s
= 65535/
$max
;
}
else
{
$s
= 255/
$max
;
}
$bpc
= 8 *
$bytes_per_sample
;
my
$format
=
'C'
;
if
(
$bytes_per_sample
== 2) {
$format
=
'S>'
; }
my
$sample
;
for
(
$pix
=(
$w
*$h
);
$pix
>0;
$pix
--) {
(
$buffer
,
$content
) = read_content(
$inf
,
$buffer
);
if
(
length
(
$content
) == 0) {
print
STDERR
"Unexpected EOF or read error reading pixel data.\n"
;
return
$self
;
}
(
$buffer
,
$comment
) = eat_whitespace(
$inf
,
$buffer
,
$pix
==1);
if
(
$content
=~ m/^\d+$/) {
if
(
$content
>
$max
) {
print
STDERR
"Pixel data entry '$content' higher than $max. Value changed to $max.\n"
;
$content
=
$max
;
}
}
else
{
print
STDERR
"Invalid pixel data entry '$content'.\n"
;
return
$self
;
}
$sample
=
$content
;
if
(
$s
> 0) {
$sample
=
int
(
$sample
*$s
+ 0.5);
}
$self
->{
' stream'
} .=
pack
(
$format
,
$sample
);
}
$cs
=
'DeviceGray'
;
}
elsif
(
$info
->{
'type'
} == 3) {
if
(
$max
== 255 ||
$max
== 65535) {
$s
= 0;
}
elsif
(
$max
> 255) {
$s
= 65535/
$max
;
}
else
{
$s
= 255/
$max
;
}
$bpc
= 8 *
$bytes_per_sample
;
my
$format
=
'C'
;
if
(
$bytes_per_sample
== 2) {
$format
=
'S>'
; }
my
(
$sample
,
$rgb
);
for
(
$pix
=(
$w
*$h
);
$pix
>0;
$pix
--) {
for
(
$rgb
= 0;
$rgb
< 3;
$rgb
++) {
(
$buffer
,
$comment
) = eat_whitespace(
$inf
,
$buffer
,
$pix
==1);
(
$buffer
,
$content
) = read_content(
$inf
,
$buffer
);
if
(
length
(
$content
) == 0) {
print
STDERR
"Unexpected EOF or read error reading pixel data.\n"
;
return
$self
;
}
if
(
$content
=~ m/^\d+$/) {
if
(
$content
>
$max
) {
print
STDERR
"Pixel $pix data entry '$content' higher than $max. Value changed to $max.\n"
;
$content
=
$max
;
}
}
else
{
print
STDERR
"Invalid pixel data entry '$content'.\n"
;
return
$self
;
}
$sample
=
$content
;
if
(
$s
> 0) {
$sample
=
int
(
$sample
*$s
+ 0.5);
}
$self
->{
' stream'
} .=
pack
(
$format
,
$sample
);
}
}
$cs
=
'DeviceRGB'
;
}
elsif
(
$info
->{
'type'
} == 4) {
$bpc
= 1;
my
$bytes
=
int
((
$w
+7)/8) *
$h
;
$bytes
-=
length
(
$buffer
);
$rc
=
read
(
$inf
,
$buf2
,
$bytes
);
if
(
$rc
!=
$bytes
) {
print
STDERR
"Unexpected EOF or read error while reading PNM binary pixel data.\n"
;
return
$self
;
}
$self
->{
' stream'
} =
$buffer
.
$buf2
;
$cs
=
'DeviceGray'
;
$self
->{
'Decode'
} = PDFArray(PDFNum(1), PDFNum(0));
}
elsif
(
$info
->{
'type'
} == 5) {
if
(
$max
== 255 ||
$max
== 65535) {
$s
= 0;
}
elsif
(
$max
> 255) {
$s
= 65535/
$max
;
}
else
{
$s
= 255/
$max
;
}
$bpc
= 8 *
$bytes_per_sample
;
my
$format
=
'C'
;
if
(
$bytes_per_sample
== 2) {
$format
=
'S>'
; }
my
(
$buf
,
$sample
);
my
$bytes
=
$w
*
$h
*
$bytes_per_sample
;
$bytes
-=
length
(
$buffer
);
$rc
=
read
(
$inf
,
$buf
,
$bytes
);
if
(
$rc
!=
$bytes
) {
print
STDERR
"Unexpected EOF or read error reading pixel data.\n"
;
return
$self
;
}
$buf
=
$buffer
.
$buf
;
if
(
$s
> 0) {
for
(
$pix
=(
$w
*$h
);
$pix
>0;
$pix
--) {
$buf2
=
substr
(
$buf
, 0,
$bytes_per_sample
);
$buf
=
substr
(
$buf
,
$bytes_per_sample
);
$sample
=
unpack
(
$format
,
$buf2
);
$sample
=
int
(
$sample
*$s
+ 0.5);
$self
->{
' stream'
} .=
pack
(
$format
,
$sample
);
}
}
else
{
$self
->{
' stream'
} =
$buf
;
}
$cs
=
'DeviceGray'
;
}
elsif
(
$info
->{
'type'
} == 6) {
if
(
$max
== 255 ||
$max
== 65535) {
$s
= 0;
}
elsif
(
$max
> 255) {
$s
= 65535/
$max
;
}
else
{
$s
= 255/
$max
;
}
$bpc
= 8 *
$bytes_per_sample
;
my
$format
=
'C'
;
if
(
$bytes_per_sample
== 2) {
$format
=
'S>'
; }
my
(
$buf
,
$sample
);
my
$bytes
=
$w
*
$h
*
$bytes_per_sample
* 3;
$bytes
-=
length
(
$buffer
);
$rc
=
read
(
$inf
,
$buf
,
$bytes
);
if
(
$rc
!=
$bytes
) {
print
STDERR
"Unexpected EOF or read error reading pixel data.\n"
;
return
$self
;
}
$buf
=
$buffer
.
$buf
;
if
(
$s
> 0) {
for
(
$pix
=(
$w
*$h
);
$pix
>0;
$pix
--) {
$buf2
=
substr
(
$buf
, 0,
$bytes_per_sample
);
$sample
=
unpack
(
$format
,
$buf2
);
$sample
=
int
(
$sample
*$s
+ 0.5);
$self
->{
' stream'
} .=
pack
(
$format
,
$sample
);
$buf2
=
substr
(
$buf
,
$bytes_per_sample
,
$bytes_per_sample
);
$sample
=
unpack
(
$format
,
$buf2
);
$sample
=
int
(
$sample
*$s
+ 0.5);
$self
->{
' stream'
} .=
pack
(
$format
,
$sample
);
$buf2
=
substr
(
$buf
, 2
*$bytes_per_sample
,
$bytes_per_sample
);
$sample
=
unpack
(
$format
,
$buf2
);
$sample
=
int
(
$sample
*$s
+ 0.5);
$self
->{
' stream'
} .=
pack
(
$format
,
$sample
);
$buf
=
substr
(
$buf
,
$bytes_per_sample
*3);
}
}
else
{
$self
->{
' stream'
} =
$buf
;
}
$cs
=
'DeviceRGB'
;
}
close
(
$inf
);
$self
->width(
$w
);
$self
->height(
$h
);
$self
->bits_per_component(
$bpc
);
$self
->filters(
'FlateDecode'
);
$self
->colorspace(
$cs
);
return
$self
;
}
1;