#!/usr/bin/perl

#######################################################################
# LiVES colour_filter plugin, version 1.7
# RFX version 1.8
# 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 "colour_filter version 1.0 : builder version 2.0.3\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 "Colour filter|Colour filtering|1|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 "scol|_Start Colour|colRGB24|255|255|255|\n";
    print "ecol|_End Colour|colRGB24|0|0|0|\n";
    print "rand|_Random colour each frame|bool|0|\n";
    print "start|S_tart %|num0|50|0|100|\n";
    print "end|E_nd %|num0|50|0|100|\n";
    print "link|_Link start and end colours|bool|0|\n";
    exit 0;
}

if ($command eq "get_param_window") {
    print "layout|p0||\n";
    print "layout|p5||\n";
    print "layout|p1||\n";
    print "layout|p2||\n";
    print "layout|hseparator||\n";
    print "layout|p3|fill||\n";
    print "layout|p4|fill||\n";
    exit 0;
}

if ($command eq "get_onchange") {
    print "0|\n";
    print "1|\n";
    print "5|\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("convert") eq "") {
      &sig_error("You must install 'convert' before you can use this effect.");
      exit 1;
    }

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

    unless (defined($ARGV[1])) {
      $p0=255;
    }
    else {
      $p0=$ARGV[1];
    }
    unless (defined($ARGV[2])) {
      $p1=0;
    }
    else {
      $p1=$ARGV[2];
    }
    unless (defined($ARGV[3])) {
      $p2=0;
    }
    else {
      $p2=$ARGV[3];
    }
    unless (defined($ARGV[4])) {
      $p3=50;
    }
    else {
      $p3=$ARGV[4];
    }
    unless (defined($ARGV[5])) {
      $p4=50;
    }
    else {
      $p4=$ARGV[5];
    }
    unless (defined($ARGV[6])) {
      $p5=0;
    }
    else {
      $p5=$ARGV[6];
    }
    $p2=~(~$p2);
    $!=0;
    if ($p3>=0) {
        $p3=int(POSIX::strtod($p3)*1+.5)/1;
    } else {
        $p3=int(POSIX::strtod($p3)*1-.5)/1;
    }
    if ($p3<0) {
       &sig_error("start must be >= 0");
       exit 1;
    }
    if ($p3>100) {
       &sig_error("start must be <= 100");
       exit 1;
    }
    $!=0;
    if ($p4>=0) {
        $p4=int(POSIX::strtod($p4)*1+.5)/1;
    } else {
        $p4=int(POSIX::strtod($p4)*1-.5)/1;
    }
    if ($p4<0) {
       &sig_error("end must be >= 0");
       exit 1;
    }
    if ($p4>100) {
       &sig_error("end must be <= 100");
       exit 1;
    }
    $p5=~(~$p5);
$p0=int($p0);
if ($p0>0xFFFFFF||$p0<0) {
    &sig_error("Invalid colour for scol.");
    exit 1;
}
$p0_red=int($p0/65536);
$p0-=$p0_red*65536;
$p0_green=int($p0/256);
$p0-=$p0_green*256;
$p0_blue=$p0;
$p1=int($p1);
if ($p1>0xFFFFFF||$p1<0) {
    &sig_error("Invalid colour for ecol.");
    exit 1;
}
$p1_red=int($p1/65536);
$p1-=$p1_red*65536;
$p1_green=int($p1/256);
$p1-=$p1_green*256;
$p1_blue=$p1;

   if ($img_ext eq ".png") {
        $img_prefix="PNG32:";
   } else {
        $img_prefix="";
   }

   if ($out_ext eq ".png") {
        $out_prefix="PNG32:";
   } else {
        $out_prefix="";
   }

    if ($end==$start) {
        $pcstep=0;
    }
    else {
        $pcstep=($p4-$p3)/($end-$start);
    }
    $length=$end-$start+1;
    $cstep_red=($p1_red-$p0_red)/$length;
    $cstep_green=($p1_green-$p0_green)/$length;
    $cstep_blue=($p1_blue-$p0_blue)/$length;

    if ($start==0) {$start = 1;}


################# loop through frames #################
   if ($img_ext eq ".png") {
        $img_prefix="PNG32:";
   } else {
        $img_prefix="";
   }

   if ($out_ext eq ".png") {
        $out_prefix="PNG32:";
   } else {
        $out_prefix="";
   }

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

     if (!defined($end) || $end==0) {
         print STDERR "WARNING: generator plugin did not set $end !";
         &sig_error("Generator plugin did not set $end.");
     }
	$out="$name$out_ext";

# wait for front end to create 
 while (!-f $in) {
     sleep 1;
 }

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

        if ($p2) {
            $p0_red=int(rand 256);
            $p0_green=int(rand 256);
            $p0_blue=int(rand 256);
        }
        $cstring=&RGB24_to_string($p0_red,$p0_green,$p0_blue);
        $pcint=int($p3+.5);
        $pcstring="$pcint/$pcint/$pcint";
        
        system("$convert_command -size $width!x$height! xc:$cstring $img_prefix"."blank$img_ext >/dev/null 2>&1");
        system("$composite_command -compose multiply $img_prefix$in $img_prefix"."blank$img_ext $name.tmp >/dev/null 2>&1");
        system("$composite_command -compose plus -dissolve $pcstring $name.tmp $img_prefix$in $out_prefix$out >/dev/null 2>&1");
        
        unlink "$name.tmp";
        	
        #builder will handle wrapping
        $p0_red+=$cstep_red;
        $p0_green+=$cstep_green;
        $p0_blue+=$cstep_blue;
        
        $p3+=$pcstep;
        if ($p3>100.) {
            $p3=100;
        }
        elsif ($p3<0.) {
            $p3=0;
        }

