no
warnings
'uninitialized'
;
our
$VERSION
=
'2.047'
;
sub
new {
my
(
$class
,
$pdf
,
$file
,
$name
) =
@_
;
my
$self
;
my
$tif
= PDF::API2::Resource::XObject::Image::TIFF::File->new(
$file
);
$class
=
ref
(
$class
)
if
ref
(
$class
);
$self
=
$class
->SUPER::new(
$pdf
,
$name
||
'Ix'
. pdfkey());
$pdf
->new_obj(
$self
)
unless
$self
->is_obj(
$pdf
);
$self
->{
' apipdf'
} =
$pdf
;
weaken
$self
->{
' apipdf'
};
$self
->read_tiff(
$pdf
,
$tif
);
$tif
->
close
();
return
$self
;
}
sub
deLZW {
my
(
$ibits
,
$stream
) =
@_
;
my
$bits
=
$ibits
;
my
$resetcode
= 1 << (
$ibits
- 1);
my
$endcode
=
$resetcode
+ 1;
my
$nextcode
=
$endcode
+ 1;
my
$ptr
= 0;
$stream
=
unpack
(
'B*'
,
$stream
);
my
$maxptr
=
length
(
$stream
);
my
$tag
;
my
$out
=
''
;
my
$outptr
= 0;
my
@d
=
map
{
chr
(
$_
) } (0 ..
$resetcode
- 1);
while
((
$ptr
+
$bits
) <=
$maxptr
) {
$tag
=0;
foreach
my
$off
(
reverse
1 ..
$bits
) {
$tag
<<= 1;
$tag
|=
substr
(
$stream
,
$ptr
+
$bits
-
$off
, 1);
}
$ptr
+=
$bits
;
if
(
$tag
==
$resetcode
) {
$bits
=
$ibits
;
$nextcode
=
$endcode
+ 1;
next
;
}
elsif
(
$tag
==
$endcode
) {
last
;
}
elsif
(
$tag
<
$resetcode
) {
$d
[
$nextcode
] =
$d
[
$tag
];
$out
.=
$d
[
$nextcode
];
$nextcode
++;
}
elsif
(
$tag
>
$endcode
) {
$d
[
$nextcode
] =
$d
[
$tag
];
$d
[
$nextcode
] .=
substr
(
$d
[
$tag
+ 1], 0, 1);
$out
.=
$d
[
$nextcode
];
$nextcode
++;
}
$bits
++
if
$nextcode
== (1 <<
$bits
);
}
return
$out
;
}
sub
handle_generic {
my
(
$self
,
$pdf
,
$tif
) =
@_
;
if
(
$tif
->{
'filter'
}) {
$self
->filters(
$tif
->{filter});
$self
->{
' nofilt'
} = 1;
}
else
{
$self
->filters(
'FlateDecode'
);
}
if
(
ref
(
$tif
->{
'imageOffset'
})) {
$self
->{
' stream'
} =
''
;
my
$d
=
scalar
@{
$tif
->{
'imageOffset'
}};
foreach
(1..
$d
) {
my
$buf
;
$tif
->{
'fh'
}->
seek
(
shift
(@{
$tif
->{
'imageOffset'
}}), 0);
$tif
->{
'fh'
}->
read
(
$buf
,
shift
(@{
$tif
->{
'imageLength'
}}));
$self
->{
' stream'
} .=
$buf
;
}
}
else
{
$tif
->{
'fh'
}->
seek
(
$tif
->{
'imageOffset'
}, 0);
$tif
->{
'fh'
}->
read
(
$self
->{
' stream'
},
$tif
->{
'imageLength'
});
}
return
$self
;
}
sub
handle_flate {
my
(
$self
,
$pdf
,
$tif
) =
@_
;
$self
->filters(
'FlateDecode'
);
if
(
ref
(
$tif
->{
'imageOffset'
})) {
$self
->{
' stream'
} =
''
;
my
$d
=
scalar
@{
$tif
->{
'imageOffset'
}};
foreach
(1 ..
$d
) {
my
$buf
;
$tif
->{
'fh'
}->
seek
(
shift
(@{
$tif
->{
'imageOffset'
}}),0);
$tif
->{
'fh'
}->
read
(
$buf
,
shift
(@{
$tif
->{
'imageLength'
}}));
$buf
=uncompress(
$buf
);
$self
->{
' stream'
} .=
$buf
;
}
}
else
{
$tif
->{
'fh'
}->
seek
(
$tif
->{
'imageOffset'
}, 0);
$tif
->{
'fh'
}->
read
(
$self
->{
' stream'
},
$tif
->{
'imageLength'
});
$self
->{
' stream'
} = uncompress(
$self
->{
' stream'
});
}
return
$self
;
}
sub
handle_lzw {
my
(
$self
,
$pdf
,
$tif
) =
@_
;
$self
->filters(
'FlateDecode'
);
my
$imageWidth
=
$tif
->{
'imageWidth'
};
my
$mod
=
$imageWidth
% 8;
if
(
$mod
> 0) {
$imageWidth
+= 8 -
$mod
;
}
my
$max_raw_strip
=
$imageWidth
*
$tif
->{
'bitsPerSample'
} *
$tif
->{
'RowsPerStrip'
} / 8;
if
(
ref
(
$tif
->{
'imageOffset'
})) {
$self
->{
' stream'
}=
''
;
my
$d
=
scalar
@{
$tif
->{
'imageOffset'
}};
foreach
(1 ..
$d
) {
my
$buf
;
$tif
->{
'fh'
}->
seek
(
shift
(@{
$tif
->{imageOffset}}), 0);
$tif
->{
'fh'
}->
read
(
$buf
,
shift
(@{
$tif
->{
'imageLength'
}}));
$buf
= deLZW(9,
$buf
);
if
(
length
(
$buf
) >
$max_raw_strip
) {
$buf
=
substr
(
$buf
, 0,
$max_raw_strip
);
}
$self
->{
' stream'
} .=
$buf
;
}
}
else
{
$tif
->{
'fh'
}->
seek
(
$tif
->{
'imageOffset'
}, 0);
$tif
->{
'fh'
}->
read
(
$self
->{
' stream'
},
$tif
->{
'imageLength'
});
$self
->{
' stream'
} = deLZW(9,
$self
->{
' stream'
});
}
return
$self
;
}
sub
handle_ccitt {
my
(
$self
,
$pdf
,
$tif
) =
@_
;
$self
->{
' nofilt'
} = 1;
$self
->{
'Filter'
} = PDFName(
'CCITTFaxDecode'
);
$self
->{
'DecodeParms'
} = PDFDict();
$self
->{
'DecodeParms'
}->{
'K'
} = ((
$tif
->{
'ccitt'
} == 4 || (
$tif
->{
'g3Options'
} & 0x1)) ? PDFNum(-1) : PDFNum(0));
$self
->{
'DecodeParms'
}->{
'Columns'
} = PDFNum(
$tif
->{
'imageWidth'
});
$self
->{
'DecodeParms'
}->{
'Rows'
} = PDFNum(
$tif
->{
'imageHeight'
});
$self
->{
'DecodeParms'
}->{
'Blackls1'
} = PDFBool(
$tif
->{
'whiteIsZero'
} == 1 ? 1 : 0);
if
(
defined
(
$tif
->{
'g3Options'
}) && (
$tif
->{
'g3Options'
} & 0x4)) {
$self
->{
'DecodeParms'
}->{
'EndOfLine'
} = PDFBool(1);
$self
->{
'DecodeParms'
}->{
'EncodedByteAlign'
} = PDFBool(1);
}
$self
->{
'DecodeParms'
}->{
'DamagedRowsBeforeError'
} = PDFNum(100);
if
(
ref
(
$tif
->{
'imageOffset'
})) {
die
"chunked ccitt g4 tif not supported."
;
}
else
{
$tif
->{
'fh'
}->
seek
(
$tif
->{
'imageOffset'
}, 0);
$tif
->{
'fh'
}->
read
(
$self
->{
' stream'
},
$tif
->{
'imageLength'
});
}
return
$self
;
}
sub
read_tiff {
my
(
$self
,
$pdf
,
$tif
) =
@_
;
$self
->width(
$tif
->{
'imageWidth'
});
$self
->height(
$tif
->{
'imageHeight'
});
if
(
$tif
->{
'colorSpace'
} eq
'Indexed'
) {
my
$dict
= PDFDict();
$pdf
->new_obj(
$dict
);
$self
->colorspace(PDFArray(PDFName(
$tif
->{
'colorSpace'
}), PDFName(
'DeviceRGB'
), PDFNum(255),
$dict
));
$dict
->{
'Filter'
} = PDFArray(PDFName(
'FlateDecode'
));
$tif
->{
'fh'
}->
seek
(
$tif
->{
'colorMapOffset'
}, 0);
my
$colormap
;
my
$straight
;
$tif
->{
'fh'
}->
read
(
$colormap
,
$tif
->{
'colorMapLength'
});
$dict
->{
' stream'
} =
''
;
$straight
.=
pack
(
'C'
, (
$_
/ 256))
for
unpack
(
$tif
->{
'short'
} .
'*'
,
$colormap
);
foreach
my
$c
(0 .. ((
$tif
->{
'colorMapSamples'
} / 3) - 1)) {
$dict
->{
' stream'
} .=
substr
(
$straight
,
$c
, 1);
$dict
->{
' stream'
} .=
substr
(
$straight
,
$c
+ (
$tif
->{
'colorMapSamples'
} / 3), 1);
$dict
->{
' stream'
} .=
substr
(
$straight
,
$c
+ (
$tif
->{
'colorMapSamples'
} / 3) * 2, 1);
}
}
else
{
$self
->colorspace(
$tif
->{
'colorSpace'
});
}
$self
->{
'Interpolate'
} = PDFBool(1);
$self
->bpc(
$tif
->{
'bitsPerSample'
});
if
(
$tif
->{
'whiteIsZero'
} == 1 &&
$tif
->{
'filter'
} ne
'CCITTFaxDecode'
) {
$self
->{
'Decode'
} = PDFArray(PDFNum(1), PDFNum(0));
}
if
(
defined
$tif
->{
'filter'
} and
$tif
->{
'filter'
} eq
'CCITTFaxDecode'
) {
$self
->handle_ccitt(
$pdf
,
$tif
);
}
elsif
(
defined
$tif
->{
'filter'
} and
$tif
->{
'filter'
} eq
'LZWDecode'
) {
$self
->handle_lzw(
$pdf
,
$tif
);
}
elsif
(
defined
$tif
->{
'filter'
} and
$tif
->{filter} eq
'FlateDecode'
) {
$self
->handle_flate(
$pdf
,
$tif
);
}
else
{
$self
->handle_generic(
$pdf
,
$tif
);
}
if
(
$tif
->{
'fillOrder'
} == 2) {
my
@bl
= ();
foreach
my
$n
(0 .. 255) {
my
$b
=
$n
;
my
$f
= 0;
foreach
(0 .. 7) {
my
$bit
= 0;
if
(
$b
& 0x1) {
$bit
= 1;
}
$b
>>= 1;
$f
<<= 1;
$f
|=
$bit
;
}
$bl
[
$n
] =
$f
;
}
my
$l
=
length
(
$self
->{
' stream'
}) - 1;
foreach
my
$n
(0 ..
$l
) {
vec
(
$self
->{
' stream'
},
$n
, 8) =
$bl
[
vec
(
$self
->{
' stream'
},
$n
, 8)];
}
}
$self
->{
' tiff'
} =
$tif
;
return
$self
;
}
sub
tiffTag {
my
(
$self
,
$tag
) =
@_
;
return
$self
->{
' tiff'
}->{
$tag
};
}
1;