Commit af9ecf06 authored by Marc Lehmann's avatar Marc Lehmann
Browse files

see plug-ins/perl/Changes

parent 764d8827
Revision history for Gimp-Perl extension.
- Gimp::Fu does no longer display the returned image when it
is the same as the one passed in.
- append imagenumber to "Untitled"-images in widget.
- removed publicly-visible non-PDB pixelfunctions.
"uuuuuse peedee-ell or dieieie".
- implemented Gimp::Fu::PF_RADIO.
- added blowinout.pl.
1.055 Mon Feb 22 22:38:44 CET 1999
- applied seth's script changes.
- gimp11ified some plug-ins.
......
......@@ -12,7 +12,7 @@ use base qw(DynaLoader);
require DynaLoader;
$VERSION = 1.055;
$VERSION = 1.06;
@_param = qw(
PARAM_BOUNDARY PARAM_CHANNEL PARAM_COLOR PARAM_DISPLAY PARAM_DRAWABLE
......@@ -312,6 +312,16 @@ sub AUTOLOAD {
if (exists $ignore_function{$sub}) {
*{$AUTOLOAD} = sub { () };
goto &$AUTOLOAD;
} elsif (UNIVERSAL::can(Gimp::Util,$sub)) {
my $ref = \&{"Gimp::Util::$sub"};
*{$AUTOLOAD} = sub {
shift unless ref $_[0];
# goto &$ref # does not always work, PERLBUG! #FIXME
my @r = eval { &$ref };
_croak $@ if $@;
wantarray ? @r : $r[0];
};
goto &$AUTOLOAD;
} elsif (UNIVERSAL::can($interface_pkg,$sub)) {
my $ref = \&{"${interface_pkg}::$sub"};
*{$AUTOLOAD} = sub {
......@@ -333,16 +343,6 @@ sub AUTOLOAD {
goto &$AUTOLOAD;
} elsif (defined(*{"${interface_pkg}::$sub"}{CODE})) {
die "safety net $interface_pkg :: $sub (REPORT THIS!!)";#d#
} elsif (UNIVERSAL::can(Gimp::Util,$sub)) {
my $ref = \&{"Gimp::Util::$sub"};
*{$AUTOLOAD} = sub {
shift unless ref $_[0];
# goto &$ref # does not always work, PERLBUG! #FIXME
my @r = eval { &$ref };
_croak $@ if $@;
wantarray ? @r : $r[0];
};
goto &$AUTOLOAD;
}
}
# for performance reasons: supply a DESTROY method
......
......@@ -79,6 +79,7 @@ sub PF_ADJUSTMENT(){ PARAM_END+5 }; # compatibility fix for script-fu _ONLY_
sub PF_BRUSH () { PARAM_END+6 };
sub PF_PATTERN () { PARAM_END+7 };
sub PF_GRADIENT () { PARAM_END+8 };
sub PF_RADIO () { PARAM_END+9 };
sub PF_BOOL () { PF_TOGGLE };
sub PF_INT () { PF_INT32 };
......@@ -101,6 +102,7 @@ sub Gimp::RUN_FULLINTERACTIVE (){ Gimp::RUN_INTERACTIVE+100 }; # you don't want
&PF_SLIDER => 'integer',
&PF_SPINNER => 'integer',
&PF_ADJUSTMENT => 'integer',
&PF_RADIO => 'string',
&PF_IMAGE => 'NYI',
&PF_LAYER => 'NYI',
&PF_CHANNEL => 'NYI',
......@@ -111,7 +113,7 @@ sub Gimp::RUN_FULLINTERACTIVE (){ Gimp::RUN_INTERACTIVE+100 }; # you don't want
PF_STRING PF_COLOR PF_COLOUR PF_TOGGLE PF_IMAGE
PF_DRAWABLE PF_FONT PF_LAYER PF_CHANNEL PF_BOOL
PF_SLIDER PF_INT PF_SPINNER PF_ADJUSTMENT
PF_BRUSH PF_PATTERN PF_GRADIENT);
PF_BRUSH PF_PATTERN PF_GRADIENT PF_RADIO);
@EXPORT = (qw(register main),@_params);
@EXPORT_OK = qw(interact $run_mode save_image);
......@@ -280,6 +282,25 @@ sub interact($$$@) {
push(@setvals,sub{set_state $a ($_[0] ? 1 : 0)});
push(@getvals,sub{state $a eq "active"});
} elsif($type == PF_RADIO) {
my $b = new Gtk::HBox 0,5;
my($r,$prev);
my $prev_sub = sub { $r = $_[0] };
for (@$extra) {
my ($label,$value)=@$_;
my $radio = new Gtk::RadioButton $label;
$radio->set_group ($prev) if $prev;
$b->pack_start ($radio,1,0,5);
$radio->signal_connect(clicked => sub { $r = $value });
my $prev_sub_my = $prev_sub;
$prev_sub = sub { $radio->set_active ($_[0] == $value); &$prev_sub_my };
$prev = $radio;
}
$a = new Gtk::Frame;
$a->add($b);
push(@setvals,$prev_sub);
push(@getvals,sub{$r});
} elsif($type == PF_IMAGE) {
my $res;
$a=new Gtk::HBox (0,5);
......@@ -443,6 +464,7 @@ sub string2pf($$) {
|| $type==PF_FONT
|| $type==PF_PATTERN
|| $type==PF_BRUSH
|| $type==PF_RADIO # for now! #d#
|| $type==PF_GRADIENT) {
$s;
} elsif($type==PF_INT8
......@@ -553,6 +575,7 @@ sub query {
$_->[0]=PARAM_INT32 if $_->[0] == PF_SLIDER;
$_->[0]=PARAM_INT32 if $_->[0] == PF_SPINNER;
$_->[0]=PARAM_INT32 if $_->[0] == PF_ADJUSTMENT;
$_->[0]=PARAM_INT32 if $_->[0] == PF_RADIO;
$_->[0]=PARAM_STRING if $_->[0] == PF_FONT;
$_->[0]=PARAM_STRING if $_->[0] == PF_BRUSH;
$_->[0]=PARAM_STRING if $_->[0] == PF_PATTERN;
......@@ -703,6 +726,19 @@ Default values will be substitued for missing entries, like in:
The same as PF_SLIDER, except that this one uses a spinbutton instead of a scale.
=item PF_RADIO
In addition to a default value, an extra argument describing the various
options I<must> be provided. That extra argument must be a reference
to an array filled with ["Option-Name", integer-value] pairs. Gimp::Fu
will then generate a horizontal frame with radio buttons, one for each
alternative. For example:
[PF_RADIO, "direction", "the direction to move to", 5, [["Left",5],["Right",7]]]
draws two buttons, when the first (the default, "Left") is activated, 5
will be returned. If the second is activated, 7 is returned.
=item PF_FONT
Lets the user select a font and returns a X Logical Font Descriptor (XLFD).
......@@ -737,7 +773,7 @@ sub register($$$$$$$$$;@) {
*$function = sub {
$run_mode=shift; # global!
my(@pre,@defaults,@lastvals);
my(@pre,@defaults,@lastvals,$input_image);
if ($menupath=~/^<Image>\//) {
@_ >= 2 or die "<Image> plug-in called without an image and drawable!\n";
@pre = (shift,shift);
......@@ -779,6 +815,8 @@ sub register($$$$$$$$$;@) {
} else {
die "run_mode must be INTERACTIVE, NONINTERACTIVE or WITH_LAST_VALS\n";
}
$input_image = $_[0] if ref $_[0] eq "Gimp::Image";
$input_image = $pre[0] if ref $pre[0] eq "Gimp::Image";
$Gimp::Data{"$function/_fu_data"}=Dumper([@_]);
......@@ -802,7 +840,7 @@ sub register($$$$$$$$$;@) {
save_image($img,$path);
$img->delete;
} elsif ($run_mode != &Gimp::RUN_NONINTERACTIVE) {
$img->display_new;
$img->display_new unless $input_image && $$img == $$input_image;
}
} elsif (!@$results) {
warn "WARNING: $function returned something that is not an image: \"$img\"\n";
......
......@@ -1539,7 +1539,7 @@ gimp_pixel_rgn_resize(sv, x, y, width, height)
}
SV *
gimp_pixel_rgn_get_pixel(pr, x, y)
_gimp_pixel_rgn_get_pixel(pr, x, y)
GPixelRgn * pr
int x
int y
......@@ -1552,7 +1552,7 @@ gimp_pixel_rgn_get_pixel(pr, x, y)
RETVAL
SV *
gimp_pixel_rgn_get_row(pr, x, y, width)
_gimp_pixel_rgn_get_row(pr, x, y, width)
GPixelRgn * pr
int x
int y
......@@ -1566,7 +1566,7 @@ gimp_pixel_rgn_get_row(pr, x, y, width)
RETVAL
SV *
gimp_pixel_rgn_get_col(pr, x, y, height)
_gimp_pixel_rgn_get_col(pr, x, y, height)
GPixelRgn * pr
int x
int y
......@@ -1580,7 +1580,7 @@ gimp_pixel_rgn_get_col(pr, x, y, height)
RETVAL
SV *
gimp_pixel_rgn_get_rect(pr, x, y, width, height)
_gimp_pixel_rgn_get_rect(pr, x, y, width, height)
GPixelRgn * pr
int x
int y
......@@ -1595,7 +1595,7 @@ gimp_pixel_rgn_get_rect(pr, x, y, width, height)
RETVAL
void
gimp_pixel_rgn_set_pixel(pr, data, x, y)
_gimp_pixel_rgn_set_pixel(pr, data, x, y)
GPixelRgn * pr
SV * data
int x
......@@ -1608,7 +1608,7 @@ gimp_pixel_rgn_set_pixel(pr, data, x, y)
gimp_pixel_rgn_set_pixel (pr, SvPV(data, dc), x, y);
void
gimp_pixel_rgn_set_row(pr, data, x, y)
_gimp_pixel_rgn_set_row(pr, data, x, y)
GPixelRgn * pr
SV * data
int x
......@@ -1621,7 +1621,7 @@ gimp_pixel_rgn_set_row(pr, data, x, y)
gimp_pixel_rgn_set_row (pr, SvPV(data, dc), x, y, SvCUR (data) / pr->bpp);
void
gimp_pixel_rgn_set_col(pr, data, x, y)
_gimp_pixel_rgn_set_col(pr, data, x, y)
GPixelRgn * pr
SV * data
int x
......@@ -1634,7 +1634,7 @@ gimp_pixel_rgn_set_col(pr, data, x, y)
gimp_pixel_rgn_set_col (pr, SvPV(data, dc), x, y, SvCUR (data) / pr->bpp);
void
gimp_pixel_rgn_set_rect(pr, data, x, y, width)
_gimp_pixel_rgn_set_rect(pr, data, x, y, width)
GPixelRgn * pr
SV * data
int x
......@@ -1663,7 +1663,7 @@ PROTOTYPES: DISABLE
# construction/destruction.
SV *
get_data(tile)
_get_data(tile)
GTile * tile
CODE:
gimp_tile_ref (tile);
......@@ -1673,7 +1673,7 @@ get_data(tile)
RETVAL
void
set_data(tile, data)
_set_data(tile, data)
GTile * tile
SV * data
CODE:
......
......@@ -11,87 +11,71 @@ require AutoLoader;
@EXPORT = ();
$old_w = $^W; $^W = 0;
*old_set_data = \&Gimp::Tile::set_data;
*Gimp::Tile::set_data = sub {
sub Gimp::Tile::set_data($) {
(my $p = byte $_[1])->make_physical;
old_set_data($_[0],${$p->get_dataref});
Gimp::Tile::_set_data($_[0],${$p->get_dataref});
};
*old_get_data = \&Gimp::Tile::get_data;
*Gimp::Tile::get_data = sub {
sub Gimp::Tile::get_data($) {
my($tile)=@_;
my($pdl)=new_from_specification PDL (byte,width(),height(),
$tile->bpp > 1 ? $tile->bpp : ());
${$pdl->get_dataref} = old_get_data($tile);
${$pdl->get_dataref} = &Gimp::Tile::_get_data;
$pdl->upd_data;
return $pdl;
};
# this tries to overwrite a function with another one. this is quite tricky
# (almost impossible in general), we only overwrite Gimp::<iface>::function
# and hope no other references are around.
sub rep ($&) {
my($name,$sub)=@_;
*{"old_$name"}=\&{"${Gimp::interface_pkg}::gimp_pixel_rgn_$name"};
undef *{"${Gimp::interface_pkg}::gimp_pixel_rgn_$name"};
*{"${Gimp::interface_pkg}::gimp_pixel_rgn_$name"}=$sub;
}
rep "get_pixel", sub($$$) {
sub Gimp::PixelRgn::get_pixel {
my($rgn)=@_;
my($pdl)=new_from_specification PDL (byte,$_[0]->bpp);
${$pdl->get_dataref} = &old_get_pixel;
${$pdl->get_dataref} = &Gimp::PixelRgn::_get_pixel;
$pdl->upd_data;
return $pdl;
};
rep "get_col", sub($$$$) {
sub Gimp::PixelRgn::get_col {
my($rgn)=@_;
my($pdl)=new_from_specification PDL (byte,$_[0]->bpp,$_[3]);
${$pdl->get_dataref} = &old_get_col;
${$pdl->get_dataref} = &Gimp::PixelRgn::__get_col;
$pdl->upd_data;
return $pdl;
};
rep "get_row", sub($$$$) {
sub Gimp::PixelRgn::get_row {
my($rgn)=@_;
my($pdl)=new_from_specification PDL (byte,$_[0]->bpp,$_[3]);
${$pdl->get_dataref} = &old_get_row;
${$pdl->get_dataref} = &Gimp::PixelRgn::_get_row;
$pdl->upd_data;
return $pdl;
};
rep "get_rect", sub($$$$$) {
sub Gimp::PixelRgn::get_rect {
my($pdl)=new_from_specification PDL (byte,$_[0]->bpp,$_[3],$_[4]);
${$pdl->get_dataref} = &old_get_rect;
${$pdl->get_dataref} = &Gimp::PixelRgn::_get_rect;
$pdl->upd_data;
return $pdl;
};
rep "set_pixel", sub($$$$) {
sub Gimp::PixelRgn::set_pixel {
(my $p = byte $_[1])->make_physical;
old_set_pixel($_[0],${$p->get_dataref},$_[2],$_[3]);
Gimp::PixelRgn::_set_pixel($_[0],${$p->get_dataref},$_[2],$_[3]);
};
rep "set_col", sub($$$$) {
sub Gimp::PixelRgn::set_col {
(my $p = byte $_[1])->make_physical;
old_set_col($_[0],${$p->get_dataref},$_[2],$_[3]);
Gimp::PixelRgn::_set_col($_[0],${$p->get_dataref},$_[2],$_[3]);
};
rep "set_row", sub($$$$) {
sub Gimp::PixelRgn::set_row {
(my $p = byte $_[1])->make_physical;
old_set_row($_[0],${$p->get_dataref},$_[2],$_[3]);
Gimp::PixelRgn::_set_row($_[0],${$p->get_dataref},$_[2],$_[3]);
};
rep "set_rect", sub($$$$) {
sub Gimp::PixelRgn::set_rect {
(my $p = byte $_[1])->make_physical;
old_set_rect($_[0],${$p->get_dataref},$_[2],$_[3],($_[1]->dims)[1]);
Gimp::PixelRgn::_set_rect($_[0],${$p->get_dataref},$_[2],$_[3],($_[1]->dims)[1]);
};
$^W = $old_w; undef $old_w;
1;
__END__
......@@ -102,15 +86,15 @@ Gimp::PDL - Overwrite Tile/Region functions to work with piddles.
=head1 SYNOPSIS
use Gimp;
use Gimp::PDL; # must be use'd _after_ Gimp!
use Gimp::PDL;
use PDL;
=head1 DESCRIPTION
This module overwrites all methods of Gimp::Tile and Gimp::PixelRgn. The new
functions return and accept piddles instead of strings for pixel values. The
last argument (height) of C<gimp_pixel_rgn_set_rect> is calculated from the
piddle.
This module overwrites some methods of Gimp::Tile and Gimp::PixelRgn. The
new functions return and accept piddles. The last argument (height) of
C<gimp_pixel_rgn_set_rect> is calculated from the piddle. There is no
other way to access the raw pixeldata in Gimp.
Some exmaples:
......
......@@ -4,7 +4,9 @@ Gimp::Pixel - how to operate on raw pixels
=head1 SYNOPSIS
use Gimp; # all you need is in Gimp.
use Gimp;
use Gimp::PDL; # you need Gimp::PDL for pixel access
use PDL; # to make sensible things with the pixels
# Gimp::GDrawable - The GDrawable structure
# Gimp::Tile - The Tile family of functions.
......@@ -57,8 +59,8 @@ expects pixel coordinates and will return the tile that pixel is in:
The C<data> method returns and sets the raw pixel data.
$packed_data = $tile->data; # you don't want this, use Gimp::PDL
$tile->data($packed_data); # and modify the tile
$piddle = $tile->data; # get the tile data as a piddle
$tile->data($piddle); # and modify the tile
=head1 PIXELREGIONS
......@@ -83,20 +85,20 @@ which method you choose is purely a question of style...
The following functions return packed pixel data (see L<Gimp::PDL> for an
easier way to manipulate on image data):
$packed_data = $region->get_pixel(45,60); # return the pixel at (45|60)
$packed_data = $region->get_row(45,60,10); # return ten horizontal pixels
$packed_data = $region->get_col(45,60,10); # same but vertically
$packed_data = $region->get_rect(45,60,10,12); # a 10x12 rectangle
$piddle = $region->get_pixel(45,60); # return the pixel at (45|60)
$piddle = $region->get_row(45,60,10); # return ten horizontal pixels
$piddle = $region->get_col(45,60,10); # same but vertically
$piddle = $region->get_rect(45,60,10,12); # a 10x12 rectangle
To modify pixels, the dirty bit of the region must be set (I believe, but I
don't see the reason what the dirty bit in a region is for so I might be
wrong), and you can write pixel data to the region with the following
functions, each one corresponding to a get-function:
$region->set_pixel($packed_data,45,60); # set pixel at (45|60)
$region->set_row($packed_data,45,60); # set a row
$region->set_col($packed_data,45,60); # set a column
$region->set_rect($packed_data,45,60,10); # a 10 pixel wide rectangle
$region->set_pixel($piddle,45,60); # set pixel at (45|60)
$region->set_row($piddle,45,60); # set a row
$region->set_col($piddle,45,60); # set a column
$region->set_rect($piddle,45,60,10); # a 10 pixel wide rectangle
Please note that (different to the C functions they call), the last
parameter (width or height) is missing, it can be calculcated from the perl
......@@ -112,3 +114,4 @@ Marc Lehmann <pcg@goof.com>
perl(1), Gimp(1).
=cut
......@@ -41,22 +41,28 @@ reimplement all of it in perl.
@Gimp::UI::ChannelMenu::ISA =qw(Gimp::UI);
@Gimp::UI::DrawableMenu::ISA=qw(Gimp::UI);
sub image_name {
my $name = $_[0]->get_filename;
$name.="-".${$_[0]} if $name eq "Untitled";
$name;
}
sub Gimp::UI::ImageMenu::_items {
map [[$_],$_,$_->get_filename],
map [[$_],$_,image_name($_)],
Gimp->list_images ();
}
sub Gimp::UI::LayerMenu::_items {
map { my $i = $_; map [[$i,$_],$_,$i->get_filename."/".$_->get_name],$i->get_layers }
map { my $i = $_; map [[$i,$_],$_,image_name($i)."/".$_->get_name],$i->get_layers }
Gimp->list_images ();
}
sub Gimp::UI::ChannelMenu::_items {
map { my $i = $_; map [[$i,$_],$_,$i->get_filename."/".$_->get_name],$i->get_channels }
map { my $i = $_; map [[$i,$_],$_,image_name($i)."/".$_->get_name],$i->get_channels }
Gimp->list_images ();
}
sub Gimp::UI::DrawableMenu::_items {
map { my $i = $_; map [[$i,$_],$_,$i->get_filename."/".$_->get_name],($i->get_layers, $i->get_channels) }
map { my $i = $_; map [[$i,$_],$_,image_name($i)."/".$_->get_name],($i->get_layers, $i->get_channels) }
Gimp->list_images ();
}
......
......@@ -222,7 +222,7 @@ sub layer_add_layer_as_mask {
1;
##############################################################################
# all functions below are originally for the chart module
# all functions below are by Marc Lehmann
=pod
=item C<gimp_text_wh $text,$fontname>
......@@ -236,6 +236,22 @@ sub gimp_text_wh {
=pod
=item C<gimp_image_layertype $alpha>
returns the corresponding layer type for an image, alpha controls wether the layer type
is with alpha or not. Example: imagetype: RGB -> RGB_IMAGE (or RGBA_IMAGE).
=cut
sub gimp_image_layertype {
my $type = $_[0]->base_type;
$type == RGB ? $alpha ? RGBA_IMAGE : RGB_IMAGE :
$type == GRAY ? $alpha ? GRAYA_IMAGE : GRAY_IMAGE :
$type == INDEXED ? $alpha ? INDEXEDA_IMAGE : INDEXED_IMAGE :
die;
}
=pod
=back
=head1 AUTHOR
......
......@@ -56,3 +56,5 @@ examples/feedback.pl
examples/xachlego.pl
examples/xachshadow.pl
examples/parasite-editor
examples/scratches.pl
examples/blowinout.pl
......@@ -116,7 +116,8 @@ EOF
@examples =
qw(windy.pl prep4gif.pl webify.pl PDB alpha2color.pl tex-to-float ditherize.pl
border.pl view3d.pl feedback.pl xachlego.pl xachshadow.pl parasite-editor);
border.pl view3d.pl feedback.pl xachlego.pl xachshadow.pl parasite-editor
scratches.pl blowinout.pl);
@shebang = (map("examples/$_",@examples),
qw(Perl-Server scm2perl scm2scm examples/example-net.pl examples/homepage-logo.pl
examples/example-fu.pl));
......
......@@ -10,14 +10,13 @@ make test TEST_VERBOSE=1
bugs
[DONE] * auto-edit shebang
[XXXX] * only install plug-ins that really work
* perl_fu_webify in homepage-logo.pl
* wait for working gimp_file_load (or do it myself?)
[DONE] * Gimp::import should croak on importing "garbage".
important issues
* fix auto-edit shebang for check-ins
* gimp-tiles are not accessible in any way..
* register dummy function to calm gimp down
* paths in module(!)
* gimp->object_id, drawable_object_id remove!
......@@ -44,7 +43,7 @@ important issues
* create working progress when Net and $verbose
* require Storable soon(!)
* Gimp::Fu::command(?)
* Untitled/0 Untitled/1 etc..
[DONE] * Untitled/0 Untitled/1 etc..
* default parameters at end(!)
* try to deduce default parameters
......
#!/usr/bin/perl
# Blow In/Out
# John Pitney
use Gimp;
use Gimp::Fu;
# print "hello there\n";
# Gimp::set_trace(TRACE_CALL);
sub blowinout {
my ($img, $drawable, $angle, $nsteps, $distance, $inmode, $arithmode) = @_;
# bail out if $drawable isn't a layer
# print "Starting\n";
if( gimp_selection_is_empty($img) == 0) { return };
# if ($nsteps == 0) return;
eval { $img->undo_push_group_start };
# save the background color for later restoration
my $oldbg = gimp_palette_get_background();
#get the drawable dimensions
my $xsize = gimp_drawable_width($drawable);
my $ysize = gimp_drawable_height($drawable);
# Set background color to 128, for clearing dm
gimp_palette_set_background([128,128,128]);
# Create a grayscale workspace image for displacement map
my $dm = gimp_image_new($xsize, $ysize, 1);
eval { $dm->undo_push_group_start($dm) };
# It needs to have 2 layers
my $dmlayer = gimp_layer_new($dm, $xsize, $ysize, GRAY_IMAGE, "newlayer",
100, NORMAL_MODE);
gimp_image_add_layer($dm, $dmlayer, 0);
# Create the layers, one-by-one
my $i = 1;
my $xdist = ($arithmode) ?
$i * $distance / $nsteps * -cos($angle * 3.14159 / 180) :
$distance ** ($i/$nsteps) * -cos($angle * 3.14159 / 180);
my $ydist = ($arithmode) ?
$i * $distance / $nsteps * sin($angle * 3.14159 / 180) :
$distance ** ($i/$nsteps) * sin($angle * 3.14159 / 180);
gimp_edit_clear($dmlayer);
plug_in_noisify(1, $dm, $dmlayer, 0, 255, 255, 255, 0);
gimp_levels($dmlayer, 0, 0, 255, 1.0, 128, 255);
$drawable = gimp_layer_copy($drawable, 0);
gimp_image_add_layer($img, $drawable, -1);
plug_in_displace(1, $img, $drawable, $xdist, $ydist, 1, 1, $dmlayer,
$dmlayer, 1);
if ( $inmode == 1 )
{
gimp_image_lower_layer($img, $drawable);
};
for ( $i = 2; $i <= $nsteps; $i++ ) {
$xdist = ($arithmode) ?
$i * $distance / $nsteps * -cos($angle * 3.14159 / 180) :
$distance ** ($i/$nsteps) * -cos($angle * 3.14159 / 180);
$ydist = ($arithmode) ?
$i * $distance / $nsteps * sin($angle * 3.14159 / 180) :
$distance ** ($i/$nsteps) * sin($angle * 3.14159 / 180);
gimp_edit_clear($dmlayer);
plug_in_noisify(1, $dm, $dmlayer, 0, 255, 255, 255, 0);
gimp_levels($dmlayer, 0, 0, 255, 1.0, 128, 255);
$drawable = gimp_layer_copy($drawable, 0);
gimp_image_add_layer($img, $drawable, -1);
plug_in_displace(1, $img, $drawable, $xdist, $ydist, 1, 1, $dmlayer,
$dmlayer, 1);