The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/app/bin/perl

eval 'exec /usr/app/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell

use Gimp;
use Gimp::Fu;
use Gimp::Util;

# this is silly, sorry that I am too dumb to come up with niftier functions :(
# btw, this should generate something between 1/f and 1/f² noise.
{
   my @weight = (1/8, 1/4, 1/2, 1);
   my @dice;
   my $total = 0;
   my $tweight = 0;
   my $n = 0;
   my $seed;

   sub gen_rand() {
      my ($prevrand, $newrand, $k);

      $n++;
      for (0..$#weight) {
         if ($n & (1<<$_)) {
            $prevrand = $dice[$_];
            $newrand = rand() * $weight[$_];
            $dice[$_] = $newrand;
            $total += $newrand - $prevrand;
         }
      }

      $total / $tweight;
   }

   sub set_seed($) {
      if ($_[0]) {
         srand $_[0];
      } else {
         srand;
      }
      $total = 0;
      $tweight = 0;
      for (0..$#weight) {
         $dice[$_] = rand()*$weight[$_];
         $total += $dice[$_];
         $tweight += $weight[$_];
      }
   }
}

# the next line  just shows a graph of the "random" numbers.
#set_seed 0; use PDL; use PDL::Graphics::PGPLOT; line(pdl(float,map gen_rand, 1..500));

register "dust",
         "",
         "",
         "Marc Lehmann",
         "Marc Lehmann <pcg\@goof.com",
         "0.1",
         N_"<Image>/Filters/Render/Add Dust...",
         "*",
         # Eingabeparameter
         # Typ		Name		Beschreibung		Wert
         [
          [PF_FLOAT,	'density',	'dust density in dust/pixel',	 0.0001],
          [PF_INT32,	'seed',		'the random seed (0 == unspecified)', 0],
          [PF_SPINNER,	'length',	'the average dust corn length', 50, [1,300]],
         ],
         sub {					# Perl-Code
   # Die Parameter werden ganz "normal" übergeben:
   my ($image, $layer, $density, $seed, $len) = @_;

   $len *= 0.75;

   set_seed $seed;

   my ($w, $h) = ($image->width, $image->height);

   $image->undo_push_group_start;

   my $state = Gimp::Util::get_state();
   Palette->set_foreground("white");
   Brushes->set_brush("Circle (01)");
   Brushes->set_opacity(50);
   Brushes->set_spacing(100);
   Brushes->set_paint_mode(NORMAL_MODE);

   if (1) {
      $layer = $image->add_new_layer (0, TRANS_IMAGE_FILL, 1);
      $layer->set_mode(DIFFERENCE_MODE);
   }
   
   for (1..($w*$h*$density)) {
      my ($x, $y) = (rand $w, rand $h);
      my $l = int($len + rand $len);
      my @c;
      my $b = 0;
      for (1..$l) {
         push @c, $b += 5*(gen_rand-0.5);
         push @c, $b += 5*(gen_rand-0.5);
      }
      
      $layer->paintbrush_default([map { $x+$c[$_], $y+$c[$_+$l] } 0..$l-1]);
   }

   Gimp::Util::set_state($state);

   $image->undo_push_group_end;

   ();
};

#register "gen_rand_1f",
#         "generate 1/f noise",
#         "Generate approximate 1/f (white) noise in the range [0,1[",
#         "Marc Lehmann",
#         "Marc Lehmann <pcg\@goof.com",
#         "0.1",
#         "<None>",
#         undef,
#         # Eingabeparameter
#         # Typ		Name		Beschreibung		Wert
#         [
#          [PF_FLOAT,	'count',	'the number of values',	 1],
#          [PF_INT32,	'seed',		'the random seed (0 == unspecified)', 0],
#         ],
#         [
#          [&Gimp::PDB_FLOATARRAY,'noise','the requested number of 1/f noise values'],
#         ],
#         sub {
#            my ($count, $seed) = @_;
#            set_seed $seed;
#            [map gen_rand_1f, 1..$count];
#         };

exit main;