Gimp
view release on metacpan or search on metacpan
examples/iland view on Meta::CPAN
#!/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
( run in 1.671 second using v1.01-cache-2.11-cpan-d06a3f9ecfd )