Commit a8df3ea8 authored by Barak Itkin's avatar Barak Itkin
Browse files

Remove unused (programmatic) seamless cloning ops and update the main op

parent 089ef815
......@@ -17,10 +17,8 @@ noinst_LTLIBRARIES = libsc.la
libsc_la_SOURCES = $(sc_common_files)
seamless_clone_la_SOURCES = seamless-clone.c $(sc_common_files)
seamless_clone_render_la_SOURCES = seamless-clone-render.c $(sc_common_files)
seamless_clone_prepare_la_SOURCES = seamless-clone-prepare.c $(sc_common_files)
seamless_clone_compose_la_SOURCES = seamless-clone-compose.c
opdir = $(libdir)/gegl-@GEGL_API_VERSION@
op_LTLIBRARIES = seamless-clone.la seamless-clone-render.la seamless-clone-prepare.la seamless-clone-compose.la
op_LTLIBRARIES = seamless-clone.la seamless-clone-compose.la
/* This file is an image processing operation for GEGL
*
* seamless-clone-prepare.c
* Copyright (C) 2011 Barak Itkin <lightningismyname@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This is part 1 of 2 in the process of real-time seamless cloning.
* This operation takes a paste to be seamlessly cloned, and a property
* which is a pointer to a pointer. Through that pointer, the operation
* should return a data structure that is to be passed to the next
* operations.
*/
#ifdef GEGL_CHANT_PROPERTIES
gegl_chant_pointer (result, _("result"),
_("A pointer to a pointer (gpointer*) to store the result in"))
gegl_chant_int (max_refine_steps, _("Refinement Steps"), 0, 100000.0, 2000,
_("Maximal amount of refinement points to be used for the interpolation mesh"))
#else
#define GEGL_CHANT_TYPE_SINK
#define GEGL_CHANT_C_FILE "seamless-clone-prepare.c"
#include "config.h"
#include <glib/gi18n-lib.h>
#include "gegl-chant.h"
#include <poly2tri-c/p2t/poly2tri.h>
#include <poly2tri-c/refine/refine.h>
#include <poly2tri-c/render/mesh-render.h>
#include "seamless-clone-common.h"
static void
prepare (GeglOperation *operation)
{
const Babl *format = babl_format ("R'G'B'A float");
gpointer *dest = GEGL_CHANT_PROPERTIES (operation) -> result;
gegl_operation_set_format (operation, "input", format);
if (dest == NULL)
{
g_warning ("sc-prepare: No place to store the preprocessing result given!");
}
}
static gboolean
process (GeglOperation *operation,
GeglBuffer *input,
const GeglRectangle *roi,
gint level)
{
gpointer *dest = GEGL_CHANT_PROPERTIES (operation) -> result;
if (dest == NULL)
{
return FALSE;
}
*dest = sc_generate_cache (input, roi, GEGL_CHANT_PROPERTIES (operation) -> max_refine_steps);
return TRUE;
}
static void
gegl_chant_class_init (GeglChantClass *klass)
{
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
GeglOperationSinkClass *sink_class = GEGL_OPERATION_SINK_CLASS (klass);
operation_class->prepare = prepare;
gegl_operation_class_set_keys (operation_class,
"name", "gegl:seamless-clone-prepare",
"categories", "programming",
"description", _("Seamless cloning preprocessing operation"),
NULL);
sink_class->process = process;
sink_class->needs_full = TRUE;
}
#endif
/* This file is an image processing operation for GEGL
*
* seamless-clone-render.c
* Copyright (C) 2011 Barak Itkin <lightningismyname@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef GEGL_CHANT_PROPERTIES
gegl_chant_int (x, "x", G_MININT, G_MAXINT, 0,
_("The x offset to apply to the paste"))
gegl_chant_int (y, "y", G_MININT, G_MAXINT, 0,
_("The y offset to apply to the paste"))
gegl_chant_pointer (prepare, _("prepare"),
_("The pointer returned from the seamless-clone-prepare operation, applied on the aux buf"))
#else
#define GEGL_CHANT_TYPE_COMPOSER
#define GEGL_CHANT_C_FILE "seamless-clone-render.c"
#include "config.h"
#include <glib/gi18n-lib.h>
#include "gegl-chant.h"
#include <poly2tri-c/p2t/poly2tri.h>
#include <poly2tri-c/refine/refine.h>
#include <poly2tri-c/render/mesh-render.h>
#include "seamless-clone-common.h"
static GeglRectangle
get_required_for_output (GeglOperation *operation,
const gchar *input_pad,
const GeglRectangle *region)
{
GeglRectangle *temp = NULL;
GeglRectangle result;
if (g_strcmp0 (input_pad, "input") || g_strcmp0 (input_pad, "aux"))
temp = gegl_operation_source_get_bounding_box (operation, input_pad);
else
g_warning ("seamless-clone::Unknown input pad \"%s\"\n", input_pad);
if (temp != NULL)
result = *temp;
else
{
result.width = result.height = 0;
}
return result;
}
static void
prepare (GeglOperation *operation)
{
const Babl *format = babl_format ("R'G'B'A float");
gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "aux", format);
gegl_operation_set_format (operation, "output", format);
}
static gboolean
process (GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *aux,
GeglBuffer *output,
const GeglRectangle *result,
gint level)
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
ScCache *spr = o->prepare;
if (spr == NULL)
{
g_warning ("No preprocessing result given. Stop.");
return FALSE;
}
return sc_render_seamless (input, aux, o->x, o->y, output, result, spr);
}
static void
gegl_chant_class_init (GeglChantClass *klass)
{
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
GeglOperationComposerClass *composer_class = GEGL_OPERATION_COMPOSER_CLASS (klass);
operation_class->prepare = prepare;
operation_class->get_required_for_output = get_required_for_output;
gegl_operation_class_set_keys (operation_class,
"name", "gegl:seamless-clone-render",
"categories", "programming",
"description", "Seamless cloning rendering operation",
NULL);
composer_class->process = process;
}
#endif
......@@ -37,18 +37,15 @@ gegl_chant_string (error_msg, _("Error message"), NULL, _("An error message in c
#include <glib/gi18n-lib.h>
#include "gegl-chant.h"
#include <stdio.h> /* TODO: get rid of this debugging way! */
#include <poly2tri-c/p2t/poly2tri.h>
#include <poly2tri-c/refine/refine.h>
#include <poly2tri-c/render/mesh-render.h>
#include "seamless-clone-common.h"
#include "sc-context.h"
#include "sc-common.h"
typedef struct SCProps_
{
GMutex *mutex;
GeglBuffer *aux;
ScCache *preprocess;
GMutex mutex;
gboolean first_processing;
gboolean is_valid;
ScContext *context;
} SCProps;
static GeglRectangle
......@@ -74,18 +71,23 @@ get_required_for_output (GeglOperation *operation,
return result;
}
/* The prepare function is called at least once before every processing.
* So, this is the right place to mark a flag to indicate the first
* processing so that the context object will be updated
*/
static void
prepare (GeglOperation *operation)
{
const Babl *format = babl_format ("R'G'B'A float");
const Babl *format = babl_format (SC_COLOR_BABL_NAME);
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
if (o->chant_data == NULL)
{
SCProps *props = g_slice_new (SCProps);
props->mutex = g_mutex_new ();
props->aux = NULL;
props->preprocess = NULL;
g_mutex_init (&props->mutex);
props->first_processing = TRUE;
props->is_valid = FALSE;
props->context = NULL;
o->chant_data = props;
}
gegl_operation_set_format (operation, "input", format);
......@@ -100,10 +102,10 @@ static void finalize (GObject *object)
if (o->chant_data)
{
SCProps *props = (SCProps*) o->chant_data;
g_mutex_free (props->mutex);
props->aux = NULL;
if (props->preprocess)
sc_cache_free (props->preprocess);
g_mutex_clear (&props->mutex);
if (props->context)
sc_context_free (props->context);
g_slice_free (SCProps, props);
o->chant_data = NULL;
}
G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
......@@ -120,41 +122,64 @@ process (GeglOperation *operation,
gboolean return_val;
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
SCProps *props;
ScCreationError error;
ScRenderInfo info;
g_assert (o->chant_data != NULL);
info.bg = input;
info.bg_rect = *gegl_operation_source_get_bounding_box (operation, "input");
info.fg = aux;
info.fg_rect = *gegl_operation_source_get_bounding_box (operation, "aux");
info.xoff = o->xoff;
info.yoff = o->yoff;
info.render_bg = FALSE;
props = (SCProps*) o->chant_data;
g_mutex_lock (props->mutex);
if (props->aux != aux)
g_mutex_lock (&props->mutex);
if (props->first_processing)
{
if (props->preprocess)
sc_cache_free (props->preprocess);
if (props->context == NULL)
props->context = sc_context_new (aux, gegl_operation_source_get_bounding_box (operation, "aux"), 0.5, &error);
else
sc_context_update (props->context, aux, gegl_operation_source_get_bounding_box (operation, "aux"), 0.5, &error);
props->aux = aux;
props->preprocess = sc_generate_cache (aux, gegl_operation_source_get_bounding_box (operation, "aux"), o -> max_refine_steps);
switch (props->preprocess->error)
switch (error)
{
case SC_ERROR_NONE:
case SC_CREATION_ERROR_NONE:
o->error_msg = NULL;
props->is_valid = TRUE;
break;
case SC_ERROR_NO_PASTE:
o->error_msg = _("The paste does not contain opaque parts");
case SC_CREATION_ERROR_EMPTY:
o->error_msg = _("The foreground does not contain opaque parts");
break;
case SC_ERROR_SMALL_PASTE:
o->error_msg = _("The paste is too small to use");
case SC_CREATION_ERROR_TOO_SMALL:
o->error_msg = _("The foreground is too small to use");
break;
case SC_ERROR_HOLED_OR_SPLIT_PASTE:
o->error_msg = _("The paste contains holes and/or several unconnected parts");
case SC_CREATION_ERROR_HOLED_OR_SPLIT:
o->error_msg = _("The foreground contains holes and/or several unconnected parts");
break;
default:
g_warning ("Unknown preprocessing status %d", props->preprocess->error);
g_warning ("Unknown preprocessing status %d", error);
break;
}
if (props->is_valid)
{
if (! sc_context_prepare_render (props->context, &info))
{
o->error_msg = _("The opaque parts of the foreground are not above the background!");
props->is_valid = FALSE;
}
}
props->first_processing = FALSE;
}
g_mutex_unlock (props->mutex);
g_mutex_unlock (&props->mutex);
if (props->preprocess->error == SC_ERROR_NONE)
return sc_render_seamless (input, aux, o->xoff, o->yoff, output, result, props->preprocess);
if (props->is_valid)
return sc_context_render (props->context, &info, result, output);
else
return FALSE;
return return_val;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment