File Coverage

blib/lib/App/PNGCrush.pm
Criterion Covered Total %
statement 24 70 34.2
branch 1 26 3.8
condition 0 6 0.0
subroutine 7 12 58.3
pod 4 4 100.0
total 36 118 30.5


line stmt bran cond sub pod time code
1             package App::PNGCrush;
2              
3 1     1   63518 use warnings;
  1         4  
  1         35  
4 1     1   5 use strict;
  1         2  
  1         48  
5              
6             our $VERSION = '0.002';
7              
8 1     1   5 use Carp;
  1         6  
  1         67  
9 1     1   14 use Proc::Reliable;
  1         2  
  1         35  
10 1     1   6 use Devel::TakeHashArgs;
  1         1  
  1         47  
11 1     1   6 use base 'Class::Data::Accessor';
  1         2  
  1         2548  
12              
13             my %Valid_Options = qw(
14             already_size -already
15             bit_depth -bit_depth
16             background -bkgd
17             brute_force -brute
18             color_type -c
19             color_counting -cc
20             output_dir -d
21             double_image_gamma -dou
22             output_extension -e
23             filter -f
24             fix_fatal -fix
25             output_force -force
26             gamma -g
27             itxt -itxt
28             level -l
29             method -m
30             maximum_idat -max
31             no_output -n
32             no_color_counting -no_cc
33             plte_length -plte_len
34             remove -rem
35             replace_gamma -replace_gamma
36             resolution -res
37             save_unknown -save
38             srgb -srgb
39             text -text
40             transparency -trns
41             window_size -w
42             strategy -z
43             insert_ztxt -zitxt
44             ztxt -ztxt
45             verbose -v
46             );
47              
48             my %No_Arg_Options = map { $_ => 1 } qw(
49             brute_force
50             color_counting
51             double_image_gamma
52             fix_fatal
53             output_force
54             no_output
55             no_color_counting
56             save_unknown
57             verbose
58             );
59              
60             __PACKAGE__->mk_classaccessors (
61             qw( proc error results ),
62             keys %Valid_Options
63             );
64              
65             sub new {
66 1     1 1 318 my $self = bless {}, shift;
67 1 50       12 get_args_as_hash( \@_, \my %args, { maxtime => 300 } )
68             or croak $@;
69              
70 1         33 my $proc = Proc::Reliable->new;
71              
72 1         131 $proc->$_( $args{$_} ) for keys %args;
73              
74 1         27 $self->proc( $proc );
75              
76 1         19 return $self;
77             }
78              
79             sub run {
80 0     0 1   my $self = shift;
81 0           my $in = shift;
82              
83 0 0         get_args_as_hash( \@_, \ my %args, { in => $in }, )
84             or croak $@;
85              
86 0           $self->$_(undef) for qw(error results);
87              
88 0           my @options = exists $args{opts}
89 0 0         ? @{ $args{opts} }
90             : $self->_make_options;
91              
92 0           my $proc = $self->proc;
93 0           my %out;
94 0           @out{ qw(stdout stderr status msg) }
95             = $proc->run( [ 'pngcrush', @options, $in ] );
96              
97 0 0         return $self->_set_error("Proc::Reliable error: $out{error}")
98             if defined $out{error};
99              
100 0 0         return $self->_set_error("File $in does not seem to exist")
101             if $out{stdout} =~ /Could not find file: \Q$in/;
102              
103 0           @out{ qw(idat size) } = $out{stdout}
104             =~ /\(([\d.]+)% IDAT reduction\).+?\(([\d.]+)% filesize reduction\)/s;
105              
106 0 0 0       $out{idat} = 0
107             if not defined $out{idat}
108             and $out{stdout} =~ /\Q(no IDAT change)/;
109              
110 0 0 0       $out{size} = 0
111             if not defined $out{size}
112             and $out{stdout} =~ /\Q(no filesize change)/;
113              
114 0           @{ $out{cpu} }{ qw(total decoding encoding other) } = $out{stdout}
  0            
115             =~ /CPU \s time \s used \s = \s ([\d.]+) \s seconds \s
116             \(decoding \s ([\d.]+), \s+
117             encoding \s ([\d.]+), \s other \s ([\d.]+) \s seconds\)
118             /x;
119              
120 0           ( $out{total_idat_length} ) = $out{stdout}
121             =~ /Total length of data found in IDAT chunks\s+=\s+([\d.]+)/;
122              
123 0           return $self->results( \%out );
124             }
125              
126             sub set_options {
127 0     0 1   my $self = shift;
128 0 0         get_args_as_hash( \@_, \my %args, {}, [], [ %Valid_Options ] )
129             or croak $@;
130              
131 0           $self->reset_options;
132              
133 0           keys %args;
134 0           my %shell_args = reverse %Valid_Options;
135 0           while ( my ( $key, $value ) = each %args ) {
136 0 0         $key = $shell_args{$key}
137             unless exists $Valid_Options{$key};
138              
139 0           $self->$key( $value );
140             }
141              
142 0           return 1;
143             }
144              
145             sub reset_options {
146 0     0 1   my $self = shift;
147              
148 0           $self->$_(undef) for keys %Valid_Options;
149              
150 0           return 1;
151             }
152              
153             sub _make_options {
154 0     0     my $self = shift;
155              
156 0           my @options;
157 0           for my $opt ( keys %Valid_Options ) {
158 0           my $value = $self->$opt;
159             next
160 0 0         unless defined $value;
161              
162 0 0         if ( ref $value eq 'ARRAY' ) {
163 0 0         if ( $opt eq 'verbose' ) {
164 0           push @options, ('-v') x @$value;
165 0           next;
166             }
167 0           push @options, map { $Valid_Options{$opt} => $_ } @$value;
  0            
168             }
169             else {
170 0 0         push @options, $Valid_Options{$opt},
171             exists $No_Arg_Options{$opt} ? () : $value;
172             }
173             }
174 0           return @options;
175             }
176              
177             sub _set_error {
178 0     0     my ( $self, $error ) = @_;
179 0           $self->error($error);
180 0           return;
181             }
182              
183             1;
184             __END__