File Coverage

blib/lib/Color/Model/RGB.pm
Criterion Covered Total %
statement 177 206 85.9
branch 48 80 60.0
condition 16 43 37.2
subroutine 41 42 97.6
pod 14 26 53.8
total 296 397 74.5


line stmt bran cond sub pod time code
1             # =============================================================================
2             package Color::Model::RGB;
3             # -----------------------------------------------------------------------------
4             $Color::Model::RGB::VERSION = '1.02';
5             # -----------------------------------------------------------------------------
6 4     4   201391 use warnings;
  4         10  
  4         159  
7 4     4   25 use strict;
  4         9  
  4         203  
8              
9             =head1 NAME
10              
11             Color::Model::RGB - Color model of RGB
12              
13             =head1 SYNOPSIS
14              
15             $navy = rgb(0, 0, 0.5);
16             $limegreen = rgb('#32CD32');
17              
18             # use Color::Model::RGB qw(:primary);
19             $white = R + G + B; # addition (Constant O and W are also prepared)
20             $yellow = $white - $b; # subtraction
21             $midgray = $while / 2; # divide
22             $hilight = $midgray * 1.5; # multiply
23             print qq(see); # stringify
24              
25             @rgbval = $color->array(); # decimal
26             @rgb256 = $color->array256(); # integers
27              
28             # applying ...
29             @gradation = map { rgb('#010101') << $_ } (0..7);
30             @tricolor = ( $c, rgb(($c->array)[1,2,0]), rgb(($c->array)[2,0,1]) );
31              
32             # use Color::Model::RGB qw(:blender);
33             $violet = blend_half(R, B);
34             $pink = blend_plus(R, $hilight);
35              
36             =head1 DESCRIPTION
37              
38             Color::Model::RGB is a color model of RGB implemented by 3D mathematical
39             vector.
40             This provides abstruct calculation for colors with overloding and methods
41             to convert values to simply hexadecimal string designed for HTML, CSS and etc.
42              
43             Color::Model::RGB is based on B.
44              
45             =cut
46              
47             # =============================================================================
48 4     4   31 use Carp;
  4         12  
  4         409  
49 4     4   3949 use POSIX qw(ceil);
  4         48419  
  4         49  
50 4     4   6173 use Scalar::Util ();
  4         12  
  4         132  
51              
52 4     4   22 use base qw(Math::VectorReal Exporter);
  4         9  
  4         6113  
