File Coverage

blib/lib/Image/ExifTool/PPM.pm
Criterion Covered Total %
statement 63 75 84.0
branch 24 54 44.4
condition n/a
subroutine 4 4 100.0
pod 0 1 0.0
total 91 134 67.9


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: PPM.pm
3             #
4             # Description: Read and write PPM meta information
5             #
6             # Revisions: 09/03/2005 - P. Harvey Created
7             #
8             # References: 1) http://netpbm.sourceforge.net/doc/ppm.html
9             # 2) http://netpbm.sourceforge.net/doc/pgm.html
10             # 3) http://netpbm.sourceforge.net/doc/pbm.html
11             #------------------------------------------------------------------------------
12              
13             package Image::ExifTool::PPM;
14              
15 1     1   4407 use strict;
  1         6  
  1         33  
16 1     1   5 use vars qw($VERSION);
  1         2  
  1         39  
17 1     1   6 use Image::ExifTool qw(:DataAccess :Utils);
  1         2  
  1         1028  
18              
19             $VERSION = '1.10';
20              
21             #------------------------------------------------------------------------------
22             # Read or write information in a PPM/PGM/PBM image
23             # Inputs: 0) ExifTool object reference, 1) Directory information reference
24             # Returns: 1 on success, 0 if this wasn't a valid PPM file, -1 on write error
25             sub ProcessPPM($$)
26             {
27 3     3 0 9 my ($et, $dirInfo) = @_;
28 3         8 my $raf = $$dirInfo{RAF};
29 3         6 my $outfile = $$dirInfo{OutFile};
30 3         12 my $verbose = $et->Options('Verbose');
31 3         12 my $out = $et->Options('TextOut');
32 3         8 my ($buff, $num, $type, %info);
33             #
34             # read as much of the image as necessary to extract the header and comments
35             #
36 3         5 for (;;) {
37 3 50       9 if (defined $buff) {
38             # need to read some more data
39 0         0 my $tmp;
40 0 0       0 return 0 unless $raf->Read($tmp, 1024);
41 0         0 $buff .= $tmp;
42             } else {
43 3 50       10 return 0 unless $raf->Read($buff, 1024);
44             }
45             # verify this is a valid PPM file
46 3 50       25 return 0 unless $buff =~ /^P([1-6])\s+/g;
47 3         9 $num = $1;
48             # note: may contain comments starting with '#'
49 3 50       15 if ($buff =~ /\G#/gc) {
50             # must read more if we are in the middle of a comment
51 3 50       18 next unless $buff =~ /\G ?(.*[\n\r]+(#.*[\n\r]+)*)\s*/g;
52 3         11 $info{Comment} = $1;
53 3 50       22 next if $buff =~ /\G#/gc;
54             } else {
55 0         0 delete $info{Comment};
56             }
57 3 50       13 next unless $buff =~ /\G(\S+)\s+(\S+)\s+/g;
58 3         10 $info{ImageWidth} = $1;
59 3         10 $info{ImageHeight} = $2;
60 3         19 $type = [qw{PPM PBM PGM}]->[$num % 3];
61 3 50       12 last if $type eq 'PBM'; # (no MaxVal for PBM images)
62 3 50       12 if ($buff =~ /\G\s*#/gc) {
63 0 0       0 next unless $buff =~ /\G ?(.*[\n\r]+(#.*[\n\r]+)*)\s*/g;
64 0 0       0 $info{Comment} = '' unless exists $info{Comment};
65 0         0 $info{Comment} .= $1;
66 0 0       0 next if $buff =~ /\G#/gc;
67             }
68 3 50       12 next unless $buff =~ /\G(\S+)\s/g;
69 3         9 $info{MaxVal} = $1;
70 3         7 last;
71             }
72             # validate numerical values
73 3         13 foreach (keys %info) {
74 12 100       28 next if $_ eq 'Comment';
75 9 50       38 return 0 unless $info{$_} =~ /^\d+$/;
76             }
77 3 50       13 if (defined $info{Comment}) {
78 3         8 $info{Comment} =~ s/^# ?//mg; # remove "# " at the start of each line
79 3         18 $info{Comment} =~ s/[\n\r]+$//; # remove trailing newline
80             }
81 3         18 $et->SetFileType($type);
82 3         7 my $len = pos($buff);
83             #
84             # rewrite the file if requested
85             #
86 3 100       11 if ($outfile) {
87 1         2 my $nvHash;
88 1         5 my $newComment = $et->GetNewValue('Comment', \$nvHash);
89 1         3 my $oldComment = $info{Comment};
90 1 50       10 if ($et->IsOverwriting($nvHash, $oldComment)) {
91 1         3 ++$$et{CHANGED};
92 1 50       9 $et->VerboseValue('- Comment', $oldComment) if defined $oldComment;
93 1 50       5 $et->VerboseValue('+ Comment', $newComment) if defined $newComment;
94             } else {
95 0         0 $newComment = $oldComment; # use existing comment
96             }
97 1         4 my $hdr = "P$num\n";
98 1 50       4 if (defined $newComment) {
99 1         3 $newComment =~ s/\n/\n# /g;
100 1         4 $hdr .= "# $newComment\n";
101             }
102 1         5 $hdr .= "$info{ImageWidth} $info{ImageHeight}\n";
103 1 50       6 $hdr .= "$info{MaxVal}\n" if $type ne 'PBM';
104             # write header and start of image
105 1 50       8 Write($outfile, $hdr, substr($buff, $len)) or return -1;
106             # copy over the rest of the image
107 1         11 while ($raf->Read($buff, 0x10000)) {
108 0 0       0 Write($outfile, $buff) or return -1;
109             }
110 1         8 return 1;
111             }
112             #
113             # save extracted information
114             #
115 2 50       9 if ($verbose > 2) {
116 0         0 print $out "$type header ($len bytes):\n";
117 0         0 $et->VerboseDump(\$buff, Len => $len);
118             }
119 2         4 my $tag;
120 2         5 foreach $tag (qw{Comment ImageWidth ImageHeight MaxVal}) {
121 8 50       34 $et->FoundTag($tag, $info{$tag}) if defined $info{$tag};
122             }
123 2         11 return 1;
124             }
125              
126             1; # end
127              
128             __END__