The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Acme::Noisemaker - Visual noise generator

VERSION

This document is for version 0.003 of Acme::Noisemaker.

SYNOPSIS;

  use Acme::Noisemaker;

Make some noise and save it as an image to the specified filename:

  Acme::Noisemaker::make(
    type => $type,        # white|square|perlin|complex
    out  => $filename,    # "pattern.bmp"
  );

A wrapper script, bin/make-noise, is included with this distribution.

  bin/make-noise --type complex --out pattern.bmp

Noise sets are just 2D arrays:

  my $grid = Acme::Noisemaker::square(%args);

  #
  # Look up a value, given X and Y coords
  #
  my $value = $grid->[$x]->[$y];

Imager can take care of further post-processing.

  my $grid = Acme::Noisemaker::perlin(%args);

  my $img = Acme::Noisemaker::img($grid);

  #
  # Insert image manip methods here!
  #

  $img->write(file => "oot.png");

DESCRIPTION

This module generates various types of two-dimensional grayscale noise. It is not fast, it is not a faithful implementation of any particular algorithm, and it probably never will be.

It is, possibly, a fun and/or educational toy if you are interested in procedural texture generation, or might be useful if you just want a simple module to make a few unique patterns with.

As long as the provided side length is a power of the noise's base frequency, this module will produce seamless tiles. For example, a base frequency of 2 would work fine for an image with a side length of 256 (256x256).

Other than using Imager for output, this is a pure Perl module.

FUNCTIONS

  • make(type => $type, out => $filename, %ARGS)

      my ( $grid, $img ) = Acme::Noisemaker::make(
        type => "perlin",
        out  => "perlin.bmp"
      );
      

    Creates the specified noise type (white, square, perlin, or complex), writing the resulting image to the received filename.

    Returns the resulting dataset, as well as the Imager object which was created from it.

  • img($grid)

      my $grid = Acme::Noisemaker::perlin();
    
      my $img = Acme::Noisemaker::img($grid);
    
      #
      # Insert Imager image manip stuff here!
      #
    
      $img->write(file => "oot.png");

    Returns an Imager object from the received two-dimensional grid.

  • smooth($grid)

      #
      # Unsmoothed noise source
      #
      my $grid = Acme::Noisemaker::white(smooth => 0);
    
      my $smooth = smooth($grid);

    Perform smoothing of the values contained in the received two-dimensional grid. Returns a new grid.

  • clamp($value)

      my $clamped = clamp($num);

    Limits the received value to between 0 and 255. If the received value is less than 0, returns 0; more than 255, returns 255; otherwise returns the same value which was received.

  • noise($grid, $x, $y)

    The so-called "noise function" required to generate coherent noise. Returns the same "random" value each time it is called with the same arguments (makes it more like a key hashing function a la memcached doesn't it? Not very random, if you ask me).

    Acme::Noisemaker diverges from most Perlin implementations in that its noise function simply utilizes a lookup table. The lookup table contains pre-populated random values. Turns out, this works fine.

  • lerp($a, $b, $x)

    Linear interpolate from $a to $b, by $x percent. $x is between 0 and 1. Not currently used, but it's there.

    http://en.wikipedia.org/wiki/Linear_interpolation

  • coslerp($a, $b, $x)

    Cosine interpolate from $a to $b, by $x percent. $x is between 0 and 1.

GENERATORS

Each noise function returns a two-dimentional array containing grayscale values.

All function args are optional-- the built-in defaults should be reasonable to get started with. Each noise function accepts the following args in hash key form:

  amp     - Amplitude, or max variance from the bias value
  freq    - Frequency, or "density" of the noise produced
  len     - Side length of the output images, which are always square
  bias    - "Baseline" value for all pixels, .5 = 50%
  smooth  - Enable/disable noise smoothing. 1 is recommended.

...in addition, Perlin and Complex noise accept:

  oct     - Octave count, increases the complexity of Perlin noise

...and Complex noise has several more possible args:

  feather - Edge falloff amount for Complex noise. 0-255
  layers  - Number of noise sources to use for Complex noise
  • White

      my $grid = Acme::Noisemaker::white(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        bias    => <num>,
        smooth  => <0|1>
      );

    White noise, for the purposes of this module, is probably what most people think of as noise. It looks like television static-- every pixel contains a pseudo-random value.

  • Diamond-Square

      my $grid = Acme::Noisemaker::square(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        bias    => <num>,
        smooth  => <0|1>
      );

    Sometimes called "cloud" or "plasma" noise. Often suffers from diamond- and square-shaped artifacts, but there are ways of dealing with them.

    This module seeds the initial values with White noise.

  • Perlin

      my $grid = Acme::Noisemaker::perlin(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        oct     => <int>,
        bias    => <num>,
        smooth  => <0|1>
      )

    Perlin noise (not related to Perl) combines multiple noise sources to produce very turbulent-looking noise.

    This module generates its Perlin slices from Diamond-Square noise.

  • Complex Perlin

      my $grid = Acme::Noisemaker::complex(
        amp     => <num>,
        freq    => <num>,
        len     => <int>,
        oct     => <int>,
        bias    => <num>,
        feather => <num>,
        layers  => <int>,
        smooth  => <0|1>
      )

    Complex Perlin noise combines multiple Perlin noise sources. This is not a real name for any noise type beyond this module, as far as I can tell, but the methodology used to combine the noise is heavily inspired by the way libnoise allows the daisy-chaining of different noise modules.

SEE ALSO

Acme::Noisemaker is on github: http://github.com/aayars/noisemaker

  • Wikipedia

    As usual, Wikipedia is there for us.

    Diamond-Square algorithm: http://en.wikipedia.org/wiki/Diamond-square_algorithm

    Perlin Noise: http://en.wikipedia.org/wiki/Perlin_noise

    White Noise: http://en.wikipedia.org/wiki/White_noise

    Interpolation: http://en.wikipedia.org/wiki/Interpolation

  • Generating Random Fractal Terrain - http://gameprogrammer.com/fractal.html

    This page has a good intro to Diamond-Square noise. It taught me how to make clouds.

  • Perlin Noise - http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

    Acme::Noisemaker heavily pilfers the pseudo-code for interpolation and smoothing functions which I found at the above site.

  • libnoise - http://libnoise.sourceforge.net/

    "A portable, open-source, coherent noise-generating library for C++"

    Though it does not use it, Acme::Noisemaker is inspired by libnoise, which is what you should really be using if you're serious about this sort of thing. It is very cool stuff. The developer has provided many examples which let you write C++ without actually knowing it (cue Sorcerer's Apprentice music...)

  • pynoise - http://home.gna.org/pynoise/

    Python bindings to libnoise via swig. I would like to make a package like this for Perl one day, unless someone else wants to first.

AUTHOR

  Alex Ayars <pause@nodekit.org>

COPYRIGHT

  File: Acme/Noisemaker.pm
 
  Copyright (c) 2009 Alex Ayars
 
  All rights reserved. This program and the accompanying materials
  are made available under the terms of the Common Public License v1.0
  which accompanies this distribution, and is available at
  http://opensource.org/licenses/cpl1.0.txt