| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Image::ThousandWords; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | our $NAME	= 'Image::ThousandWords'; | 
| 4 |  |  |  |  |  |  | our $VERSION	= '0.10'; | 
| 5 |  |  |  |  |  |  | our $CHAT = undef; | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | =head1 NAME | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | Image::ThousandWords - convert an image to colored HTML text | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | use Image::ThousandWords; | 
| 14 |  |  |  |  |  |  | my $html = Image::ThousandWords::html( | 
| 15 |  |  |  |  |  |  | image_path	=> 'image.jpg', | 
| 16 |  |  |  |  |  |  | text		=> 'TurnMeIntoAnImage', | 
| 17 |  |  |  |  |  |  | }; | 
| 18 |  |  |  |  |  |  | print "$html\n\n"; | 
| 19 |  |  |  |  |  |  | exit; | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | Or: | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | use Image::ThousandWords; | 
| 24 |  |  |  |  |  |  | my $o = Image::ThousandWords->new( | 
| 25 |  |  |  |  |  |  | text 	=> $text, | 
| 26 |  |  |  |  |  |  | image_path => 'shakespeare.jpg', | 
| 27 |  |  |  |  |  |  | whitespace	=> ' ', | 
| 28 |  |  |  |  |  |  | line_ends	=> '•', | 
| 29 |  |  |  |  |  |  | font_size  => 20, | 
| 30 |  |  |  |  |  |  | auto_size => 1, | 
| 31 |  |  |  |  |  |  | size	=> 400, | 
| 32 |  |  |  |  |  |  | font_face	=> "'Courier New'", | 
| 33 |  |  |  |  |  |  | ); | 
| 34 |  |  |  |  |  |  | $html = $o->html; | 
| 35 |  |  |  |  |  |  | print "Content-type:text/html\n\n", $o->wrap_html(background=>'black'); | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | B> for examples of use>. | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | This module is designed to take as input the path to an image file, | 
| 42 |  |  |  |  |  |  | and a string of text, and return an HTML colored text, resembling the image made out | 
| 43 |  |  |  |  |  |  | of the string, repeated as necessary. | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | Henning Møller-Nielsen wrote the original, Lee Goddard modified it slightly. | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | Henning said, | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | The inspiration I got from http://www4.telge.kth.se/~d99_kme/ | 
| 50 |  |  |  |  |  |  | look at http://rto.dk/images/camel.html or http://rto.dk/images/llama.html for the first versions | 
| 51 |  |  |  |  |  |  | (and I look like this: http://rto.dk/images/henning.htm) | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | Lee adds: | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | Modified by Lee Goddard (lgoddard-at-cpan.org) 2003, and again 15 February 2004 | 
| 56 |  |  |  |  |  |  | - I did send Henning the mod, but he didn't publish it; I lost it, rewrote it | 
| 57 |  |  |  |  |  |  | and didn't want to re-write it again. Module now has more parameters, and more | 
| 58 |  |  |  |  |  |  | control over the HTML, using a combination of CSS and image resizing (the latter | 
| 59 |  |  |  |  |  |  | being one of Henning's original requests). | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | B> for examples of use>. | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =head1 DEPENDENCIES | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | Carp | 
| 66 |  |  |  |  |  |  | GD | 
| 67 |  |  |  |  |  |  | Image::Thumbnail | 
| 68 |  |  |  |  |  |  | HTML::Entities | 
| 69 |  |  |  |  |  |  | Image::Size | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | =cut | 
| 72 |  |  |  |  |  |  |  | 
| 73 | 1 |  |  | 1 |  | 34455 | use strict; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 33 |  | 
| 74 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 75 | 1 |  |  | 1 |  | 6 | use Carp "cluck"; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 73 |  | 
| 76 | 1 |  |  | 1 |  | 443 | use GD; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | use Image::Thumbnail; | 
| 78 |  |  |  |  |  |  | use HTML::Entities; | 
| 79 |  |  |  |  |  |  | use Image::Size; | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | # Returns an object blessed into this class | 
| 82 |  |  |  |  |  |  | sub new { my $class = shift; | 
| 83 |  |  |  |  |  |  | die unless defined $class and not ref $class; | 
| 84 |  |  |  |  |  |  | my $self = bless {}, $class; | 
| 85 |  |  |  |  |  |  | $self->_populate(@_); | 
| 86 |  |  |  |  |  |  | return $self; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | sub _populate { my $self = shift; | 
| 90 |  |  |  |  |  |  | my $args = (ref $_[0]? shift : {@_}); | 
| 91 |  |  |  |  |  |  | $self->{$_} = $args->{$_} foreach keys %$args; | 
| 92 |  |  |  |  |  |  | } | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | =head1 CONSTRUCTOR html | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | Returns a HTML formatted string, colored to resemble IMAGE. The string consists | 
| 97 |  |  |  |  |  |  | of the letters and characters from STRING. | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | Accepts parameters as a hash, list or hash-reference: | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | =over 4 | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | =item image_path | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | Path to the file to convert. Must be openable by your version of GD. | 
| 106 |  |  |  |  |  |  | If you don't supply this, you must supply C as a GD image. | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | =item thumb | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | If you do not supply C (above), you must supply this | 
| 111 |  |  |  |  |  |  | as a loaded GD image. | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | =item size | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | The length in pixels of the largest size of the image when | 
| 116 |  |  |  |  |  |  | re-sized prior to conversion to text. Default is C<100>. | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | =item auto_size | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | If set, experimentally tries to re-size the output to be | 
| 121 |  |  |  |  |  |  | the same size, in pixels, as the input. If supplied, don't | 
| 122 |  |  |  |  |  |  | bother with C or C (below), but maybe | 
| 123 |  |  |  |  |  |  | use C (above). | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | So, if you supply C as well as C, you are | 
| 126 |  |  |  |  |  |  | requesting the output to the be C in pixels, the number | 
| 127 |  |  |  |  |  |  | of characters in each row being determind by C | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | If you supply C without C, then C | 
| 130 |  |  |  |  |  |  | specifies the number of characters per row. | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | =item text | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | Text to use in conversion of the C. Default is C, | 
| 135 |  |  |  |  |  |  | so you'd better supply your own. Note that whitesapce will be stripped. | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | =item whitespace | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | If you don't supply this at all, all whitespace will be removed. | 
| 140 |  |  |  |  |  |  | If you do supply this, all whitespace will be substituted for whatever | 
| 141 |  |  |  |  |  |  | this C value is. Intention is that you'll supply a single | 
| 142 |  |  |  |  |  |  | space to maintain whitespace - or some character to maintain spacing | 
| 143 |  |  |  |  |  |  | and colouring. See also C below. | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | =item line_ends | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | Replace line terminators C<[\n\r\f]> with this string: may be multiple | 
| 148 |  |  |  |  |  |  | characters. By default this paramter is set to whatever C | 
| 149 |  |  |  |  |  |  | is set to - setting this parameter over-rides the effets of the former | 
| 150 |  |  |  |  |  |  | parameter on line terminators. | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | =item font_face | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | String to use in the HTML, which will be quoted in "double-quotes". | 
| 155 |  |  |  |  |  |  | Defaults to C<'Arial Black','Lucida Console','Courier New', Courier'>. | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | =item font_size | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | Number of pixels for the size of the font used: default is C<8>. | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | =item line_height | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | Number of pixels for the height of a line of text. Default value | 
| 164 |  |  |  |  |  |  | is two pixels less than the C. | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | =item scanline_skip | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | You shuldn't need this, but... | 
| 169 |  |  |  |  |  |  | The number of scan-lines or rows to skip jump in each read of | 
| 170 |  |  |  |  |  |  | the image. The default is to read every line, which is a C | 
| 171 |  |  |  |  |  |  | of C<1> - not a very clear name, sorry.  Check the relation of this to | 
| 172 |  |  |  |  |  |  | the C parameter, above. | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | =back | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | B> for examples of use>. | 
| 177 |  |  |  |  |  |  |  | 
| 178 |  |  |  |  |  |  | =cut | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | sub html { | 
| 181 |  |  |  |  |  |  | local $_; | 
| 182 |  |  |  |  |  |  | my $self = (ref $_[0] eq __PACKAGE__? shift : __PACKAGE__->new); | 
| 183 |  |  |  |  |  |  | $self->_populate(@_); | 
| 184 |  |  |  |  |  |  | unless (defined $self->{image_path} or defined $self->{thumb}){ | 
| 185 |  |  |  |  |  |  | cluck "No image path" ; | 
| 186 |  |  |  |  |  |  | return undef; | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  | $self->{result} = ""; | 
| 189 |  |  |  |  |  |  | warn "# Image path: ".$self->{image_path} if defined $self->{image_path} and defined $CHAT; | 
| 190 |  |  |  |  |  |  | $self->{font_size} = 8 unless defined $self->{font_size}; | 
| 191 |  |  |  |  |  |  | warn "# Font size: ".$self->{font_size} if defined $self->{font_size} and defined $CHAT; | 
| 192 |  |  |  |  |  |  | $self->{font_face} = "'Arial Black','Lucida Console','Courier New', Courier'" unless defined $self->{font_face}; | 
| 193 |  |  |  |  |  |  | warn "# Font face: ".$self->{font_face} if defined $self->{font_face} and defined $CHAT; | 
| 194 |  |  |  |  |  |  | $self->{line_height} = $self->{font_size} - int ($self->{font_size}/3) 	unless defined $self->{line_height}; | 
| 195 |  |  |  |  |  |  | warn "# Line height: ".$self->{line_height} if defined $self->{line_height} and defined $CHAT; | 
| 196 |  |  |  |  |  |  | $self->{scanline_skip} = 1 unless defined $self->{scanline_skip}; | 
| 197 |  |  |  |  |  |  | warn "# Scanline: ".$self->{scanline_skip} if defined $self->{scanline_skip} and defined $CHAT; | 
| 198 |  |  |  |  |  |  | $self->{text} = 'aPictureIsWorthAThousandWords' unless defined $self->{text}; | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | $self->{whitespace} = "" unless defined $self->{whitespace}; | 
| 201 |  |  |  |  |  |  | my $whitespace; | 
| 202 |  |  |  |  |  |  | if ($self->{line_ends}){ | 
| 203 |  |  |  |  |  |  | $whitespace = '[ |\t]'; | 
| 204 |  |  |  |  |  |  | $self->{text} =~ s/([\n\r\f])+/$1/sg;	# collapse line endings | 
| 205 |  |  |  |  |  |  | } else { | 
| 206 |  |  |  |  |  |  | $self->{line_ends} = $self->{whitespace}; | 
| 207 |  |  |  |  |  |  | $whitespace = '\s' | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  | $self->{text} =~ s/${whitespace}+/$self->{whitespace}/smg if defined $self->{whitespace}; | 
| 210 |  |  |  |  |  |  | my @text = split //, $self->{text}; | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | # Set size.... | 
| 213 |  |  |  |  |  |  | if (defined $self->{image_path} and $self->{auto_size}){ | 
| 214 |  |  |  |  |  |  | my ($x, $y) = imgsize( $self->{image_path}  ); | 
| 215 |  |  |  |  |  |  | unless ($x and $y){ | 
| 216 |  |  |  |  |  |  | cluck "No x or y?"; | 
| 217 |  |  |  |  |  |  | return undef; | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | # Get the size of original | 
| 221 |  |  |  |  |  |  | if (defined $self->{size}){ | 
| 222 |  |  |  |  |  |  | my $r = $x>$y ? $x / $self->{size} : $y / $self->{size}; | 
| 223 |  |  |  |  |  |  | $x /= $r; | 
| 224 |  |  |  |  |  |  | $y /= $r; | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  | warn "# Size is $x,$y" if $CHAT; | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | # Set 'size' to longest side of original, over the font_size | 
| 229 |  |  |  |  |  |  | # - what is wrong with this?! | 
| 230 |  |  |  |  |  |  | $x /= $self->{font_size}; | 
| 231 |  |  |  |  |  |  | $y /= $self->{line_height}; | 
| 232 |  |  |  |  |  |  | $x = int($x)+1 if int($x) != $x; | 
| 233 |  |  |  |  |  |  | $y = int($y)+1 if int($y) != $y; | 
| 234 |  |  |  |  |  |  | $self->{size} = $x > $y? $x : $y; | 
| 235 |  |  |  |  |  |  | warn "# New size from $x,$y is $self->{size}, so lines are $x characters of $self->{font_size}px" if $CHAT; | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  | elsif (not defined $self->{size}){ | 
| 238 |  |  |  |  |  |  | $self->{size}	= 100; | 
| 239 |  |  |  |  |  |  | warn "# Set size (B) to: ".$self->{size} if defined $CHAT; | 
| 240 |  |  |  |  |  |  | } elsif ($self->{size} <= $self->{font_size}){ | 
| 241 |  |  |  |  |  |  | cluck "Please make sure size ($self->{size}) > font_size ($self->{font_size})"; | 
| 242 |  |  |  |  |  |  | return undef; | 
| 243 |  |  |  |  |  |  | } else { | 
| 244 |  |  |  |  |  |  | warn "# Size (C) is ".$self->{size} if defined $CHAT; | 
| 245 |  |  |  |  |  |  | } | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | # Re-size the image if necessary (ie unless orig interface used) | 
| 248 |  |  |  |  |  |  | # This is quicker than us trying to work out an average colour for | 
| 249 |  |  |  |  |  |  | # a block of pixels | 
| 250 |  |  |  |  |  |  | my $t; | 
| 251 |  |  |  |  |  |  | unless ($self->{thumb}){ | 
| 252 |  |  |  |  |  |  | $t = new Image::Thumbnail( | 
| 253 |  |  |  |  |  |  | module     => 'GD', | 
| 254 |  |  |  |  |  |  | create     => 1, | 
| 255 |  |  |  |  |  |  | size       => $self->{size}, | 
| 256 |  |  |  |  |  |  | inputpath  => $self->{image_path}, | 
| 257 |  |  |  |  |  |  | ); | 
| 258 |  |  |  |  |  |  | $self->{thumb} = $t->{thumb}; | 
| 259 |  |  |  |  |  |  | undef $t; | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | unless (defined $self->{thumb}){ | 
| 263 |  |  |  |  |  |  | cluck "Could not re-size the image"; | 
| 264 |  |  |  |  |  |  | return undef; | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | my ($x, $y) = $self->{thumb}->getBounds(); | 
| 268 |  |  |  |  |  |  | my ($R, $G, $B) = (-1); | 
| 269 |  |  |  |  |  |  | @text = (@text, @text) while ($x*$y > scalar(@text)); | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | # Finally do the job | 
| 272 |  |  |  |  |  |  | my $j; | 
| 273 |  |  |  |  |  |  | for ($j = 0; $j < $y; $j += $self->{scanline_skip}) { | 
| 274 |  |  |  |  |  |  | my $i; | 
| 275 |  |  |  |  |  |  | for ($i = 0; $i < $x; $i++) { | 
| 276 |  |  |  |  |  |  | my $index = $self->{thumb}->getPixel($i, $j); | 
| 277 |  |  |  |  |  |  | my ($r,$g,$b) = $self->{thumb}->rgb($index); | 
| 278 |  |  |  |  |  |  | unless (($r == $R) and ($g == $G) and ($b == $B)) { | 
| 279 |  |  |  |  |  |  | ($R, $G, $B) = ($r, $g, $b); | 
| 280 |  |  |  |  |  |  | my $color = '#' . sprintf("%.2X%.2X%.2X", $r, $g, $b); | 
| 281 |  |  |  |  |  |  | $self->{result} .= qq¤¤; | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  | my $char; | 
| 284 |  |  |  |  |  |  | # Do not begin or end a line with whitespace | 
| 285 |  |  |  |  |  |  | do { | 
| 286 |  |  |  |  |  |  | $char = shift @text | 
| 287 |  |  |  |  |  |  | } while (($i==0 or $i==$x-1) and $char eq $self->{whitespace}); | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | if ($self->{line_ends}){ | 
| 290 |  |  |  |  |  |  | if (not $char =~ s/[\n\r\f]/$self->{line_ends}/){ | 
| 291 |  |  |  |  |  |  | $char = HTML::Entities::encode($char); | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  | } else { | 
| 294 |  |  |  |  |  |  | $char = HTML::Entities::encode($char); | 
| 295 |  |  |  |  |  |  | } | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | $self->{result} .= $char; | 
| 298 |  |  |  |  |  |  | } | 
| 299 |  |  |  |  |  |  | $self->{result} .= "\n ";
 | 
| 300 |  |  |  |  |  |  | } | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | if ($self->{result}){ | 
| 303 |  |  |  |  |  |  | $self->{result} = qq¤¤ | 
| 304 |  |  |  |  |  |  | . $self->{result} | 
| 305 |  |  |  |  |  |  | . qq¤\n¤; | 
| 306 |  |  |  |  |  |  | return $self->{result}; | 
| 307 |  |  |  |  |  |  | } else { | 
| 308 |  |  |  |  |  |  | return undef; | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  | } | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | =head2 METHOD wrap_html | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | Convenience method to return the C field wrapped in | 
| 315 |  |  |  |  |  |  | HTML to make a complete page. Accepts values valid for CSS | 
| 316 |  |  |  |  |  |  | in the parameter C, and text in the C (which | 
| 317 |  |  |  |  |  |  | is otherwise inherited from the calling object) or the C. | 
| 318 |  |  |  |  |  |  |  | 
| 319 |  |  |  |  |  |  | Sets the C field and returns an HTML page. | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | =cut | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | sub wrap_html { my ($self, $args) = (shift, (ref $_[0]? shift : {@_})); | 
| 324 |  |  |  |  |  |  | $args->{background} = "black" unless defined $args->{background}; | 
| 325 |  |  |  |  |  |  | $self->{title} = $args->{title} if defined $args->{title}; | 
| 326 |  |  |  |  |  |  | if (not defined $self->{title}){ | 
| 327 |  |  |  |  |  |  | $self->{title} = $self->{image_path}; | 
| 328 |  |  |  |  |  |  | ($self->{title}) = $self->{title} =~ /([^\\\/]+)\.\w{3,4}$/; | 
| 329 |  |  |  |  |  |  | $self->{title} =~ s/_+/ /g; | 
| 330 |  |  |  |  |  |  | } | 
| 331 |  |  |  |  |  |  | return "\n\n | 
| 332 |  |  |  |  |  |  | $self->{title} | 
| 333 |  |  |  |  |  |  | $self->{result} | 
| 334 |  |  |  |  |  |  | \n"; | 
| 335 |  |  |  |  |  |  | } | 
| 336 |  |  |  |  |  |  |  | 
| 337 |  |  |  |  |  |  | =head1 BACKWARDS COMPARABILITY | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | The original C module's C method is still acceptable. | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | =cut | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | sub giveme ($$) { | 
| 344 |  |  |  |  |  |  | return html( | 
| 345 |  |  |  |  |  |  | thumb => $_[0], | 
| 346 |  |  |  |  |  |  | text  => $_[1], | 
| 347 |  |  |  |  |  |  | ); | 
| 348 |  |  |  |  |  |  | } | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | 1; | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | =head1 EXAMPLES FROM HENNING: | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | Made with the v. 0.01 (just a script, inspired by http://www4.telge.kth.se/~d99_kme/) | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | http://rto.dk/images/camel.html | 
| 357 |  |  |  |  |  |  | http://rto.dk/images/llama.html | 
| 358 |  |  |  |  |  |  | http://rto.dk/images/henning.html (me) | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | Made with the v. 0.03 | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | http://rto.dk/images/neptune.html | 
| 363 |  |  |  |  |  |  | http://rto.dk/images/mars.html | 
| 364 |  |  |  |  |  |  | http://rto.dk/images/pluto_charon.html | 
| 365 |  |  |  |  |  |  | http://rto.dk/images/earth.html | 
| 366 |  |  |  |  |  |  | http://rto.dk/images/saturn.html | 
| 367 |  |  |  |  |  |  | http://rto.dk/images/jupiter.html (here the reason for v. 0.04 is apparent) | 
| 368 |  |  |  |  |  |  | http://rto.dk/images/ira1.html | 
| 369 |  |  |  |  |  |  | http://rto.dk/images/ira2.html (my colleagues) | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | =head1 KNOWN BUGS | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | None, from a perl perspective. From an image perspective things look different :-) | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | =head1 AUTHOR ETC. | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | Henning Michael Møller-Nielsen, hmn -at- datagraf.dk | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | Slightly modified by Lee Goddard, lgoddard -at- cpan.org | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | =head1 VERSION HISTORY | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | A bit of an overkill, but hey - this is Fun! | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | 0.01	Not really a module, just a script | 
| 386 |  |  |  |  |  |  | 0.02	'ThousandWords.pm' came to life | 
| 387 |  |  |  |  |  |  | 0.03	Fixed an error so the first text in a black image wouldn't be white | 
| 388 |  |  |  |  |  |  | 0.04	Fixed an error so the first text in a black image wouldn't be larger | 
| 389 |  |  |  |  |  |  | than the rest and so spaces no longer would be used | 
| 390 |  |  |  |  |  |  | 0.05	Ah - added POD | 
| 391 |  |  |  |  |  |  | 0.06	Lee added: re-sizing of image; new access method; proper HTML entities | 
| 392 |  |  |  |  |  |  | 0.07	Sod it - full OO interface, more re-sizing, line-feeds/whitespace | 
| 393 |  |  |  |  |  |  | 0.08	Fixed MANIFEST for test.pl | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | Future: | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | ANSI colored text? | 
| 398 |  |  |  |  |  |  |  | 
| 399 |  |  |  |  |  |  | Work on the 'size' field | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | L, | 
| 404 |  |  |  |  |  |  | L, | 
| 405 |  |  |  |  |  |  | L. | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | B> for examples of use>. |