1 package Imager::Fountain;
3 use Imager::Color::Float;
10 Imager::Fountain - a class for building fountain fills suitable for use by
16 my $f1 = Imager::Fountain->read(gimp=>$filename);
17 $f->write(gimp=>$filename);
18 my $f1 = Imager::Fountain->new;
19 $f1->add(start=>0, middle=>0.5, end=>1.0,
20 c0=>Imager::Color->new(...),
21 c1=>Imager::Color->new(...),
22 type=>$trans_type, color=>$color_trans_type);
26 Provide an interface to build arrays suitable for use by the Imager
27 fountain filter. These can be loaded from or saved to a GIMP gradient
28 file or you can build them from scratch.
32 =item read(gimp=>$filename)
34 =item read(gimp=>$filename, name=>\$name)
36 Loads a gradient from the given GIMP gradient file, and returns a
37 new Imager::Fountain object.
39 If the name parameter is supplied as a scalar reference then any name
40 field from newer GIMP gradient files will be returned in it.
42 my $gradient = Imager::Fountain->read(gimp=>'foo.ggr');
44 my $gradient2 = Imager::Fountain->read(gimp=>'bar.ggr', name=>\$name);
49 my ($class, %opts) = @_;
53 $fh = ref($opts{gimp}) ? $opts{gimp} : IO::File->new($opts{gimp});
55 $Imager::ERRSTR = "Cannot open $opts{gimp}: $!";
60 my $name_ref = $opts{name} && ref $opts{name} ? $opts{name} : \$trash_name;
62 return $class->_load_gimp_gradient($fh, $opts{gimp}, $name_ref);
65 warn "$class::read: Nothing to do!";
70 =item write(gimp=>$filename)
72 =item write(gimp=>$filename, name=>$name)
74 Save the gradient to a GIMP gradient file.
76 The second variant allows the gradient name to be set (for newer
77 versions of the GIMP).
79 $gradient->write(gimp=>'foo.ggr')
80 or die Imager->errstr;
81 $gradient->write(gimp=>'bar.ggr', name=>'the bar gradient')
82 or die Imager->errstr;
87 my ($self, %opts) = @_;
91 $fh = ref($opts{gimp}) ? $opts{gimp} : IO::File->new("> ".$opts{gimp});
93 $Imager::ERRSTR = "Cannot open $opts{gimp}: $!";
97 return $self->_save_gimp_gradient($fh, $opts{gimp}, $opts{name});
100 warn "Nothing to do\n";
107 Create an empty fountain fill description.
114 return bless [], $class;
119 return $_ if defined;
124 =item add(start=>$start, middle=>$middle, end=>1.0, c0=>$start_color, c1=>$end_color, type=>$trans_type, color=>$color_trans_type)
126 Adds a new segment to the fountain fill, the possible options are:
132 The start position in the gradient where this segment
133 takes effect between 0 and 1. Default: 0.
137 The mid-point of the transition between the 2
138 colors, between 0 and 1. Default: average of I<start> and I<end>.
142 The end of the gradient, from 0 to 1. Default: 1.
146 The color of the fountain fill where the fill parameter is equal
147 to I<start>. Default: opaque black.
151 The color of the fountain fill where the fill parameter is equal to
152 I<end>. Default: opaque black.
156 The type of segment, controls the way in which the fill parameter
157 moves from 0 to 1. Default: linear.
159 This can take any of the following values:
167 Unimplemented so far.
179 The way in which the color transitions between I<c0> and I<c1>.
182 This can take any of the following values:
188 Each channel is simple scaled between c0 and c1.
192 The color is converted to a HSV value and the scaling is done such
193 that the hue increases as the fill parameter increases.
197 The color is converted to a HSV value and the scaling is done such
198 that the hue decreases as the fill parameter increases.
204 In most cases you can ignore some of the arguments, eg.
206 # assuming $f is a new Imager::Fountain in each case here
208 # simple transition from red to blue
209 $f->add(c0=>NC('#FF0000'), c1=>NC('#0000FF'));
210 # simple 2 stages from red to green to blue
211 $f->add(end=>0.5, c0=>NC('#FF0000'), c1=>NC('#00FF00'))
212 $f->add(start=>0.5, c0=>NC('#00FF00'), c1=>NC('#0000FF'));
216 # used to translate segment types and color transition types to numbers
234 my ($self, %opts) = @_;
236 my $start = _first($opts{start}, 0);
237 my $end = _first($opts{end}, 1);
238 my $middle = _first($opts{middle}, ($start+$end)/2);
241 $start, $middle, $end,
242 _first($opts{c0}, Imager::Color::Float->new(0,0,0,1)),
243 _first($opts{c1}, Imager::Color::Float->new(1,1,1,0)),
244 _first($opts{type} && $type_names{$opts{type}}, $opts{type}, 0),
245 _first($opts{color} && $color_names{$opts{color}}, $opts{color}, 0)
252 =item simple(positions=>[ ... ], colors=>[...])
254 Creates a simple fountain fill object consisting of linear segments.
256 The arrayrefs passed as positions and colors must have the same number
257 of elements. They must have at least 2 elements each.
259 colors must contain Imager::Color or Imager::Color::Float objects.
263 my $f = Imager::Fountain->simple(positions=>[0, 0.2, 1.0],
264 colors=>[ NC(255,0,0), NC(0,255,0),
270 my ($class, %opts) = @_;
272 if ($opts{positions} && $opts{colors}) {
273 my $positions = $opts{positions};
274 my $colors = $opts{colors};
275 unless (@$positions == @$colors) {
276 $Imager::ERRSTR = "positions and colors must be the same size";
279 unless (@$positions >= 2) {
280 $Imager::ERRSTR = "not enough segments";
284 for my $i (0.. $#$colors-1) {
285 $f->add(start=>$positions->[$i], end=>$positions->[$i+1],
286 c0 => $colors->[$i], c1=>$colors->[$i+1]);
291 warn "Nothing to do";
298 =head2 Implementation Functions
300 Documented for internal use.
304 =item _load_gimp_gradient($class, $fh, $name)
306 Does the work of loading a GIMP gradient file.
310 sub _load_gimp_gradient {
311 my ($class, $fh, $filename, $name) = @_;
315 unless ($head eq 'GIMP Gradient') {
316 $Imager::ERRSTR = "$filename is not a GIMP gradient file";
321 if ($count =~ /^name:\s?(.*)/i) {
322 ref $name and $$name = $1;
323 $count = <$fh>; # try again
326 unless ($count =~ /^\d+$/) {
327 $Imager::ERRSTR = "$filename is missing the segment count";
331 for my $i (1..$count) {
334 my @row = split ' ', $row;
335 unless (@row == 13) {
336 $Imager::ERRSTR = "Bad segment definition";
339 my ($start, $middle, $end) = splice(@row, 0, 3);
340 my $c0 = Imager::Color::Float->new(splice(@row, 0, 4));
341 my $c1 = Imager::Color::Float->new(splice(@row, 0, 4));
342 my ($type, $color) = @row;
343 push(@result, [ $start, $middle, $end, $c0, $c1, $type, $color ]);
345 return bless \@result,
348 =item _save_gimp_gradient($self, $fh, $name)
350 Does the work of saving to a GIMP gradient file.
354 sub _save_gimp_gradient {
355 my ($self, $fh, $filename, $name) = @_;
357 print $fh "GIMP Gradient\n";
358 defined $name or $name = '';
359 $name =~ tr/ -~/ /cds;
361 print $fh "Name: $name\n";
363 print $fh scalar(@$self),"\n";
364 for my $row (@$self) {
365 printf $fh "%.6f %.6f %.6f ",@{$row}[0..2];
367 for ($row->[3+$i]->rgba) {
368 printf $fh "%.6f ", $_/255.0;
371 print $fh "@{$row}[5,6]";
372 unless (print $fh "\n") {
373 $Imager::ERRSTR = "write error: $!";
383 =head1 FILL PARAMETER
385 The add() documentation mentions a fill parameter in a few places,
386 this is as good a place as any to discuss it.
388 The process of deciding the color produced by the gradient works
389 through the following steps:
395 calculate the base value, which is typically a distance or an angle of
396 some sort. This can be positive or occasinally negative, depending on
397 the type of fill being performed (linear, radial, etc).
401 clamp or convert the base value to the range 0 through 1, how this is
402 done depends on the repeat parameter. I'm calling this result the
407 the appropriate segment is found. This is currently done with a
408 linear search, and the first matching segment is used. If there is no
409 matching segment the pixel is not touched.
413 the fill parameter is scaled from 0 to 1 depending on the segment type.
417 the color produced, depending on the segment color type.
423 Tony Cook <tony@develop-help.com>