| 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; |