#!/usr/bin/perl -w

# 02/06/2001
# V1.0
#        -The stuff works but it's still slow.
#	  Problem resides in the brutal m/slice.
#	  I hope to find out some artifact to use PDL more efficiently for this "non-matrix" algorithm.

use Gimp;
use Gimp::Fu;
use PDL::LiteF;
use strict;
use warnings;

podregister {
  $image->selection_none if ($image->selection_bounds)[0];
  $drawable->transform_rotate_simple($camerapos, TRUE, 0, 0) if $camerapos >= 0;
  my $width = $drawable->width;
  my $height = $drawable->height;
  #Pixel region of selection
  my $src = Gimp::PixelRgn->new($drawable, 0, 0, $width, $height, 0, 0);
  my $newimage = Gimp::Image->new($width, $height, RGB);
  my $alpha = $drawable->has_alpha;
  my $layer = $newimage->layer_new(
    $width, $height,
    $alpha ? RGBA_IMAGE : RGB_IMAGE,
    "L1", 100, NORMAL_MODE
  );
  $newimage->insert_layer($layer, 0, -1);
  my $newdrawable = $newimage->get_active_drawable;
  my $dest = Gimp::PixelRgn->new($newdrawable, 0, 0, $width, $height, 1, 1);
  my $srcdata = $src->get_rect($drawable->bounds);
  my $destdata = $srcdata->zeroes;
  Gimp::Progress->init("Rendering...");
  my $relord = $width / 255;
  $newdrawable->fill(FOREGROUND_FILL);
  $delta = 1 if $delta < 1;
  for (my $y = 0; $y < $height; $y++){
    my $row = $srcdata->slice('', '', "($y)");
    my $drow = $destdata->slice('', '', "($y)");
    my $red = $row->slice("($component)");
    my $dred = $drow->slice("(0)");
    my $dgreen = $drow->slice("(1)");
    my $dblue = $drow->slice("(2)");
    $drow->slice(3) .= 255 if $alpha;
    for (my $x = 0; $x < $width; $x++) {
      my $r = at($red, $x);
      next if $r <= $floor;
      my $remain = $r;
      my $currentx = $width - $r * $relord + ($x / $elevation);
      #Apply elevation following the x offset in original picture
      while ($remain > 0 && $currentx < $width) {
	if ($remain > 150) {
	  set ($dred, $currentx, 0);
	  set ($dgreen, $currentx, $remain);
	  set ($dblue, $currentx, $remain);
	}
	if ($remain < 150 && $remain > 50) {
	  set ($dred, $currentx, 0);
	  set ($dgreen, $currentx, $remain + 55);
	  set ($dblue, $currentx, 0);
	}
	if ($remain < 50) {
	  set ($dred, $currentx, 0);
	  set ($dgreen, $currentx, 0);
	  set ($dblue, $currentx, $remain + 200);
	}
	$remain -= $delta;
	$currentx++;
      }
    }
    Gimp::Progress->update($y / $height);
  }
  Gimp::Progress->update(1);
  $dest->set_rect($destdata, 0, 0);
#  die "merge_shadow failed for $newdrawable\n" unless
    $newdrawable->merge_shadow(TRUE); # returns false but works and is needed
  $newdrawable->update(0, 0, $width, $height);
  $newdrawable->transform_rotate_simple(ROTATE_90, TRUE, 0, 0);
  $newimage->resize_to_layers;
  eval { Gimp::Display->new($newimage); };
  #Original pic => original state
  if ($camerapos == 2) {
    $camerapos = 0;
  } elsif ($camerapos == 0) {
    $camerapos = 2;
  }
  $drawable->transform_rotate_simple($camerapos, TRUE, 0, 0) if $camerapos >= 0;
  return $newimage;
};

exit main;
__END__

=head1 NAME

intensitylandscape - Generate an intensity based landscape

=head1 SYNOPSIS

<Image>/Filters/Render/_Intensity Landscape

=head1 DESCRIPTION

Generate an alpha landscape based on intensity. The result is an
interpolated view as if you were looking from one side of the original
picture (which is taken as an apical view).

=head1 AUTHOR

Fabian Frederick <fabian.frederick@gmx.fr>

=head1 DATE

20010601

=head1 IMAGE TYPES

RGB*

=head1 PARAMETERS

  [PF_SLIDER, "floor", "Floor", 100, [0, 255, 5]],
  [PF_RADIO, "component", "Active component", 0, [ Red => 0, Green => 1, Blue => 2]],
  [PF_SLIDER, "delta", "Delta color", 6, [1, 100, 1]],
  [PF_FLOAT, "elevation", "Elevation argument should be 2 or 3", 2],
  [PF_RADIO, "camerapos", "Camera position", -1, [ Right => -1, Bottom => 2, Left => 1, Top => 0]]

=head1 RETURN VALUES

  [PF_IMAGE, "image", "Return image"],

=head1 LICENSE

This plugin may be distributed under the same terms as GIMP itself.
