File Coverage

blib/lib/Image/DeAnim.pm
Criterion Covered Total %
statement 6 77 7.7
branch 0 26 0.0
condition 0 2 0.0
subroutine 2 7 28.5
pod 0 5 0.0
total 8 117 6.8


line stmt bran cond sub pod time code
1             package Image::DeAnim;
2              
3 1     1   1452 use strict;
  1         2  
  1         51  
4 1     1   5 use vars qw($VERSION @ISA @EXPORT_OK $gif_in $gif_out);
  1         2  
  1         1133  
5              
6             require Exporter;
7              
8             @ISA = qw(Exporter);
9             @EXPORT_OK = qw(gif);
10              
11             $VERSION = '0.02';
12              
13             sub gif {
14 0     0 0   my $nullstr = "";
15 0           my $nullstr_ref = \$nullstr;
16              
17 0   0       my $gif_in_ref = shift || return \$nullstr_ref;
18              
19 0           $gif_out = "";
20 0           $gif_in = $$gif_in_ref;
21            
22             # header
23 0           my $header = &safe_read(6);
24 0 0         unless ($header =~ /^GIF\d\d[a-z]/) {
25 0           warn "not a GIF header: $header";
26 0           return $nullstr_ref;
27             }
28 0           $gif_out .= "GIF89a";
29            
30             # logical screen description
31 0           my $ls_desc = &safe_read(7);
32 0           my ($ls_size, $ls_flag, $ls_misc) = unpack("A4 C A2", $ls_desc);
33 0           $gif_out .= $ls_desc;
34            
35 0 0         if ($ls_flag & 0x80) { # check for global color table
36 0           $gif_out .= &get_colormap($ls_flag & 0x07);
37             }
38            
39 0           my $data_block;
40            
41 0           while (1) {
42 0           my $ext_label;
43 0           my $block_label = &safe_read(1);
44            
45             # if we detect end of file marker, $gif_out .= last block and return
46 0 0         if ($block_label eq "\x3b") {
47 0           $gif_out .= $data_block . "\x3b";
48 0           return \$gif_out;
49             }
50            
51 0 0         if ($block_label eq "\x2c") { # found image descriptor
52 0           $data_block = "\x2c" . &get_image;
53 0           next;
54             }
55            
56 0 0         unless ($block_label eq "\x21") {
57 0           warn "Illegal block label found: " . ord($block_label);
58 0           return $nullstr_ref;
59             }
60            
61 0           $ext_label = &safe_read(1);
62 0 0         if ($ext_label eq "\xf9") { # graphic control; keep and then get image
63 0           $data_block = "\x21\xf9" . &safe_read(6);
64 0 0         unless (&safe_read(1) eq "\x2c") {
65 0           warn "graphic control extension not followed by image";
66 0           return $nullstr_ref;
67             }
68 0           $data_block .= "\x2c" . &get_image;
69 0           next;
70             }
71            
72 0 0         if ($ext_label eq "\xff") { # application extension; skip
    0          
    0          
73 0           &safe_read(12);
74 0           &get_data_block;
75             } elsif ($ext_label eq "\xfe") { # comment extension; skip
76 0           &get_data_block;
77             } elsif ($ext_label eq "\x01") { # plain text extension; skip
78 0           &safe_read(13);
79 0           &get_data_block;
80             } else {
81 0           warn "Illegal extension label found: " . ord($ext_label);
82 0           return $nullstr_ref;
83             }
84             }
85            
86 0           warn "exit abnormally";
87 0           return $nullstr_ref;
88             }
89             ##########################################################################
90            
91             sub safe_read {
92             # read from $fh_in with error checking.
93 0     0 0   my $len = shift;
94 0           my $buf;
95              
96 0 0         unless (length($gif_in) >= $len) {
97 0           die "read error: unsafe read";
98             }
99              
100 0           ($buf, $gif_in) = unpack("a$len a*", $gif_in);
101            
102 0           return $buf;
103             }
104            
105             sub get_data_block {
106 0     0 0   my ($byte, $size);
107 0           my $block = "";
108            
109 0           do {
110 0           $byte = &safe_read(1);
111 0           $size = ord($byte);
112            
113 0 0         if ($size) {
114 0           $block .= $byte . &safe_read($size);
115             }
116             } while ($size);
117            
118 0           return $block . "\x00";
119             }
120            
121             sub get_colormap {
122 0     0 0   my $size = shift;
123            
124 0           my $bytes = 3 * 2**($size+1);
125 0           return &safe_read($bytes);
126             }
127            
128             sub get_image {
129 0     0 0   my $id_bytes = &safe_read(9);
130 0           my $block = $id_bytes;
131            
132 0           my ($id_info, $id_flag) = unpack("A8 C", $id_bytes);
133 0 0         if ($id_flag & 0x80) {
134 0           $block .= &get_colormap($id_flag & 0x07);
135             }
136            
137 0           $block .= &safe_read(1); # LZW minimum code size
138 0           $block .= &get_data_block;
139            
140 0           return $block;
141             }
142              
143             1;
144             __END__