comparison GD/Simple.pm @ 0:e94de0ea3351 draft default tip

Uploaded
author dereeper
date Wed, 11 Sep 2013 09:08:15 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:e94de0ea3351
1 package GD::Simple;
2
3 =head1 NAME
4
5 GD::Simple - Simplified interface to GD library
6
7 =head1 SYNOPSIS
8
9 use GD::Simple;
10
11 # create a new image
12 $img = GD::Simple->new(400,250);
13
14 # draw a red rectangle with blue borders
15 $img->bgcolor('red');
16 $img->fgcolor('blue');
17 $img->rectangle(10,10,50,50);
18
19 # draw an empty rectangle with green borders
20 $img->bgcolor(undef);
21 $img->fgcolor('green');
22 $img->rectangle(30,30,100,100);
23
24 # move to (80,80) and draw a green line to (100,190)
25 $img->moveTo(80,80);
26 $img->lineTo(100,190);
27
28 # draw a solid orange ellipse
29 $img->moveTo(110,100);
30 $img->bgcolor('orange');
31 $img->fgcolor('orange');
32 $img->ellipse(40,40);
33
34 # draw a black filled arc
35 $img->moveTo(150,150);
36 $img->fgcolor('black');
37 $img->arc(50,50,0,100,gdNoFill|gdEdged);
38
39 # draw a string at (10,180) using the default
40 # built-in font
41 $img->moveTo(10,180);
42 $img->string('This is very simple');
43
44 # draw a string at (280,210) using 20 point
45 # times italic, angled upward 90 degrees
46 $img->moveTo(280,210);
47 $img->font('Times:italic');
48 $img->fontsize(20);
49 $img->angle(-90);
50 $img->string('This is very fancy');
51
52 # some turtle graphics
53 $img->moveTo(300,100);
54 $img->penSize(3,3);
55 $img->angle(0);
56 $img->line(20); # 20 pixels going to the right
57 $img->turn(30); # set turning angle to 30 degrees
58 $img->line(20); # 20 pixel line
59 $img->line(20);
60 $img->line(20);
61 $img->turn(-90); # set turning angle to -90 degrees
62 $img->line(50); # 50 pixel line
63
64 # draw a cyan polygon edged in blue
65 my $poly = new GD::Polygon;
66 $poly->addPt(150,100);
67 $poly->addPt(199,199);
68 $poly->addPt(100,199);
69 $img->bgcolor('cyan');
70 $img->fgcolor('blue');
71 $img->penSize(1,1);
72 $img->polygon($poly);
73
74 # convert into png data
75 print $img->png;
76
77 =head1 DESCRIPTION
78
79 GD::Simple is a subclass of the GD library that shortens many of the
80 long GD method calls by storing information about the pen color, size
81 and position in the GD object itself. It also adds a small number of
82 "turtle graphics" style calls for those who prefer to work in polar
83 coordinates. In addition, the library allows you to use symbolic
84 names for colors, such as "chartreuse", and will manage the colors for
85 you.
86
87 =head2 The Pen
88
89 GD::Simple maintains a "pen" whose settings are used for line- and
90 shape-drawing operations. The pen has the following properties:
91
92 =over 4
93
94 =item fgcolor
95
96 The pen foreground color is the color of lines and the borders of
97 filled and unfilled shapes.
98
99 =item bgcolor
100
101 The pen background color is the color of the contents of filled
102 shapes.
103
104 =item pensize
105
106 The pen size is the width of the pen. Larger sizes draw thicker
107 lines.
108
109 =item position
110
111 The pen position is its current position on the canvas in (X,Y)
112 coordinates.
113
114 =item angle
115
116 When drawing in turtle mode, the pen angle determines the current
117 direction of lines of relative length.
118
119 =item turn
120
121 When drawing in turtle mode, the turn determines the clockwise or
122 counterclockwise angle that the pen will turn before drawing the next
123 line.
124
125 =item font
126
127 The font to use when drawing text. Both built-in bitmapped fonts and
128 TrueType fonts are supported.
129
130 =item fontsize
131
132 The size of the font to use when drawing with TrueType fonts.
133
134 =back
135
136 One sets the position and properties of the pen and then draws. As
137 the drawing progresses, the position of the pen is updated.
138
139 =head2 Methods
140
141 GD::Simple introduces a number of new methods, a few of which have the
142 same name as GD::Image methods, and hence change their behavior. In
143 addition to these new methods, GD::Simple objects support all of the
144 GD::Image methods. If you make a method call that isn't directly
145 supported by GD::Simple, it refers the request to the underlying
146 GD::Image object. Hence one can load a JPEG image into GD::Simple and
147 declare it to be TrueColor by using this call, which is effectively
148 inherited from GD::Image:
149
150 my $img = GD::Simple->newFromJpeg('./myimage.jpg',1);
151
152 The rest of this section describes GD::Simple-specific methods.
153
154 =cut
155
156 use strict;
157 use GD;
158 use GD::Group;
159 use Math::Trig;
160 use Carp 'croak';
161
162 our @ISA = 'Exporter';
163 our @EXPORT = @GD::EXPORT;
164 our @EXPORT_OK = @GD::EXPORT_OK;
165 our $AUTOLOAD;
166
167 my %COLORS;
168 my $IMAGECLASS = 'GD::Image';
169 my $TRANSPARENT;
170
171 sub AUTOLOAD {
172 my $self = shift;
173 my($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/;
174 return if $func_name eq 'DESTROY';
175
176 if (ref $self && exists $self->{gd}) {
177 $self->{gd}->$func_name(@_);
178 } else {
179 my @result = $IMAGECLASS->$func_name(@_);
180 if (UNIVERSAL::isa($result[0],'GD::Image')) {
181 return $self->new($result[0]);
182 } else {
183 return @result;
184 }
185 }
186 }
187
188 =over 4
189
190 =item $img = GD::Simple->new($x,$y [,$truecolor])
191
192 =item $img = GD::Simple->new($gd)
193
194 Create a new GD::Simple object. There are two forms of new(). In the
195 first form, pass the width and height of the desired canvas, and
196 optionally a boolean flag to request a truecolor image. In the second
197 form, pass a previously-created GD::Image object.
198
199 =cut
200
201 # dual-purpose code - beware
202 sub new {
203 my $pack = shift;
204
205 unshift @_,(100,100) if @_ == 0;
206
207 if (@_ >= 2) { # traditional GD::Image->new() call
208 my $gd = $IMAGECLASS->new(@_);
209 my $self = $pack->new($gd);
210 $self->clear;
211 return $self;
212 }
213
214 if (@_ == 1) { # initialize from existing image
215 my $gd = shift;
216 my $self = bless {
217 gd => $gd,
218 xy => [0,0],
219 font => gdSmallFont,
220 fontsize => 9,
221 turningangle => 0,
222 angle => 0,
223 pensize => 1,
224 },$pack;
225 $self->{bgcolor} = $self->translate_color(255,255,255);
226 $self->{fgcolor} = $self->translate_color(0,0,0);
227 return $self;
228 }
229 }
230
231 =item GD::Simple->class('GD');
232
233 =item GD::Simple->class('GD::SVG');
234
235 Select whether new() should use GD or GD::SVG internally. Call
236 GD::Simple->class('GD::SVG') before calling new() if you wish to
237 generate SVG images.
238
239 If future GD subclasses are created, this method will subport them.
240
241 =cut
242
243 sub class {
244 my $pack = shift;
245 if (@_) {
246 $IMAGECLASS = shift;
247 eval "require $IMAGECLASS; 1" or die $@;
248 $IMAGECLASS = "$IMAGECLASS\:\:Image"
249 if $IMAGECLASS eq 'GD::SVG';
250 }
251 $IMAGECLASS;
252 }
253
254 =item $img->moveTo($x,$y)
255
256 This call changes the position of the pen without drawing. It moves
257 the pen to position ($x,$y) on the drawing canvas.
258
259 =cut
260
261 sub moveTo {
262 my $self = shift;
263 croak 'Usage GD::Simple->moveTo($x,$y)' unless @_ == 2;
264 my ($x,$y) = @_;
265 $self->{xy} = [$x,$y];
266 }
267
268 =item $img->move($dx,$dy)
269
270 =item $img->move($dr)
271
272 This call changes the position of the pen without drawing. When called
273 with two arguments it moves the pen $dx pixels to the right and $dy
274 pixels downward. When called with one argument it moves the pen $dr
275 pixels along the vector described by the current pen angle.
276
277 =cut
278
279 sub move {
280 my $self = shift;
281 if (@_ == 1) { # polar coordinates -- this is r
282 $self->{angle} += $self->{turningangle};
283 my $angle = deg2rad($self->{angle});
284 $self->{xy}[0] += $_[0] * cos($angle);
285 $self->{xy}[1] += $_[0] * sin($angle);
286 }
287 elsif (@_ == 2) { # cartesian coordinates
288 $self->{xy}[0] += $_[0];
289 $self->{xy}[1] += $_[1];
290 } else {
291 croak 'Usage GD::Simple->move($dx,$dy) or move($r)';
292 }
293 }
294
295 =item $img->lineTo($x,$y)
296
297 The lineTo() call simultaneously draws and moves the pen. It draws a
298 line from the current pen position to the position defined by ($x,$y)
299 using the current pen size and color. After drawing, the position of
300 the pen is updated to the new position.
301
302 =cut
303
304 sub lineTo {
305 my $self = shift;
306 croak 'Usage GD::Simple->lineTo($x,$y)' unless @_ == 2;
307 $self->gd->line($self->curPos,@_,$self->fgcolor);
308 $self->moveTo(@_);
309 }
310
311 =item $img->line($dx,$dy)
312
313 =item $img->line($dr)
314
315 The line() call simultaneously draws and moves the pen. When called
316 with two arguments it draws a line from the current position of the
317 pen to the position $dx pixels to the right and $dy pixels down. When
318 called with one argument, it draws a line $dr pixels long along the
319 angle defined by the current pen angle.
320
321 =cut
322
323 sub line {
324 my $self = shift;
325 croak 'Usage GD::Simple->line($dx,$dy) or line($r)' unless @_ >= 1;
326 my @curPos = $self->curPos;
327 $self->move(@_);
328 my @newPos = $self->curPos;
329 $self->gd->line(@curPos,@newPos,$self->fgcolor);
330 }
331
332 =item $img->clear
333
334 This method clears the canvas by painting over it with the current
335 background color.
336
337 =cut
338
339 sub clear {
340 my $self = shift;
341 $self->gd->filledRectangle(0,0,$self->getBounds,$self->bgcolor);
342 }
343
344 =item $img->rectangle($x1,$y1,$x2,$y2)
345
346 This method draws the rectangle defined by corners ($x1,$y1),
347 ($x2,$y2). The rectangle's edges are drawn in the foreground color and
348 its contents are filled with the background color. To draw a solid
349 rectangle set bgcolor equal to fgcolor. To draw an unfilled rectangle
350 (transparent inside), set bgcolor to undef.
351
352 =cut
353
354 sub rectangle {
355 my $self = shift;
356 croak 'Usage GD::Simple->rectangle($x1,$y1,$x2,$y2)' unless @_ == 4;
357 my $gd = $self->gd;
358 my ($bg,$fg) = ($self->bgcolor,$self->fgcolor);
359 $gd->filledRectangle(@_,$bg) if defined $bg;
360 $gd->rectangle(@_,$fg) if defined $fg && (!defined $bg || $bg != $fg);
361 }
362
363 =item $img->ellipse($width,$height)
364
365 This method draws the ellipse centered at the current location with
366 width $width and height $height. The ellipse's border is drawn in the
367 foreground color and its contents are filled with the background
368 color. To draw a solid ellipse set bgcolor equal to fgcolor. To draw
369 an unfilled ellipse (transparent inside), set bgcolor to undef.
370
371 =cut
372
373 sub ellipse {
374 my $self = shift;
375 croak 'Usage GD::Simple->ellipse($width,$height)' unless @_ == 2;
376 my $gd = $self->gd;
377 my ($bg,$fg) = ($self->bgcolor,$self->fgcolor);
378 $gd->filledEllipse($self->curPos,@_,$bg) if defined $bg;
379 $gd->ellipse($self->curPos,@_,$fg) if defined $fg && (!defined $bg || $bg != $fg);
380 }
381
382 =item $img->arc($cx,$cy,$width,$height,$start,$end [,$style])
383
384 This method draws filled and unfilled arcs. See L<GD> for a
385 description of the arguments. To draw a solid arc (such as a pie
386 wedge) set bgcolor equal to fgcolor. To draw an unfilled arc, set
387 bgcolor to undef.
388
389 =cut
390
391 sub arc {
392 my $self = shift;
393 croak 'Usage GD::Simple->arc($width,$height,$start,$end,$style)' unless @_ >= 4;
394 my ($width,$height,$start,$end,$style) = @_;
395 my $gd = $self->gd;
396 my ($bg,$fg) = ($self->bgcolor,$self->fgcolor);
397 my ($cx,$cy) = $self->curPos;
398
399 if ($bg) {
400 my @args = ($cx,$cy,$width,$height,$start,$end,$bg);
401 push @args,$style if defined $style;
402 $gd->filledArc(@args);
403 } else {
404 my @args = ($cx,$cy,$width,$height,$start,$end,$fg);
405 $gd->arc(@args);
406 }
407 }
408
409 =item $img->polygon($poly)
410
411 This method draws filled and unfilled polygon using the current
412 settings of fgcolor for the polygon border and bgcolor for the polygon
413 fill color. See L<GD> for a description of creating polygons. To draw
414 a solid polygon set bgcolor equal to fgcolor. To draw an unfilled
415 polygon, set bgcolor to undef.
416
417 =cut
418
419 sub polygon {
420 my $self = shift;
421 croak 'Usage GD::Simple->polygon($poly)' unless @_ == 1;
422 my $gd = $self->gd;
423 my ($bg,$fg) = ($self->bgcolor,$self->fgcolor);
424 $gd->filledPolygon(@_,$bg) if defined $bg;
425 $gd->openPolygon(@_,$fg) if defined $fg && (!defined $bg || $bg != $fg);
426 }
427
428 =item $img->polyline($poly)
429
430 This method draws polygons without closing the first and last vertices
431 (similar to GD::Image->unclosedPolygon()). It uses the fgcolor to draw
432 the line.
433
434 =cut
435
436 sub polyline {
437 my $self = shift;
438 croak 'Usage GD::Simple->polyline($poly)' unless @_ == 1;
439 my $gd = $self->gd;
440 my $fg = $self->fgcolor;
441 $gd->unclosedPolygon(@_,$fg);
442 }
443
444 =item $img->string($string)
445
446 This method draws the indicated string starting at the current
447 position of the pen. The pen is moved to the end of the drawn string.
448 Depending on the font selected with the font() method, this will use
449 either a bitmapped GD font or a TrueType font. The angle of the pen
450 will be consulted when drawing the text. For TrueType fonts, any angle
451 is accepted. For GD bitmapped fonts, the angle can be either 0 (draw
452 horizontal) or -90 (draw upwards).
453
454 For consistency between the TrueType and GD font behavior, the string
455 is always drawn so that the current position of the pen corresponds to
456 the bottom left of the first character of the text. This is different
457 from the GD behavior, in which the first character of bitmapped fonts
458 hangs down from the pen point.
459
460 This method returns a polygon indicating the bounding box of the
461 rendered text. If an error occurred (such as invalid font
462 specification) it returns undef and an error message in $@.
463
464 =cut
465
466 sub string {
467 my $self = shift;
468 my $string = shift;
469 my $font = $self->font;
470 my @bounds;
471 if (ref $font && $font->isa('GD::Font')) {
472 my ($x,$y) = $self->curPos;
473 if ($self->angle == -90) {
474 $x -= $font->height;
475 $y -= $font->width;
476 $self->gd->stringUp($font,$x,$y,$string,$self->fgcolor);
477 $self->{xy}[1] -= length($string) * $font->width;
478 @bounds = ( ($self->{xy}[0],$y), ($x,$y), ($x,$self->{xy}[1]-$font->width), ($self->{xy}[0],$self->{xy}[1]-$font->width) );
479 } else {
480 $y -= $font->height;
481 $self->gd->string($font,$x,$y,$string,$self->fgcolor);
482 $self->{xy}[0] += length($string) * $font->width;
483 @bounds = ( ($x,$self->{xy}[1]), ($self->{xy}[0],$self->{xy}[1]), ($self->{xy}[0],$y), ($x,$y) );
484 }
485 }
486 else {
487 $self->useFontConfig(1);
488 @bounds = $self->stringFT($self->fgcolor,$font,
489 $self->fontsize,-deg2rad($self->angle), # -pi * $self->angle/180,
490 $self->curPos,$string);
491 return unless @bounds;
492 my ($delta_x,$delta_y) = $self->_string_width(@bounds);
493 $self->{xy}[0] += $delta_x;
494 $self->{xy}[1] += $delta_y;
495 }
496 my $poly = GD::Polygon->new;
497 while (@bounds) {
498 $poly->addPt(splice(@bounds,0,2));
499 }
500 return $poly;
501 }
502
503 =item $metrics = $img->fontMetrics
504
505 =item ($metrics,$width,$height) = GD::Simple->fontMetrics($font,$fontsize,$string)
506
507 This method returns information about the current font, most commonly
508 a TrueType font. It can be invoked as an instance method (on a
509 previously-created GD::Simple object) or as a class method (on the
510 'GD::Simple' class).
511
512 When called as an instance method, fontMetrics() takes no arguments
513 and returns a single hash reference containing the metrics that
514 describe the currently selected font and size. The hash reference
515 contains the following information:
516
517 xheight the base height of the font from the bottom to the top of
518 a lowercase 'm'
519
520 ascent the length of the upper stem of the lowercase 'd'
521
522 descent the length of the lower step of the lowercase 'j'
523
524 lineheight the distance from the bottom of the 'j' to the top of
525 the 'd'
526
527 leading the distance between two adjacent lines
528
529 =cut
530
531 # return %$fontmetrics
532 # keys: 'ascent', 'descent', 'lineheight', 'xheight', 'leading'
533 sub fontMetrics {
534 my $self = shift;
535
536 unless (ref $self) { #class invocation -- create a scratch
537 $self = $self->new;
538 $self->font(shift) if defined $_[0];
539 $self->fontsize(shift) if defined $_[0];
540 }
541
542 my $font = $self->font;
543 my $metrics;
544
545 if (ref $font && $font->isa('GD::Font')) {
546 my $height = $font->height;
547 $metrics = {ascent => 0,
548 descent => 0,
549 lineheight => $height,
550 xheight => $height,
551 leading => 0};
552 }
553 else {
554 $self->useFontConfig(1);
555 my @mbounds = GD::Image->stringFT($self->fgcolor,$font,
556 $self->fontsize,0,
557 0,0,'m');
558 my $xheight = $mbounds[3]-$mbounds[5];
559 my @jbounds = GD::Image->stringFT($self->fgcolor,$font,
560 $self->fontsize,0,
561 0,0,'j');
562 my $ascent = $mbounds[7]-$jbounds[7];
563 my $descent = $jbounds[3]-$mbounds[3];
564
565 my @mmbounds = GD::Image->stringFT($self->fgcolor,$font,
566 $self->fontsize,0,
567 0,0,"m\nm");
568 my $twolines = $mmbounds[3]-$mmbounds[5];
569 my $lineheight = $twolines - 2*$xheight;
570 my $leading = $lineheight - $ascent - $descent;
571 $metrics = {ascent => $ascent,
572 descent => $descent,
573 lineheight => $lineheight,
574 xheight => $xheight,
575 leading => $leading};
576 }
577
578 if ((my $string = shift) && wantarray) {
579 my ($width,$height) = $self->stringBounds($string);
580 return ($metrics,abs($width),abs($height));
581 }
582 return $metrics;
583 }
584
585 =item ($delta_x,$delta_y)= $img->stringBounds($string)
586
587 This method indicates the X and Y offsets (which may be negative) that
588 will occur when the given string is drawn using the current font,
589 fontsize and angle. When the string is drawn horizontally, it gives
590 the width and height of the string's bounding box.
591
592 =cut
593
594 sub stringBounds {
595 my $self = shift;
596 my $string = shift;
597 my $font = $self->font;
598 if (ref $font && $font->isa('GD::Font')) {
599 if ($self->angle == -90) {
600 return ($font->height,-length($string) * $font->width);
601 } else {
602 return (length($string) * $font->width,$font->height);
603 }
604 }
605 else {
606 $self->useFontConfig(1);
607 my @bounds = GD::Image->stringFT($self->fgcolor,$font,
608 $self->fontsize,-deg2rad($self->angle),
609 $self->curPos,$string);
610 return $self->_string_width(@bounds);
611 }
612 }
613
614 =item $delta_x = $img->stringWidth($string)
615
616 This method indicates the width of the string given the current font,
617 fontsize and angle. It is the same as ($img->stringBounds($string))[0]
618
619 =cut
620
621 sub stringWidth {
622 return ((shift->stringBounds(@_))[0]);
623 }
624
625
626 sub _string_width {
627 my $self = shift;
628 my @bounds = @_;
629 my $delta_x = abs($bounds[2]-$bounds[0]);
630 my $delta_y = abs($bounds[5]-$bounds[3]);
631 my $angle = $self->angle % 360;
632 if ($angle >= 0 && $angle < 90) {
633 return ($delta_x,$delta_y);
634
635 } elsif ($angle >= 90 && $angle < 180) {
636 return (-$delta_x,$delta_y);
637
638 } elsif ($angle >= 180 && $angle < 270) {
639 return (-$delta_x,-$delta_y);
640
641 } elsif ($angle >= 270 && $angle < 360) {
642 return ($delta_x,-$delta_y);
643 }
644 }
645
646 =item ($x,$y) = $img->curPos
647
648 Return the current position of the pen. Set the current position
649 using moveTo().
650
651 =cut
652
653 sub curPos { @{shift->{xy}}; }
654
655 =item $font = $img->font([$newfont] [,$newsize])
656
657 Get or set the current font. Fonts can be GD::Font objects, TrueType
658 font file paths, or fontconfig font patterns like "Times:italic" (see
659 L<fontconfig>). The latter feature requires that you have the
660 fontconfig library installed and are using libgd version 2.0.33 or
661 higher.
662
663 As a shortcut, you may pass two arguments to set the font and the
664 fontsize simultaneously. The fontsize is only valid when drawing with
665 TrueType fonts.
666
667 =cut
668
669 sub font {
670 my $self = shift;
671 $self->{font} = shift if @_;
672 $self->{fontsize} = shift if @_;
673 $self->{font};
674 }
675
676 =item $size = $img->fontsize([$newfontsize])
677
678 Get or set the current font size. This is only valid for TrueType
679 fonts.
680
681 =cut
682
683 sub fontsize {
684 my $self = shift;
685 $self->{fontsize} = shift if @_;
686 $self->{fontsize};
687 }
688
689 =item $size = $img->penSize([$newpensize])
690
691 Get or set the current pen width for use during line drawing
692 operations.
693
694 =cut
695
696 sub penSize {
697 my $self = shift;
698 if (@_) {
699 $self->{pensize} = shift;
700 $self->gd->setThickness($self->{pensize});
701 }
702 $self->{pensize};
703 }
704
705 =item $angle = $img->angle([$newangle])
706
707 Set the current angle for use when calling line() or move() with a
708 single argument.
709
710 Here is an example of using turn() and angle() together to draw an
711 octagon. The first line drawn is the downward-slanting top right
712 edge. The last line drawn is the horizontal top of the octagon.
713
714 $img->moveTo(200,50);
715 $img->angle(0);
716 $img->turn(360/8);
717 for (1..8) { $img->line(50) }
718
719 =cut
720
721 sub angle {
722 my $self = shift;
723 $self->{angle} = shift if @_;
724 $self->{angle};
725 }
726
727 =item $angle = $img->turn([$newangle])
728
729 Get or set the current angle to turn prior to drawing lines. This
730 value is only used when calling line() or move() with a single
731 argument. The turning angle will be applied to each call to line() or
732 move() just before the actual drawing occurs.
733
734 Angles are in degrees. Positive values turn the angle clockwise.
735
736 =cut
737
738 # degrees, not radians
739 sub turn {
740 my $self = shift;
741 $self->{turningangle} = shift if @_;
742 $self->{turningangle};
743 }
744
745 =item $color = $img->fgcolor([$newcolor])
746
747 Get or set the pen's foreground color. The current pen color can be
748 set by (1) using an (r,g,b) triple; (2) using a previously-allocated
749 color from the GD palette; or (3) by using a symbolic color name such
750 as "chartreuse." The list of color names can be obtained using
751 color_names(). The special color name 'transparent' will create a
752 completely transparent color.
753
754 =cut
755
756 sub fgcolor {
757 my $self = shift;
758 $self->{fgcolor} = $self->translate_color(@_) if @_;
759 $self->{fgcolor};
760 }
761
762 =item $color = $img->bgcolor([$newcolor])
763
764 Get or set the pen's background color. The current pen color can be
765 set by (1) using an (r,g,b) triple; (2) using a previously-allocated
766 color from the GD palette; or (3) by using a symbolic color name such
767 as "chartreuse." The list of color names can be obtained using
768 color_names(). The special color name 'transparent' will create a
769 completely transparent color.
770
771 =cut
772
773 sub bgcolor {
774 my $self = shift;
775 $self->{bgcolor} = $self->translate_color(@_) if @_;
776 $self->{bgcolor};
777 }
778
779 =item $index = $img->translate_color(@args)
780
781 Translates a color into a GD palette or TrueColor index. You may pass
782 either an (r,g,b) triple or a symbolic color name. If you pass a
783 previously-allocated index, the method will return it unchanged.
784
785 =cut
786
787 sub translate_color {
788 my $self = shift;
789 return unless defined $_[0];
790 my ($r,$g,$b);
791 if (@_ == 1 && $_[0] =~ /^-?\d+/) { # previously allocated index
792 return $_[0];
793 }
794 elsif (@_ == 3) { # (rgb triplet)
795 ($r,$g,$b) = @_;
796 }
797 elsif (lc $_[0] eq 'transparent') {
798 return $TRANSPARENT ||= $self->alphaColor('white',127);
799 }
800 else {
801 $self->read_color_table unless %COLORS;
802 die "unknown color" unless exists $COLORS{lc $_[0]};
803 ($r,$g,$b) = @{$COLORS{lc $_[0]}};
804 }
805 return $self->colorResolve($r,$g,$b);
806 }
807
808 sub transparent {
809 my $self = shift;
810 my $index = $self->translate_color(@_);
811 $self->gd->transparent($index);
812 }
813
814 =item $index = $img->alphaColor(@args,$alpha)
815
816 Creates an alpha color. You may pass either an (r,g,b) triple or a
817 symbolic color name, followed by an integer indicating its
818 opacity. The opacity value ranges from 0 (fully opaque) to 127 (fully
819 transparent).
820
821 =cut
822
823 sub alphaColor {
824 my $self = shift;
825 return unless defined $_[0];
826 my ($r,$g,$b,$a);
827 if (@_ == 4) { # (rgb triplet)
828 ($r,$g,$b,$a) = @_;
829 } else {
830 $self->read_color_table unless %COLORS;
831 die "unknown color" unless exists $COLORS{lc $_[0]};
832 ($r,$g,$b) = @{$COLORS{lc $_[0]}};
833 $a = $_[1];
834 }
835 return $self->colorAllocateAlpha($r,$g,$b,$a);
836 }
837
838 =item @names = GD::Simple->color_names
839
840 =item $translate_table = GD::Simple->color_names
841
842 Called in a list context, color_names() returns the list of symbolic
843 color names recognized by this module. Called in a scalar context,
844 the method returns a hash reference in which the keys are the color
845 names and the values are array references containing [r,g,b] triples.
846
847 =cut
848
849 sub color_names {
850 my $self = shift;
851 $self->read_color_table unless %COLORS;
852 return wantarray ? sort keys %COLORS : \%COLORS;
853 }
854
855 =item $gd = $img->gd
856
857 Return the internal GD::Image object. Usually you will not need to
858 call this since all GD methods are automatically referred to this object.
859
860 =cut
861
862 sub gd { shift->{gd} }
863
864 sub read_color_table {
865 my $class = shift;
866 while (<DATA>) {
867 chomp;
868 last if /^__END__/;
869 my ($name,$r,$g,$b) = split /\s+/;
870 $COLORS{$name} = [hex $r,hex $g,hex $b];
871 }
872 }
873
874 sub setBrush {
875 my $self = shift;
876 my $brush = shift;
877 if ($brush->isa('GD::Simple')) {
878 $self->gd->setBrush($brush->gd);
879 } else {
880 $self->gd->setBrush($brush);
881 }
882 }
883
884 =item ($red,$green,$blue) = GD::Simple->HSVtoRGB($hue,$saturation,$value)
885
886 Convert a Hue/Saturation/Value (HSV) color into an RGB triple. The
887 hue, saturation and value are integers from 0 to 255.
888
889 =cut
890
891 sub HSVtoRGB {
892 my $self = shift;
893 @_ == 3 or croak "Usage: GD::Simple->HSVtoRGB(\$hue,\$saturation,\$value)";
894
895 my ($h,$s,$v)=@_;
896 my ($r,$g,$b,$i,$f,$p,$q,$t);
897
898 if( $s == 0 ) {
899 ## achromatic (grey)
900 return ($v,$v,$v);
901 }
902 $h %= 255;
903 $s /= 255; ## scale saturation from 0.0-1.0
904 $h /= 255; ## scale hue from 0 to 1.0
905 $h *= 360; ## and now scale it to 0 to 360
906
907 $h /= 60; ## sector 0 to 5
908 $i = $h % 6;
909 $f = $h - $i; ## factorial part of h
910 $p = $v * ( 1 - $s );
911 $q = $v * ( 1 - $s * $f );
912 $t = $v * ( 1 - $s * ( 1 - $f ) );
913
914 if($i<1) {
915 $r = $v;
916 $g = $t;
917 $b = $p;
918 } elsif($i<2){
919 $r = $q;
920 $g = $v;
921 $b = $p;
922 } elsif($i<3){
923 $r = $p;
924 $g = $v;
925 $b = $t;
926 } elsif($i<4){
927 $r = $p;
928 $g = $q;
929 $b = $v;
930 } elsif($i<5){
931 $r = $t;
932 $g = $p;
933 $b = $v;
934 } else {
935 $r = $v;
936 $g = $p;
937 $b = $q;
938 }
939 return (int($r+0.5),int($g+0.5),int($b+0.5));
940 }
941
942 =item ($hue,$saturation,$value) = GD::Simple->RGBtoHSV($hue,$saturation,$value)
943
944 Convert a Red/Green/Blue (RGB) value into a Hue/Saturation/Value (HSV)
945 triple. The hue, saturation and value are integers from 0 to 255.
946
947 =back
948
949 =cut
950
951 sub RGBtoHSV {
952 my $self = shift;
953 my ($r, $g ,$bl) = @_;
954 my ($min,undef,$max) = sort {$a<=>$b} ($r,$g,$bl);
955 return (0,0,0) unless $max > 0;
956
957 my $v = $max;
958 my $s = 255 * ($max - $min)/$max;
959 my $h;
960 my $range = $max - $min;
961
962 if ($range == 0) { # all colors are equal, so monochrome
963 return (0,0,$max);
964 }
965
966 if ($max == $r) {
967 $h = 60 * ($g-$bl)/$range;
968 }
969 elsif ($max == $g) {
970 $h = 60 * ($bl-$r)/$range + 120;
971 }
972 else {
973 $h = 60 * ($r-$g)/$range + 240;
974 }
975
976 $h = int($h*255/360 + 0.5);
977
978 return ($h, $s, $v);
979 }
980
981 sub newGroup {
982 my $self = shift;
983 return $self->GD::newGroup(@_);
984 }
985
986 1;
987
988 __DATA__
989 white FF FF FF
990 black 00 00 00
991 aliceblue F0 F8 FF
992 antiquewhite FA EB D7
993 aqua 00 FF FF
994 aquamarine 7F FF D4
995 azure F0 FF FF
996 beige F5 F5 DC
997 bisque FF E4 C4
998 blanchedalmond FF EB CD
999 blue 00 00 FF
1000 blueviolet 8A 2B E2
1001 brown A5 2A 2A
1002 burlywood DE B8 87
1003 cadetblue 5F 9E A0
1004 chartreuse 7F FF 00
1005 chocolate D2 69 1E
1006 coral FF 7F 50
1007 cornflowerblue 64 95 ED
1008 cornsilk FF F8 DC
1009 crimson DC 14 3C
1010 cyan 00 FF FF
1011 darkblue 00 00 8B
1012 darkcyan 00 8B 8B
1013 darkgoldenrod B8 86 0B
1014 darkgray A9 A9 A9
1015 darkgreen 00 64 00
1016 darkkhaki BD B7 6B
1017 darkmagenta 8B 00 8B
1018 darkolivegreen 55 6B 2F
1019 darkorange FF 8C 00
1020 darkorchid 99 32 CC
1021 darkred 8B 00 00
1022 darksalmon E9 96 7A
1023 darkseagreen 8F BC 8F
1024 darkslateblue 48 3D 8B
1025 darkslategray 2F 4F 4F
1026 darkturquoise 00 CE D1
1027 darkviolet 94 00 D3
1028 deeppink FF 14 100
1029 deepskyblue 00 BF FF
1030 dimgray 69 69 69
1031 dodgerblue 1E 90 FF
1032 firebrick B2 22 22
1033 floralwhite FF FA F0
1034 forestgreen 22 8B 22
1035 fuchsia FF 00 FF
1036 gainsboro DC DC DC
1037 ghostwhite F8 F8 FF
1038 gold FF D7 00
1039 goldenrod DA A5 20
1040 gray 80 80 80
1041 green 00 80 00
1042 greenyellow AD FF 2F
1043 honeydew F0 FF F0
1044 hotpink FF 69 B4
1045 indianred CD 5C 5C
1046 indigo 4B 00 82
1047 ivory FF FF F0
1048 khaki F0 E6 8C
1049 lavender E6 E6 FA
1050 lavenderblush FF F0 F5
1051 lawngreen 7C FC 00
1052 lemonchiffon FF FA CD
1053 lightblue AD D8 E6
1054 lightcoral F0 80 80
1055 lightcyan E0 FF FF
1056 lightgoldenrodyellow FA FA D2
1057 lightgreen 90 EE 90
1058 lightgrey D3 D3 D3
1059 lightpink FF B6 C1
1060 lightsalmon FF A0 7A
1061 lightseagreen 20 B2 AA
1062 lightskyblue 87 CE FA
1063 lightslategray 77 88 99
1064 lightsteelblue B0 C4 DE
1065 lightyellow FF FF E0
1066 lime 00 FF 00
1067 limegreen 32 CD 32
1068 linen FA F0 E6
1069 magenta FF 00 FF
1070 maroon 80 00 00
1071 mediumaquamarine 66 CD AA
1072 mediumblue 00 00 CD
1073 mediumorchid BA 55 D3
1074 mediumpurple 100 70 DB
1075 mediumseagreen 3C B3 71
1076 mediumslateblue 7B 68 EE
1077 mediumspringgreen 00 FA 9A
1078 mediumturquoise 48 D1 CC
1079 mediumvioletred C7 15 85
1080 midnightblue 19 19 70
1081 mintcream F5 FF FA
1082 mistyrose FF E4 E1
1083 moccasin FF E4 B5
1084 navajowhite FF DE AD
1085 navy 00 00 80
1086 oldlace FD F5 E6
1087 olive 80 80 00
1088 olivedrab 6B 8E 23
1089 orange FF A5 00
1090 orangered FF 45 00
1091 orchid DA 70 D6
1092 palegoldenrod EE E8 AA
1093 palegreen 98 FB 98
1094 paleturquoise AF EE EE
1095 palevioletred DB 70 100
1096 papayawhip FF EF D5
1097 peachpuff FF DA B9
1098 peru CD 85 3F
1099 pink FF C0 CB
1100 plum DD A0 DD
1101 powderblue B0 E0 E6
1102 purple 80 00 80
1103 red FF 00 00
1104 rosybrown BC 8F 8F
1105 royalblue 41 69 E1
1106 saddlebrown 8B 45 13
1107 salmon FA 80 72
1108 sandybrown F4 A4 60
1109 seagreen 2E 8B 57
1110 seashell FF F5 EE
1111 sienna A0 52 2D
1112 silver C0 C0 C0
1113 skyblue 87 CE EB
1114 slateblue 6A 5A CD
1115 slategray 70 80 90
1116 snow FF FA FA
1117 springgreen 00 FF 7F
1118 steelblue 46 82 B4
1119 tan D2 B4 8C
1120 teal 00 80 80
1121 thistle D8 BF D8
1122 tomato FF 63 47
1123 turquoise 40 E0 D0
1124 violet EE 82 EE
1125 wheat F5 DE B3
1126 whitesmoke F5 F5 F5
1127 yellow FF FF 00
1128 yellowgreen 9A CD 32
1129 gradient1 00 ff 00
1130 gradient2 0a ff 00
1131 gradient3 14 ff 00
1132 gradient4 1e ff 00
1133 gradient5 28 ff 00
1134 gradient6 32 ff 00
1135 gradient7 3d ff 00
1136 gradient8 47 ff 00
1137 gradient9 51 ff 00
1138 gradient10 5b ff 00
1139 gradient11 65 ff 00
1140 gradient12 70 ff 00
1141 gradient13 7a ff 00
1142 gradient14 84 ff 00
1143 gradient15 8e ff 00
1144 gradient16 99 ff 00
1145 gradient17 a3 ff 00
1146 gradient18 ad ff 00
1147 gradient19 b7 ff 00
1148 gradient20 c1 ff 00
1149 gradient21 cc ff 00
1150 gradient22 d6 ff 00
1151 gradient23 e0 ff 00
1152 gradient24 ea ff 00
1153 gradient25 f4 ff 00
1154 gradient26 ff ff 00
1155 gradient27 ff f4 00
1156 gradient28 ff ea 00
1157 gradient29 ff e0 00
1158 gradient30 ff d6 00
1159 gradient31 ff cc 00
1160 gradient32 ff c1 00
1161 gradient33 ff b7 00
1162 gradient34 ff ad 00
1163 gradient35 ff a3 00
1164 gradient36 ff 99 00
1165 gradient37 ff 8e 00
1166 gradient38 ff 84 00
1167 gradient39 ff 7a 00
1168 gradient40 ff 70 00
1169 gradient41 ff 65 00
1170 gradient42 ff 5b 00
1171 gradient43 ff 51 00
1172 gradient44 ff 47 00
1173 gradient45 ff 3d 00
1174 gradient46 ff 32 00
1175 gradient47 ff 28 00
1176 gradient48 ff 1e 00
1177 gradient49 ff 14 00
1178 gradient50 ff 0a 00
1179 __END__
1180
1181 =head1 COLORS
1182
1183 This script will create an image showing all the symbolic colors.
1184
1185 #!/usr/bin/perl
1186
1187 use strict;
1188 use GD::Simple;
1189
1190 my @color_names = GD::Simple->color_names;
1191 my $cols = int(sqrt(@color_names));
1192 my $rows = int(@color_names/$cols)+1;
1193
1194 my $cell_width = 100;
1195 my $cell_height = 50;
1196 my $legend_height = 16;
1197 my $width = $cols * $cell_width;
1198 my $height = $rows * $cell_height;
1199
1200 my $img = GD::Simple->new($width,$height);
1201 $img->font(gdSmallFont);
1202
1203 for (my $c=0; $c<$cols; $c++) {
1204 for (my $r=0; $r<$rows; $r++) {
1205 my $color = $color_names[$c*$rows + $r] or next;
1206 my @topleft = ($c*$cell_width,$r*$cell_height);
1207 my @botright = ($topleft[0]+$cell_width,$topleft[1]+$cell_height-$legend_height);
1208 $img->bgcolor($color);
1209 $img->fgcolor($color);
1210 $img->rectangle(@topleft,@botright);
1211 $img->moveTo($topleft[0]+2,$botright[1]+$legend_height-2);
1212 $img->fgcolor('black');
1213 $img->string($color);
1214 }
1215 }
1216
1217 print $img->png;
1218
1219 =head1 AUTHOR
1220
1221 The GD::Simple module is copyright 2004, Lincoln D. Stein. It is
1222 distributed under the same terms as Perl itself. See the "Artistic
1223 License" in the Perl source code distribution for licensing terms.
1224
1225 The latest versions of GD.pm are available at
1226
1227 http://stein.cshl.org/WWW/software/GD
1228
1229 =head1 SEE ALSO
1230
1231 L<GD>,
1232 L<GD::Polyline>,
1233 L<GD::SVG>,
1234 L<Image::Magick>
1235
1236 =cut