File Coverage

blib/lib/PDF/API3/Compat/API2/Resource/XObject/Image/TIFF.pm
Criterion Covered Total %
statement 26 334 7.7
branch 0 144 0.0
condition 0 21 0.0
subroutine 9 22 40.9
pod 3 9 33.3
total 38 530 7.1


line stmt bran cond sub pod time code
1             #=======================================================================
2             # ____ ____ _____ _ ____ ___ ____
3             # | _ \| _ \| ___| _ _ / \ | _ \_ _| |___ \
4             # | |_) | | | | |_ (_) (_) / _ \ | |_) | | __) |
5             # | __/| |_| | _| _ _ / ___ \| __/| | / __/
6             # |_| |____/|_| (_) (_) /_/ \_\_| |___| |_____|
7             #
8             # A Perl Module Chain to faciliate the Creation and Modification
9             # of High-Quality "Portable Document Format (PDF)" Files.
10             #
11             # Copyright 1999-2005 Alfred Reibenschuh .
12             #
13             #=======================================================================
14             #
15             # This library is free software; you can redistribute it and/or
16             # modify it under the terms of the GNU Lesser General Public
17             # License as published by the Free Software Foundation; either
18             # version 2 of the License, or (at your option) any later version.
19             #
20             # This library is distributed in the hope that it will be useful,
21             # but WITHOUT ANY WARRANTY; without even the implied warranty of
22             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23             # Lesser General Public License for more details.
24             #
25             # You should have received a copy of the GNU Lesser General Public
26             # License along with this library; if not, write to the
27             # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28             # Boston, MA 02111-1307, USA.
29             #
30             # $Id: TIFF.pm,v 2.3 2007/09/17 16:03:07 areibens Exp $
31             #
32             #=======================================================================
33             package PDF::API3::Compat::API2::Resource::XObject::Image::TIFF;
34            
35             BEGIN {
36            
37 1     1   7 use PDF::API3::Compat::API2::Util;
  1         2  
  1         229  
38 1     1   7 use PDF::API3::Compat::API2::Basic::PDF::Utils;
  1         2  
  1         123  
39 1     1   14 use PDF::API3::Compat::API2::Resource::XObject::Image;
  1         2  
  1         30  
40            
41 1     1   6 use POSIX;
  1         2  
  1         8  
42 1     1   13178 use Compress::Zlib;
  1         3  
  1         490  
43            
44 1     1   8 use vars qw(@ISA $VERSION);
  1         4  
  1         185  
45            
46 1     1   36 @ISA = qw( PDF::API3::Compat::API2::Resource::XObject::Image );
47            
48 1         57 ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 2.3 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2007/09/17 16:03:07 $
49            
50             }
51 1     1   9 no warnings qw[ deprecated recursion uninitialized ];
  1         3  
  1         2461  
