Script file generated from LiVES
<define>
|1.7
</define>
<name>
ripple
</name>
<version>
1
</version>
<author>
saulgoode|http://chiselapp.com/user/saulgoode/repository/RFX-GIMP/home
</author>
<description>
Ripple|rippling|1|1|
</description>
<requires>
gimp
</requires>
<params>
ripple-period|Period|num0|50|0|10000|
ripple-amp|Amplitude|num0|20|0|10000|
ripple-modulation|Modulation|num2|0.00|0.00|10000.00|0.25|
ripple-mod-type|Modulation Type|string_list|0|Linear|Sinusoidal|
ripple-direction|Vertical|bool|1|
ripple-edge|Edge Handling|string_list|0|Smear|Wrap|Blank|
ripple-sine|Sine Wave|bool|1|1|
ripple-triangle|Triangle Wave|bool|0|1|
ripple-velocity|Velocity|num0|0|-10000|10000|
</params>
<param_window>
</param_window>
<properties>
0x0001
</properties>
<language_code>
0xF0
</language_code>
<pre>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 or higher
# as published by the Free Software Foundation.
use IO::Socket;
use Text::Balanced;
if ($ENV{'RFXGIMP_PORT'}) {
$rfx_port = $ENV{'RFXGIMP_PORT'};
}
else {
$rfx_port = 10008;
}
$sock = new IO::Socket::INET ( PeerAddr => 'localhost',
PeerPort => $rfx_port,
Proto => 'tcp'
);
if ( not defined $sock ) {
my $rfx_pid = fork();
if (not defined $rfx_pid) {
&sig_error("UNABLE TO EXECUTE GIMP: Not enough resources");
}
elsif ($rfx_pid == 0) {
if ( -f $tmpdir . "rfxgimp.pid") {
open(PIDFILE, $tmpdir . "rfxgimp.pid");
# should probably do some sanity checking for the off chance that
# the PID has been recycled or the system has rebooted (e.g, check
# if process was executed with /usr/bin/perl. But for now...
kill(15, -<PIDFILE>); # the negative PID means kill all children, too.
close(PIDFILE);
}
setpgid($$,0); # change the pgroup to this forked process, rather than
# the original LiVES (so that we don't kill LiVES when
# this prgroup is killed).
open(PIDFILE, ">" . $tmpdir . "rfxgimp.pid"); # overwrite old file
print PIDFILE $$;
close(PIDFILE);
my $start_gimp = qq{ gimp -i -b "(plug-in-script-fu-server 1 $rfx_port \\\"\\\")" & };
system ( $start_gimp ); # though started as separate process, GIMP now
# is part of this spawned child's pgroup, not the LiVES pgroup
sleep(); # do nothing, forever
&sig_error("GIMP killed by external process\n");
}
else {
while (not defined $sock) {
sleep (1);
$sock = new IO::Socket::INET ( PeerAddr => 'localhost',
PeerPort => $rfx_port,
Proto => 'tcp'
);
}
}
}
# Define a Perl subroutine for sending messages to the SF server and waiting
# for a response.
#
sub rfx_sendmsg {
my $message = $_[0];
my $len = length ($message);
if ($len > 65535) {
&sig_error("ERROR: script is too long for one server request: $len > 65535");
};
# send script to GIMP
my $header = pack( 'an', 'G', $len);
syswrite( $sock, $_ ) for ($header, $message);
# wait for response
my $rin = '';
vec( $rin, fileno($sock), 1 ) = 1;
select( $rin, undef, undef, undef ); # wait (forever) for response start
select( undef, undef, undef, .1 ); # wait a bit for response to finish
# increase wait if INVALID/INCOMPLETE RESPONSE occurs
# response
$len = sysread( $sock, $header, 4 ) or &sig_error("INVALID RESPONSE: empty response");
( $len == 4 and $header =~ /^G/ ) or &sig_error("INVALID RESPONSE: bad header");
my $status;
($status, $len) = unpack( 'xCn', $header );
my $response;
( sysread( $sock, $response, $len ) == $len ) or &sig_error("INCOMPLETE RESPONSE: $response");
# exit if response is not "Success"
if ( $status and $response =~ /^Error: Success\n/i ) {
&sig_error("UNSUCCESSFUL EXECUTION: Script-fu error");
}
$status;
}
# define a Script-fu utility function to save frames using the PNG or JPG
# compression levels specified in 'gimprc'.
# To specify a PNG compression level of 5, include the following line
# in gimprc:
# (rfx-png-compression "5")
# If not specified then a default level of "3" is assumed.
# "3" is a good choice for PNGs because higher levels double the write
# times while only offering about 15% reduction in file size.
# To specify a JPG compression level of 85, include the following line
# in gimprc:
# (rfx-jpg-compression "85")
# If not specified then a default level of "93" is assumed.
# NOTE: 'rfx-save-frame' DELETES the image.
&rfx_sendmsg( qq{
(begin
(define rfx-curtmpdir "$curtmpdir")
(define rfx-imgext "$img_ext")
(unless (defined? 'rfx-save-frame)
(define rfx-png-compression (catch #f (gimp-gimprc-query "rfx-png-compression")))
(set! rfx-png-compression (if rfx-png-compression
(string->number (car rfx-png-compression))
3 ))
(define rfx-jpg-compression (catch #f (gimp-gimprc-query "rfx-jpg-compression")))
(set! rfx-jpg-compression (if rfx-jpg-compression
(string->number (car rfx-jpg-compression))
93 ))
(define (rfx-save-frame image basename)
(let ((filename (string-append rfx-curtmpdir DIR-SEPARATOR basename))
(layer (car (gimp-image-get-active-layer image))) )
(if (string-ci=? rfx-imgext ".jpg")
(begin
(gimp-context-push)
(gimp-context-set-background '(6 6 6))
(let loop ((layers (vector->list (cadr (gimp-image-get-layers image)))))
(unless (null? layers)
(if (= (car layers) layer)
(gimp-drawable-set-visible layer TRUE)
(gimp-drawable-set-visible (car layers) FALSE) )
(loop (cdr layers)) ))
(set! layer (car (gimp-image-flatten image)))
(file-jpeg-save RUN-NONINTERACTIVE
image
layer
filename
filename
(/ rfx-jpg-compression 100)
0 ; smoothing
1 ; optimize
1 ; progressive
"" ; comment
0 ; subsmp (0-4)
1 ; baseline
0 ; restart
0 ;dct
)
(gimp-context-pop) )
(begin
(unless (zero? (car (gimp-image-base-type image)))
(gimp-image-convert-rgb image) )
(file-png-save2 RUN-NONINTERACTIVE
image
layer
filename
filename
FALSE ; interlace
rfx-png-compression
FALSE ; bkgd
(car (gimp-drawable-has-alpha layer))
FALSE ; offs
FALSE ; phys
FALSE ; time
TRUE ; comment
FALSE ; svtrans
)))
(gimp-image-delete image) ))))
}
);
</pre>
<loop>
# $p0 ; period (in pixels)
# $p1 ; amplitude
# $p2 ; amplitude modulation cycles (0=none, number cycles during frame sequence)
# $p3 ; modulation type linear/sinusoidal (dropdown)
# $p4 ; direction (bool: horiz=0 vert=1)
# $p5 ; edge type (dropdown: smear, wrap, blank)
# $p6 ; sine wave (radio group 1)
# $p7 ; triangle (radio group 1)
# $p8 ; velocity (0=constant, else number of pixels shifted each frame)
# Note: GIMP's Ripple plug-in does not directly support either phase shifting
# or negative amplitudes. To implement phase shifting, it is therefore
# necessary to resize the drawable by the amount of the shift. To
# accommodate negative amplitudes, the effect is also phase shifted
# by half the period.
#
# rfx-ripple-mod and rfx-ripple-phase are each a pair containing
# the current value and the increment amount. Both need to be defined
# globally and therefore can not be defined within a lambda/let.
#
# In the case of rfx-ripple-phase, the value is an offset in the
# range 0 <= X < period (period is in pixels).
#
# In the case of rfx-ripple-mod, the value is an offset that is in the
# range 0 <= X < 1. The script then determines the scaling of
# the actual ripple amplitude based upon the evaluation of either
# the triangle or sinusoidal.
#
&rfx_sendmsg (
qq{
(begin
(unless (zero? $p8)
(if (= $frame $start)
(define rfx-ripple-phase (cons 0
(if (> $p8 0)
(- $p0 $p8)
(- $p8) )))
(set! rfx-ripple-phase (cons (let loop ((phase-offset (+ (car rfx-ripple-phase)
(cdr rfx-ripple-phase) )))
(if (< phase-offset $p0)
phase-offset
(loop (- phase-offset $p0)) ))
(cdr rfx-ripple-phase) ))))
(unless (zero? $p2)
(if (= $frame $start)
(define rfx-ripple-mod (cons 0 (* $p2 (/ (succ (- $end $start))))))
(set! rfx-ripple-mod (cons (let loop ((amp-offset (+ (car rfx-ripple-mod)
(cdr rfx-ripple-mod) )))
(if (< amp-offset 1)
amp-offset
(loop (- amp-offset 1)) ))
(cdr rfx-ripple-mod) ))))
(let ((period $p0)
(amplitude $p1)
(mod-cycles $p2)
(mod-linear $p3)
(direction $p4)
(edge $p5)
(sine $p6)
(triangle $p7)
(velocity (- $p8))
(phase-offset 0)
)
(let* ((input-file (string-append "$curtmpdir" DIR-SEPARATOR "$in"))
(image (car (gimp-file-load RUN-NONINTERACTIVE input-file input-file)))
(layer (car (gimp-image-get-active-layer image))) )
; calculate layer offfset owing to animated phase
(unless (zero? velocity) ; phase motion
(set! phase-offset (car rfx-ripple-phase)) )
(set! amplitude
(* amplitude
(if (zero? mod-cycles)
1
(let ((fract (- (car rfx-ripple-mod) (truncate (car rfx-ripple-mod)))))
(if mod-linear
(cond
((< fract 0.25)
(* amplitude fract 4) )
((< fract 0.50)
(* amplitude (- 1 (* (- fract 0.25) 4))) )
((< fract 0.75)
(* amplitude (- (* amplitude (- fract 0.5) 4))) )
(else
(- (* amplitude (- fract 0.75) 4) 1) )))
(sin (* 2 *pi* fract)) ))))
(when (< amplitude 0)
(set! phase-offset (+ phase-offset (/ period 2)))
(if (>= phase-offset period)
(set! phase-offset (- phase-offset period)) ))
(set! amplitude (abs amplitude))
(unless (zero? phase-offset)
(if (zero? direction)
(gimp-layer-resize layer
$width
(+ phase-offset $height)
0
phase-offset )
(gimp-layer-resize layer
(+ phase-offset $width)
$height
phase-offset
0 )))
(plug-in-ripple RUN-NONINTERACTIVE image layer
period
amplitude
direction
edge
sine
TRUE ; always use antialias
FALSE ; we don't need tilability
)
(gimp-layer-resize-to-image-size layer)
(rfx-save-frame image "$out")
)
)
)
}
);
</loop>
<post>
</post>
<onchange>
init|if ($p4 == 1) { # horizontal
init| $p0_max = $width;
init| $p1_max = $height;
init| }
init|else { # vertical
init| $p0_max = $height;
init| $p1_max = $width;
init| }
init|$p2_max = $end - $start;
init|$p2_min = 0;
init|$p8_max = $end - $start;
init|$p8_min = $start - $end;
</onchange>