53             our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
54             @EXPORT = qw( rgb rgb256 rgbhex );
55             @EXPORT_OK = qw( O R G B W
56             set_format get_format
57             blend_alpha blend_half blend_plus blend_minus
58             );
59             %EXPORT_TAGS = (
60             primary => [ qw(O R G B W) ], RGB => [ qw(O R G B W) ],
61             format => [ qw(set_format get_format) ],
62             blender => [ qw(blend_alpha blend_half blend_plus blend_minus) ],
63             all => [@EXPORT, @EXPORT_OK],
64             );
65              
66              
67             our $FORMAT = '%02x%02x%02x';
68             our $FORMAT_HEXED = 1; # flag of magic to represent hexadecimal numbers.
69              
70              
71              
72             # =============================================================================
73              
74             =head1 CONSTANTS
75              
76             Some primary colors below are defined as constant. To use these, import them
77             with tag ':primary' or ':RGB'
78              
79             # R G B
80             O = [ 0 0 0 ]
81             R = [ 1 0 0 ]
82             G = [ 0 1 0 ]
83             B = [ 0 0 1 ]
84             W = [ 1 1 1 ]
85              
86             =cut
87              
88             # -----------------------------------------------------------------------------
89 2     2 0 359 sub O() { bless __PACKAGE__->SUPER::O(), __PACKAGE__ }
90 4     4 0 47 sub R() { bless __PACKAGE__->SUPER::X(), __PACKAGE__ }
91 4     4 0 49 sub G() { bless __PACKAGE__->SUPER::Y(), __PACKAGE__ }
92 4     4 0 95 sub B() { bless __PACKAGE__->SUPER::Z(), __PACKAGE__ }
93 3     3 0 164 sub W() { bless [ [[1,1,1]], 1,3 ], __PACKAGE__; }
94              
95              
96              
97              
98             # =============================================================================
99              
100             =head1 CONSTRUCTORS
101              
102             $col1 = Color::Model::RGB->new(0.1, 0.2, 0.3);
103             $col2 = rgb(0.5,0.6,0.7);
104             $col3 = rgb256(128,128,255);
105             $col3 = rgbhex('0080ff'); # rgbhex('#0080ff') is also ok.
106             # and rgb($hexstr) is also ok.
107             $col4 = $col1->clone();
108              
109             There are functions to make an object.
110              
111             Method I, I and I are defalut exported functions
112             returns new Color::Model::RGB object as I.
113              
114             Method I and I require three decimal values as arguments. Values
115             out of a range, from -1.0 to 1.0, will be set -1.0 or 1.0.
116             If one argument is given to I, it will be treated as a hexadecimal
117             string and call I internaly.
118              
119             Method I requires three integer values from -255 to 255. Out of range
120             value will be set -255 or 255.
121              
122             Method I requires a hexadecimal string like HTML format. An argument
123             starts with '#' is also allowed.
124              
125             I returns new copy of object.
126              
127             =cut
128              
129             # -----------------------------------------------------------------------------
130             sub new
131             {
132 88     88 1 1627 my $class = shift;
133 88   100     257 my $ref = ref($class) || __PACKAGE__;
134 88         412 return bless __PACKAGE__->SUPER::new(@_), $ref;
135             }
136              
137             sub rgb
138             {
139 5 50   5 0 23 if ( !ref($_[0]) ){
140 5 50       21 if ( @_ == 1 ){
141             # Assume hex string is given
142 0         0 return rgbhex($_[0]);
143             }
144             } else {
145 0         0 shift;
146             }
147 15 50       82 my @rgb = map {
    50          
148 5         12 ($_ < -1)? -1:
149             ($_ > 1)? 1:
150             $_
151             } @_;
152 5         35 return bless __PACKAGE__->SUPER::new(@rgb), __PACKAGE__;
153             }
154              
155             sub rgb256
156             {
157 12 50   12 0 34 shift if ( @_ == 4 );
158 36 100       143 my @rgb = map {
    50          
159 12         19 ($_ < -255)? -1:
160             ($_ > 255)? 1:
161             ($_/255)
162             } @_;
163 12         51 return bless __PACKAGE__->SUPER::new(@rgb), __PACKAGE__;
164             }
165              
166             sub rgbhex
167             {
168 1     1 0 4 my $h = lc(shift);
169 1 50 33     26 if ( defined($h) && $h =~ /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/ ){
170 3         16 return bless __PACKAGE__->SUPER::new(
171 1         3 map { hex($_)/255 } ($1,$2,$3)
172             ), __PACKAGE__;
173             } else {
174 0         0 Carp::croak("rgbHex() needs a hex values argument. ($h was given)");
175             }
176             }
177              
178              
179             # =============================================================================
180              
181             =head1 METHODS
182              
183             =over
184              
185             =item r(), g(), b()
186              
187             Returns decimal value of an element.
188              
189             =item r256(), g256(), b256()
190              
191             Returns integer value of an element, which is multiplyed by 255 and rounded by
192             I.
193              
194             =item array()
195             =item array256()
196              
197             These methods return an array contains values of elements. I
198             returns values multiplyed by 255 and rounded by I.
199              
200             =item hexstr([ $head_letter ])
201              
202             Returns 6 digits hexadecimal string. If some string is given as argument,
203             value starting with it returns.
204              
205             =item truncate(), limit()
206              
207             These methods return new clone object, values of elements of which are set in
208             regulated range. I makes a values lesser than 0 set to 0, and
209             grater than 1 set to 1. And I set values from -1 to 1 similarly.
210              
211             =item stringify( [ $format [, $flag2hex] ] )
212              
213             This method can take 2 arguments. The first is format string for I,
214             and the second is a boolean flag to convert to hexadecimal or not. If this
215             flag is true, values multiplyed by 255 will be used at outputing.
216             Default values of the format and the flag are keeped by package variable;
217              
218             $Color::Model::RGB::FORMAT = "%02x%02x%02x";
219             $Color::Model::RGB::FORMAT_HEXED = 1;
220              
221             Arguments are omitted at I calling, these defalut values will be
222             used.
223              
224             Function I and I describing below gives a way to
225             change these defalut values simply.
226              
227             =back
228              
229             =cut
230              
231             # -----------------------------------------------------------------------------
232             sub _treat_elem
233             {
234 36     36   140 my $self = shift;
235 36         59 my $colno= shift;
236 36 100       104 if ( !@_ ){
    50          
237 33         420 return $self->[0][0][$colno];
238             } elsif ( @_ == 1 ){
239 3         12 $self->[0][0][$colno] = $_[0];
240             } else {
241 0         0 Carp::carp("Too many arguments. Ignored");
242             }
243             }
244              
245 12     12 1 81 sub r { my $self = shift; return _treat_elem($self,0,@_) }
  12         36  
