#!/usr/bin/perl

#######################################################################
# LiVES shrink_expand plugin, version 1.7
# RFX version 1.7
# autogenerated from script by Salsaman|

# rendered plugins should accept:
# <plugin_name> version (return <plugin_name> version <version>)
# <plugin_name> get_define
# <plugin_name> get_capabilities
# <plugin_name> get_description (e.g. "Edge detect|Edge detecting|1|1|")
# <plugin_name> clear (clean up any plugin generated temp files)
# and optionally any of: 
# <plugin_name> get_parameters
# <plugin_name> get_param_window
# <plugin_name> get_onchange
# <plugin_name> onchange_<when> (for any triggers, e.g. onchange_init)
#
# they must accept:
# <plugin_name> process <parameters>

# You should not skip any frames, if a frame is not changed you must do:
# `cp $in $out`
#
# for *non-Perl* plugins, LiVES will call:
# <plugin_name> process "<dir>" <in_ext> <out_ext> <start> <end>
#  <width> <height> <parameters>
# first you should chdir to <dir>
# then you should create all output frames %8d$out_ext in numerical 
# from start to end inclusive,
# each time calling sig_progress (see smogrify) - writes current frame number to 
# <dir>/.status
# and checking for pause
#
# Any errors should be transmitted as in sig_error - 
# write "error|msg1|msg2|msg3|" to <dir>/.status
# msgn must not contain "\n", but can be omitted

# output frames should be named %8d$out_ext in the same directory
# after processing, you should leave no gaps in out frames, you should not resize
# or change the palette from RGB24 (LiVES will check and autocorrect this soon)

# Also you must implement your own: &sig_error and &sig_progress


#######################################################################

use POSIX;

my $command=$ARGV[0];

if ($command eq "get_capabilities") {
    # capabilities is a bitmap field
    # 0x0001 == slow (hint to GUI)
    # 0x0002 == may resize (all frames to  x )
    # 0x0004 == block mode generator
    # 0x8000 == reserved
    print "32768\n";
    exit 0;
}

if ($command eq "version") {
    print "shrink_expand version 1.1 : builder version 1.0.10\n";
    exit 0;
}

if ($command eq "get_define") {
    print "|1.7\n";
    exit 0;
}

if ($command eq "get_description") {
    #format here is "Menu entry|Action description|min_frames|number_of_in_channels|"
    # min_frames==-1 indicates a special "no processing" effect. This allows more
    #general parameter windows which are not really effects (e.g. frame_calculator)
    print "Shrink/Expand|Shrinking/Expanding|2|1|\n";
    exit 0;
}


if ($command eq "get_parameters") {
    # "name|label|type|other fields..."
    # eg. print "radius|_radius|num0|1|1|100|";
    # types can be numx,colRGB24,bool,string or string_list
    print "fframe|_First frame|num2|100.00|0.00|1000.00|\n";
    print "ffinal|Fina_l frame|num2|100.00|0.00|1000.00|\n";
    print "xcen|_X Center|num0|-100000|0|100000|\n";
    print "ycen|_Y Center|num0|-100000|0|100000|\n";
    print "top|_Top|bool|0|1|\n";
    print "left|L_eft|bool|0|1|\n";
    print "middle|_Middle|bool|1|1|\n";
    print "right|_Right|bool|0|1|\n";
    print "bottom|_Bottom|bool|0|1|\n";
    print "other|_Other Center|bool|0|1|\n";
    print "bgcol|_Background Colour|colRGB24|0|0|0|\n";
    exit 0;
}

if ($command eq "get_param_window") {
    print "layout|fill|p0|\"% of normal\"|fill4||\n";
    print "layout|fill|p1|\"% of normal\"|fill4||\n";
    print "layout|hseparator||\n";
    print "layout|\"Shrink/expand from...\"|fill||\n";
    print "layout|fill|p4|fill||\n";
    print "layout|fill|p5|p6|p7|fill||\n";
    print "layout|fill|p8|fill||\n";
    print "layout|hseparator||\n";
    print "layout|p9|fill|p2|p3|fill||\n";
    exit 0;
}

if ($command eq "get_onchange") {
    print "init|\n";
    print "2|\n";
    print "3|\n";
    exit 0;
}

#######################################################

