{ A simple edge-detection by calculating gradient (actually,
  the length of the gradient vector) with Sobel operator, in CastleScript.
  See [http://en.wikipedia.org/wiki/Sobel_operator].
  Source image filename is constant below, you can change it to
  any RGB(+possibly with alpha) existing image filename.

  Note that this may take a while for larger images.
  With current optimizations, it takes 6.5 seconds for 640 x 480 image.
  Hm, quite fast actually (before profiling, it was 93 seconds...).
  For other image sizes --- do the math, time is proportional to pixels count.

  Take into account that CastleScript is not speed-optimal,
  it's image functions are comfortable but not fast (3-byte convertion
  between 3-single/float mix, for starters), we try to catch
  FP exceptions immediately (which means we don't use FP unit efficiently)
  and such. If you want optimal language, any scripting lang is bad choice,
  rather use ObjectPascal with Castle Game Engine :).
}

function main()
  helper_img := image_load('/usr/share/images/desktop-base/debian-blueish-wallpaper-640x480.png');

  { copy helper_img, to copy it's size and alpha channel }
  result := helper_img;

  for (i, 0, image_width(result) - 1,
    for (j, 0, image_height(result) - 1,
      x :=
        if(i > 0,
          if (j > 0, grayscale(image_get_color(helper_img, i-1, j-1)), 0) +
          2 * grayscale(image_get_color(helper_img, i-1, j)) +
          if (j < image_height(result) - 1, grayscale(image_get_color(helper_img, i-1, j+1)), 0),
          0) -
        if(i < image_width(result) - 1,
          if (j > 0, grayscale(image_get_color(helper_img, i+1, j-1)), 0) +
          2 * grayscale(image_get_color(helper_img, i+1, j)) +
          if (j < image_height(result) - 1, grayscale(image_get_color(helper_img, i+1, j+1)), 0),
          0);
      y :=
        if(j > 0,
          if (i > 0, grayscale(image_get_color(helper_img, i-1, j-1)), 0) +
          2 * grayscale(image_get_color(helper_img, i, j-1)) +
          if (i < image_width(result) - 1, grayscale(image_get_color(helper_img, i+1, j-1)), 0),
          0) -
        if(j < image_height(result) - 1,
          if (i > 0, grayscale(image_get_color(helper_img, i-1, j+1)), 0) +
          2 * grayscale(image_get_color(helper_img, i, j+1)) +
          if (i < image_width(result) - 1, grayscale(image_get_color(helper_img, i+1, j+1)), 0),
          0);
      z := sqrt(sqr(x) + sqr(y));
      image_set_color(result, i, j, vector(z, z, z))))