246 12     12 1 39 sub g { my $self = shift; return _treat_elem($self,1,@_) }
  12         29  
247 12     12 1 50 sub b { my $self = shift; return _treat_elem($self,2,@_) }
  12         28  
248              
249 5     5 1 23 sub r256 { ceil($_[0]->r * 255) }
250 5     5 1 32 sub g256 { ceil($_[0]->g * 255) }
251 5     5 1 34 sub b256 { ceil($_[0]->b * 255) }
252              
253              
254             sub array256
255             {
256 57     57 1 81 my $v = shift;
257 57         74 return map {ceil($_ * 255)} @{$v->[0][0]};
  171         938  
  57         134  
258             }
259              
260             sub hexstr
261             {
262 27     27 1 380 my( $v, $head ) = @_;
263 27   50     181 $head ||= '';
264 27         105 return $v->stringify("$head%02x%02x%02x",1);
265             }
266              
267             sub truncate
268             {
269 62     62 1 230 my $v = shift;
270 62         241 my $c = $v->clone();
271 62         933 for ( 0 .. 2 ) {
272 186 100       520 $c->[0][0][$_] = 0 if $c->[0][0][$_] < 0;
273 186 100       593 $c->[0][0][$_] = 1 if $c->[0][0][$_] > 1;
274             }
275 62         98 $#{$c} = 2;
  62         184  
276 62         211 return $c;
277             }
278              
279             sub limit
280             {
281 0     0 1 0 my $v = shift;
282 0         0 for ( 0 .. 2 ) {
283 0 0       0 $v->[0][0][$_] = -1 if $v->[0][0][$_] < -1;
284 0 0       0 $v->[0][0][$_] = 1 if $v->[0][0][$_] > 1;
285             }
286 0         0 $#{$v} = 2;
  0         0  
287 0         0 return $v;
288             }
289              
290             sub stringify
291             {
292 45     45 1 279 my( $v, $fmt, $hexed ) = @_;
293 45 100       143 $fmt = $FORMAT unless defined $fmt; # if not given use current default
294 45 100       102 $hexed = $FORMAT_HEXED unless defined $hexed;
295 45 100       102 if ( $hexed ){
296 43         122 return sprintf($fmt, $v->truncate->array256());
297             } else {
298 2         9 return sprintf($fmt, $v->array());
299             }
300             }
301              
302              
303              
304              
305             # =============================================================================
306              
307             =head1 OPERATOR OVERLOAD
308              
309             Color::Model::RGB inherits operators overloading from Math::VextorReal. These
310             functions are so useful for mathematical calculation of colors.
311              
312             Note: for avoiding error of conflcting with File Test Operation, put a constant
313             object,
314             R, B, W or O, in blanckets"()" or separate with space when using expression
315             with muinus and them.
316              
317             $c = -(W) # OK
318             $c = W - R # OK
319             $c = -W # error or raises bug. ( Perl thinks as "-W $_" )
320             $c = W-R # error too.
321              
322             =over
323              
324             =item Negation (unary minus)
325              
326             $c = -$x # -object -> rgb(-r,-b,-c)
327              
328             A Color::Model::RGB object some values of which are minus is allowed for
329             calculation. When stringifying such object, minus value will be represented as
330             0.
331              
332             =item Addition (+)
333              
334             $c = R + G; # object1 + object2 -> rgb(r1+r2, g1+g2, b1+b2)
335             $c = B + 10; # object + scalar -> rgb(r +x, g +x, b +x)
336              
337             =item Subtraction (-)
338              
339             $c = W - B; # object1 - objext2 -> rgb(r1-r2, g1-g2, b1-b2)
340             $c = W - 10; # object - scalar -> rgb(r1-x, g1-x, b1-x)
341              
342             =item Object scalar multiplication (*)
343              
344             $c = W * 0.5 # object * scalar -> rgb(r1*x, g1*x, b1*x)
345             # use Math::MatrixReal
346             $c = $col * $m # Color::Model::RGB * Math::MatrixReal
347              
348             Color::Model::RGB multiplication by a object is allowed by
349             B instance. This function may be good to calculate hue
350             rotation of a color.
351              
352             # hue rotation sample
353             $r = 2 * (atan2(1,1)*4) / 10; # for 2pi/10 radian
354             ($sin,$cos) = (sin($r), cos($r));
355             $p = (1/3) * (1-$cos);
356             $q = sqrt(1/3) * $sin; # (1/3,1/3,1/3) is norm of W
357              
358             $matrix = Math::MatrixReal->new_from_rows([
359             [ $p+$cos, $p-$q, $p+$q, ],
360             [ $p+$q, $p+$cos, $p-$q, ],
361             [ $p-$q, $p+$q, $p+$cos,],
362             ]);
363              
364             $rgb = R;
365             foreach ( 1..10 ){
366             print qq(#$rgb
\n);
367             $rgb *= $matrix;
368             }
369              
370             =item Object scalar division (/)
371              
372             $c = W / 3 # object / scalar -> rgb(r1/x, g1/x, b1/x)
373             # object1 / object2 is not allowed (croaking)
374              
375             =item Cross and dot products (x and .)
376              
377             Calculation corss and dot product are seldom used at color manipulation.
378             These may be used for hue rotation, too.
379              
380             # hue rotation sample 2
381             $r = 2 * (atan2(1,1)*4) / 10; # for 2pi/10 radian
382             $n = W->norm;
383             $rgb = R;
384             foreach ( 1..10 ){
385             print qq(#$rgb
\n);
386             $p = $n * ($n . $rgb);
387             $rgb = $p + ($rgb - $p)*cos($r) - ($rgb x $n)*sin($r);
388             }
389              
390             =item Bitwise operations
391              
392             There are bitwise operations in Color::Model::RGB such as '<<', '>>','&',
393             '|', '^' and '~'.
394              
395             $col1 = rgbhex('010101');
396             $col2 = $col1 << 7; # Bit shift left, becomes 808080
397             $col3 = $col2 >> 1; # Bit shift right, becomes 404040
398              
399             $col4 = $col2 | $col3; # Object-object bit OR, becomes c0c0c0
400             $col5 = $col2 | 0x66; # Object-scalar bit OR, becomes e6e6e6
401              
402             $col6 = $col4 & $col5 # Object-object bit AND, becomes c0c0c0
403             $col7 = $col4 & 0x80 # Object-scalar bit AND, becomes 808080
404              
405             $col8 = $col6 ^ $col7 # Object-object bit XOR, becomes 404040
406             $col9 = $col6 ^ 0xff; # Object-scalar bit XOR, becomes 3f3f3f
407              
408             $col10 = ~$col8; # Bit Negate, becomes bfbfbf
409              
410             In bitwise operation, each element values of Color::Model::RGB are internaly
411             conveted to integers from 0 to 255 and than caluculated individually, and
412             converted to decimal again.
413              
414             Package parameter, $Color::Model::RGB::BIT_SHIFT_RIGID, changes bit shift
415             operation's result. If this is true value, caluculated value will be ANDed
416             with 0xff. If it is false, valuse over 0xff will be set to 0xff(255). Default
417             is false(0).
418              
419             $Color::Model::RGB::BIT_SHIFT_RIGID = 1;
420             $col = rgbhex('010101')<<8; # becomes 000000
421             $Color::Model::RGB::BIT_SHIFT_RIGID = 0;
422             $col = rgbhex('010101')<<8; # becomes ffffff
423              
424             =back
425              
426             =cut
427              
428             # -----------------------------------------------------------------------------
429             $Color::Model::RGB::BIT_SHIFT_RIGID = 0;
430             #$Math::VectorReal::TRACE = 1;
431              
432             use overload
433 4         68 '*' => \&_multiply,
434             '<<' => \&_bit_shiftl,
435             '>>' => \&_bit_shiftr,
436             '&' => \&_bit_and,
437             '|' => \&_bit_or,
438             '^' => \&_bit_xor,
439             '~' => \&_bit_not,
440 4     4   57047 'fallback' => undef;
  4         516  
