mirror of https://github.com/GNOME/gimp.git
216 lines
7.8 KiB
Perl
Executable File
216 lines
7.8 KiB
Perl
Executable File
#!/usr/app/bin/perl
|
|
|
|
eval 'exec /usr/app/bin/perl -S $0 ${1+"$@"}'
|
|
if 0; # not running under some shell
|
|
|
|
#
|
|
# Note: Seth has transferred the maintainer `position' to me, so bother me
|
|
# instead of him now :-)
|
|
# - Steinar H. Gunderson <sgunderson@bigfoot.com>
|
|
|
|
|
|
# This one's all mine. Well, its GPL/Artisitic but I'm the author and creator.
|
|
# You need gimp 1.1 or better for this; too much has changed, and I don't think
|
|
# 1.0.x had a perspective PDB function anyway
|
|
|
|
# Here's the working theory on this:
|
|
# There's a function called spinlayer which will spin from a spinlayer to a
|
|
# destlayer. It won't touch those 2 layers at all, and will leave its results
|
|
# on the top of the layer stack.
|
|
#
|
|
# If the user wants to spin back, it will take 1/2 the layers otherwise required
|
|
# per call to the spin_layer, so that the number of total layers comes out the
|
|
# same.
|
|
#
|
|
# The main function makes a new image, copies the source and destination onto it
|
|
# with appropriate offsets, and passes this image with the bottom 2 layers to
|
|
# spin_layer. At the end, remove the original 2 layers, since they won't be
|
|
# needed, and add in some Layer comments for timing your gif.
|
|
#
|
|
################################################################################
|
|
# Many thanks to Steinar and Marc, for expressing an intrest in the script that
|
|
# kept me going, and to Steinar in particular for helping me track down why the
|
|
# script was crashing gimp (hint - don't make layers of height=0, and if you do
|
|
# make sure you're logging to console since the Gtk messagebox will never show
|
|
# up due to a rapid segfault).
|
|
#
|
|
# Just a comment on that: We fixed the bug, so height=0 no longer segfaults, but
|
|
# gives the error message it should. However, if GIMP segfaults, you should try
|
|
# logging to console to make sure you get all applicable error messages. This
|
|
# will make it _much_ easier to find the bug. - Steinar
|
|
#
|
|
# Revision History:
|
|
# 1.0 - Initial (too early) release
|
|
# 1.1 - Second (still ugly) release: Made the perspective setting actually do
|
|
# something
|
|
# 1.2 - Used some of the convienence functions, and made things a little eaiser
|
|
# from the user's standpoint too. Also moved it from the
|
|
# Filters->Animations-> menu to Xtns->Animations. I think its
|
|
# clearer whats going on this way. It also works w/ any 2 layers now.
|
|
# 1.5 - Some debugging by Steinar and myself to make it work again.
|
|
# 1.6 - Moved some renaming into the main loop, more cleanups.
|
|
#
|
|
# TODO: Clean it up; allow for other effects (skewing, ripples?) while spinning;
|
|
|
|
# Seth Burgess
|
|
# <sjburges@gimp.org>
|
|
|
|
use Gimp; # No qw(:auto) - Trying to use all OO-styling
|
|
use Gimp::Fu;
|
|
use Gimp::Util;
|
|
|
|
# Gimp::set_trace(TRACE_ALL);
|
|
|
|
sub saw { # a sawtooth function on PI
|
|
($val) = @_;
|
|
if ($val < 3.14159/2.0) {
|
|
return ($val/3.14159);
|
|
} elsif ($val < 3.14159) {
|
|
return (-1+$val/3.14159);
|
|
} elsif ($val < 3.14159+3.14159/2.0) {
|
|
return ($val/3.14159);
|
|
} else {
|
|
return (-1+$val/3.14159);
|
|
}
|
|
}
|
|
|
|
sub spin_layer { # the function for actually spinning the layer
|
|
my ($img, $spin, $dest, $numframes, $prp) = @_;
|
|
|
|
my $floater, # The transformed image
|
|
$framelay, # The background color
|
|
$frameno; # The current frame
|
|
|
|
# Now let's spin it!
|
|
$stepsize = 3.14159/$numframes; # in radians
|
|
$frameno = 0;
|
|
for ($i=0; $i<=3.14159; $i+=$stepsize) {
|
|
Gimp->progress_update ($i/3.14159);
|
|
|
|
# create a new layer for spinning
|
|
$framelay = ($i < 3.14159/2.0) ? $spin->copy(1) : $dest->copy(1);
|
|
$img->add_layer($framelay, 0);
|
|
$floater = $framelay->copy(1);
|
|
$img->add_layer($floater, 0);
|
|
|
|
# spin it a step
|
|
$img->selection_all();
|
|
@x = $img->selection_bounds();
|
|
$img->selection_none();
|
|
|
|
# x[1],x[2] x[3],x[2]
|
|
# x[1],x[4] x[3],x[4]
|
|
my($y1, $y3);
|
|
$y1 = int($x[2]+$spin->height *sin($i)/2);
|
|
$y3 = int($x[4]-$spin->height *sin($i)/2);
|
|
|
|
# height must be != 0
|
|
$y3++ if ($y1 == $y3);
|
|
|
|
$floater = Gimp->perspective($floater, 1,
|
|
$x[1]+saw($i)*$prp*$framelay->width,$y1,
|
|
$x[3]-saw($i)*$prp*$framelay->width,$y1,
|
|
$x[1]-saw($i)*$prp*$framelay->width,$y3,
|
|
$x[3]+saw($i)*$prp*$framelay->width,$y3);
|
|
$framelay->fill(1); # BG-IMAGE-FILL
|
|
|
|
# merge the two layers together before we continue
|
|
$img->set_visible($floater, $framelay);
|
|
$framelay = $img->merge_visible_layers(0);
|
|
|
|
$frameno++;
|
|
$framelay->set_name("Spin Layer $frameno (50ms)");
|
|
}
|
|
}
|
|
|
|
register "seth_spin",
|
|
"Seth Spin",
|
|
"Take one image. Spin it about the horizontal axis, and end up with another image. I made it for easy web buttons.",
|
|
"Seth Burgess",
|
|
"Seth Burgess <sjburges\@gimp.org>",
|
|
"1.6",
|
|
N_"<Toolbox>/Xtns/Animation/Seth Spin",
|
|
"*",
|
|
[
|
|
[PF_DRAWABLE, "source", "What drawable to spin from?"],
|
|
[PF_DRAWABLE, "destination","What drawable to spin to?"],
|
|
[PF_INT8, "frames", "How many frames to use?", 16],
|
|
[PF_COLOR, "background", "What color to use for background if not transparent", [0,0,0]],
|
|
[PF_SLIDER, "perspective", "How much perspective effect to get", 40, [0,255,5]],
|
|
[PF_TOGGLE, "spin_back", "Also spin back?" , 1],
|
|
[PF_TOGGLE, "convert_indexed", "Convert to indexed?", 1],
|
|
],
|
|
[],
|
|
['gimp-1.1'],
|
|
sub {
|
|
my($src,$dest,$frames,$color,$perspective,$spinback,$indexed) = @_;
|
|
|
|
$oldbackground = Gimp->palette_get_background();
|
|
Gimp->palette_set_background($color);
|
|
|
|
$perspective = $perspective/255.0; # PF_SLIDER doesn't work right for < 1
|
|
|
|
Gimp->progress_init(__"Seth Spin...",-1);
|
|
|
|
# Copy souce and destination to new image
|
|
|
|
$maxwide = ($src->width > $dest->width) ? $src->width : $dest->width;
|
|
$maxhigh = ($src->height > $dest->height) ? $src->height: $dest->height;
|
|
|
|
$img = Gimp->image_new($maxwide, $maxhigh, RGB);
|
|
$tmpimglayer = $img->add_new_layer(0,3,1); # have to have a layer before displaying
|
|
$img->display_new;
|
|
|
|
$src->edit_copy();
|
|
$spinlayer = $tmpimglayer->edit_paste(1);
|
|
$spinlayer->floating_sel_to_layer();
|
|
|
|
$dest->edit_copy();
|
|
$destlayer = $tmpimglayer->edit_paste(1);
|
|
$destlayer->floating_sel_to_layer();
|
|
|
|
$tmpimglayer->remove_layer; # remove temporary layer.
|
|
|
|
# set the layer size to be the full layer for each copied layer
|
|
$spinlayer->resize($maxwide, $maxhigh, $spinlayer->offsets);
|
|
$destlayer->resize($maxwide, $maxhigh, $destlayer->offsets);
|
|
|
|
# need an even number of frames for spinback
|
|
if ($frames%2 && $spinback) {
|
|
$frames++;
|
|
Gimp->message(__"An even number of frames is needed for spin back.\nAdjusted frames up to $frames");
|
|
}
|
|
|
|
spin_layer($img, $spinlayer, $destlayer, $spinback ? $frames/2 : $frames, $perspective);
|
|
|
|
# go back from destination to spinlayer if spinning back
|
|
if ($spinback) {
|
|
@layerlist = $img->get_layers();
|
|
spin_layer($img, $destlayer, $spinlayer, $frames/2, $perspective);
|
|
}
|
|
|
|
# remove the original 2 pasted layers
|
|
$img->remove_layer($destlayer);
|
|
$img->remove_layer($spinlayer);
|
|
|
|
# unhide and name layers (Give timings)
|
|
@all_layers = $img->get_layers;
|
|
$img->set_visible(@all_layers);
|
|
|
|
if ($spinback) {
|
|
$all_layers[$frames/2-1]->set_name(__"Spin Layer DEST (250ms)");
|
|
}
|
|
$all_layers[$frames-1]->set_name(__"Spin Layer SRC (250ms)");
|
|
|
|
# indexed conversion wants a display for some reason
|
|
if ($indexed) {
|
|
$img->convert_indexed(1,MAKE_PALETTE,255,0,1,"buffy" );
|
|
}
|
|
|
|
Gimp->palette_set_background($oldbackground);
|
|
return();
|
|
};
|
|
|
|
exit main;
|
|
|