File Coverage

blib/lib/PDF/API3/Compat/API2/Resource/XObject/Image/GIF.pm
Criterion Covered Total %
statement 20 160 12.5
branch 0 34 0.0
condition 0 12 0.0
subroutine 7 11 63.6
pod 2 4 50.0
total 29 221 13.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: GIF.pm,v 2.0 2005/11/16 02:18:23 areibens Exp $
31             #
32             #=======================================================================
33            
34             package PDF::API3::Compat::API2::Resource::XObject::Image::GIF;
35            
36             BEGIN {
37            
38 1     1   7 use PDF::API3::Compat::API2::Util;
  1         3  
  1         229  
39 1     1   6 use PDF::API3::Compat::API2::Basic::PDF::Utils;
  1         3  
  1         171  
40 1     1   6 use PDF::API3::Compat::API2::Resource::XObject::Image;
  1         3  
  1         25  
41            
42 1     1   6 use POSIX;
  1         2  
  1         18  
43            
44 1     1   3156 use vars qw(@ISA $VERSION);
  1         2  
  1         160  
45 1     1   28 @ISA = qw( PDF::API3::Compat::API2::Resource::XObject::Image );
46            
47 1         37 ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 2.0 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2005/11/16 02:18:23 $
48            
49             }
50 1     1   8 no warnings qw[ deprecated recursion uninitialized ];
  1         3  
  1         1571  
