Blame operations/workshop/fractal-trace.c

Packit Service 2781ba
/* This file is an image processing operation for GEGL
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is free software; you can redistribute it and/or
Packit Service 2781ba
 * modify it under the terms of the GNU Lesser General Public
Packit Service 2781ba
 * License as published by the Free Software Foundation; either
Packit Service 2781ba
 * version 3 of the License, or (at your option) any later version.
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is distributed in the hope that it will be useful,
Packit Service 2781ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2781ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2781ba
 * Lesser General Public License for more details.
Packit Service 2781ba
 *
Packit Service 2781ba
 * You should have received a copy of the GNU Lesser General Public
Packit Service 2781ba
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit Service 2781ba
 *
Packit Service 2781ba
 * Copyright (C) 1997 Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>
Packit Service 2781ba
 * Copyright (C) 2011 Robert Sasu <sasu.robert@gmail.com>
Packit Service 2781ba
 */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
#include <glib/gi18n-lib.h>
Packit Service 2781ba
Packit Service 2781ba
#ifdef GEGL_CHANT_PROPERTIES
Packit Service 2781ba
Packit Service 2781ba
gegl_chant_string (fractal, _("Fractal"), "fractal",
Packit Service 2781ba
                   _("Type of fractal to use. "
Packit Service 2781ba
                     "Choices are julia, mandelbrot. Default is mandelbrot."))
Packit Service 2781ba
gegl_chant_double (X1, _("X1"), -50.0, 50.0, -1.00,
Packit Service 2781ba
                   _("X1 value, position"))
Packit Service 2781ba
gegl_chant_double (X2, _("X2"), -50.0, 50.0, 0.50,
Packit Service 2781ba
                   _("X2 value, position"))
Packit Service 2781ba
gegl_chant_double (Y1, _("Y1"), -50.0, 50.0, -1.00,
Packit Service 2781ba
                   _("X2 value, position"))
Packit Service 2781ba
gegl_chant_double (Y2, _("Y2"), -50.0, 50.0, 1.00,
Packit Service 2781ba
                   _("Y2 value, position"))
Packit Service 2781ba
gegl_chant_double (JX, _("JX"), -50.0, 50.0, 0.5,
Packit Service 2781ba
                   _("Julia seed X value, position"))
Packit Service 2781ba
gegl_chant_double (JY, _("JY"), -50.0, 50.0, 0.5,
Packit Service 2781ba
                   _("Julia seed Y value, position"))
Packit Service 2781ba
gegl_chant_int    (depth, _("Depth"), 1, 65536, 3,
Packit Service 2781ba
                   _("Depth value"))
Packit Service 2781ba
gegl_chant_double (bailout, _("Bailout"), 0.0, G_MAXDOUBLE, G_MAXDOUBLE,
Packit Service 2781ba
                   _("Bailout length"))
Packit Service 2781ba
gegl_chant_string (background, _("Background"), "wrap",
Packit Service 2781ba
                   _("Optional parameter to override automatic selection of wrap background. "
Packit Service 2781ba
                     "Choices are wrap, black, white and transparent."))
