#!/usr/app/bin/perl

eval 'exec /usr/app/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell

use Gimp qw(:auto __ N_);
use Gimp::Fu;

register	"layer_apply",
		"Apply a perl expression to every layer of the image",
		"=pod",
		"Marc Lehmann <pcg\@goof.com>",
		"Marc Lehmann <pcg\@goof.com>",
		"19990708",
		N_"<Image>/Filters/Apply Perl Expression...",
		"*",
		[
                 [PF_TEXT,	"expr",	"the perl expression to run for each layer",
                                '$d->gauss_rle($P*100+1,1,1)'],
                 [PF_DRAWABLE,	"drawable2", "an optional extra drawable for use by the code"],
		],
                [],
                ['gimp-1.1'],
	sub {
		my($image,$_drawable,$function,$d2) = @_;

                my($d,$i,$I,$n,$p,$P);

                my @layers = $image->get_layers;
                $n = @layers;
                $n or die "at least one layer is required\n";

                my $func = eval "sub{\n#line 0 \"expression\"\n$function\n}";
                die "syntax error in expression '$function': $@\n" if $@;

                # now apply the function
                eval { $image->undo_push_group_start };
                Gimp->progress_init("Applying Expression...");
                for my $index (0..$n-1) {
                   $i = $index;
                   $I = $n-$i-1;
                   $p = @layers > 1 ? $i/$#layers : 0;
                   $P = 1-$p;
                   $d = $layers[$i];

                   eval { &$func };
                   die "evaluation error in frame $i: $@\n" if $@;

                   Gimp->progress_update(($i+1)/$n);
                }
                Gimp->displays_flush;
                eval { $image->undo_push_group_end };
	};

exit main;

=head1 DESCRIPTION

This function runs a perl expression for each layer of an image. The perl expression
can use the following variables:

=over 4

=item $image

The image.

=item $d ("drawable")

The current drawable (currently always a layer).

=item $i, $I ("index")

The index of the current layer. C<$i> counts from 0 to $n-1, i.e. from top
to the bottom of the stack with layer #0 being the top of the stack.

C<$I> counts "backwards", i.e. from $n-1 to 0, so layer 0 is at the
bottom.

=item $p, $P ("percent")

Similar to $i, but counts from 0 to 1 (inclusive). $p is equivalent to
C<$i/($n-1)> and $P is equivalent to C<$I/($n-1)>.

=item $n ("number of frames")

The number of layers in the image.

=item $d2 ("drawable")

The drawable2 argument, entirely optional and can be used for anthing you
like.

=back

=head2 EXAMPLES

The following expression will gradually fade out an animation.

 $d->brightness_contrast ($P * 127, 0);

This little script can be used to merge two animations, $d2 should
point to another animation with the same number of frames (only the
image is of concern). It does it by copying each frame of the other
animation onto the corresponding frame in the current animation and using
DARKEN_MODE to combine the frames. You might want to use other modes or
maybe C<$f->set_opacity(50)> for your animation.

 $i2=$d2->image;
 $l2=($i2->get_layers)[$i];

 $i2->selection_all;
 $l2->edit_copy;
 $f=$d->edit_paste(0);
 $f->set_mode(DARKEN_ONLY_MODE);
 $f->anchor;