51            
52             =item $res = PDF::API3::Compat::API2::Resource::XObject::Image::GIF->new $pdf, $file [, $name]
53            
54             Returns a gif-image object.
55            
56             =cut
57            
58             # added from PDF::Create:
59             # PDF::Image::GIFImage - GIF image support
60             # Author: Michael Gross
61             # modified for internal use. (c) 2004 fredo.
62             sub unInterlace {
63 0     0 0   my $self = shift;
64 0           my $data = $self->{' stream'};
65 0           my $row;
66             my @result;
67 0           my $width = $self->width;
68 0           my $height = $self->height;
69 0           my $idx = 0;
70            
71             #Pass 1 - every 8th row, starting with row 0
72 0           $row = 0;
73 0           while ($row < $height) {
74 0           $result[$row] = substr($data, $idx*$width, $width);
75 0           $row+=8;
76 0           $idx++;
77             }
78            
79             #Pass 2 - every 8th row, starting with row 4
80 0           $row = 4;
81 0           while ($row < $height) {
82 0           $result[$row] = substr($data, $idx*$width, $width);
83 0           $row+=8;
84 0           $idx++;
85             }
86            
87             #Pass 3 - every 4th row, starting with row 2
88 0           $row = 2;
89 0           while ($row < $height) {
90 0           $result[$row] = substr($data, $idx*$width, $width);
91 0           $row+=4;
92 0           $idx++;
93             }
94            
95             #Pass 4 - every 2th row, starting with row 1
96 0           $row = 1;
97 0           while ($row < $height) {
98 0           $result[$row] = substr($data, $idx*$width, $width);
99 0           $row+=2;
100 0           $idx++;
101             }
102            
103 0           $self->{' stream'}=join('', @result);
104             }
105            
106             sub deGIF {
107 0     0 0   my ($ibits,$stream)=@_;
108 0           my $bits=$ibits;
109 0           my $resetcode=1<<($ibits-1);
110 0           my $endcode=$resetcode+1;
111 0           my $nextcode=$endcode+1;
112 0           my $ptr=0;
113 0           my $maxptr=8*length($stream);
114 0           my $tag;
115 0           my $out='';
116 0           my $outptr=0;
117            
118             # print STDERR "reset=$resetcode\nend=$endcode\nmax=$maxptr\n";
119            
120 0           my @d=map { chr($_) } (0..$resetcode-1);
  0            
121            
122 0           while(($ptr+$bits)<=$maxptr) {
123 0           $tag=0;
124 0           foreach my $off (reverse 0..$bits-1) {
125 0           $tag<<=1;
126 0           $tag|=vec($stream,$ptr+$off,1);
127             }
128             # foreach my $off (0..$bits-1) {
129             # $tag<<=1;
130             # $tag|=vec($stream,$ptr+$off,1);
131             # }
132             # print STDERR "ptr=$ptr,tag=$tag,bits=$bits,next=$nextcode\n";
133             # print STDERR "tag to large\n" if($tag>$nextcode);
134 0           $ptr+=$bits;
135 0 0         $bits++ if($nextcode == (1<<$bits));
136 0 0         if($tag==$resetcode) {
    0          
    0          
    0          
137 0           $bits=$ibits;
138 0           $nextcode=$endcode+1;
139 0           next;
140             } elsif($tag==$endcode) {
141 0           last;
142             } elsif($tag<$resetcode) {
143 0           $d[$nextcode]=$d[$tag];
144 0           $out.=$d[$nextcode];
145 0           $nextcode++;
146             } elsif($tag>$endcode) {
147 0           $d[$nextcode]=$d[$tag];
148 0           $d[$nextcode].=substr($d[$tag+1],0,1);
149 0           $out.=$d[$nextcode];
150 0           $nextcode++;
151             }
152             }
153 0           return($out);
154             }
155            
156             sub new {
157 0     0 1   my ($class,$pdf,$file,$name,%opts) = @_;
158 0           my $self;
159 0           my $inter=0;
160            
161 0 0         $class = ref $class if ref $class;
162            
163 0   0       $self=$class->SUPER::new($pdf,$name || 'Gx'.pdfkey());
164 0 0         $pdf->new_obj($self) unless($self->is_obj($pdf));
165            
166 0           $self->{' apipdf'}=$pdf;
167            
168 0           my $fh = IO::File->new;
169 0           open($fh,$file);
170 0           binmode($fh,':raw');
171 0           my $buf;
172 0           $fh->read($buf,6); # signature
173 0 0         die "unknown image signature '$buf' -- not a gif." unless($buf=~/^GIF[0-9][0-9][a-b]/);
174            
175 0           $fh->read($buf,7); # logical descr.
176 0           my($wg,$hg,$flags,$bgColorIndex,$aspect)=unpack('vvCCC',$buf);
177            
178 0 0         if($flags&0x80) {
179 0           my $colSize=2**(($flags&0x7)+1);
180 0           my $dict=PDFDict();
181 0           $pdf->new_obj($dict);
182 0           $self->colorspace(PDFArray(PDFName('Indexed'),PDFName('DeviceRGB'),PDFNum($colSize-1),$dict));
183 0           $fh->read($dict->{' stream'},3*$colSize); # color-table
184             }
185            
186 0           while(!$fh->eof) {
187 0           $fh->read($buf,1); # tag.
188 0           my $sep=unpack('C',$buf);
189 0 0         if($sep==0x2C){
    0          
    0          
190 0           $fh->read($buf,9); # image-descr.
191 0           my ($left,$top,$w,$h,$flags)=unpack('vvvvC',$buf);
192            
193 0   0       $self->width($w||$wg);
194 0   0       $self->height($h||$hg);
195 0           $self->bpc(8);
196            
197 0 0         if($flags&0x80) { # local colormap
198 0           my $colSize=2**(($flags&0x7)+1);
199 0           my $dict=PDFDict();
200 0           $pdf->new_obj($dict);
201 0           $self->colorspace(PDFArray(PDFName('Indexed'),PDFName('DeviceRGB'),PDFNum($colSize-1),$dict));
202 0           $fh->read($dict->{' stream'},3*$colSize); # color-table
203             }
204 0 0         if($flags&0x40) { # need de-interlace
205 0           $inter=1;
206             }
207            
208 0           $fh->read($buf,1); # image-lzw-start (should be 9).
209 0           my ($sep)=unpack('C',$buf);
210            
211 0           $fh->read($buf,1); # first chunk.
212 0           my ($len)=unpack('C',$buf);
213 0           my $stream='';
214 0           while($len>0) {
215 0           $fh->read($buf,$len);
216 0           $stream.=$buf;
217 0           $fh->read($buf,1);
218 0           $len=unpack('C',$buf);
219             }
220 0           $self->{' stream'}=deGIF($sep+1,$stream);
221 0 0         $self->unInterlace if($inter);
222 0           last;
223             } elsif($sep==0x3b) {
224 0           last;
225             } elsif($sep==0x21) {
226             # Graphic Control Extension
227 0           $fh->read($buf,1); # tag.
228 0           my $tag=unpack('C',$buf);
229 0 0         die "unsupported graphic control extension ($tag)" unless($tag==0xF9);
230 0           $fh->read($buf,1); # len.
231 0           my $len=unpack('C',$buf);
232 0           my $stream='';
233 0           while($len>0) {
234 0           $fh->read($buf,$len);
235 0           $stream.=$buf;
236 0           $fh->read($buf,1);
237 0           $len=unpack('C',$buf);
238             }
239 0           my ($cFlags,$delay,$transIndex)=unpack('CvC',$stream);
240 0 0 0       if(($cFlags&0x01) && !$opts{-notrans}) {
241 0           $self->{Mask}=PDFArray(PDFNum($transIndex),PDFNum($transIndex));
242             }
243             } else {
244             # extension
245 0           $fh->read($buf,1); # tag.
246 0           my $tag=unpack('C',$buf);
247 0           $fh->read($buf,1); # tag.
248 0           my $len=unpack('C',$buf);
249 0           while($len>0) {
250 0           $fh->read($buf,$len);
251 0           $fh->read($buf,1);
252 0           $len=unpack('C',$buf);
253             }
254             }
255             }
256 0           $fh->close;
257            
258 0           $self->filters('FlateDecode');
259            
260 0           return($self);
261             }
262            
263             =item $res = PDF::API3::Compat::API2::Resource::XObject::Image::GIF->new_api $api, $file [, $name]
264            
265             Returns a gif-image object. This method is different from 'new' that
266             it needs an PDF::API3::Compat::API2-object rather than a Text::PDF::File-object.
267            
268             =cut
269            
270             sub new_api {
271 0     0 1   my ($class,$api,@opts)=@_;
272            
273 0           my $obj=$class->new($api->{pdf},@opts);
274 0           $obj->{' api'}=$api;
275            
276 0           return($obj);
277             }
278            
279             1;
280            
281             __END__