###################################################################
        $opfailed=0;
        if (! -f $out) {
            print STDERR "Warning: effect plugin colour_filter skipped frame $frame !\n";
            print STDERR "Retrying\n";
            $frame--;
            $opfailed=1;
        }
        unless ($opfailed) {
	    &sig_progress($frame);
        }
        if ($p0_red>255) {
            $p0_red=255;
        }
        elsif ($p0_red<0) {
            $p0_red=0;
        }
        if ($p0_green>255) {
            $p0_green=255;
        }
        elsif ($p0_green<0) {
            $p0_green=0;
        }
        if ($p0_blue>255) {
            $p0_blue=255;
        }
        elsif ($p0_blue<0) {
            $p0_blue=0;
        }
        if ($p1_red>255) {
            $p1_red=255;
        }
        elsif ($p1_red<0) {
            $p1_red=0;
        }
        if ($p1_green>255) {
            $p1_green=255;
        }
        elsif ($p1_green<0) {
            $p1_green=0;
        }
        if ($p1_blue>255) {
            $p1_blue=255;
        }
        elsif ($p1_blue<0) {
            $p1_blue=0;
        }
    }
    return 1;
}



########## Post loop code ############
if ($command eq "clear") {
    $start=$ARGV[1];
    $end=$ARGV[2];
    $img_ext=$ARGV[3];

    unlink "blank$img_ext";
    exit 0;
}

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

if ($command eq "onchange_1") {
    $p0_red=@ARGV[1];
    $p0_green=@ARGV[2];
    $p0_blue=@ARGV[3];
    $p1_red=@ARGV[4];
    $p1_green=@ARGV[5];
    $p1_blue=@ARGV[6];
    $p2=@ARGV[7];
    $p3=@ARGV[8];
    $p3_min=@ARGV[9];
    $p3_max=@ARGV[10];
    $p4=@ARGV[11];
    $p4_min=@ARGV[12];
    $p4_max=@ARGV[13];
    $p5=@ARGV[14];
    $width=@ARGV[15];
    $height=@ARGV[16];
    $start=@ARGV[17];
    $end=@ARGV[18];
    $last=@ARGV[19];
    $length=$end-$start+1;

    if ($p5) {$p0_red=$p1_red;$p0_green=$p1_green;$p0_blue=$p1_blue;}

    print "$p0_red $p0_green $p0_blue $p1_red $p1_green $p1_blue $p2 $p3 $p3_min $p3_max $p4 $p4_min $p4_max $p5 ";
    exit 0;
}

if ($command eq "onchange_0") {
    $p0_red=@ARGV[1];
    $p0_green=@ARGV[2];
    $p0_blue=@ARGV[3];
    $p1_red=@ARGV[4];
    $p1_green=@ARGV[5];
    $p1_blue=@ARGV[6];
    $p2=@ARGV[7];
    $p3=@ARGV[8];
    $p3_min=@ARGV[9];
    $p3_max=@ARGV[10];
    $p4=@ARGV[11];
    $p4_min=@ARGV[12];
    $p4_max=@ARGV[13];
    $p5=@ARGV[14];
    $width=@ARGV[15];
    $height=@ARGV[16];
    $start=@ARGV[17];
    $end=@ARGV[18];
    $last=@ARGV[19];
    $length=$end-$start+1;

    if ($p5) {$p1_red=$p0_red;$p1_green=$p0_green;$p1_blue=$p0_blue;}

    print "$p0_red $p0_green $p0_blue $p1_red $p1_green $p1_blue $p2 $p3 $p3_min $p3_max $p4 $p4_min $p4_max $p5 ";
    exit 0;
}

if ($command eq "onchange_5") {
    $p0_red=@ARGV[1];
    $p0_green=@ARGV[2];
    $p0_blue=@ARGV[3];
    $p1_red=@ARGV[4];
    $p1_green=@ARGV[5];
    $p1_blue=@ARGV[6];
    $p2=@ARGV[7];
    $p3=@ARGV[8];
    $p3_min=@ARGV[9];
    $p3_max=@ARGV[10];
    $p4=@ARGV[11];
    $p4_min=@ARGV[12];
    $p4_max=@ARGV[13];
    $p5=@ARGV[14];
    $width=@ARGV[15];
    $height=@ARGV[16];
    $start=@ARGV[17];
    $end=@ARGV[18];
    $last=@ARGV[19];
    $length=$end-$start+1;

    if ($p5) {$p1_red=$p0_red;$p1_green=$p0_green;$p1_blue=$p0_blue;}

    print "$p0_red $p0_green $p0_blue $p1_red $p1_green $p1_blue $p2 $p3 $p3_min $p3_max $p4 $p4_min $p4_max $p5 ";
    exit 0;
}