if ($command eq "process") {

# in case of error, you should do:
# &sig_error("msg1","msg2","msg3","msg4"); [ msg's are optional, but must not
# contain newlines (\n) ]

##### check requirements first #######
    if (&location("convert") eq "") {
      &sig_error("You must install 'convert' before you can use this effect.");
      exit 1;
    }
    if (&location("composite") eq "") {
      &sig_error("You must install 'composite' before you can use this effect.");
      exit 1;
    }

###### handle parameters #############
# autogenerated from get_parameters

    unless (defined($ARGV[1])) {
      $p0=100.00;
    }
    else {
      $p0=$ARGV[1];
    }
    unless (defined($ARGV[2])) {
      $p1=100.00;
    }
    else {
      $p1=$ARGV[2];
    }
    unless (defined($ARGV[3])) {
      $p2=-100000;
    }
    else {
      $p2=$ARGV[3];
    }
    unless (defined($ARGV[4])) {
      $p3=-100000;
    }
    else {
      $p3=$ARGV[4];
    }
    unless (defined($ARGV[5])) {
      $p4=0;
    }
    else {
      $p4=$ARGV[5];
    }
    unless (defined($ARGV[6])) {
      $p5=0;
    }
    else {
      $p5=$ARGV[6];
    }
    unless (defined($ARGV[7])) {
      $p6=1;
    }
    else {
      $p6=$ARGV[7];
    }
    unless (defined($ARGV[8])) {
      $p7=0;
    }
    else {
      $p7=$ARGV[8];
    }
    unless (defined($ARGV[9])) {
      $p8=0;
    }
    else {
      $p8=$ARGV[9];
    }
    unless (defined($ARGV[10])) {
      $p9=0;
    }
    else {
      $p9=$ARGV[10];
    }
    unless (defined($ARGV[11])) {
      $p10=0;
    }
    else {
      $p10=$ARGV[11];
    }
    $!=0;
    $p0=int(POSIX::strtod($p0)*100.+.5)/100.;
    if ($p0<0.00) {
       &sig_error("fframe must be >= 0.00");
       exit 1;
    }
    if ($p0>1000.00) {
       &sig_error("fframe must be <= 1000.00");
       exit 1;
    }
    $!=0;
    $p1=int(POSIX::strtod($p1)*100.+.5)/100.;
    if ($p1<0.00) {
       &sig_error("ffinal must be >= 0.00");
       exit 1;
    }
    if ($p1>1000.00) {
       &sig_error("ffinal must be <= 1000.00");
       exit 1;
    }
    $!=0;
    $p2=int(POSIX::strtod($p2)*1+.5)/1;
    if ($p2<0) {
       &sig_error("xcen must be >= 0");
       exit 1;
    }
    if ($p2>100000) {
       &sig_error("xcen must be <= 100000");
       exit 1;
    }
    $!=0;
    $p3=int(POSIX::strtod($p3)*1+.5)/1;
    if ($p3<0) {
       &sig_error("ycen must be >= 0");
       exit 1;
    }
    if ($p3>100000) {
       &sig_error("ycen must be <= 100000");
       exit 1;
    }
    $p4=~(~$p4);
    $p5=~(~$p5);
    $p6=~(~$p6);
    $p7=~(~$p7);
    $p8=~(~$p8);
    $p9=~(~$p9);
$p10=int($p10);
if ($p10>0xFFFFFF||$p10<0) {
    &sig_error("Invalid colour for bgcol.");
    exit 1;
}
$p10_red=int($p10/65536);
$p10-=$p10_red*65536;
$p10_green=int($p10/256);
$p10-=$p10_green*256;
$p10_blue=$p10;

    $cstring=&RGB24_to_string($p10_red,$p10_green,$p10_blue);
    
    # for zoom_frame
    $antialias=&rc_get("antialias");
    
    # this is for resize_frame
    $resize_ext=".mgk2";
    
    $factor=$width;
    if ($height>$width) {
        $factor=$height;
    }
    $rscale=$p0/100.;
    $rstep=($p1-$p0)/($end-$start)/100.;
    
    # make a background frame
    system("$convert_command -size $width!x$height! xc:$cstring blank$img_ext");
    
    
    if ($p4) {
        $center_x=int($width/2);
        $center_y=0;
    }
    elsif ($p5) {
        $center_x=0;
        $center_y=int($height/2);
    }
    elsif ($p6) {
        $center_x=int($width/2);
        $center_y=int($height/2);
    }
    elsif ($p7) {
        $center_x=$width;
        $center_y=int($height/2);
    }
    elsif ($p8) {
        $center_x=int($width/2);
        $center_y=$height;
    }
    else {
        $center_x=$p2;
        $center_y=$p3;
    }

################# loop through frames #################
    for ($frame=$start;$frame<=$end;$frame++) {
	# sig progress will update the progress bar from $start->$end
	$name=&mkname($frame);
	$in="$name$img_ext";
	$out="$name$out_ext";

 while (! -f $in) {
     sleep 1;
 }

##################### the all-important bit #######################

        if ($rscale<1.) {
            #shrink the frame
            $hsize=int($width*$rscale);
            $vsize=int($height*$rscale);
            if ($hsize>1&&$vsize>1) {
        	$x=int($center_x-$hsize/2);
        	$y=int($center_y-$vsize/2);
        
        	if ($x+$hsize>$width) {
                    $x=$width-$hsize;
        	}
        	if ($y+$vsize>$height) {
        	    $y=$height-$vsize;
        	}
        	if ($y<0) {
        	    $y=0;
        	}
        	if ($x<0) {
        	    $x=0;
        	}
        
        	&resize_frame($name,$hsize,$vsize);
        
                # composite does not recognise -antialias
                system("$composite_command -compose plus -dissolve 100 -geometry +$x!+$y! $name$resize_ext blank$img_ext $out >/dev/null 2>&1");
        	unlink "$name$resize_ext";
            }
            else {
                `cp blank$img_ext $out`;
            }
        }
        else {
            if ($rscale>1.) {
               $resize_ext=$out_ext;
               &zoom_frame($name,$center_x,$center_y,$width,$height,$rscale);
            }
            else {
                `cp $in $out`;
            }
        }
        $rscale+=$rstep;

###################################################################
        if (! -f $out) {
            print STDERR "Warning: effect plugin shrink_expand skipped frame $frame !";
            `cp $in $out`;
        }
	&sig_progress($frame);
        if ($p10_red>255) {
            $p10_red=255;
        }
        elsif ($p10_red<0) {
            $p10_red=0;
        }
        if ($p10_green>255) {
            $p10_green=255;
        }
        elsif ($p10_green<0) {
            $p10_green=0;
        }
        if ($p10_blue>255) {
            $p10_blue=255;
        }
        elsif ($p10_blue<0) {
            $p10_blue=0;
        }
    }
    return 1;
}



