File Coverage

blib/lib/Image/Mate.pm
Criterion Covered Total %
statement 25 183 13.6
branch 1 146 0.6
condition 0 6 0.0
subroutine 7 15 46.6
pod 6 6 100.0
total 39 356 10.9


line stmt bran cond sub pod time code
1             ####################################################
2             ######################## The Image::Mate module
3             ######################## Created by Lyle Hopkins (Cosmic Networks Ltd).
4             ######################## Provides easy use of GD, Imager or ImageMagick
5             ##################################################
6            
7             package Image::Mate;
8            
9 1     1   23779 use 5.005;
  1         4  
  1         38  
10 1     1   6 use strict;
  1         2  
  1         33  
11 1     1   5 use warnings;
  1         7  
  1         35  
12 1     1   5 use Carp;
  1         2  
  1         95  
13 1     1   5 use vars qw(@GMODS %GMODLIST @GMODPREF $GMOD $IMGS @ISA @EXPORT_OK $VERSION);
  1         2  
  1         229  
14            
15             BEGIN {
16 1     1   5 require Exporter;
17 1         20 @ISA = qw(Exporter);
18 1         4 @EXPORT_OK = qw( im_available im_setpref );
19 1         2852 $VERSION = 0.05;
20             } #BEGIN
21            
22             $GMOD = "";
23             @GMODS = (
24             "Imager",
25             "GD",
26             "Image::Magick",
27             );
28             %GMODLIST = ();
29             foreach my $module (@GMODS) {
30             my $exist = &_CheckForModule($module);
31             $GMODLIST{$module} = $exist;
32             if ($exist) {
33             &_LoadModule($module);
34             push (@GMODPREF, $module);
35             unless ($GMOD) {
36             $GMOD = $module;
37             } #unless
38             } #if
39             } #foreach
40            
41            
42             ##################################################
43             ######################## Available graphics modules
44             ##################################################
45            
46             sub im_available {
47 0 0   0 1 0 if ($_[1] eq "hash") {
48 0         0 return %GMODLIST;
49             } #if
50 0 0       0 if ($_[1] eq "array") {
51 0         0 return @GMODPREF;
52             } #if
53             } #sub
54            
55            
56             ##################################################
57             ######################## Set module preference
58             ##################################################
59            
60             sub im_setpref {
61 0     0 1 0 my $name = shift;
62 0 0       0 if (scalar(@_) < 1) {
63 0         0 return "1: Must have at least one preference";
64             } #if
65 0         0 foreach my $module (@_) {
66 0         0 my $valid = 0;
67 0         0 foreach my $validmod (@GMODS) {
68 0 0       0 $valid = 1 if ($module eq $validmod);
69             } #foreach
70 0 0       0 croak "Invalid option '$module'" if !$valid;
71             } #foreach
72 0         0 @GMODPREF = @_;
73 0         0 $GMOD = $_[0];
74 0         0 return 0;
75             } #sub
76            
77            
78             ##################################################
79             ######################## Create image object
80             ##################################################
81            
82             sub new {
83 0     0 1 0 my $class = shift;
84 0         0 my $self = {};
85 0         0 bless $self,$class;
86 0         0 my %input = @_;
87            
88             ## Generate a unique image reference
89 0         0 my @chars=('A'..'Z','a'..'z',0..9);
90 0         0 my $imgid = join('',@chars[map{rand @chars}(1..16)]);
  0         0  
91            
92 0 0 0     0 unless ($input{blank} || $input{file}) {
93 0         0 $@ = "Requires filename or blank image details";
94 0         0 return undef;
95             } #unless
96            
97             ## Imager
98 0 0       0 if ($GMOD eq "Imager") {
99 0 0       0 if ($input{blank}) {
100 0         0 my $bits = 8;
101 0 0       0 $bits = 16 if $input{blank}->{c};
102 0         0 $IMGS->{$imgid} = Imager->new(xsize=>$input{blank}->{x},ysize=>$input{blank}->{y},bits=>$bits);
103 0 0       0 unless (ref($IMGS->{$imgid})) {
104 0         0 croak 'Imager Error creating image';
105             } #unless
106 0         0 $self->{X} = $input{blank}->{x};
107 0         0 $self->{Y} = $input{blank}->{y};
108             } #if
109             else {
110 0         0 $IMGS->{$imgid} = Imager->new;
111 0 0       0 $IMGS->{$imgid}->read(file => $input{file}) or croak $IMGS->{$imgid}->errstr;
112 0         0 $self->{X} = $IMGS->{$imgid}->getwidth();
113 0         0 $self->{Y} = $IMGS->{$imgid}->getheight();
114             } #else
115             } #if
116            
117             ## GD
118 0 0       0 if ($GMOD eq "GD") {
119 0 0       0 if ($input{blank}) {
120 0         0 my $truecolour = 0;
121 0 0       0 $truecolour = 1 if $input{blank}->{c};
122 0         0 $IMGS->{$imgid} = GD::Image->new($input{blank}->{x},$input{blank}->{y},$truecolour);
123 0 0       0 unless (ref($IMGS->{$imgid})) {
124 0         0 croak 'Image::Magick Error creating image';
125             } #unless
126 0         0 $self->{X} = $input{blank}->{x};
127 0         0 $self->{Y} = $input{blank}->{y};
128             } #if
129             else {
130 0         0 $IMGS->{$imgid} = GD::Image->new($input{file});
131 0 0       0 croak $@ if $@;
132 0         0 ($self->{X},$self->{Y}) = $IMGS->{$imgid}->getBounds()
133             } #else
134             } #if
135            
136             ## Image::Magick
137 0 0       0 if ($GMOD eq "Image::Magick") {
138 0 0       0 if ($input{blank}) {
139 0 0       0 if ($input{blank}->{c}) {
140 0         0 $IMGS->{$imgid} = Image::Magick->new(size=>"$input{blank}->{x}x$input{blank}->{y}", type=>'TrueColor');
141             } #if
142             else {
143 0         0 $IMGS->{$imgid} = Image::Magick->new(size=>"$input{blank}->{x}x$input{blank}->{y}");
144             } #else
145 0 0       0 unless (ref($IMGS->{$imgid})) {
146 0         0 croak 'Image::Magick Error creating image';
147             } #unless
148 0         0 $self->{X} = $input{blank}->{x};
149 0         0 $self->{Y} = $input{blank}->{y};
150 0         0 my $x = $IMGS->{$imgid}->ReadImage('xc:white');
151 0 0       0 croak $x if $x;
152             } #if
153             else {
154 0         0 $IMGS->{$imgid} = Image::Magick->new;
155 0         0 my $error = $IMGS->{$imgid}->Read($input{file});
156 0 0       0 croak $error if $error;
157 0 0       0 ($self->{X},$self->{Y}) = $IMGS->{$imgid}->Get('width','height') or croak 'Image::Magick Cannot get width and height';
158             } #else
159             } #if
160            
161 0         0 $self->{IMGID} = $imgid;
162            
163 0         0 return $self;
164             } ## End sub
165            
166            
167             ##################################################
168             ######################## Colour whole image
169             ##################################################
170            
171             sub fillall {
172 0     0 1 0 my $self=shift;
173 0 0       0 unless ($self->{IMGID}) {
174 0         0 $self->{ERROR}='No image';
175 0         0 return undef;
176             } #unless
177 0         0 my %input = @_;
178            
179             ## Imager
180 0 0       0 if ($GMOD eq "Imager") {
181 0 0       0 $IMGS->{$self->{IMGID}}->box(filled => 1, color => $input{c}) or croak $IMGS->{$self->{IMGID}}->errstr;
182             } #if
183            
184             ## GD
185 0 0       0 if ($GMOD eq "GD") {
186 0         0 my $colour = &_MakeGDColour($self->{IMGID},$input{c});
187 0         0 $IMGS->{$self->{IMGID}}->filledRectangle(0,0,$self->{X}-1,$self->{Y}-1,$colour);
188 0 0       0 croak $@ if $@;
189             } #if
190            
191             ## Image::Magick
192 0 0       0 if ($GMOD eq "Image::Magick") {
193 0         0 my $error = $IMGS->{$self->{IMGID}}->Colorize(fill => $input{c});
194 0 0       0 croak $error if $error;
195             } #if
196 0         0 return $self;
197             } #sub
198            
199            
200             ##################################################
201             ######################## Draw line in image
202             ##################################################
203            
204             sub line {
205 0     0 1 0 my $self=shift;
206 0 0       0 unless ($self->{IMGID}) {
207 0         0 $self->{ERROR}='No image';
208 0         0 return undef;
209             } #unless
210 0         0 my %input = @_;
211            
212             ## Imager
213 0 0       0 if ($GMOD eq "Imager") {
214 0 0       0 $IMGS->{$self->{IMGID}}->line(color=>$input{c}, x1=>$input{start}->{x}, x2=>$input{end}->{x}, y1=>$input{start}->{y}, y2=>$input{end}->{y}, aa=>1, endp=>1 ) or croak $IMGS->{$self->{IMGID}}->errstr;
215             } #if
216            
217             ## GD
218 0 0       0 if ($GMOD eq "GD") {
219 0 0       0 $IMGS->{$self->{IMGID}}->setThickness($input{thick}) if $input{thick};
220 0         0 my $colour = &_MakeGDColour($self->{IMGID},$input{c});
221 0         0 $IMGS->{$self->{IMGID}}->line($input{start}->{x},$input{start}->{y},$input{end}->{x},$input{end}->{y},$colour);
222 0 0       0 croak $@ if $@;
223 0 0       0 $IMGS->{$self->{IMGID}}->setThickness(1) if ($input{thick});
224             } #if
225            
226             ## Image::Magick
227 0 0       0 if ($GMOD eq "Image::Magick") {
228 0 0       0 $input{thick} = 1 unless $input{thick};
229 0         0 my $error = $IMGS->{$self->{IMGID}}->Draw(stroke=>$input{c}, primitive=>'line', points=>"$input{start}->{x},$input{start}->{y} $input{end}->{x},$input{end}->{y}", strokewidth=>$input{thick});
230 0 0       0 croak $error if $error;
231             } #if
232 0         0 return $self;
233             } ## End sub
234            
235            
236             ##################################################
237             ######################## Save image
238             ##################################################
239            
240             sub save {
241 0     0 1 0 my $self=shift;
242 0 0       0 croak 'No image!' unless $self->{IMGID};
243 0         0 my %input = @_;
244 0 0 0     0 croak 'File exists!' if (-e "$input{filename}" && !$input{overwrite});
245            
246             ## Imager
247 0 0       0 if ($GMOD eq "Imager") {
248 0 0       0 if ($input{type} eq "gif") {
    0          
249 0 0       0 $IMGS->{$self->{IMGID}}->write(file => $input{filename}, type => $input{type}) or croak $IMGS->{$self->{IMGID}}->errstr;
250             } #if
251             elsif ($input{type} eq "png") {
252 0 0       0 $IMGS->{$self->{IMGID}}->write(file => $input{filename}) or croak $IMGS->{$self->{IMGID}}->errstr;
253             } #elsif
254             else {
255 0         0 $input{type} = "jpeg";
256 0 0       0 if ($input{'quality'}) {
257 0 0       0 $IMGS->{$self->{IMGID}}->write(file => $input{filename}, type => $input{type}, jpegquality=>$input{'quality'}) or croak $IMGS->{$self->{IMGID}}->errstr;
258             } #if
259             else {
260 0 0       0 $IMGS->{$self->{IMGID}}->write(file => $input{filename}, type => $input{type}) or croak $IMGS->{$self->{IMGID}}->errstr;
261             } #else
262             } #else
263             } #if
264            
265             ## GD
266 0 0       0 if ($GMOD eq "GD") {
267 0         0 open (OUTF, ">$input{filename}");
268 0         0 binmode OUTF;
269 0 0       0 if ($input{type} eq "gif") {
    0          
270 0         0 print OUTF $IMGS->{$self->{IMGID}}->gif();
271 0 0       0 croak $@ if $@;
272             } #if
273             elsif ($input{type} eq "png") {
274 0 0       0 if ($input{'compression'}) {
275 0         0 print OUTF $IMGS->{$self->{IMGID}}->png([$input{compression}]);
276 0 0       0 croak $@ if $@;
277             } #if
278             else {
279 0         0 print OUTF $IMGS->{$self->{IMGID}}->png();
280 0 0       0 croak $@ if $@;
281             } #else
282             } #if
283             else {
284 0 0       0 if ($input{'quality'}) {
285 0         0 print OUTF $IMGS->{$self->{IMGID}}->jpeg([$input{quality}]);
286 0 0       0 croak $@ if $@;
287             } #if
288             else {
289 0         0 print OUTF $IMGS->{$self->{IMGID}}->jpeg();
290 0 0       0 croak $@ if $@;
291             } #else
292             } #else
293 0         0 close(OUTF);
294             } #if
295            
296             ## Image::Magick
297 0 0       0 if ($GMOD eq "Image::Magick") {
298 0 0       0 if ($input{type} eq "gif") {
    0          
299 0         0 my $error = $IMGS->{$self->{IMGID}}->Write($input{filename});
300 0 0       0 croak $error if $error;
301             } #if
302             elsif ($input{type} eq "png") {
303 0 0       0 if ($input{'compression'}) {
304 0         0 my @compression = qw( None BZip Fax Group4 JPEG JPEG2000 LosslessJPEG LZW RLE Zip );
305 0         0 my $error = $IMGS->{$self->{IMGID}}->Write(filename => $input{filename}, compression => $compression[ $input{'compression'} ]);
306 0 0       0 croak $error if $error;
307             } #if
308             else {
309 0         0 my $error = $IMGS->{$self->{IMGID}}->Write(filename => $input{filename});
310 0 0       0 croak $error if $error;
311             } #else
312             } #elsif
313             else {
314 0 0       0 if ($input{'quality'}) {
315 0         0 my $error = $IMGS->{$self->{IMGID}}->Write(filename => $input{filename}, quality => $input{'quality'});
316 0 0       0 croak $error if $error;
317             } #if
318             else {
319 0         0 my $x = $IMGS->{$self->{IMGID}}->Set(magick => 'JPEG');
320 0 0       0 croak $x if $x;
321 0         0 my $error = $IMGS->{$self->{IMGID}}->Write(filename => $input{filename});
322 0 0       0 croak $error if $error;
323             } #else
324             } #else
325             } #if
326 0         0 return $self;
327             } ## End sub
328            
329            
330            
331             ##################################################
332             ######################## Make GD colour
333             ##################################################
334            
335             sub _MakeGDColour {
336 0     0   0 my ($imgid, $colour) = @_;
337 0         0 $colour =~ s/\#//;
338 0         0 $colour =~ /([0-1a-f][0-1a-f])([0-1a-f][0-1a-f])([0-1a-f][0-1a-f])/i;
339 0         0 my $gdcolour = $IMGS->{$imgid}->colorAllocate(hex($1),hex($2),hex($3));
340             } #sub
341            
342            
343             ##################################################
344             ######################## Load Module
345             ##################################################
346            
347             sub _LoadModule {
348 0     0   0 my $module = $_[0];
349 0         0 my $loadok = 1;
350             package main;
351 0         0 eval "require $module";
352 0 0       0 if ($@) {
353             package Image::Mate;
354 0         0 $loadok = 0;
355             package main;
356             } #if
357             else {
358 0         0 $module->import(@_[1 .. $#_]);
359             } #else
360             package Image::Mate;
361 0         0 return $loadok;
362             } #sub
363            
364            
365             ##################################################
366             ######################## Check for module
367             ##################################################
368            
369             sub _CheckForModule {
370 3     3   4 my $modulename = $_[0];
371 3         5 my $modulefound = 0;
372 3         9 $modulename =~ s/::/\//gis;
373 3         7 foreach my $modulepath (@INC) {
374 30 50       880 $modulefound = 1 if (-e "$modulepath/$modulename.pm");
375             } #foreach
376 3         7 return $modulefound;
377             } #sub
378            
379            
380            
381            
382            
383            
384             ##################################################
385             ######################## Clean Up
386             ##################################################
387            
388             #END {
389             # foreach my $imgid (keys %$IMGS) {
390             # &DESTROY($imgid);
391             # } #foreach
392             #} #END
393            
394             #sub DESTROY {
395             # my $imgid=shift;
396             # if (defined($IMGS->{$imgid})) {
397             # undef($IMGS->{$imgid});
398             # } #if
399             #} #sub
400            
401            
402            
403            
404            
405            
406            
407            
408             =head1 NAME
409            
410             Image::Mate - Interface to Gd, Imager, ImageMagick modules
411            
412             =head1 VERSION
413            
414             This document refers to Image::Mate.pm version 0.05
415            
416             =head1 SYNOPSIS
417            
418             use Image::Mate;
419            
420             # Get available graphics modules
421             my %list = &Image::Mate->im_available("hash");
422            
423             # Set new preference list
424             my $error = &Image::Mate->im_setpref("Imager","GD","Image::Magick");
425            
426             # create a new image
427             $img = Image::Mate->new(blank => {x => 100, y => 100, c => 1});
428             $img = Image::Mate->new(file => "image.jpg");
429            
430             # colour the whole image red
431             $img->fillall(c => "#ff0000");
432            
433             # draw a black line in the image
434             $img->line(c => "#000000", start => {x => 0, y => 0}, end => {x => 10, y => 10});
435            
436             # save image
437             $img->save(filename => "picture.jpg", type => "jpg", quality => 90);
438            
439             =head1 DESCRIPTION
440            
441             B is an interface to the Perl GD, Imager and ImageMagick
442             modules. Theoretically you'll be able to code the same image routines no
443             matter which of the before mentioned modules you have available. Very useful
444             if your scripts can end up on all different kinds of servers and you never
445             know what image modules are available.
446            
447             =head1 ROUTINES
448            
449             Here are the routines.
450            
451             =over 1
452            
453             =item B<$error = Image::Mate-Eim_available(["array","hash"])>
454            
455             This method returns a list of what graphics modules are available. List can be in the form of a hash
456             listing all modules with either a 1 or 0 value. Or an array listing only those available. NOTE: If
457             you run setpref before this routine then the array returned by this method will only contain what
458             you set. This routine can be exported the local namespace using use Image::Mate qw( im_available );
459            
460             =item B<$error = Image::Mate-Eim_setpref(LIST)>
461            
462             This method allows you to set the preference list of which graphics modules you should use first.
463             The default is "Imager","GD","Image::Magick". If successful 0 will be returned, otherwise it'll be
464             an error code with descriptive error. You cannot set modules that are not available. If you are
465             unsure what graphics modules you have available run Image::Mate->available first.
466             This routine can be exported the local namespace using use Image::Mate qw( im_setpref );
467            
468             =item B<$img = Image::Mate-Enew(blank => {x => 100, y => 100, c => 1])>
469             =item B<$img = Image::Mate-Enew(file => "image.jpg")>
470            
471             Returns an image object. If there was an error with creating this object it will be in $img->{ERROR}.
472             "c" can have the value of 0 or 1. 0 for stand colour (usually 8bit) or 1 for high colour (usually 16bit).
473            
474             =item B<$img = Image::Mate-Efillall(c => "#FFFFFF")>
475            
476             Fills the whole image with the set colour.
477            
478             =item B<$img->line(c => "#000000", start => {x => 0, y => 0}, end => {x => 10, y => 10})>
479            
480             Draws a line from start x,y point to end x,y point of colour c.
481            
482             =item B<$img->save(filename => "FILENAME", type => "TYPE", quality => QUALITY, compression => COMPRESSION)>
483            
484             Saves the image to a file. Supported types are GIF, PNG, and JPG, default is JPG.
485             For JPG you can define QUALITY as 0-100 (100 best quality, 0 worest). For PNG you can define
486             COMPRESSION as 0-9 (0 best quality, 9 worest).
487            
488             =back
489            
490             =head1 Obtaining the GD, Imager and Image::Magick perl modules
491            
492             They are all available on CPAN. Just run a search http://search.cpan.org
493             As long as you have any one of these modules installed Image::Mate will work.
494            
495             On linux I recommend using the CPAN module. Type "perl -MCPAN -e shell;" from
496             your shell. (If this is the first time you've ran the CPAN module you'll have to
497             go through a little config first, but don't worry this is menu driven). Then type either
498             (or all):-
499             install Imager
500             install GD
501             install Image::Magick
502            
503             On Windows your are probably using ActivePerl from ActiveState (which I also recommend). Use their ppm
504             utility, from the command prompt type:-
505             ppm install http://ppd.develop-help.com/ppd/Imager.ppd
506             ppm install http://theoryx5.uwinnipeg.ca/ppms/GD.ppd
507             ppm install http://www.bribes.org/perl/ppm/Image-Magick.ppd
508            
509             Unfortunately, ActiveStates automatic build machine does not include the necessary modules to build
510             Imager, GD and Image::Magick, so they are not available from their default repository.
511            
512             =head1 BUGS AND LIMITATIONS
513            
514             This is the first release and distinctly lacking in features :(
515             Although I'll be adding new features as time goes on :)
516             Hopefully others will also add new functions as well :D
517            
518             =head1 AUTHOR
519            
520             The Image::Mate interface is copyright 2007, Lyle Raymond Hopkins. It is
521             distributed under the same terms as Perl itself. See the "Artistic
522             License" in the Perl source code distribution for licensing terms.
523            
524             I welcome other programmers to submit new features to this module!!
525            
526             =head1 SEE ALSO
527            
528             L,
529             L,
530             L
531            
532             =cut
533            
534             1;
535            
536             __END__