File Coverage

blib/lib/Image/Magick/NFPADiamond.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Image::Magick::NFPADiamond;
2            
3 1     1   54611 use 5.00;
  1         4  
  1         53  
4 1     1   6 use strict "vars";
  1         2  
  1         35  
5 1     1   5 use strict "subs";
  1         7  
  1         31  
6 1     1   481 use Image::Magick;
  0            
  0            
7            
8             our $VERSION = '1.00';
9            
10             =head1 Name
11            
12             Image::Magick::NFPADiamond - This module renders a NFPA diamond using ImageMagick
13            
14             =head1 Synopsis
15            
16             use Image::Magick::NFPADiamond;
17            
18             my $diamond=Image::Magick::NFPADiamond->new(red=>3, blue=>0, yellow=>1);
19             $diamond->save('warning.jpg');
20            
21             =head1 Description
22            
23             This module composes a NFPA diamond or I image using ImageMagick perl module.
24            
25             =head1 Methods
26            
27             =head2 Image::Magick::NFPADiamond::new()
28            
29            
30             The constructor takes a series of arguments in a hash notation style, none of wich are mandatory:
31            
32             =over
33            
34             =item red
35            
36             =item blue
37            
38             =item yellow
39            
40             The values to appear inside the red, yellow and blud diamonds. Should be a number, but any string would do.
41            
42             =item white
43            
44             The text to appear inside the white diamond. Any string would do. A C<-W-> has a special meaning and produces
45             a strikethrough W to signal a hazardous material that shouln't be mixed with water. C is a synonim for this.
46            
47             =item size
48            
49             The size of the resulting image expressed as a single integer. The resulting image is always a square of size x size.
50             If this argument is missing, a size of 320 is assumed.
51            
52             =back
53            
54             =head2 save([I])
55            
56             The save() method writes the image to a specified argument. The argument may be a filename, but anything acceptable by
57             ImageMagick should work.
58            
59             =head2 response([I])
60            
61             The response method() writes the image to STDOUT. This is usefull for a CGI implementation (see the sample below).
62             The argument is a ImageMagick format argument (like 'jpg','gif','png', etc).
63            
64             =head2 handle()
65            
66             Returns the underlying Magick image so it can be used as an element to another one
67            
68             =head1 Restrictions
69            
70             The diamond generation is done according to the following diagram:
71            
72             =for html
73            
74             All 4 text are scaled the same, based on the 'AAAA' string on 24px
75             as a seed. This should cover strings like 'ALK', 'ACID'. A longer text will overlap.
76            
77             The red and blue regions are colored using the ImageMagick provided 'red' and 'yellow' colors.
78             The blue region is '#0063FF' to get a lighter tone.
79            
80             =head1 Sample
81            
82             This script works both with PerlEx and Apache
83            
84             #!perl
85            
86             #This Perl script will produce a dynamic NFPA alike diamond
87             use strict "vars";
88             use strict "subs";
89            
90             use CGI;
91             use Image::Magick::NFPADiamond;
92            
93             my $request=new CGI;
94            
95             #Using $request->Vars allows for a query_string like 'red=1&blue=2' to work
96             my $img=Image::Magick::NFPADiamond->new($request->Vars) || die "Fail\n";
97            
98             print $request->header(-type=> "image/jpeg", -expires=>'+3d');
99             binmode STDOUT;
100             $img->response('jpg');
101            
102             =head1 See Also
103            
104             L, the PerlMagick man page.
105            
106             =head1 AUTHOR
107            
108             Erich Strelow
109            
110             =head1 COPYRIGHT AND LICENSE
111            
112             Copyright (C) 2008 by Erich Strelow
113            
114             This library is free software; you can redistribute it and/or modify
115             it under the same terms as Perl itself, either Perl version 5.8.8 or,
116             at your option, any later version of Perl 5 you may have available.
117            
118             =head1 Disclaimer
119            
120             This module is provided "as is". This is in no way a sanctioned nor official nor verified version of the NFPA standard.
121            
122            
123             =cut
124            
125             sub new() {
126             my $class=shift();
127             my %params=@_;
128            
129             my $size;
130            
131             if (exists $params{size}) {
132             $size=$params{size};
133             } else {
134             $size=320; #Default for size
135             }
136            
137             my $canvas=Image::Magick->new(size => $size.'x'.$size);
138             $canvas->Read('xc:white');
139            
140             my $self={canvas => $canvas, size=>$size};
141             bless ($self,$class);
142             $self->_doit();
143            
144             #Using "AAAA" as the seed to get the text metrics
145             my @metrics = $canvas->QueryFontMetrics(family=>'Arial', text => "AAAA", stroke=> 'black', align=>'Center', pointsize=>24);
146             my $scale=($size/4/$metrics[4]).','.($size/4/$metrics[1]);
147            
148             $canvas->Annotate(family=>'Arial',scale => $scale, text => $params{red}, x => $size/2, y => $size*3/8,stroke=> 'black', align=>'Center', pointsize=>24)
149             if exists $params{red};
150            
151             $canvas->Annotate(family=>'Arial',scale => $scale, text => $params{blue}, x => $size/4, y => $size*5/8,stroke=> 'black', align=>'Center', pointsize=>24)
152             if exists $params{blue};
153            
154             $canvas->Annotate(family=>'Arial',scale => $scale, text => $params{yellow}, x => $size*3/4, y => $size*5/8,stroke=> 'black', align=>'Center', pointsize=>24)
155             if exists $params{yellow};
156            
157             if ($params{white} =~ /-W-|JackDaniels/) {
158             #Setting up the no-water sign
159             $canvas->Annotate(family=>'Arial',scale => $scale, text => "W", x => $size/2, y => $size*7/8,stroke=> 'black', align=>'Center', pointsize=>24);
160            
161             #Don't have a clue how to render a strikethrough font, I crafty place a line over the W
162             $canvas->Draw(primitive =>'line', points=> ($size*3/8).','.($size*6.4/8).' '.($size*5/8).','.($size*6.4/8), stroke=> 'black', strokewidth => (8*$size/400));
163             } else {
164             $canvas->Annotate(family=>'Arial',scale => $scale, text => $params{white}, x => $size/2, y => $size*7/8,stroke=> 'black', align=>'Center', pointsize=>24)
165             if exists $params{white};
166             }
167             return $self;
168             }
169            
170             sub handle() { return shift()->{canvas}; }
171            
172             sub _diamond() {
173             my $self=shift();
174             my $x=shift();
175             my $y=shift();
176             my $fill=shift();
177             my $w=shift();
178            
179             my $p=($x + $w/2).','.$y.' '.
180             $x.','.($y + $w/2).' '.
181             ($x + $w/2).','.($y + $w).' '.
182             ($x + $w).','.($y+$w/2).' '.
183             ($x + $w/2).','.$y
184             ;
185             $x=$self->{canvas}->Draw(primitive => 'polyline', points => $p,fill => $fill, stroke=>'black');
186             print $x if ($x);
187             }
188            
189             sub _doit($)
190             {
191             my $self=shift();
192             my $s=$self->{size};
193             $self->_diamond($s/4,0,'red', $s/2);
194             $self->_diamond(0,$s/4,'#0063FF', $s/2);
195             $self->_diamond($s/2,$s/4,'yellow', $s/2);
196            
197             $self->_diamond(0,0,'none',$s);
198             }
199            
200            
201             sub response() {
202            
203             my $self=shift();
204             my $format='jpg';
205             if (@_) {
206             $format=shift();
207             }
208             #For some reason, I can't get a simple save to "-" to work on this
209             my @blob = $self->handle()->ImageToBlob(magick=>$format);
210            
211             for ( @blob) {
212             print;
213             }
214             }
215            
216             sub save() {
217             my $self=shift();
218             my $file=shift();
219             return $self->{canvas}->Write($file);
220            
221             }
222             1;