gimp/plug-ins/map-object/map-object-image.c

431 lines
10 KiB
C
Raw Permalink Normal View History

/*********************************************************/
/* Image manipulation routines. Calls mapobject_shade.c */
/* functions to compute the shading of the image at each */
/* pixel. These routines are used by the functions in */
/* mapobject_preview.c and mapobject_apply.c */
/*********************************************************/
#include "config.h"
#include <string.h>
Libgimp cleanup part II (with a little help from Yosh who moved the CVS 2000-05-27 Michael Natterer <mitch@gimp.org> Libgimp cleanup part II (with a little help from Yosh who moved the CVS files). * libgimp/Makefile.am * libgimp/gimpchannel_pdb.c * libgimp/gimpdisplay_pdb.c * libgimp/gimpdrawable_pdb.c * libgimp/gimpgradient_pdb.c * libgimp/gimphelp_pdb.c * libgimp/gimpimage_pdb.c * libgimp/gimplayer_pdb.c * libgimp/gimppalette_pdb.c * libgimp/gimpparasite_pdb.c * libgimp/gimpselection_pdb.c * libgimp/gimpunit_pdb.c: new names of all files which contain PDB wrappers. * modules/Makefile.am * libgimp/gimpcolordisplay.h * libgimp/gimpcolorselector.h * modules/gimpmodregister.[ch]: renamed. * libgimp/gimpparasiteF.h * libgimp/gimpparasiteP.h: removed because gimp.h had to include the private header anyway. * app/color_notebook.c * app/color_select.c * app/gdisplay_color.[ch] * app/gdisplay_color_ui.c * app/gimpbrushpipe.c * app/gimpdrawable.[ch] * app/gimpimage.c * app/gimpimage.h * app/gimpparasite.[ch] * app/gimprc.c * app/image_new.c * app/layer.c * app/parasite_cmds.c * app/parasitelist.[ch] * app/plug_in.c * app/procedural_db.c * app/undo.c * app/xcf.c * libgimp/gimp.[ch] * libgimp/gimpcolordisplay.h * libgimp/gimpparasite.[ch] * modules/cdisplay_gamma.c * modules/cdisplay_highcontrast.c * modules/colorsel_gtk.c * modules/colorsel_triangle.c * modules/colorsel_water.c * plug-ins/FractalExplorer/Dialogs.c * plug-ins/FractalExplorer/Events.c * plug-ins/Lighting/lighting_apply.c * plug-ins/Lighting/lighting_shade.c * plug-ins/MapObject/mapobject_image.c * plug-ins/common/gpb.c * plug-ins/common/psp.c * plug-ins/sel2path/sel2path.c * po-libgimp/POTFILES.in * tools/pdbgen/pdb.pl * tools/pdbgen/pdb/parasite.pdb: changed includes accordingly.
2000-05-27 01:30:21 +00:00
#include <sys/types.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
plug-ins/libgck/gck/gck.h removed the GckRGB color type and all it's 2001-01-01 Michael Natterer <mitch@gimp.org> * plug-ins/libgck/gck/gck.h * plug-ins/libgck/gck/gckcolor.c: removed the GckRGB color type and all it's functions. * libgimp/Makefile.am * libgimp/gimpcolor.[ch]: new files containing the new GimpRGB color type and assorted functions. * libgimp/gimpcolorspace.[ch]: colorspace conversion routines for the new GimpRGB type. Also taken from LibGCK. * libgimp/gimp.h * libgimp/gimptypes.h: #include "gimpcolor.h". It's ugly to include it in both files but unavoidable to follow our new "*.c" file include policy. This will go away as libgimp will be chopped up into pieces anyway. * app/apptypes.h * app/asupsample.[ch] * app/blend.c * app/color_transfer.h * app/gradient_header.h: removed "color_t" and use GimpRGB instead. * plug-ins/Lighting/lighting_apply.c * plug-ins/Lighting/lighting_image.c * plug-ins/Lighting/lighting_image.h * plug-ins/Lighting/lighting_main.c * plug-ins/Lighting/lighting_main.h * plug-ins/Lighting/lighting_preview.c * plug-ins/Lighting/lighting_shade.c * plug-ins/Lighting/lighting_shade.h * plug-ins/MapObject/mapobject_apply.c * plug-ins/MapObject/mapobject_image.c * plug-ins/MapObject/mapobject_image.h * plug-ins/MapObject/mapobject_main.c * plug-ins/MapObject/mapobject_main.h * plug-ins/MapObject/mapobject_preview.c * plug-ins/MapObject/mapobject_shade.c * plug-ins/MapObject/mapobject_shade.h * modules/colorsel_triangle.c: s/GckRGB/GimpRGB/g * plug-ins/gdyntext/gdyntextcompat.h: check also for GIMP's minor version when deciding if to add a missing PDB wrapper. (All this compat cruft including libgimp/gimpcompat.h should go away ASAP)
2001-01-01 18:35:09 +00:00
#include "map-object-main.h"
#include "map-object-preview.h"
#include "map-object-shade.h"
#include "map-object-ui.h"
#include "map-object-image.h"
GimpImage *image;
GimpDrawable *input_drawable;
GimpDrawable *output_drawable;
GeglBuffer *source_buffer;
GeglBuffer *dest_buffer;
1998-07-16 00:45:41 +00:00
GimpDrawable *box_drawables[6];
GeglBuffer *box_buffers[6];
GimpDrawable *cylinder_drawables[2];
GeglBuffer *cylinder_buffers[2];
1998-07-16 20:14:54 +00:00
guchar *preview_rgb_data = NULL;
gint preview_rgb_stride;
cairo_surface_t *preview_surface = NULL;
2019-07-09 17:10:45 +02:00
glong maxcounter, old_depth, max_depth;
gint width, height;
gdouble background[4];
gint border_x, border_y, border_w, border_h;
void peek_box_image (gint image,
gint x,
gint y,
gdouble *color);
/******************/
/* Implementation */
/******************/
void
peek (gint x,
gint y,
gdouble *color)
{
2019-07-09 17:10:45 +02:00
gegl_buffer_sample (source_buffer, x, y, NULL,
color, babl_format ("R'G'B'A double"),
2019-07-09 17:10:45 +02:00
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
2019-07-09 17:10:45 +02:00
if (! babl_format_has_alpha (gegl_buffer_get_format (source_buffer)))
color[3] = 1.0;
}
void
peek_box_image (gint image,
gint x,
gint y,
gdouble *color)
1998-07-16 00:45:41 +00:00
{
2019-07-09 17:10:45 +02:00
gegl_buffer_sample (box_buffers[image], x, y, NULL,
color, babl_format ("R'G'B'A double"),
2019-07-09 17:10:45 +02:00
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
1998-07-16 00:45:41 +00:00
2019-07-09 17:10:45 +02:00
if (! babl_format_has_alpha (gegl_buffer_get_format (box_buffers[image])))
color[3] = 1.0;
1998-07-16 00:45:41 +00:00
}
static void
peek_cylinder_image (gint image,
gint x,
gint y,
gdouble *color)
1998-07-16 20:14:54 +00:00
{
2019-07-09 17:10:45 +02:00
gegl_buffer_sample (cylinder_buffers[image], x, y, NULL,
color, babl_format ("R'G'B'A double"),
2019-07-09 17:10:45 +02:00
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
1998-07-16 20:14:54 +00:00
2019-07-09 17:10:45 +02:00
if (! babl_format_has_alpha (gegl_buffer_get_format (cylinder_buffers[image])))
color[3] = 1.0;
1998-07-16 20:14:54 +00:00
}
void
poke (gint x,
gint y,
gdouble *color,
2019-07-09 17:10:45 +02:00
gpointer user_data)
{
2019-07-09 17:10:45 +02:00
gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, 1, 1), 0,
babl_format ("R'G'B'A double"), color,
GEGL_AUTO_ROWSTRIDE);
}
gint
checkbounds (gint x,
2011-02-20 15:23:22 +01:00
gint y)
{
2019-07-09 17:10:45 +02:00
if (x < border_x ||
y < border_y ||
x >= border_x + border_w ||
y >= border_y + border_h)
return FALSE;
else
return TRUE;
}
static gint
checkbounds_box_image (gint image,
2011-02-20 15:23:22 +01:00
gint x,
gint y)
1998-07-16 00:45:41 +00:00
{
gint w, h;
1998-07-16 00:45:41 +00:00
2019-07-09 17:10:45 +02:00
w = gegl_buffer_get_width (box_buffers[image]);
h = gegl_buffer_get_height (box_buffers[image]);
1998-07-16 00:45:41 +00:00
if (x < 0 || y < 0 || x >= w || y >= h)
return FALSE ;
1998-07-16 00:45:41 +00:00
else
return TRUE ;
1998-07-16 00:45:41 +00:00
}
static gint
checkbounds_cylinder_image (gint image,
2011-02-20 15:23:22 +01:00
gint x,
gint y)
1998-07-16 20:14:54 +00:00
{
gint w, h;
1998-07-16 20:14:54 +00:00
2019-07-09 17:10:45 +02:00
w = gegl_buffer_get_width (cylinder_buffers[image]);
h = gegl_buffer_get_height (cylinder_buffers[image]);
1998-07-16 20:14:54 +00:00
if (x < 0 || y < 0 || x >= w || y >= h)
return FALSE;
1998-07-16 20:14:54 +00:00
else
return TRUE;
1998-07-16 20:14:54 +00:00
}
GimpVector3
int_to_pos (gint x,
2011-02-20 15:23:22 +01:00
gint y)
{
GimpVector3 pos;
pos.x = (gdouble) x / (gdouble) width;
pos.y = (gdouble) y / (gdouble) height;
pos.z = 0.0;
return pos;
}
void
pos_to_int (gdouble x,
2011-02-20 15:23:22 +01:00
gdouble y,
gint *scr_x,
gint *scr_y)
{
*scr_x = (gint) ((x * (gdouble) width));
*scr_y = (gint) ((y * (gdouble) height));
}
/**********************************************/
/* Compute the image color at pos (u,v) using */
/* Quartics bilinear interpolation stuff. */
/**********************************************/
void
get_image_color (gdouble u,
2011-02-20 15:23:22 +01:00
gdouble v,
gint *inside,
gdouble *color)
{
gint x1;
gint y1;
gint x2;
gint y2;
gdouble p[4];
gdouble pixels[16];
pos_to_int (u, v, &x1, &y1);
if (mapvals.tiled == TRUE)
{
*inside = TRUE;
if (x1 < 0) x1 = (width-1) - (-x1 % width);
else x1 = x1 % width;
if (y1 < 0) y1 = (height-1) - (-y1 % height);
else y1 = y1 % height;
x2 = (x1 + 1) % width;
y2 = (y1 + 1) % height;
peek (x1, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i] = p[i];
peek (x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek (x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek (x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * width, v * height, pixels, TRUE, color);
return;
}
if (checkbounds (x1, y1) == FALSE)
{
*inside =FALSE;
for (gint i = 0; i < 4; i++)
color[i] = background[i];
return;
}
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds (x2, y2) == FALSE)
{
*inside = TRUE;
return peek (x1, y1, color);
}
*inside = TRUE;
peek (x1, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i] = p[i];
peek (x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek (x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek (x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * width, v * height, pixels, TRUE, color);
}
void
get_box_image_color (gint image,
gdouble u,
gdouble v,
gdouble *color)
1998-07-16 00:45:41 +00:00
{
gint w;
gint h;
gint x1;
gint y1;
gint x2;
gint y2;
gdouble p[4];
gdouble pixels[16];
2019-07-09 17:10:45 +02:00
w = gegl_buffer_get_width (box_buffers[image]);
h = gegl_buffer_get_height (box_buffers[image]);
1998-07-16 00:45:41 +00:00
x1 = (gint) ((u * (gdouble) w));
y1 = (gint) ((v * (gdouble) h));
1998-07-16 00:45:41 +00:00
if (checkbounds_box_image (image, x1, y1) == FALSE)
{
for (gint i = 0; i < 4; i++)
color[i] = background[i];
return;
}
1998-07-16 20:14:54 +00:00
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds_box_image (image, x2, y2) == FALSE)
return peek_box_image (image, x1, y1, color);
1998-07-16 20:14:54 +00:00
peek_box_image (image, x1, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i] = p[i];
peek_box_image (image, x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek_box_image (image, x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek_box_image (image, x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * w, v * w, pixels, TRUE, color);
1998-07-16 20:14:54 +00:00
}
void
get_cylinder_image_color (gint image,
gdouble u,
gdouble v,
gdouble *color)
1998-07-16 20:14:54 +00:00
{
gint w;
gint h;
gint x1;
gint y1;
gint x2;
gint y2;
gdouble p[4];
gdouble pixels[16];
2019-07-09 17:10:45 +02:00
w = gegl_buffer_get_width (cylinder_buffers[image]);
h = gegl_buffer_get_height (cylinder_buffers[image]);
1998-07-16 20:14:54 +00:00
x1 = (gint) ((u * (gdouble) w));
y1 = (gint) ((v * (gdouble) h));
1998-07-16 20:14:54 +00:00
if (checkbounds_cylinder_image (image, x1, y1) == FALSE)
{
for (gint i = 0; i < 4; i++)
color[i] = background[i];
return;
}
1998-07-16 00:45:41 +00:00
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds_cylinder_image (image, x2, y2) == FALSE)
return peek_cylinder_image (image, x1, y1, color);
1998-07-16 00:45:41 +00:00
peek_cylinder_image (image, x1, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i] = p[i];
peek_cylinder_image (image, x2, y1, p);
for (gint i = 0; i < 4; i++)
pixels[i + 4] = p[i];
peek_cylinder_image (image, x1, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 8] = p[i];
peek_cylinder_image (image, x2, y2, p);
for (gint i = 0; i < 4; i++)
pixels[i + 12] = p[i];
gimp_bilinear_rgb (u * w, v * h, pixels, TRUE, color);
1998-07-16 00:45:41 +00:00
}
/****************************************/
/* Allocate memory for temporary images */
/****************************************/
gint
image_setup (GimpDrawable *drawable,
gint interactive,
GimpProcedureConfig *config)
{
gboolean transparent_background;
input_drawable = drawable;
output_drawable = drawable;
g_object_get (config,
"transparent_background", &transparent_background,
NULL);
if (! gimp_drawable_mask_intersect (drawable, &border_x, &border_y,
&border_w, &border_h))
return FALSE;
width = gimp_drawable_get_width (input_drawable);
height = gimp_drawable_get_height (input_drawable);
source_buffer = gimp_drawable_get_buffer (input_drawable);
maxcounter = (glong) width * (glong) height;
if (transparent_background == TRUE)
{
for (gint i = 0; i < 4; i++)
background[i] = 0;
}
else
{
GeglColor *gegl_color;
gegl_color = gimp_context_get_background ();
gimp_color_set_alpha (gegl_color, 1.0);
gegl_color_get_rgba_with_space (gegl_color, &background[0], &background[1],
&background[2], &background[3], NULL);
g_object_unref (gegl_color);
}
if (interactive == TRUE)
{
preview_rgb_stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24,
PREVIEW_WIDTH);
preview_rgb_data = g_new0 (guchar, preview_rgb_stride * PREVIEW_HEIGHT);
preview_surface = cairo_image_surface_create_for_data (preview_rgb_data,
CAIRO_FORMAT_RGB24,
PREVIEW_WIDTH,
PREVIEW_HEIGHT,
preview_rgb_stride);
}
return TRUE;
}