52            
53             =item $res = PDF::API3::Compat::API2::Resource::XObject::Image::TIFF->new $pdf, $file [, $name]
54            
55             Returns a tiff-image object.
56            
57             =cut
58            
59             sub new
60             {
61 0     0 1   my ($class,$pdf,$file,$name) = @_;
62 0           my $self;
63            
64 0           my $tif=TiffFile->new($file);
65            
66             # in case of problematic things
67             # proxy to other modules
68            
69 0 0         $class = ref $class if ref $class;
70            
71 0   0       $self=$class->SUPER::new($pdf,$name|| 'Ix'.pdfkey());
72 0 0         $pdf->new_obj($self) unless($self->is_obj($pdf));
73            
74 0           $self->{' apipdf'}=$pdf;
75            
76 0           $self->read_tiff($pdf,$tif);
77            
78 0           $tif->close;
79            
80 0           return($self);
81             }
82            
83             =item $res = PDF::API3::Compat::API2::Resource::XObject::Image::TIFF->new_api $api, $file [, $name]
84            
85             Returns a tiff-image object. This method is different from 'new' that
86             it needs an PDF::API3::Compat::API2-object rather than a Text::PDF::File-object.
87            
88             =cut
89            
90             sub new_api
91             {
92 0     0 1   my ($class,$api,@opts)=@_;
93            
94 0           my $obj=$class->new($api->{pdf},@opts);
95 0           $obj->{' api'}=$api;
96            
97 0           return($obj);
98             }
99            
100             sub deLZW
101             {
102 0     0 0   my ($ibits,$stream)=@_;
103 0           my $bits=$ibits;
104 0           my $resetcode=1<<($ibits-1);
105 0           my $endcode=$resetcode+1;
106 0           my $nextcode=$endcode+1;
107 0           my $ptr=0;
108 0           $stream=unpack('B*',$stream);
109 0           my $maxptr=length($stream);
110 0           my $tag;
111 0           my $out='';
112 0           my $outptr=0;
113            
114             # print STDERR "reset=$resetcode\nend=$endcode\nmax=$maxptr\n";
115            
116 0           my @d=map { chr($_) } (0..$resetcode-1);
  0            
117            
118 0           while(($ptr+$bits)<=$maxptr)
119             {
120 0           $tag=0;
121 0           foreach my $off (reverse 1..$bits)
122             {
123 0           $tag<<=1;
124 0           $tag|=substr($stream,$ptr+$bits-$off,1);
125             }
126             # print STDERR "ptr=$ptr,tag=$tag,bits=$bits,next=$nextcode\n";
127             # print STDERR "tag to large\n" if($tag>$nextcode);
128 0           $ptr+=$bits;
129 0 0         if($tag==$resetcode)
    0          
    0          
    0          
130             {
131 0           $bits=$ibits;
132 0           $nextcode=$endcode+1;
133 0           next;
134             }
135             elsif($tag==$endcode) {
136 0           last;
137             }
138             elsif($tag<$resetcode) {
139 0           $d[$nextcode]=$d[$tag];
140 0           $out.=$d[$nextcode];
141 0           $nextcode++;
142             }
143             elsif($tag>$endcode)
144             {
145 0           $d[$nextcode]=$d[$tag];
146 0           $d[$nextcode].=substr($d[$tag+1],0,1);
147 0           $out.=$d[$nextcode];
148 0           $nextcode++;
149             }
150 0 0         $bits++ if($nextcode == (1<<$bits));
151             }
152 0           return($out);
153             }
154            
155             sub handle_generic
156             {
157 0     0 0   my ($self,$pdf,$tif)=@_;
158            
159 0 0         if($tif->{filter})
160             {
161             # should we die here ?
162             # die "unknown tiff-compression ";
163 0           $self->filters($tif->{filter});
164 0           $self->{' nofilt'}=1;
165             }
166             else
167             {
168 0           $self->filters('FlateDecode');
169             }
170            
171 0 0         if(ref($tif->{imageOffset}))
172             {
173 0           $self->{' stream'}='';
174 0           my $d=scalar @{$tif->{imageOffset}};
  0            
175 0           foreach (1..$d)
176             {
177 0           my $buf;
178 0           $tif->{fh}->seek(shift @{$tif->{imageOffset}},0);
  0            
179 0           $tif->{fh}->read($buf,shift @{$tif->{imageLength}});
  0            
180 0           $self->{' stream'}.=$buf;
181             }
182             }
183             else
184             {
185 0           $tif->{fh}->seek($tif->{imageOffset},0);
186 0           $tif->{fh}->read($self->{' stream'},$tif->{imageLength});
187             }
188             }
189            
190             sub handle_flate
191             {
192 0     0 0   my ($self,$pdf,$tif)=@_;
193 0           $self->filters('FlateDecode');
194            
195 0 0         if(ref($tif->{imageOffset}))
196             {
197 0           $self->{' stream'}='';
198 0           my $d=scalar @{$tif->{imageOffset}};
  0            
199 0           foreach (1..$d)
200             {
201 0           my $buf;
202 0           $tif->{fh}->seek(shift @{$tif->{imageOffset}},0);
  0            
203 0           $tif->{fh}->read($buf,shift @{$tif->{imageLength}});
  0            
204 0           $buf=uncompress($buf);
205 0           $self->{' stream'}.=$buf;
206             }
207             }
208             else
209             {
210 0           $tif->{fh}->seek($tif->{imageOffset},0);
211 0           $tif->{fh}->read($self->{' stream'},$tif->{imageLength});
212 0           $self->{' stream'}=uncompress($self->{' stream'});
213             }
214             }
215            
216             sub handle_lzw
217             {
218 0     0 0   my ($self,$pdf,$tif)=@_;
219 0           $self->filters('FlateDecode');
220            
221 0 0         if(ref($tif->{imageOffset})) {
222 0           $self->{' stream'}='';
223 0           my $d=scalar @{$tif->{imageOffset}};
  0            
224 0           foreach (1..$d)
225             {
226 0           my $buf;
227 0           $tif->{fh}->seek(shift @{$tif->{imageOffset}},0);
  0            
228 0           $tif->{fh}->read($buf,shift @{$tif->{imageLength}});
  0            
229 0           $buf=deLZW(9,$buf);
230 0           $self->{' stream'}.=$buf;
231             }
232             }
233             else
234             {
235 0           $tif->{fh}->seek($tif->{imageOffset},0);
236 0           $tif->{fh}->read($self->{' stream'},$tif->{imageLength});
237 0           $self->{' stream'}=deLZW(9,$self->{' stream'});
238             }
239             }
240            
241             sub handle_ccitt
242             {
243 0     0 0   my ($self,$pdf,$tif)=@_;
244            
245 0           $self->{' nofilt'}=1;
246 0           $self->{Filter}=PDFName('CCITTFaxDecode');
247 0           $self->{DecodeParms}=PDFDict();
248 0 0 0       $self->{DecodeParms}->{K}=(($tif->{ccitt}==4 || ($tif->{g3Options}&0x1)) ? PDFNum(-1) : PDFNum(0));
249 0           $self->{DecodeParms}->{Columns}=PDFNum($tif->{imageWidth});
250 0           $self->{DecodeParms}->{Rows}=PDFNum($tif->{imageHeight});
251 0 0         $self->{DecodeParms}->{Blackls1}=PDFBool($tif->{whiteIsZero}==1?1:0);
252 0 0 0       if(defined($tif->{g3Options}) && ($tif->{g3Options}&0x4))
253             {
254 0           $self->{DecodeParms}->{EndOfLine}=PDFBool(1);
255 0           $self->{DecodeParms}->{EncodedByteAlign}=PDFBool(1);
256             }
257             # $self->{DecodeParms}=PDFArray($self->{DecodeParms});
258 0           $self->{DecodeParms}->{DamagedRowsBeforeError}=PDFNum(100);
259            
260 0 0         if(ref($tif->{imageOffset}))
261             {
262 0           die "chunked ccitt g4 tif not supported.";
263             }
264             else
265             {
266 0           $tif->{fh}->seek($tif->{imageOffset},0);
267 0           $tif->{fh}->read($self->{' stream'},$tif->{imageLength});
268             }
269             }
270            
271             sub read_tiff
272             {
273 0     0 0   my ($self,$pdf,$tif)=@_;
274            
275 0           $self->width($tif->{imageWidth});
276 0           $self->height($tif->{imageHeight});
277 0 0         if($tif->{colorSpace} eq 'Indexed')
278             {
279 0           my $dict=PDFDict();
280 0           $pdf->new_obj($dict);
281 0           $self->colorspace(PDFArray(PDFName($tif->{colorSpace}),PDFName('DeviceRGB'),PDFNum(255),$dict));
282 0           $dict->{Filter}=PDFArray(PDFName('FlateDecode'));
283 0           $tif->{fh}->seek($tif->{colorMapOffset},0);
284 0           my $colormap;
285             my $straight;
286 0           $tif->{fh}->read($colormap,$tif->{colorMapLength});
287 0           $dict->{' stream'}='';
288 0           map { $straight.=pack('C',($_/256)) } unpack($tif->{short}.'*',$colormap);
  0            
289 0           foreach my $c (0..(($tif->{colorMapSamples}/3)-1))
290             {
291 0           $dict->{' stream'}.=substr($straight,$c,1);
292 0           $dict->{' stream'}.=substr($straight,$c+($tif->{colorMapSamples}/3),1);
293 0           $dict->{' stream'}.=substr($straight,$c+($tif->{colorMapSamples}/3)*2,1);
294             }
295             }
296             else
297             {
298 0           $self->colorspace($tif->{colorSpace});
299             }
300            
301 0           $self->{Interpolate}=PDFBool(1);
302 0           $self->bpc($tif->{bitsPerSample});
303            
304 0 0 0       if($tif->{whiteIsZero}==1 && $tif->{filter} ne 'CCITTFaxDecode')
305             {
306 0           $self->{Decode}=PDFArray(PDFNum(1),PDFNum(0));
307             }
308            
309             # check filters and handle seperately
310 0 0         if($tif->{filter} eq 'CCITTFaxDecode')
    0          
    0          
311             {
312 0           $self->handle_ccitt($pdf,$tif);
313             }
314             elsif($tif->{filter} eq 'LZWDecode')
315             {
316 0           $self->handle_lzw($pdf,$tif);
317             }
318             elsif($tif->{filter} eq 'FlateDecode')
319             {
320 0           $self->handle_flate($pdf,$tif);
321             }
322             else
323             {
324 0           $self->handle_generic($pdf,$tif);
325             }
326            
327 0 0         if($tif->{fillOrder}==2)
328             {
329 0           my @bl=();
330 0           foreach my $n (0..255)
331             {
332 0           my $b=$n;
333 0           my $f=0;
334 0           foreach (0..7)
335             {
336 0           my $bit=0;
337 0 0         if($b &0x1)
338             {
339 0           $bit=1;
340             }
341 0           $b>>=1;
342 0           $f<<=1;
343 0           $f|=$bit;
344             }
345 0           $bl[$n]=$f;
346             }
347 0           my $l=length($self->{' stream'})-1;
348 0           foreach my $n (0..$l)
349             {
350 0           vec($self->{' stream'},$n,8)=$bl[vec($self->{' stream'},$n,8)];
351             }
352             }
353 0           $self->{' tiff'}=$tif;
354            
355 0           return($self);
356             }
357            
358             =item $value = $tif->tiffTag $tag
359            
360             returns the value of the internal tiff-tag.
361            
362             B
363            
364             imageDescription, imageId (strings)
365             xRes, yRes (dpi; pixel/cm if resUnit==3)
366             resUnit
367            
368             =cut
369            
370             sub tiffTag {
371 0     0 1   my $self=shift @_;
372 0           my $tag=shift @_;
373 0           return($self->{' tiff'}->{$tag});
374             }
375            
376             package TiffFile;
377            
378 1     1   13 use IO::File;
  1         2  
  1         1947  
