#!/usr/bin/perl -w

# 11/09/2024
# V1.01

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, LAYER_MODE_NORMAL_LEGACY
  );
  $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;
  $destdata->slice(3) .= 255 if $alpha;
  my $quant = ($srcdata->slice("($component)")->max / $delta)->floor->sclr;
  goto FINISH if $quant <= 0; # nothing to do
  my $destmv = $destdata->mv(0,-1); # x y rgb
  Gimp::Progress->init("Rendering...");
  my $relord = $width / 255;
  $newdrawable->fill(FILL_FOREGROUND);
  $delta = 1 if $delta < 1;
  for my $x (0..$width-1) {
    my $col = $srcdata->slice("($component),($x)");
    my $exceed_floor = ($col > $floor);
    my $r = $col->where($exceed_floor); # nvals
    my $destx = ($width - $r * $relord + ($x / $elevation))->long; # nvals
    #Apply elevation following the x offset in original picture
    my $remain_s = zeroes(long, 3, $quant, $r->dim(0)); # xyr quant nvals
    my $yslice = $remain_s->slice("(1)") .= $exceed_floor->which->dummy(0); # quant nvals
    my $xslice = $remain_s->slice("(0)") .= $yslice->xvals + $destx->dummy(0); # quant nvals
    my $rslice = $remain_s->slice("(2)") .= $yslice->xlinvals(0,-1) * $quant*$delta + $r->dummy(0); # quant nvals
    $rslice->whereND($xslice >= $width) .= -1;
    my $gt150_ind = whichND($rslice > 150);
    my $btwn_ind = whichND(($rslice <= 150) & ($rslice >= 50));
    my $lt50_ind = whichND(($rslice < 50) & ($rslice > 0));
    $destmv->slice(',,1:2')->indexND(cat(map $_->indexND($gt150_ind), $xslice, $yslice)->mv(-1,0)) .= $rslice->indexND($gt150_ind) if $gt150_ind->nelem;
    $destmv->slice(',,1')->indexND(cat(map $_->indexND($btwn_ind), $xslice, $yslice)->mv(-1,0)) .= $rslice->indexND($btwn_ind) + 55 if $btwn_ind->nelem;
    $destmv->slice(',,2')->indexND(cat(map $_->indexND($lt50_ind), $xslice, $yslice)->mv(-1,0)) .= $rslice->indexND($lt50_ind) + 200 if $lt50_ind->nelem;
    Gimp::Progress->update($x / $width);
  }
  Gimp::Progress->update(1);
FINISH:
  $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.
