File Coverage

blib/lib/Email/Barcode/Decode.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package Email::Barcode::Decode;
2              
3 1     1   47003 use warnings;
  1         1  
  1         24  
4 1     1   3 use strict;
  1         1  
  1         15  
5              
6 1     1   2 use Carp 'croak';
  1         4  
  1         34  
7 1     1   477 use Email::MIME;
  1         39545  
  1         27  
8 1     1   6 use File::Temp qw(tempdir);
  1         1  
  1         59  
9 1     1   423 use File::Find::Rule;
  1         5949  
  1         7  
10 1     1   39 use Path::Class qw(file);
  1         1  
  1         42  
11 1     1   187 use Image::Magick;
  0            
  0            
12             use Barcode::ZBar;
13             use Cwd 'getcwd';
14             use Capture::Tiny 'capture';
15             use File::Which qw(which);
16              
17             our $VERSION = '0.04';
18              
19             use base 'Class::Accessor::Fast';
20              
21             __PACKAGE__->mk_accessors(qw{
22             email
23             header_obj
24             attached_files
25             _tmpdir
26             });
27              
28             our @enhancers = (
29             sub {
30             my ($magick) = @_;
31             $magick->Normalize();
32             $magick->Contrast(sharpen => 1);
33              
34             my ($width,$height) = $magick->Get(qw(columns rows));
35             $magick->Resize(height=>1500,width=>int($width*(1500/$height)))
36             if $height > 1500;
37              
38             my $raw = $magick->ImageToBlob(
39             magick => 'YUV',
40             'sampling-factor' => '4:2:2',
41             interlace => 'Plane'
42             );
43              
44             return ($raw,'Y800');
45             },
46             sub {
47             my ($magick) = @_;
48             $magick->Set(dither => 'False');
49             $magick->Quantize(colors => 2);
50             $magick->Quantize(colorspace => 'gray');
51             $magick->ContrastStretch(levels => 0);
52              
53             my ($width,$height) = $magick->Get(qw(columns rows));
54             $magick->Resize(height=>1500,width=>int($width*(1500/$height)))
55             if $height > 1500;
56              
57             my $raw = $magick->ImageToBlob(magick => 'GRAY', depth => 8);
58              
59             return ($raw,'Y800');
60             },
61             );
62              
63             sub new {
64             my ($class, %opts) = @_;
65              
66             my $email = $opts{email};
67             croak 'need email string as argument'
68             unless $email;
69              
70             my $tmpdir = tempdir( CLEANUP => 1 );
71             $opts{_tmpdir} = $tmpdir;
72              
73             my @attached_files;
74             my $parsed = Email::MIME->new($email);
75             $opts{header_obj} = $parsed->header_obj;
76             $opts{attached_files} = \@attached_files;
77              
78             foreach my $part ($parsed->parts) {
79             my $filename = $part->filename;
80             next unless $filename;
81             my $body = $part->body;
82              
83             if ((
84             ($part->content_type =~ m{application/pdf})
85             || ($filename =~ m{\.pdf$})
86             )
87             && (scalar(which("gs")))
88             ) {
89             my $tmpdir2 = tempdir( CLEANUP => 1 );
90             my $attached_pdf = file($tmpdir2, 'attached.pdf');
91             $attached_pdf->spew($body);
92            
93             my $old_cwd = getcwd;
94             chdir($tmpdir2);
95            
96             my ($stdout, $stderr, $exit) = capture {
97             system(qw(
98             gs -dNOPAUSE -sDEVICE=jpeg -dFirstPage=1 -dLastPage=237
99             -sOutputFile=page%d.jpg -dJPEGQ=100 -r150x150 -q attached.pdf
100             -c quit
101             ));
102             };
103             my @files =
104             map { file($_) }
105             sort
106             File::Find::Rule
107             ->file()
108             ->name( 'page*.jpg' )
109             ->in( $tmpdir2 );
110             my $base_name = $filename;
111             $base_name =~ s/[.]/-/g;
112             foreach my $file (@files) {
113             my $image_file = file($tmpdir, $base_name.'-'.$file->basename);
114             $file->copy_to($image_file);
115             push(@attached_files, $image_file);
116             }
117            
118             chdir($old_cwd);
119             }
120             else {
121             my $attached_file = file($tmpdir, $filename);
122             $attached_file->spew($body);
123             push(@attached_files, $attached_file);
124             }
125             }
126              
127             my $self = $class->SUPER::new(\%opts);
128             return $self;
129             }
130              
131             sub get_symbols {
132             my ($self) = @_;
133              
134             my $scanner = Barcode::ZBar::ImageScanner->new();
135             $scanner->parse_config("enable");
136              
137             my @symbols;
138             foreach my $file (@{$self->attached_files}) {
139             my %unique_data;
140             foreach my $enhancer (@enhancers) {
141             my @new_symbols = _get_symbols_from_file($scanner, $file, $enhancer,);
142              
143             push(
144             @symbols, (
145             map { +{
146             filename => $file->basename,
147             type => $_->get_type,
148             data => $_->get_data,
149             }}
150             grep { not($unique_data{$_->get_data}++) } # only new/unique
151             @new_symbols,
152             ),
153             );
154             }
155             }
156              
157             return @symbols;
158             }
159              
160             sub _get_symbols_from_file {
161             my ($scanner, $file, $enhance_code) = @_;
162              
163             my $magick = Image::Magick->new();
164             my $error = $magick->Read($file);
165             die $error if $error;
166              
167             my ($raw, $raw_format) = $enhance_code->($magick);
168              
169             my $image = Barcode::ZBar::Image->new();
170             $image->set_format($raw_format);
171             $image->set_size($magick->Get(qw(columns rows)));
172             $image->set_data($raw);
173              
174             $scanner->scan_image($image);
175              
176             return $image->get_symbols;
177             }
178              
179             sub email_name {
180             my ($self) = @_;
181             my ($from) = Email::Address->parse($self->header_obj->header('From'));
182             return $from->name;
183             }
184              
185             sub email_from {
186             my ($self) = @_;
187             my ($from) = Email::Address->parse($self->header_obj->header('From'));
188             return $from->address;
189             }
190              
191              
192              
193             1;
194              
195              
196             __END__