Packit Service 2781ba
Packit Service 2781ba
#else
Packit Service 2781ba
Packit Service 2781ba
#define GEGL_CHANT_TYPE_FILTER
Packit Service 2781ba
#define GEGL_CHANT_C_FILE       "fractal-trace.c"
Packit Service 2781ba
Packit Service 2781ba
#include "gegl-chant.h"
Packit Service 2781ba
#include <math.h>
Packit Service 2781ba
Packit Service 2781ba
typedef enum
Packit Service 2781ba
{
Packit Service 2781ba
  BACKGROUND_TYPE_WRAP,
Packit Service 2781ba
  BACKGROUND_TYPE_TRANSPARENT,
Packit Service 2781ba
  BACKGROUND_TYPE_BLACK,
Packit Service 2781ba
  BACKGROUND_TYPE_WHITE
Packit Service 2781ba
} BackgroundType;
Packit Service 2781ba
Packit Service 2781ba
typedef enum
Packit Service 2781ba
{
Packit Service 2781ba
  FRACTAL_TYPE_MANDELBROT,
Packit Service 2781ba
  FRACTAL_TYPE_JULIA
Packit Service 2781ba
} FractalType;
Packit Service 2781ba
Packit Service 2781ba
static void prepare (GeglOperation *operation)
Packit Service 2781ba
{
Packit Service 2781ba
  gegl_operation_set_format (operation, "input", babl_format ("RGBA float"));
Packit Service 2781ba
  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
julia (gdouble  x,
Packit Service 2781ba
       gdouble  y,
Packit Service 2781ba
       gdouble  jx,
Packit Service 2781ba
       gdouble  jy,
Packit Service 2781ba
       gdouble *u,
Packit Service 2781ba
       gdouble *v,
Packit Service 2781ba
       gint     depth,
Packit Service 2781ba
       gdouble  bailout2)
Packit Service 2781ba
{
Packit Service 2781ba
  gint    i;
Packit Service 2781ba
  gdouble xx = x;
Packit Service 2781ba
  gdouble yy = y;
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < depth; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      gdouble x2, y2, tmp;
Packit Service 2781ba
Packit Service 2781ba
      x2 = xx * xx;
Packit Service 2781ba
      y2 = yy * yy;
Packit Service 2781ba
      tmp = x2 - y2 + jx;
Packit Service 2781ba
      yy  = 2 * xx * yy + jy;
Packit Service 2781ba
      xx  = tmp;
Packit Service 2781ba
Packit Service 2781ba
      if ((x2 + y2) > bailout2)
Packit Service 2781ba
	break;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  *u = xx;
Packit Service 2781ba
  *v = yy;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
fractaltrace (GeglBuffer          *input,
Packit Service 2781ba
              const GeglRectangle *picture,
Packit Service 2781ba
              gfloat              *dst_buf,
Packit Service 2781ba
              const GeglRectangle *roi,
Packit Service 2781ba
              GeglChantO          *o,
Packit Service 2781ba
              gint                 y,
Packit Service 2781ba
              FractalType          fractal_type,
Packit Service 2781ba
              BackgroundType       background_type,
Packit Service 2781ba
              const Babl          *format)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglMatrix2  scale;        /* a matrix indicating scaling factors around the
Packit Service 2781ba
                                current center pixel.
Packit Service 2781ba
                              */
Packit Service 2781ba
  gint         x, i, offset;
Packit Service 2781ba
  gdouble      scale_x, scale_y;
Packit Service 2781ba
  gdouble      bailout2;
Packit Service 2781ba
  gfloat       dest[4];
Packit Service 2781ba
Packit Service 2781ba
  scale_x = (o->X2 - o->X1) / picture->width;
Packit Service 2781ba
  scale_y = (o->Y2 - o->Y1) / picture->height;
Packit Service 2781ba
Packit Service 2781ba
  bailout2 = o->bailout * o->bailout;
Packit Service 2781ba
Packit Service 2781ba
  offset = (y - roi->y) * roi->width * 4;
Packit Service 2781ba
Packit Service 2781ba
  for (x = roi->x; x < roi->x + roi->width; x++)
Packit Service 2781ba
    {
Packit Service 2781ba
      gdouble cx, cy;
Packit Service 2781ba
      gdouble px, py;
Packit Service 2781ba
      dest[1] = dest[2] = dest[3] = dest[0] = 0.0;
Packit Service 2781ba
Packit Service 2781ba
      switch (fractal_type)
Packit Service 2781ba
        {
Packit Service 2781ba
        case FRACTAL_TYPE_JULIA:
Packit Service 2781ba
#define gegl_unmap(u,v,ud,vd) {\
Packit Service 2781ba
       gdouble rx, ry;\
Packit Service 2781ba
       cx = o->X1 + ((u) - picture->x) * scale_x; \
Packit Service 2781ba
       cy = o->Y1 + ((v) - picture->y) * scale_y; \
Packit Service 2781ba
       julia (cx, cy, o->JX, o->JY, &rx, &ry, o->depth, bailout2);\
Packit Service 2781ba
       ud = (rx - o->X1) / scale_x + picture->x;\
Packit Service 2781ba
       vd = (ry - o->Y1) / scale_y + picture->y;\
Packit Service 2781ba
      }
Packit Service 2781ba
      gegl_sampler_compute_scale (scale, x, y);
Packit Service 2781ba
      gegl_unmap(x,y,px,py);
Packit Service 2781ba
#undef gegl_unmap
Packit Service 2781ba
          break;
Packit Service 2781ba
Packit Service 2781ba
        case FRACTAL_TYPE_MANDELBROT:
Packit Service 2781ba
#define gegl_unmap(u,v,ud,vd) {\
Packit Service 2781ba
           gdouble rx, ry;\
Packit Service 2781ba
           cx = o->X1 + ((u) - picture->x) * scale_x; \
Packit Service 2781ba
           cy = o->Y1 + ((v) - picture->y) * scale_y; \
Packit Service 2781ba
           julia (cx, cy, cx, cy, &rx, &ry, o->depth, bailout2);\
Packit Service 2781ba
           ud = (rx - o->X1) / scale_x + picture->x;\
Packit Service 2781ba
           vd = (ry - o->Y1) / scale_y + picture->y;\
Packit Service 2781ba
         }
Packit Service 2781ba
      gegl_sampler_compute_scale (scale, x, y);
Packit Service 2781ba
      gegl_unmap(x,y,px,py);
Packit Service 2781ba
#undef gegl_unmap
Packit Service 2781ba
          break;
Packit Service 2781ba
Packit Service 2781ba
        default:
Packit Service 2781ba
          g_error (_("Unsupported fractal type"));
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      if (0 <= px && px < picture->width && 0 <= py && py < picture->height)
Packit Service 2781ba
        {
Packit Service 2781ba
          gegl_buffer_sample (input, px, py, &scale, dest, format,
Packit Service 2781ba
                              GEGL_SAMPLER_LOHALO, GEGL_ABYSS_NONE);
Packit Service 2781ba
        }
Packit Service 2781ba
      else
Packit Service 2781ba
        {
Packit Service 2781ba
          switch (background_type)
Packit Service 2781ba
            {
Packit Service 2781ba
            case BACKGROUND_TYPE_WRAP:
Packit Service 2781ba
              px = fmod (px, picture->width);
Packit Service 2781ba
              py = fmod (py, picture->height);
Packit Service 2781ba
Packit Service 2781ba
              if (px < 0.0)
Packit Service 2781ba
                px += picture->width;
Packit Service 2781ba
              if (py < 0.0)
Packit Service 2781ba
                py += picture->height;
Packit Service 2781ba
Packit Service 2781ba
              /* Check for NaN */
Packit Service 2781ba
              if (isnan (px))
Packit Service 2781ba
                {
Packit Service 2781ba
                  if (signbit (px))
Packit Service 2781ba
                    px = 0.0;
Packit Service 2781ba
                  else
Packit Service 2781ba
                    px = picture->width - 1.0;
Packit Service 2781ba
                }
Packit Service 2781ba
Packit Service 2781ba
              if (isnan (py))
Packit Service 2781ba
                {
Packit Service 2781ba
                  if (signbit (py))
Packit Service 2781ba
                    py = 0.0;
Packit Service 2781ba
                  else
Packit Service 2781ba
                    py = picture->height - 1.0;
Packit Service 2781ba
                }
Packit Service 2781ba
Packit Service 2781ba
              gegl_buffer_sample (input, px, py, &scale, dest, format,
Packit Service 2781ba
                                  GEGL_SAMPLER_LOHALO, GEGL_ABYSS_NONE);
Packit Service 2781ba
              break;
Packit Service 2781ba
Packit Service 2781ba
            case BACKGROUND_TYPE_TRANSPARENT:
Packit Service 2781ba
              dest[0] = dest[1] = dest[2] = dest[3] = 0.0;
Packit Service 2781ba
              break;
Packit Service 2781ba
Packit Service 2781ba
            case BACKGROUND_TYPE_BLACK:
Packit Service 2781ba
              dest[0] = dest[1] = dest[2] = 0.0;
Packit Service 2781ba
              dest[3] = 1.0;
Packit Service 2781ba
              break;
Packit Service 2781ba
Packit Service 2781ba
            case BACKGROUND_TYPE_WHITE:
Packit Service 2781ba
              dest[0] = dest[1] = dest[2] = dest[3] = 1.0;
Packit Service 2781ba
              break;
Packit Service 2781ba
            }
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      for (i = 0; i < 4; i++)
Packit Service 2781ba
        dst_buf[offset++] = dest[i];
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static gboolean
Packit Service 2781ba
process (GeglOperation       *operation,
Packit Service 2781ba
         GeglBuffer          *input,
Packit Service 2781ba
         GeglBuffer          *output,
Packit Service 2781ba
         const GeglRectangle *result,
Packit Service 2781ba
         gint                 level)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglChantO	*o;
Packit Service 2781ba
  GeglRectangle  boundary;
Packit Service 2781ba
  const Babl    *format;
Packit Service 2781ba
  FractalType    fractal_type;
Packit Service 2781ba
  BackgroundType background_type;
Packit Service 2781ba
  gfloat        *dst_buf;
Packit Service 2781ba
  gint           y;
Packit Service 2781ba
Packit Service 2781ba
  o = GEGL_CHANT_PROPERTIES (operation);
Packit Service 2781ba
  boundary = gegl_operation_get_bounding_box (operation);
Packit Service 2781ba
Packit Service 2781ba
  fractal_type = FRACTAL_TYPE_MANDELBROT;
Packit Service 2781ba
  if (!strcmp (o->fractal, "mandelbrot"))
Packit Service 2781ba
    fractal_type = FRACTAL_TYPE_MANDELBROT;
Packit Service 2781ba
  else if (!strcmp(o->fractal, "julia"))
Packit Service 2781ba
    fractal_type = FRACTAL_TYPE_JULIA;
Packit Service 2781ba
Packit Service 2781ba
  background_type = BACKGROUND_TYPE_WRAP;
Packit Service 2781ba
  if (!strcmp (o->background, "wrap"))
Packit Service 2781ba
    background_type = BACKGROUND_TYPE_WRAP;
Packit Service 2781ba
  else if (!strcmp (o->background, "transparent"))
Packit Service 2781ba
    background_type = BACKGROUND_TYPE_TRANSPARENT;
Packit Service 2781ba
  else if (!strcmp (o->background, "black"))
Packit Service 2781ba
    background_type = BACKGROUND_TYPE_BLACK;
Packit Service 2781ba
  else if (!strcmp (o->background, "white"))
Packit Service 2781ba
    background_type = BACKGROUND_TYPE_WHITE;
Packit Service 2781ba
Packit Service 2781ba
  format = babl_format ("RGBA float");
Packit Service 2781ba
  dst_buf = g_new0 (gfloat, result->width * result->height * 4);
Packit Service 2781ba
Packit Service 2781ba
  for (y = result->y; y < result->y + result->height; y++)
Packit Service 2781ba
    fractaltrace (input, &boundary, dst_buf, result, o, y,
Packit Service 2781ba
                  fractal_type, background_type, format);
Packit Service 2781ba
Packit Service 2781ba
  gegl_buffer_set (output, result, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
Packit Service 2781ba
  g_free (dst_buf);
Packit Service 2781ba
Packit Service 2781ba
  gegl_buffer_sample_cleanup (input);
Packit Service 2781ba
Packit Service 2781ba
  return TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_bounding_box (GeglOperation *operation)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle  result = {0,0,0,0};
Packit Service 2781ba
  GeglRectangle *in_rect;
Packit Service 2781ba
Packit Service 2781ba
  in_rect = gegl_operation_source_get_bounding_box (operation, "input");
Packit Service 2781ba
  if (!in_rect)
Packit Service 2781ba
    return result;
Packit Service 2781ba
Packit Service 2781ba
  return *in_rect;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_required_for_output (GeglOperation       *operation,
Packit Service 2781ba
                         const gchar         *input_pad,
Packit Service 2781ba
                         const GeglRectangle *roi)
Packit Service 2781ba
{
Packit Service 2781ba
  return get_bounding_box (operation);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_chant_class_init (GeglChantClass *klass)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass       *operation_class;
Packit Service 2781ba
  GeglOperationFilterClass *filter_class;
Packit Service 2781ba
Packit Service 2781ba
  operation_class = GEGL_OPERATION_CLASS (klass);
Packit Service 2781ba
  filter_class    = GEGL_OPERATION_FILTER_CLASS (klass);
Packit Service 2781ba
Packit Service 2781ba
  filter_class->process                    = process;
Packit Service 2781ba
  operation_class->prepare                 = prepare;
Packit Service 2781ba
  operation_class->get_bounding_box        = get_bounding_box;
Packit Service 2781ba
  operation_class->get_required_for_output = get_required_for_output;
Packit Service 2781ba
Packit Service 2781ba
  gegl_operation_class_set_keys (operation_class,
Packit Service 2781ba
    "categories"  , "map",
Packit Service 2781ba
    "name"        , "gegl:fractal-trace",
Packit Service 2781ba
    "description" , _("Performs fractal trace on the image"),
Packit Service 2781ba
    NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#endif