########## Post loop code ############
if ($command eq "clear") {
    unlink "blank$img_ext";
}

########## Triggers ############

if ($command eq "onchange_3") {
    $p0=@ARGV[1];
    $p0_min=@ARGV[2];
    $p0_max=@ARGV[3];
    $p1=@ARGV[4];
    $p1_min=@ARGV[5];
    $p1_max=@ARGV[6];
    $p2=@ARGV[7];
    $p2_min=@ARGV[8];
    $p2_max=@ARGV[9];
    $p3=@ARGV[10];
    $p3_min=@ARGV[11];
    $p3_max=@ARGV[12];
    $p4=@ARGV[13];
    $p5=@ARGV[14];
    $p6=@ARGV[15];
    $p7=@ARGV[16];
    $p8=@ARGV[17];
    $p9=@ARGV[18];
    $p10_red=@ARGV[19];
    $p10_green=@ARGV[20];
    $p10_blue=@ARGV[21];
    $width=@ARGV[22];
    $height=@ARGV[23];
    $start=@ARGV[24];
    $end=@ARGV[25];
    $last=@ARGV[26];
    $length=$end-$start+1;

    $p9=1;

    print "$p0 $p0_min $p0_max $p1 $p1_min $p1_max $p2 $p2_min $p2_max $p3 $p3_min $p3_max $p4 $p5 $p6 $p7 $p8 $p9 $p10_red $p10_green $p10_blue ";
    exit 0;
}

if ($command eq "onchange_2") {
    $p0=@ARGV[1];
    $p0_min=@ARGV[2];
    $p0_max=@ARGV[3];
    $p1=@ARGV[4];
    $p1_min=@ARGV[5];
    $p1_max=@ARGV[6];
    $p2=@ARGV[7];
    $p2_min=@ARGV[8];
    $p2_max=@ARGV[9];
    $p3=@ARGV[10];
    $p3_min=@ARGV[11];
    $p3_max=@ARGV[12];
    $p4=@ARGV[13];
    $p5=@ARGV[14];
    $p6=@ARGV[15];
    $p7=@ARGV[16];
    $p8=@ARGV[17];
    $p9=@ARGV[18];
    $p10_red=@ARGV[19];
    $p10_green=@ARGV[20];
    $p10_blue=@ARGV[21];
    $width=@ARGV[22];
    $height=@ARGV[23];
    $start=@ARGV[24];
    $end=@ARGV[25];
    $last=@ARGV[26];
    $length=$end-$start+1;

    $p9=1;

    print "$p0 $p0_min $p0_max $p1 $p1_min $p1_max $p2 $p2_min $p2_max $p3 $p3_min $p3_max $p4 $p5 $p6 $p7 $p8 $p9 $p10_red $p10_green $p10_blue ";
    exit 0;
}

if ($command eq "onchange_init") {
    $p0=@ARGV[1];
    $p0_min=@ARGV[2];
    $p0_max=@ARGV[3];
    $p1=@ARGV[4];
    $p1_min=@ARGV[5];
    $p1_max=@ARGV[6];
    $p2=@ARGV[7];
    $p2_min=@ARGV[8];
    $p2_max=@ARGV[9];
    $p3=@ARGV[10];
    $p3_min=@ARGV[11];
    $p3_max=@ARGV[12];
    $p4=@ARGV[13];
    $p5=@ARGV[14];
    $p6=@ARGV[15];
    $p7=@ARGV[16];
    $p8=@ARGV[17];
    $p9=@ARGV[18];
    $p10_red=@ARGV[19];
    $p10_green=@ARGV[20];
    $p10_blue=@ARGV[21];
    $width=@ARGV[22];
    $height=@ARGV[23];
    $start=@ARGV[24];
    $end=@ARGV[25];
    $last=@ARGV[26];
    $length=$end-$start+1;

    $p2_max=$width;$p2=$width/2;$p3_max=$height;$p3=$height/2;

    print "$p0 $p0_min $p0_max $p1 $p1_min $p1_max $p2 $p2_min $p2_max $p3 $p3_min $p3_max $p4 $p5 $p6 $p7 $p8 $p9 $p10_red $p10_green $p10_blue ";
    exit 0;
}
