Script file generated from LiVES
<define>
|1.7
</define>
<name>
gap-edit
</name>
<version>
1
</version>
<author>
saulgoode|
</author>
<description>
Edit in GIMP-GAP|Importing from GAP|1|1|
</description>
<requires>
gimp
</requires>
<params>
message|Edit now in GAP, click OK only after you have finished.|bool|1|
</params>
<param_window>
</param_window>
<properties>
0x0001
</properties>
<language_code>
0xF0
</language_code>
<pre>
# reconnect to server
use IO::Socket;
use Text::Balanced;
$img_ext=".png"; # this is not set for trigger code.
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'
);
}
}
}
</pre>
<loop>
&rfx_sendmsg( qq{
(begin
(let* ((basename (car (strbreakup (car (last (strbreakup "$in" DIR-SEPARATOR))) "$img_ext")))
(input-file (string-append "$curtmpdir" "/gap-clip" DIR-SEPARATOR basename ".xcf"))
(image (car (gimp-file-load RUN-NONINTERACTIVE input-file input-file)))
(layer (car (gimp-image-get-active-layer image))) )
(rfx-save-frame image "$out")
)
)
}
);
</loop>
<post>
use File::Path;
my $rfx_gap_dir = "./gap-clip";
#-- remove the GAP directory
if (-d $rfx_gap_dir) {
rmtree($rfx_gap_dir);
};
</post>
<onchange>
init|# This program is free software; you can redistribute it and/or modify
init|# it under the terms of the GNU General Public License version 3 or higher
init|# as published by the Free Software Foundation.
init|
init|# For gap-edit much of the setup that is typically performed
init|# in preloop is done in init. This is so that closing of the
init|# dialog can be used as the indicator that the user has
init|# completed his editing in GAP.
init|#
init|# Steps in overall process:
init|# init: ensure RFX-GIMP daemon is running as per usual
init|# make or clean out directory $curtmpdir/gap-clip
init|# &mkname all frames in selection (guarantee they exist)
init|# copy (using rfx-gimp server) selection as XCF to gap-clip
init|# run gimp $first
init|# display param window (message to press OK when done editing)
init|# pre: no op
init|# loop: no op
init|# post: backup all source frames (for UNDO)
init|# convert (using rfx-gimp server) XCF frames to $img_ext in $in
init|# delete XCF frames
init|
init|use IO::Socket;
init|use Text::Balanced;
init|
init|$img_ext=".png"; # this is not set for trigger code.
init|
init|if ($ENV{'RFXGIMP_PORT'}) {
init| $rfx_port = $ENV{'RFXGIMP_PORT'};
init| }
init|else {
init| $rfx_port = 10008;
init| }
init|
init|$sock = new IO::Socket::INET ( PeerAddr => 'localhost',
init| PeerPort => $rfx_port,
init| Proto => 'tcp'
init| );
init|if ( not defined $sock ) {
init| my $rfx_pid = fork();
init| if (not defined $rfx_pid) {
init| &sig_error("UNABLE TO EXECUTE GIMP: Not enough resources");
init| }
init| elsif ($rfx_pid == 0) {
init| if ( -f $tmpdir . "rfxgimp.pid") {
init| open(PIDFILE, $tmpdir . "rfxgimp.pid");
init| # should probably do some sanity checking for the off chance that
init| # the PID has been recycled or the system has rebooted (e.g, check
init| # if process was executed with /usr/bin/perl. But for now...
init| kill(15, -<PIDFILE>); # the negative PID means kill all children, too.
init| close(PIDFILE);
init| }
init| setpgid($$,0); # change the pgroup to this forked process, rather than
init| # the original LiVES (so that we don't kill LiVES when
init| # this prgroup is killed).
init| open(PIDFILE, ">" . $tmpdir . "rfxgimp.pid"); # overwrite old file
init| print PIDFILE $$;
init| close(PIDFILE);
init| my $start_gimp = qq{ gimp -i -b "(plug-in-script-fu-server 1 $rfx_port \\\"\\\")" & };
init| system ( $start_gimp ); # though started as separate process, GIMP now
init| # is part of this spawned child's pgroup, not the LiVES pgroup
init| sleep(); # do nothing, forever
init| &sig_error("GIMP killed by external process\n");
init| }
init| else {
init| while (not defined $sock) {
init| sleep (1);
init| $sock = new IO::Socket::INET ( PeerAddr => 'localhost',
init| PeerPort => $rfx_port,
init| Proto => 'tcp'
init| );
init| }
init| }
init| }
init|
init|# Define a Perl subroutine for sending messages to the SF server and waiting
init|# for a response.
init|#
init|sub rfx_sendmsg {
init| my $message = $_[0];
init| my $len = length ($message);
init| if ($len > 65535) {
init| &sig_error("ERROR: script is too long for one server request: $len > 65535");
init| };
init| # send script to GIMP
init| my $header = pack( 'an', 'G', $len);
init| syswrite( $sock, $_ ) for ($header, $message);
init| # wait for response
init| my $rin = '';
init| vec( $rin, fileno($sock), 1 ) = 1;
init| select( $rin, undef, undef, undef ); # wait (forever) for response start
init| select( undef, undef, undef, .1 ); # wait a bit for response to finish
init| # increase wait if INVALID/INCOMPLETE RESPONSE occurs
init| # response
init| $len = sysread( $sock, $header, 4 ) or &sig_error("INVALID RESPONSE: empty response");
init| ( $len == 4 and $header =~ /^G/ ) or &sig_error("INVALID RESPONSE: bad header");
init| my $status;
init| ($status, $len) = unpack( 'xCn', $header );
init| my $response;
init| ( sysread( $sock, $response, $len ) == $len ) or &sig_error("INCOMPLETE RESPONSE: $response");
init| # exit if response is not "Success"
init| if ( $status and $response =~ /^Error: Success\n/i ) {
init| &sig_error("UNSUCCESSFUL EXECUTION: Script-fu error");
init| }
init| $status;
init| }
init|
init|# define a Script-fu utility function to save frames using the PNG or JPG
init|# compression levels specified in 'gimprc'.
init|# To specify a PNG compression level of 5, include the following line
init|# in gimprc:
init|# (rfx-png-compression "5")
init|# If not specified then a default level of "3" is assumed.
init|# "3" is a good choice for PNGs because higher levels double the write
init|# times while only offering about 15% reduction in file size.
init|# To specify a JPG compression level of 85, include the following line
init|# in gimprc:
init|# (rfx-jpg-compression "85")
init|# If not specified then a default level of "93" is assumed.
init|
init|# NOTE: 'rfx-save-frame' DELETES the image.
init|&rfx_sendmsg( qq{
init| (begin
init| (define rfx-curtmpdir "$curtmpdir")
init| (define rfx-imgext "$img_ext")
init| (unless (defined? 'rfx-save-frame)
init| (define rfx-png-compression (catch #f (gimp-gimprc-query "rfx-png-compression")))
init| (set! rfx-png-compression (if rfx-png-compression
init| (string->number (car rfx-png-compression))
init| 3 ))
init| (define rfx-jpg-compression (catch #f (gimp-gimprc-query "rfx-jpg-compression")))
init| (set! rfx-jpg-compression (if rfx-jpg-compression
init| (string->number (car rfx-jpg-compression))
init| 93 ))
init| (define (rfx-save-frame image basename)
init| (let ((filename (string-append rfx-curtmpdir DIR-SEPARATOR basename))
init| (layer (car (gimp-image-get-active-layer image))) )
init| (if (string-ci=? rfx-imgext ".jpg")
init| (begin
init| (gimp-context-push)
init| (gimp-context-set-background '(6 6 6))
init| (let loop ((layers (vector->list (cadr (gimp-image-get-layers image)))))
init| (unless (null? layers)
init| (if (= (car layers) layer)
init| (gimp-drawable-set-visible layer TRUE)
init| (gimp-drawable-set-visible (car layers) FALSE) )
init| (loop (cdr layers)) ))
init| (set! layer (car (gimp-image-flatten image)))
init| (file-jpeg-save RUN-NONINTERACTIVE
init| image
init| layer
init| filename
init| filename
init| (/ rfx-jpg-compression 100)
init| 0 ; smoothing
init| 1 ; optimize
init| 1 ; progressive
init| "" ; comment
init| 0 ; subsmp (0-4)
init| 1 ; baseline
init| 0 ; restart
init| 0 ;dct
init| )
init| (gimp-context-pop) )
init| (begin
init| (unless (zero? (car (gimp-image-base-type image)))
init| (gimp-image-convert-rgb image) )
init| (file-png-save2 RUN-NONINTERACTIVE
init| image
init| layer
init| filename
init| filename
init| FALSE ; interlace
init| rfx-png-compression
init| FALSE ; bkgd
init| (car (gimp-drawable-has-alpha layer))
init| FALSE ; offs
init| FALSE ; phys
init| FALSE ; time
init| TRUE ; comment
init| FALSE ; svtrans
init| )))
init| (gimp-image-delete image) )))
init| (define (make-progressor start delta . period)
init| (let ((start start)
init| (value start)
init| (delta delta)
init| (period (if (null? period)
init| #f
init| (car period)) ))
init| (lambda ()
init| (let ((temp value))
init| (set! value (if (and period (>= (+ value delta) (+ start period)))
init| (- (+ value delta) period)
init| (+ value delta) ))
init| temp ))))
init| )
init| }
init| );
init|
init|$rfx_gap_dir = $curtmpdir . "/gap-clip";
init|if (-d $rfx_gap_dir) {
init| &sig_error("Clip buffer already exists",
init| "Perhaps clip is in use?",
init| "Run GAP Cleanup utility before continuing");
init| }
init|else {
init| mkdir $rfx_gap_dir or &sig_error("Could not create directory", $rfx_gap_dir);
init| };
init|for ($i = $start; $i <= $end; $i++) {
init| $gap_frame=&mkname($i);
init| &rfx_sendmsg( qq{
init| (begin
init| (let* ((input-file (string-append "$curtmpdir" DIR-SEPARATOR "$gap_frame" "$img_ext"))
init| (image (car (gimp-file-load RUN-NONINTERACTIVE input-file input-file)))
init| (layer (car (gimp-image-get-active-layer image)))
init| (filename (string-append "$rfx_gap_dir" DIR-SEPARATOR "$gap_frame" ".xcf")) )
init| (gimp-file-save RUN-NONINTERACTIVE image layer filename filename)
init| (gimp-image-delete image)
init| )
init| )
init| }
init| );
init| };
init|
init|system ("gimp " . $rfx_gap_dir . "/" . &mkname($start) . ".xcf &");
init|
</onchange>