|
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
|