379            
380             sub new {
381 0     0     my $class=shift @_;
382 0           my $file=shift @_;
383 0           my $self={};
384 0           bless($self,$class);
385 0 0         if(ref($file)) {
386 0           $self->{fh} = $file;
387 0           seek($self->{fh},0,0);
388             } else {
389 0           $self->{fh} = IO::File->new;
390 0           open($self->{fh},"< $file");
391             }
392 0           binmode($self->{fh},':raw');
393 0           my $fh = $self->{fh};
394            
395 0           $self->{offset}=0;
396 0           $fh->seek( $self->{offset}, 0 );
397            
398             # checking byte order of data
399 0           $fh->read( $self->{byteOrder}, 2 );
400 0           $self->{byte}='C';
401 0 0         $self->{short}=(($self->{byteOrder} eq 'MM') ? 'n' : 'v' );
402 0 0         $self->{long}=(($self->{byteOrder} eq 'MM') ? 'N' : 'V' );
403 0 0         $self->{rational}=(($self->{byteOrder} eq 'MM') ? 'NN' : 'VV' );;
404            
405             # get/check version id
406 0           $fh->read( $self->{version}, 2 );
407 0           $self->{version}=unpack($self->{short},$self->{version});
408 0 0         die "Wrong TIFF Id '$self->{version}' (should be 42)." if($self->{version} != 42);
409            
410             # get the offset to the first tag directory.
411 0           $fh->read( $self->{ifdOffset}, 4 );
412 0           $self->{ifdOffset}=unpack($self->{long},$self->{ifdOffset});
413            
414 0           $self->readTags;
415            
416 0           return($self);
417             }
418            
419             sub readTag {
420 0     0     my $self = shift @_;
421 0           my $fh = $self->{fh};
422 0           my $buf;
423 0           $fh->read( $buf, 12 );
424 0           my $tag = unpack($self->{short}, substr($buf, 0, 2 ) );
425 0           my $type = unpack($self->{short}, substr($buf, 2, 2 ) );
426 0           my $count = unpack($self->{long}, substr($buf, 4, 4 ) );
427 0           my $len=0;
428            
429 0 0         if($type==1) {
    0          
    0          
    0          
    0          
430             # byte
431 0           $len=$count;
432             } elsif($type==2) {
433             # charZ
434 0           $len=$count;
435             } elsif($type==3) {
436             # int16
437 0           $len=$count*2;
438             } elsif($type==4) {
439             # int32
440 0           $len=$count*4;
441             } elsif($type==5) {
442             # rational: 2 * int32
443 0           $len=$count*8;
444             } else {
445 0           $len=$count;
446             }
447            
448 0           my $off = substr($buf, 8, 4 );
449            
450 0 0         if($len>4) {
451 0           $off=unpack($self->{long},$off);
452             } else {
453 0 0         if($type==1) {
    0          
    0          
    0          
454 0           $off=unpack($self->{byte},$off);
455             } elsif($type==2) {
456 0           $off=unpack($self->{long},$off);
457             } elsif($type==3) {
458 0           $off=unpack($self->{short},$off);
459             } elsif($type==4) {
460 0           $off=unpack($self->{long},$off);
461             } else {
462 0           $off=unpack($self->{short},$off);
463             }
464             }
465            
466 0           return ($tag,$type,$count,$len,$off);
467             }
468            
469             sub close {
470 0     0     my $self = shift @_;
471 0           my $fh = $self->{fh};
472 0           $fh->close;
473             # %{$self}=();
474             }
475            
476             sub readTags {
477 0     0     my $self = shift @_;
478 0           my $fh = $self->{fh};
479 0           $self->{fillOrder}=1;
480 0           $self->{ifd}=$self->{ifdOffset};
481            
482 0           while($self->{ifd} > 0) {
483 0           $fh->seek( $self->{ifd}, 0 );
484 0           $fh->read( $self->{ifdNum}, 2 );
485 0           $self->{ifdNum}=unpack($self->{short},$self->{ifdNum});
486 0           $self->{bitsPerSample}=1;
487 0           foreach (1..$self->{ifdNum}) {
488 0           my ($valTag,$valType,$valCount,$valLen,$valOffset)=$self->readTag;
489             # print "tag=$valTag type=$valType count=$valCount len=$valLen off=$valOffset\n";
490 0 0         if($valTag==0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
491             } elsif($valTag==256) {
492             # imagewidth
493 0           $self->{imageWidth}=$valOffset;
494             } elsif($valTag==257) {
495             # imageheight
496 0           $self->{imageHeight}=$valOffset;
497             } elsif($valTag==258) {
498             # bits per sample
499 0 0         if($valCount>1) {
500 0           my $here=$fh->tell;
501 0           my $val;
502 0           $fh->seek($valOffset,0);
503 0           $fh->read($val,2);
504 0           $self->{bitsPerSample}=unpack($self->{short},$val);
505 0           $fh->seek($here,0);
506             } else {
507 0           $self->{bitsPerSample}=$valOffset;
508             }
509             } elsif($valTag==259) {
510             # compression
511 0           $self->{filter}=$valOffset;
512 0 0 0       if($valOffset==1) {
    0 0        
    0 0        
    0          
    0          
    0          
513 0           delete $self->{filter};
514             } elsif($valOffset==3 || $valOffset==4) {
515 0           $self->{filter}='CCITTFaxDecode';
516 0           $self->{ccitt}=$valOffset;
517             } elsif($valOffset==5) {
518 0           $self->{filter}='LZWDecode';
519             } elsif($valOffset==6 || $valOffset==7) {
520 0           $self->{filter}='DCTDecode';
521             } elsif($valOffset==8 || $valOffset==0x80b2) {
522 0           $self->{filter}='FlateDecode';
523             } elsif($valOffset==32773) {
524 0           $self->{filter}='RunLengthDecode';
525             } else {
526 0           die "unknown/unsupported TIFF compression method with id '$self->{filter}'.";
527             }
528             } elsif($valTag==262) {
529             # photometric interpretation
530 0           $self->{colorSpace}=$valOffset;
531 0 0         if($valOffset==0) {
    0          
    0          
    0          
    0          
    0          
    0          
532 0           $self->{colorSpace}='DeviceGray';
533 0           $self->{whiteIsZero}=1;
534             } elsif($valOffset==1) {
535 0           $self->{colorSpace}='DeviceGray';
536 0           $self->{blackIsZero}=1;
537             } elsif($valOffset==2) {
538 0           $self->{colorSpace}='DeviceRGB';
539             } elsif($valOffset==3) {
540 0           $self->{colorSpace}='Indexed';
541             # } elsif($valOffset==4) {
542             # $self->{colorSpace}='TransMask';
543             } elsif($valOffset==5) {
544 0           $self->{colorSpace}='DeviceCMYK';
545             } elsif($valOffset==6) {
546 0           $self->{colorSpace}='DeviceRGB';
547             } elsif($valOffset==8) {
548 0           $self->{colorSpace}='Lab';
549             } else {
550 0           die "unknown/unsupported TIFF photometric interpretation with id '$self->{colorSpace}'.";
551             }
552             } elsif($valTag==266) {
553 0           $self->{fillOrder}=$valOffset;
554             } elsif($valTag==270) {
555             # ImageDescription
556 0           my $here=$fh->tell;
557 0           $fh->seek($valOffset,0);
558 0           $fh->read($self->{imageDescription},$valLen);
559 0           $fh->seek($here,0);
560             } elsif($valTag==282) {
561             # xRes
562 0           my $here=$fh->tell;
563 0           $fh->seek($valOffset,0);
564 0           $fh->read($self->{xRes},$valLen);
565 0           $fh->seek($here,0);
566 0           $self->{xRes}=[unpack($self->{rational},$self->{xRes})];
567 0           $self->{xRes}=($self->{xRes}->[0]/$self->{xRes}->[1]);
568             } elsif($valTag==283) {
569             # yRes
570 0           my $here=$fh->tell;
571 0           $fh->seek($valOffset,0);
572 0           $fh->read($self->{yRes},$valLen);
573 0           $fh->seek($here,0);
574 0           $self->{yRes}=[unpack($self->{rational},$self->{yRes})];
575 0           $self->{yRes}=($self->{yRes}->[0]/$self->{yRes}->[1]);
576             } elsif($valTag==296) {
577             # resolution Unit
578 0           $self->{resUnit}=$valOffset;
579             } elsif($valTag==273) {
580             # image data offset/strip offsets
581 0 0         if($valCount==1) {
582 0           $self->{imageOffset}=$valOffset;
583             } else {
584 0           my $here=$fh->tell;
585 0           my $val;
586 0           $fh->seek($valOffset,0);
587 0           $fh->read($val,$valLen);
588 0           $fh->seek($here,0);
589 0           $self->{imageOffset}=[ unpack($self->{long}.'*',$val) ];
590             }
591             } elsif($valTag==277) {
592             # samples per pixel
593 0           $self->{samplesPerPixel}=$valOffset;
594             } elsif($valTag==279) {
595             # image data length/strip lengths
596 0 0         if($valCount==1) {
597 0           $self->{imageLength}=$valOffset;
598             } else {
599 0           my $here=$fh->tell;
600 0           my $val;
601 0           $fh->seek($valOffset,0);
602 0           $fh->read($val,$valLen);
603 0           $fh->seek($here,0);
604 0           $self->{imageLength}=[ unpack($self->{long}.'*',$val) ];
605             }
606             } elsif($valTag==292) {
607 0           $self->{g3Options}=$valOffset;
608             } elsif($valTag==293) {
609 0           $self->{g4Options}=$valOffset;
610             } elsif($valTag==320) {
611             # color map
612 0           $self->{colorMapOffset}=$valOffset;
613 0           $self->{colorMapSamples}=$valCount;
614 0           $self->{colorMapLength}=$valCount*2; # shorts!
615             } elsif($valTag==317) {
616             # lzwPredictor
617 0           $self->{lzwPredictor}=$valOffset;
618             } elsif($valTag==0x800d) {
619             # imageID
620 0           my $here=$fh->tell;
621 0           $fh->seek($valOffset,0);
622 0           $fh->read($self->{imageId},$valLen);
623 0           $fh->seek($here,0);
624             # } elsif($valTag==) {
625             # } elsif($valTag==) {
626             # } elsif($valTag==) {
627             # } elsif($valTag==) {
628             # } else {
629             # print "tag=$valTag, type=$valType, len=$valLen\n";
630             }
631             }
632 0           $fh->read( $self->{ifd}, 4 );
633 0           $self->{ifd}=unpack($self->{long},$self->{ifd});
634             }
635             }
636            
637             1;
638            
639             __END__