File Coverage

lib/Image/Info.pm
Criterion Covered Total %
statement 94 106 88.6
branch 59 78 75.6
condition 7 11 63.6
subroutine 16 16 100.0
pod 5 5 100.0
total 181 216 83.8


line stmt bran cond sub pod time code
1              
2             #############################################################################
3             #
4             # ATTENTION! This file is autogenerated from dev/Info.pm.tmpl - DO NOT EDIT!
5             #
6             #############################################################################
7              
8             package Image::Info;
9              
10             # Copyright 1999-2004, Gisle Aas.
11             #
12             # This library is free software; you can redistribute it and/or
13             # modify it under the same terms as Perl v5.8.8 itself.
14             #
15             # Previously maintained by Tels - (c) 2006 - 2008.
16             # Currently maintained by Slaven Rezic - (c) 2008 - 2022.
17              
18 20     20   1918899 use strict;
  20         247  
  20         653  
19 20     20   122 use vars qw($VERSION @EXPORT_OK);
  20         30  
  20         6257  
20              
21             $VERSION = '1.43';
22              
23             require Exporter;
24             *import = \&Exporter::import;
25              
26             @EXPORT_OK = qw(image_info dim html_dim image_type determine_file_format);
27              
28             # already required and failed sub-modules are remembered here
29             my %mod_failure;
30              
31             sub image_info
32             {
33 77     77 1 123604 my $source = _source(shift);
34 77 100       281 return $source if ref $source eq 'HASH'; # Pass on errors
35              
36             # What sort of file is it?
37 76         182 my $head = _head($source);
38              
39 76 50       219 return $head if ref($head) eq 'HASH'; # error?
40              
41 76 50       482 my $format = determine_file_format($head)
42             or return { error => 'Unrecognized file format' };
43              
44 76         212 return _image_info_for_format($format, $source);
45             }
46              
47             # Note: this function is private, but may be used by Image::Info::*
48             # implementations (i.e. the WBMP implementation)
49             sub _image_info_for_format
50             {
51 77     77   153 my($format, $source) = @_;
52              
53 77         187 my $mod = "Image::Info::$format";
54 77         133 my $sub = "$mod\::process_file";
55 77         377 my $info = bless [], "Image::Info::Result";
56 77         153 eval {
57 77 100       282 unless (defined &$sub) {
58             # already required and failed?
59 29 50       116 if (my $fail = $mod_failure{$mod}) {
60 0         0 die $fail;
61             }
62 29         1958 eval "require $mod";
63 29 50       183 if ($@) {
64 0         0 $mod_failure{$mod} = $@;
65 0         0 die $@;
66             }
67 29 50       182 die "$mod did not define &$sub" unless defined &$sub;
68             }
69              
70 77         251 my %cnf = @_;
71             {
72             # call process_file()
73 20     20   126 no strict 'refs';
  20         37  
  20         22272  
  77         111  
74 77         293 &$sub($info, $source, \%cnf);
75             }
76 76         437 $info->clean_up;
77             };
78 77 100       208 return { error => $@ } if $@;
79 76 100       1487 return wantarray ? @$info : $info->[0];
80             }
81              
82             sub image_type
83             {
84 2     2 1 1078 my $source = _source(shift);
85 2 100       8 return $source if ref $source eq 'HASH'; # Pass on errors
86              
87             # What sort of file is it?
88 1 50       3 my $head = _head($source) or return _os_err("Can't read head");
89 1 50       2 my $format = determine_file_format($head)
90             or return { error => "Unrecognized file format" };
91              
92 1         14 return { file_type => $format };
93             }
94              
95             # Note: this function is private, but may be used by Image::Info::*
96             # implementations (i.e. the WBMP implementation)
97             sub _source
98             {
99 80     80   167 my $source = shift;
100 80 100       288 if (!ref $source) {
    50          
101 55         78 my $fh;
102 55 50       185 if ($] < 5.006) {
103 0         0 require Symbol;
104 0         0 $fh = Symbol::gensym();
105 0 0       0 open($fh, $source) || return _os_err("Can't open $source");
106             }
107             else {
108 55 100       2846 open $fh, '<', $source
109             or return _os_err("Can't open $source");
110             }
111 53         138 ${*$fh} = $source; # keep filename in case somebody wants to know
  53         255  
112 53         184 binmode($fh);
113 53         95 $source = $fh;
114             }
115             elsif (ref($source) eq "SCALAR") {
116             # Earlier PerlIO::scalar versions may segfault or consume lots
117             # of memory for some invalid images, see
118             # RT #100847 and img/segfault.tif
119 25 50 33     59 if (eval { require PerlIO::scalar; PerlIO::scalar->VERSION(0.21) } ||
  25         1860  
  25         1738  
120 0         0 !eval { require IO::Scalar; 1 }) {
  0         0  
121 25 50       287 open(my $s, "<", $source) or return _os_err("Can't open string");
122 25         66 $source = $s;
123             }
124             else {
125 0         0 $source = IO::Scalar->new($source);
126             }
127             }
128             else {
129 0 0       0 seek($source, 0, 0) or return _os_err("Can't rewind");
130             }
131              
132 78         156 $source;
133             }
134              
135             sub _head
136             {
137 77     77   109 my $source = shift;
138 77         136 my $head;
139              
140             # Originally was 32 bytes.
141             # In the meantime lowered to 11 bytes.
142             # But XBM probably need more because of a leading comment.
143 77         108 my $to_read = 64;
144 77         1793 my $read = read($source, $head, $to_read);
145              
146 77 50       259 return _os_err("Couldn't read any bytes") if !$read;
147              
148 77 50       232 if (ref($source) eq "IO::String") {
149             # XXX workaround until we can trap seek() with a tied file handle
150 0         0 $source->setpos(0);
151             }
152             else {
153 77 50       675 seek($source, 0, 0) or return _os_err("Can't rewind");
154             }
155 77         212 $head;
156             }
157              
158             sub _os_err
159             {
160 2     2   29 return { error => "$_[0]: $!",
161             Errno => $!+0,
162             };
163             }
164              
165             sub determine_file_format
166             {
167 78     78 1 1233 local($_) = @_;
168 78 100       312 return "JPEG" if /^\xFF\xD8/;
169 61 100       194 return "PNG" if /^\x89PNG\x0d\x0a\x1a\x0a/;
170 53 100       187 return "GIF" if /^GIF8[79]a/;
171 44 100       115 return "TIFF" if /^MM\x00\x2a/;
172 43 100       131 return "TIFF" if /^II\x2a\x00/;
173 38 100       99 return "BMP" if /^BM/;
174 34 100       82 return "ICO" if /^\000\000\001\000/;
175 31 100       87 return "PPM" if /^P[1-6]/;
176 23 100       237 return "XPM" if /(^\/\* XPM \*\/)|(static\s+char\s+\*\w+\[\]\s*=\s*{\s*"\d+)/;
177 20 100       121 return "XBM" if /^(?:\/\*.*\*\/\n)?#define\s/;
178 15 100       74 return "SVG" if /^(<\?xml|[\012\015\t ]*
179 10 50       54 return "WEBP" if /^RIFF.{4}WEBP/s;
180 0         0 return undef;
181             }
182              
183             sub dim
184             {
185 18   50 18 1 33600 my $img = shift || return;
186 18   100     62 my $x = $img->{width} || return;
187 17   50     46 my $y = $img->{height} || return;
188 17 100       110 wantarray ? ($x, $y) : "${x}x$y";
189             }
190              
191             sub html_dim
192             {
193 2     2 1 4 my($x, $y) = dim(@_);
194 2 100       7 return "" unless $x;
195 1         9 "width=\"$x\" height=\"$y\"";
196             }
197              
198             #############################################################################
199             package Image::Info::Result;
200              
201             sub push_info
202             {
203 1961     1961   3075 my($self, $n, $key) = splice(@_, 0, 3);
204 1961         1665 push(@{$self->[$n]{$key}}, @_);
  1961         5660  
205             }
206              
207             sub replace_info
208             {
209 56     56   96 my($self, $n, $key) = splice(@_, 0, 3);
210 56         124 $self->[$n]{$key}[0] = $_[0];
211             }
212              
213             sub clean_up
214             {
215 76     76   120 my $self = shift;
216 76         161 for (@$self) {
217 99         531 for my $k (keys %$_) {
218 1717         1575 my $a = $_->{$k};
219 1717 100       3091 $_->{$k} = $a->[0] if @$a <= 1;
220             }
221             }
222             }
223              
224             sub get_info {
225 188     188   307 my($self, $n, $key, $delete) = @_;
226 188 100       344 my $v = $delete ? delete $self->[$n]{$key} : $self->[$n]{$key};
227 188   100     721 $v ||= [];
228 188         502 @$v;
229             }
230              
231             1;
232              
233             __END__