441              
442             sub _trace
443             {
444 21     21   68 Math::VectorReal::_trace(@_);
445             }
446              
447             sub _multiply {
448             # copied and improved from Math::VectorReal
449 10     10   1270 my($object,$argument,$flip) = @_;
450 10         27 _trace("'*'",$object,$argument,$flip);
451 10 50       73 if ( ref($argument) ){
    50          
452 0 0       0 if ( $argument->isa('Math::MatrixReal') ) {
453             # Assume multiply by Math::MatrixReal object EG: $v * $M --> $new_v
454             # Order is communicative, but $flip should NOT be true
455 0 0       0 if ( ! $flip ) {
456 0         0 my $v = ( $object->vector2matrix_row($argument)
457             * $argument )->matrix_row2vector;
458 0         0 return bless $v, __PACKAGE__;
459             } else { # just in case flip is true..
460 0         0 my $v = ( $argument *
461             $object->vector2matrix_row($argument) )->matrix_row2vector;
462 0         0 return bless $v, __PACKAGE__;
463             }
464             } else {
465 0         0 Carp::croak("multiplication(*) is allowed by Math::MatrixReal object or scalar");
466             }
467             }
468             elsif ( defined $argument ) {
469             # defined $argument must be a scalar, so Scalar Multiply
470             # Communitive - order does not matter, $flip can be ignored
471 10         36 my $v = $object->clone;
472 10         144 for ( 0 .. 2 ) { $v->[0][0][$_] *= $argument; }
  30         79  
473 10 100       46 $v->[6] *= abs($argument) if defined $v->[6]; # multiply vector length
474 10         60 return $v;
475             }
476 0         0 Carp::croak("undefined argument given for vector multiply");
477             }
478              
479             sub _bit_shiftl
480             {
481 3     3   8 my($object,$argument,$flip) = @_;
482 3         8 _trace("'<<'",$object,$argument,$flip);
483             # $argument must be scalar and plus
484 3 50 33     45 if ( (defined $argument) && !ref($argument) && $argument>=0 ){
      33        
485 3         9 my @rgb = $object->truncate()->array256();
486 9         13 my $v = rgb256( map {
487 3         12 $_ <<= $argument;
488 9 100       20 $_ &= 0xff if $Color::Model::RGB::BIT_SHIFT_RIGID;
489 9         19 $_;
490             } @rgb );
491 3         39 $#{$v} = 2; # any cached vector length is now invalid
  3         9  
492 3         13 return $v;
493             }
494 0         0 Carp::croak("non-scalar given or minus for vector scalar bit shift left");
495             }
496              
497             sub _bit_shiftr
498             {
499 1     1   3 my($object,$argument,$flip) = @_;
500 1         4 _trace("'>>'",$object,$argument,$flip);
501             # $argument must be scalar and plus
502 1 50 33     23 if ( (defined $argument) && ! ref($argument) && $argument>=0 ){
      33        
503 1         6 my @rgb = $object->truncate()->array256();
504 3         9 my $v = rgb256( map {
505 1         5 $_ >>= $argument;
506             } @rgb );
507 1         13 $#{$v} = 2; # any cached vector length is now invalid
  1         3  
508 1         5 return $v;
509             }
510 0         0 Carp::croak("non-scalar given or minus for vector scalar bit shift right");
511             }
512              
513             sub _bit_and
514             {
515 2     2   40 my($object,$argument,$flip) = @_;
516 2         6 _trace("'&'",$object,$argument,$flip);
517 2 100       14 if ( ref($argument) ) {
    50          
518             # bitwise and of two Color::Model::RGB
519 1         5 my @vrgb = $object->truncate()->array256();
520 1         5 my @argb = $argument->truncate()->array256();
521 1         11 my $v = rgb256(
522             $vrgb[0] & $argb[0],
523             $vrgb[1] & $argb[1],
524             $vrgb[2] & $argb[2]
525             );
526 1         13 $#{$v} = 2; # any cached vector length is now invalid
  1         4  
527 1         5 return $v;
528             }
529             elsif ( defined($argument) ){
530             # bitwise and of Color::Model::RGB with scalar
531 1         5 my @rgb = $object->truncate()->array256();
532 3         10 my $v = rgb256( map {
533 1         4 $_ & $argument;
534             } @rgb );
535 1         12 $#{$v} = 2; # any cached vector length is now invalid
  1         4  
536 1         5 return $v;
537             }
538 0         0 Carp::croak("undefined argument given for vector bitwise and");
539             }
540              
541             sub _bit_or
542             {
543 2     2   5 my($object,$argument,$flip) = @_;
544 2         4 _trace("'|'",$object,$argument,$flip);
545 2 100       13 if ( ref($argument) ) {
    50          
546             # bitwise or of two Color::Model::RGB
547 1         3 my @vrgb = $object->truncate()->array256();
548 1         6 my @argb = $argument->truncate()->array256();
549 1         7 my $v = rgb256(
550             $vrgb[0] | $argb[0],
551             $vrgb[1] | $argb[1],
552             $vrgb[2] | $argb[2]
553             );
554 1         12 $#{$v} = 2; # any cached vector length is now invalid
  1         3  
555 1         5 return $v;
556             }
557             elsif ( defined($argument) ){
558             # bitwise or of Color::Model::RGB with scalar
559 1         3 my @rgb = $object->truncate()->array256();
560 3         4 my $v = rgb256( map {
561 1         5 $_ |= $argument;
562 3         8 $_ &= 0xff;
563             } @rgb );
564 1         11 $#{$v} = 2; # any cached vector length is now invalid
  1         3  
565 1         5 return $v;
566             }
567 0         0 Carp::croak("undefined argument given for vector bitwise or");
568             }
569              
570             sub _bit_xor
571             {
572 2     2   5 my($object,$argument,$flip) = @_;
573 2         7 _trace("'^'",$object,$argument,$flip);
574 2 100       15 if ( ref($argument) ) {
    50          
575             # bitwise exclusive or of two Color::Model::RGB
576 1         18 my @vrgb = $object->truncate()->array256();
577 1         6 my @argb = $argument->truncate()->array256();
578 1         7 my $v = rgb256(
579             $vrgb[0] ^ $argb[0],
580             $vrgb[1] ^ $argb[1],
581             $vrgb[2] ^ $argb[2]
582             );
583 1         10 $#{$v} = 2; # any cached vector length is now invalid
  1         3  
584 1         4 return $v;
585             }
586             elsif ( defined($argument) ){
587             # bitwise exclusive or of Color::Model::RGB with scalar
588 1         5 my @rgb = $object->truncate()->array256();
589 3         6 my $v = rgb256( map {
590 1         6 $_ ^= $argument;
591 3         11 $_ &= 0xff;
592             } @rgb );
593 1         11 $#{$v} = 2; # any cached vector length is now invalid
  1         4  
594 1         6 return $v;
595             }
596 0         0 Carp::croak("undefined argument given for vector bitwise exclusive or");
597             }
598              
599             sub _bit_not
600             {
601 1     1   4 my($object,$argument,$flip) = @_;
602 1         14 _trace("'~'",$object,$argument,$flip);
603             # bitwise complement of Color::Model::RGB with scalar
604 1         6 my @rgb = $object->truncate()->array256();
605 3         7 my $v = rgb256( map {
606 1         6 $_ = ~$_;
607 3         8 $_ &= 0xff;
608             } @rgb );
609 1         14 return $v;
610             }
611              
612              
613             # =============================================================================
614              
615             =head1 EXPORTING FUNCTION
616              
617             There are few froups for exporting.
618              
619             Defalut exporting functions are I, I and I.
620              
621             Primary colors, I (R:255,G:0,B:0), I (R:0,G:255,B:0), I (R:0,G:0,B:255),
622             I (R:0,G:0,B:0) and I (R:255,G:255,B:255), will be exported with tag ':primary'
623             or ':RGB'.
624              
625             Functions changes defalut about stringifying, I and I,
626             will be exported with tag ':format'.
627              
628             And color blending functions, I, I, I and
629             I, will be exported with tag ':blender'.
630              
631              
632             =head2 CHANGING STRINGIFYING DEFALUT
633              
634             =over
635              
636             =item set_format( $format [, $flag2hex] )
637              
638             =item get_format()
639              
640             Set and get defalut values of stringifying. See method I descriped
641             above.
642              
643             =back
644              
645             =cut
646              
647             # -----------------------------------------------------------------------------
648             sub set_format
649             {
650 4     4 1 1626 my ($fmt, $hexed) = @_;
651              
652 4 50       66 if ( !@_ ) {
653 0         0 Carp::croak("No argument given");
654             }
655 4 50       19 if ( @_ == 2 ){
656 4 50       25 $FORMAT_HEXED = $hexed? 1: 0;
657             }
658 4 50       32 if ( @_ >= 1 ){
659 4 50       36 $FORMAT = $fmt if defined $fmt;
660             }
661             }
662              
663             sub get_format
664             {
665 1     1 1 2 my ($fmt, $hexed) = @_;
666              
667 1         4 return ($FORMAT,$FORMAT_HEXED);
668             }
669              
670              
671              
672              
673             # =============================================================================
674              
675             =head2 BLENDING FUNCTIONS
676              
677             Color::Model::RGB has several blending functions which make a new object from
678             two objects.
679              
680             $blend_alpha = blend_alpha($col1,0.3,$col2,0.7); # any transparency rate
681             $blend_half = blend_half($col1,$col2); # 50%:50%
682             $blend_plus = blend_plus($col1,$col2); # $col1 + $col2
683             $blend_minus = blend_plus($col1,$col2); # $col1 - $col2
684              
685             =cut
686              
687             # -----------------------------------------------------------------------------
688             sub blend_alpha
689             {
690 4     4 0 17 my ($src,$src_rate, $dist,$dist_rate) = @_;
691 4 50 33     48 unless ( Scalar::Util::blessed($src) && $src->isa(__PACKAGE__) ){
692 0         0 Carp::croak("First argumenst must be object of ".__PACKAGE__);
693             }
694 4 50 33     94 unless ( !ref($src_rate) && $src_rate =~ /^[0-9\.\-]+$/ &&
      33        
      33        
695             $src_rate >=-1 && $src_rate <= 1 ){
696 0         0 Carp::croak("Second argumenst must be a number between -1.0 to 1.0");
697             }
698 4 50 33     38 unless ( Scalar::Util::blessed($dist) && $dist->isa(__PACKAGE__) ){
699 0         0 Carp::croak("Third argumenst must be object of ".__PACKAGE__);
700             }
701 4 50 33     59 unless ( !ref($dist_rate) && $dist_rate =~ /^[0-9\.\-]+$/ &&
      33        
      33        
702             $dist_rate >=-1 && $dist_rate <= 1 ){
703 0         0 Carp::croak("Fourth argumenst must be a number between -1.0 to 1.0");
704             }
705              
706 4         13 return ( $src * $src_rate + $dist * $dist_rate )->truncate();
707             }
708              
709              
710             sub blend_half
711             {
712 1     1 0 12 return blend_alpha($_[0], 0.5, $_[1], 0.5);
713             }
714              
715              
716             sub blend_plus
717             {
718 1     1 0 14 return blend_alpha($_[0], 1.0, $_[1], 1.0);
719             }
720              
721             sub blend_minus
722             {
723 1     1 0 14 return blend_alpha($_[0], 1.0, $_[1], -1.0);
724             }
725              
726              
727              
728              
729             # =============================================================================
730             1;
731              
732             __END__