2023-09-26 00:35:21 +02:00
|
|
|
/* PIKA - Photo and Image Kooker Application
|
|
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
|
|
*
|
|
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* Depth Merge -- Combine two image layers via corresponding depth maps
|
|
|
|
* Copyright (C) 1997, 1998 Sean Cier (scier@PostHorizon.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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Version 1.0.0: (14 August 1998)
|
|
|
|
* Math optimizations, miscellaneous speedups
|
|
|
|
*
|
|
|
|
* Version 0.1: (6 July 1997)
|
|
|
|
* Initial Release
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <libpika/pika.h>
|
|
|
|
#include <libpika/pikaui.h>
|
|
|
|
|
|
|
|
#include "libpika/stdplugins-intl.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define DEBUG
|
|
|
|
|
|
|
|
#ifndef LERP
|
|
|
|
#define LERP(frac,a,b) ((frac)*(b) + (1-(frac))*(a))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MUL255(i) ((i)*256 - (i))
|
|
|
|
#define DIV255(i) (((i) + (i)/256 + 1) / 256)
|
|
|
|
|
|
|
|
#define PLUG_IN_PROC "plug-in-depth-merge"
|
|
|
|
#define PLUG_IN_VERSION "August 1998"
|
|
|
|
#define PLUG_IN_BINARY "depth-merge"
|
|
|
|
#define PLUG_IN_ROLE "pika-depth-merge"
|
|
|
|
|
|
|
|
#define PREVIEW_SIZE 256
|
|
|
|
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
typedef struct _Merge Merge;
|
|
|
|
typedef struct _MergeClass MergeClass;
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
struct _Merge
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
PikaPlugIn parent_instance;
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
gint selectionX;
|
|
|
|
gint selectionY;
|
|
|
|
gint selectionWidth;
|
|
|
|
gint selectionHeight;
|
|
|
|
gint resultHasAlpha;
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
GtkWidget *preview;
|
|
|
|
gint previewWidth;
|
|
|
|
gint previewHeight;
|
|
|
|
|
|
|
|
guchar *previewSource1;
|
|
|
|
guchar *previewSource2;
|
|
|
|
guchar *previewDepthMap1;
|
|
|
|
guchar *previewDepthMap2;
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
PikaProcedureConfig *config;
|
2023-09-26 00:35:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _MergeClass
|
|
|
|
{
|
|
|
|
PikaPlugInClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
#define MERGE_TYPE (merge_get_type ())
|
|
|
|
#define MERGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MERGE_TYPE, Merge))
|
|
|
|
|
|
|
|
GType merge_get_type (void) G_GNUC_CONST;
|
|
|
|
|
|
|
|
static void merge_finalize (GObject *object);
|
|
|
|
|
|
|
|
static GList * merge_query_procedures (PikaPlugIn *plug_in);
|
|
|
|
static PikaProcedure * merge_create_procedure (PikaPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
|
|
|
|
|
|
|
static PikaValueArray * merge_run (PikaProcedure *procedure,
|
|
|
|
PikaRunMode run_mode,
|
|
|
|
PikaImage *image,
|
|
|
|
gint n_drawables,
|
|
|
|
PikaDrawable **drawables,
|
|
|
|
PikaProcedureConfig *config,
|
|
|
|
gpointer run_data);
|
|
|
|
|
|
|
|
static gint32 DepthMerge_execute (Merge *dm,
|
|
|
|
PikaDrawable *resultDrawable,
|
|
|
|
PikaProcedureConfig *config);
|
|
|
|
static void DepthMerge_executeRegion (PikaProcedureConfig *config,
|
|
|
|
guchar *source1Row,
|
|
|
|
guchar *source2Row,
|
|
|
|
guchar *depthMap1Row,
|
|
|
|
guchar *depthMap2Row,
|
|
|
|
guchar *resultRow,
|
|
|
|
gint length,
|
|
|
|
gfloat overlap,
|
|
|
|
gfloat offset,
|
|
|
|
gfloat scale1,
|
|
|
|
gfloat scale2);
|
|
|
|
static gboolean DepthMerge_dialog (Merge *merge,
|
|
|
|
PikaProcedure *procedure,
|
|
|
|
PikaProcedureConfig *config);
|
|
|
|
static void DepthMerge_buildPreviewSourceImage (Merge *dm,
|
|
|
|
PikaProcedureConfig *config);
|
|
|
|
static void DepthMerge_updatePreview (Merge *dm,
|
|
|
|
PikaProcedureConfig *config);
|
|
|
|
|
|
|
|
|
|
|
|
static void util_fillReducedBuffer (guchar *dest,
|
|
|
|
const Babl *dest_format,
|
|
|
|
gint destWidth,
|
|
|
|
gint destHeight,
|
|
|
|
PikaDrawable *sourceDrawable,
|
|
|
|
gint x0,
|
|
|
|
gint y0,
|
|
|
|
gint sourceWidth,
|
|
|
|
gint sourceHeight);
|
|
|
|
|
|
|
|
static void merge_preview_size_allocate (GtkWidget *widget,
|
|
|
|
GtkAllocation *allocation,
|
|
|
|
Merge *dm);
|
|
|
|
static void merge_preview_config_notify (PikaProcedureConfig *config,
|
|
|
|
const GParamSpec *pspec,
|
|
|
|
Merge *dm);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (Merge, merge, PIKA_TYPE_PLUG_IN)
|
|
|
|
|
|
|
|
PIKA_MAIN (MERGE_TYPE)
|
|
|
|
DEFINE_STD_SET_I18N
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_class_init (MergeClass *klass)
|
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2023-09-26 00:35:21 +02:00
|
|
|
PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
object_class->finalize = merge_finalize;
|
|
|
|
|
2023-09-26 00:35:21 +02:00
|
|
|
plug_in_class->query_procedures = merge_query_procedures;
|
|
|
|
plug_in_class->create_procedure = merge_create_procedure;
|
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_init (Merge *merge)
|
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
merge->previewSource1 = NULL;
|
|
|
|
merge->previewSource2 = NULL;
|
|
|
|
merge->previewDepthMap1 = NULL;
|
|
|
|
merge->previewDepthMap2 = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
Merge *merge = MERGE (object);
|
|
|
|
|
|
|
|
g_free (merge->previewSource1);
|
|
|
|
g_free (merge->previewSource2);
|
|
|
|
g_free (merge->previewDepthMap1);
|
|
|
|
g_free (merge->previewDepthMap2);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (merge_parent_class)->finalize (object);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
merge_query_procedures (PikaPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
return g_list_append (NULL, g_strdup (PLUG_IN_PROC));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PikaProcedure *
|
|
|
|
merge_create_procedure (PikaPlugIn *plug_in,
|
2023-10-30 23:55:30 +01:00
|
|
|
const gchar *name)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
|
|
|
PikaProcedure *procedure = NULL;
|
|
|
|
|
|
|
|
if (! strcmp (name, PLUG_IN_PROC))
|
|
|
|
{
|
|
|
|
procedure = pika_image_procedure_new (plug_in, name,
|
|
|
|
PIKA_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
merge_run, NULL, NULL);
|
|
|
|
|
|
|
|
pika_procedure_set_image_types (procedure, "RGB*, GRAY*");
|
|
|
|
pika_procedure_set_sensitivity_mask (procedure,
|
|
|
|
PIKA_PROCEDURE_SENSITIVE_DRAWABLE);
|
|
|
|
|
|
|
|
pika_procedure_set_menu_label (procedure, _("_Depth Merge..."));
|
|
|
|
pika_procedure_add_menu_path (procedure, "<Image>/Filters/Combine");
|
|
|
|
|
|
|
|
pika_procedure_set_documentation (procedure,
|
|
|
|
_("Combine two images using depth "
|
|
|
|
"maps (z-buffers)"),
|
|
|
|
"Taking as input two full-color, "
|
|
|
|
"full-alpha images and two "
|
|
|
|
"corresponding grayscale depth maps, "
|
|
|
|
"this plug-in combines the images based "
|
|
|
|
"on which is closer (has a lower depth "
|
|
|
|
"map value) at each point.",
|
|
|
|
name);
|
|
|
|
pika_procedure_set_attribution (procedure,
|
|
|
|
"Sean Cier",
|
|
|
|
"Sean Cier",
|
|
|
|
PLUG_IN_VERSION);
|
|
|
|
|
|
|
|
PIKA_PROC_ARG_DRAWABLE (procedure, "source-1",
|
2023-10-30 23:55:30 +01:00
|
|
|
_("Source _1"),
|
2023-09-26 00:35:21 +02:00
|
|
|
"Source 1",
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
PIKA_PROC_ARG_DRAWABLE (procedure, "depth-map-1",
|
|
|
|
_("_Depth map 1"),
|
|
|
|
"Depth map 1",
|
2023-09-26 00:35:21 +02:00
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
PIKA_PROC_ARG_DRAWABLE (procedure, "source-2",
|
|
|
|
_("Source _2"),
|
|
|
|
"Source 2",
|
2023-09-26 00:35:21 +02:00
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
PIKA_PROC_ARG_DRAWABLE (procedure, "depth-map-2",
|
2023-10-30 23:55:30 +01:00
|
|
|
_("Depth _map 2"),
|
2023-09-26 00:35:21 +02:00
|
|
|
"Depth map 2",
|
|
|
|
TRUE,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
PIKA_PROC_ARG_DOUBLE (procedure, "overlap",
|
2023-10-30 23:55:30 +01:00
|
|
|
_("O_verlap"),
|
2023-09-26 00:35:21 +02:00
|
|
|
"Overlap",
|
|
|
|
0, 2, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
PIKA_PROC_ARG_DOUBLE (procedure, "offset",
|
2023-10-30 23:55:30 +01:00
|
|
|
_("O_ffset"),
|
|
|
|
_("Depth relative offset"),
|
2023-09-26 00:35:21 +02:00
|
|
|
-1, 1, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
PIKA_PROC_ARG_DOUBLE (procedure, "scale-1",
|
2023-10-30 23:55:30 +01:00
|
|
|
_("Sc_ale 1"),
|
2023-09-26 00:35:21 +02:00
|
|
|
"Depth relative scale 1",
|
|
|
|
-1, 1, 1,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
PIKA_PROC_ARG_DOUBLE (procedure, "scale-2",
|
2023-10-30 23:55:30 +01:00
|
|
|
_("Scal_e 2"),
|
2023-09-26 00:35:21 +02:00
|
|
|
"Depth relative scale 2",
|
|
|
|
-1, 1, 1,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PikaValueArray *
|
|
|
|
merge_run (PikaProcedure *procedure,
|
|
|
|
PikaRunMode run_mode,
|
|
|
|
PikaImage *image,
|
|
|
|
gint n_drawables,
|
|
|
|
PikaDrawable **drawables,
|
2023-10-30 23:55:30 +01:00
|
|
|
PikaProcedureConfig *config,
|
2023-09-26 00:35:21 +02:00
|
|
|
gpointer run_data)
|
|
|
|
{
|
|
|
|
PikaDrawable *drawable;
|
2023-10-30 23:55:30 +01:00
|
|
|
Merge *merge = MERGE (pika_procedure_get_plug_in (procedure));
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
if (n_drawables != 1)
|
|
|
|
{
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
g_set_error (&error, PIKA_PLUG_IN_ERROR, 0,
|
|
|
|
_("Procedure '%s' only works with one drawable."),
|
|
|
|
PLUG_IN_PROC);
|
|
|
|
|
|
|
|
return pika_procedure_new_return_values (procedure,
|
|
|
|
PIKA_PDB_CALLING_ERROR,
|
|
|
|
error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drawable = drawables[0];
|
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
merge->config = config;
|
|
|
|
if (! pika_drawable_mask_intersect (drawable,
|
|
|
|
&(merge->selectionX), &(merge->selectionY),
|
|
|
|
&(merge->selectionWidth),
|
|
|
|
&(merge->selectionHeight)))
|
|
|
|
return pika_procedure_new_return_values (procedure,
|
|
|
|
PIKA_PDB_EXECUTION_ERROR,
|
|
|
|
g_error_new_literal (PIKA_PLUG_IN_ERROR, 0,
|
|
|
|
_("The selection does not intersect with the input drawable.")));
|
|
|
|
|
|
|
|
if (run_mode == PIKA_RUN_INTERACTIVE)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
g_object_set (config,
|
|
|
|
"source-1", drawable,
|
|
|
|
"source-2", drawable,
|
|
|
|
"depth-map-1", drawable,
|
|
|
|
"depth-map-2", drawable,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (! DepthMerge_dialog (merge, procedure, config))
|
|
|
|
return pika_procedure_new_return_values (procedure,
|
|
|
|
PIKA_PDB_CANCEL,
|
|
|
|
NULL);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
if (! DepthMerge_execute (merge, drawable, config))
|
|
|
|
return pika_procedure_new_return_values (procedure,
|
|
|
|
PIKA_PDB_EXECUTION_ERROR, NULL);
|
|
|
|
else if (run_mode != PIKA_RUN_NONINTERACTIVE)
|
|
|
|
pika_displays_flush ();
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----- DepthMerge ----- */
|
|
|
|
|
|
|
|
static gint32
|
2023-10-30 23:55:30 +01:00
|
|
|
DepthMerge_execute (Merge *dm,
|
|
|
|
PikaDrawable *resultDrawable,
|
|
|
|
PikaProcedureConfig *config)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
GeglBuffer *source1_buffer = NULL;
|
|
|
|
GeglBuffer *source2_buffer = NULL;
|
|
|
|
GeglBuffer *depthMap1_buffer = NULL;
|
|
|
|
GeglBuffer *depthMap2_buffer = NULL;
|
2023-10-30 23:55:30 +01:00
|
|
|
GeglBuffer *result_buffer = NULL;
|
2023-09-26 00:35:21 +02:00
|
|
|
guchar *source1Row, *source2Row;
|
|
|
|
guchar *depthMap1Row, *depthMap2Row;
|
|
|
|
guchar *resultRow;
|
|
|
|
guchar *tempRow;
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
PikaDrawable *source1Drawable = NULL;
|
|
|
|
PikaDrawable *source2Drawable = NULL;
|
|
|
|
PikaDrawable *depthMap1Drawable = NULL;
|
|
|
|
PikaDrawable *depthMap2Drawable = NULL;
|
|
|
|
gdouble overlap = 0.0;
|
|
|
|
gdouble offset = 0.0;
|
|
|
|
gdouble scale1 = 0.0;
|
|
|
|
gdouble scale2 = 0.0;
|
|
|
|
|
2023-09-26 00:35:21 +02:00
|
|
|
pika_progress_init (_("Depth-merging"));
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
g_object_get (config,
|
|
|
|
"source-1", &source1Drawable,
|
|
|
|
"source-2", &source2Drawable,
|
|
|
|
"depth-map-1", &depthMap1Drawable,
|
|
|
|
"depth-map-2", &depthMap2Drawable,
|
|
|
|
"overlap", &overlap,
|
|
|
|
"offset", &offset,
|
|
|
|
"scale-1", &scale1,
|
|
|
|
"scale-2", &scale2,
|
|
|
|
NULL);
|
|
|
|
|
2023-09-26 00:35:21 +02:00
|
|
|
resultRow = g_new (guchar, dm->selectionWidth * 4);
|
|
|
|
source1Row = g_new (guchar, dm->selectionWidth * 4);
|
|
|
|
source2Row = g_new (guchar, dm->selectionWidth * 4);
|
|
|
|
depthMap1Row = g_new (guchar, dm->selectionWidth );
|
|
|
|
depthMap2Row = g_new (guchar, dm->selectionWidth );
|
|
|
|
tempRow = g_new (guchar, dm->selectionWidth * 4);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
if (source1Drawable)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
source1_buffer = pika_drawable_get_buffer (source1Drawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (x = 0; x < dm->selectionWidth; x++)
|
|
|
|
{
|
|
|
|
source1Row[4 * x ] = 0;
|
|
|
|
source1Row[4 * x + 1] = 0;
|
|
|
|
source1Row[4 * x + 2] = 0;
|
|
|
|
source1Row[4 * x + 3] = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
if (source2Drawable)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
source2_buffer = pika_drawable_get_buffer (source2Drawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (x = 0; x < dm->selectionWidth; x++)
|
|
|
|
{
|
|
|
|
source2Row[4 * x ] = 0;
|
|
|
|
source2Row[4 * x + 1] = 0;
|
|
|
|
source2Row[4 * x + 2] = 0;
|
|
|
|
source2Row[4 * x + 3] = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
if (depthMap1Drawable)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
depthMap1_buffer = pika_drawable_get_buffer (depthMap1Drawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (x = 0; x < dm->selectionWidth; x++)
|
2023-10-30 23:55:30 +01:00
|
|
|
depthMap1Row[x] = 0;
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
if (depthMap2Drawable)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
depthMap2_buffer = pika_drawable_get_buffer (depthMap2Drawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (x = 0; x < dm->selectionWidth; x++)
|
2023-10-30 23:55:30 +01:00
|
|
|
depthMap2Row[x] = 0;
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
result_buffer = pika_drawable_get_shadow_buffer (resultDrawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
for (y = dm->selectionY; y < (dm->selectionY + dm->selectionHeight); y++)
|
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
if (source1Drawable)
|
|
|
|
gegl_buffer_get (source1_buffer,
|
|
|
|
GEGL_RECTANGLE (dm->selectionX, y,
|
|
|
|
dm->selectionWidth, 1), 1.0,
|
|
|
|
babl_format ("R'G'B'A u8"), source1Row,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
|
|
|
if (source2Drawable)
|
|
|
|
gegl_buffer_get (source2_buffer,
|
|
|
|
GEGL_RECTANGLE (dm->selectionX, y,
|
|
|
|
dm->selectionWidth, 1), 1.0,
|
|
|
|
babl_format ("R'G'B'A u8"), source2Row,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
|
|
|
if (depthMap1Drawable)
|
|
|
|
gegl_buffer_get (depthMap1_buffer,
|
|
|
|
GEGL_RECTANGLE (dm->selectionX, y,
|
|
|
|
dm->selectionWidth, 1), 1.0,
|
|
|
|
babl_format ("Y' u8"), depthMap1Row,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
|
|
|
if (depthMap2Drawable)
|
|
|
|
gegl_buffer_get (depthMap2_buffer,
|
|
|
|
GEGL_RECTANGLE (dm->selectionX, y,
|
|
|
|
dm->selectionWidth, 1), 1.0,
|
|
|
|
babl_format ("Y' u8"), depthMap2Row,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
|
|
|
DepthMerge_executeRegion (config,
|
2023-09-26 00:35:21 +02:00
|
|
|
source1Row, source2Row, depthMap1Row, depthMap2Row,
|
|
|
|
resultRow,
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->selectionWidth, overlap, offset, scale1, scale2);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
gegl_buffer_set (result_buffer,
|
|
|
|
GEGL_RECTANGLE (dm->selectionX, y,
|
|
|
|
dm->selectionWidth, 1), 0,
|
|
|
|
babl_format ("R'G'B'A u8"), resultRow,
|
|
|
|
GEGL_AUTO_ROWSTRIDE);
|
|
|
|
|
|
|
|
pika_progress_update ((double)(y-dm->selectionY) /
|
|
|
|
(double)(dm->selectionHeight - 1));
|
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
g_clear_object (&source1Drawable);
|
|
|
|
g_clear_object (&source2Drawable);
|
|
|
|
g_clear_object (&depthMap1Drawable);
|
|
|
|
g_clear_object (&depthMap2Drawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
g_free (resultRow);
|
|
|
|
g_free (source1Row);
|
|
|
|
g_free (source2Row);
|
|
|
|
g_free (depthMap1Row);
|
|
|
|
g_free (depthMap2Row);
|
|
|
|
g_free (tempRow);
|
|
|
|
|
|
|
|
pika_progress_update (1.0);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
g_clear_object (&source1_buffer);
|
|
|
|
g_clear_object (&source2_buffer);
|
|
|
|
g_clear_object (&depthMap1_buffer);
|
|
|
|
g_clear_object (&depthMap2_buffer);
|
|
|
|
g_clear_object (&result_buffer);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
pika_drawable_merge_shadow (resultDrawable, TRUE);
|
|
|
|
pika_drawable_update (resultDrawable,
|
2023-09-26 00:35:21 +02:00
|
|
|
dm->selectionX, dm->selectionY,
|
|
|
|
dm->selectionWidth, dm->selectionHeight);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-10-30 23:55:30 +01:00
|
|
|
DepthMerge_executeRegion (PikaProcedureConfig *config,
|
|
|
|
guchar *source1Row,
|
|
|
|
guchar *source2Row,
|
|
|
|
guchar *depthMap1Row,
|
|
|
|
guchar *depthMap2Row,
|
|
|
|
guchar *resultRow,
|
|
|
|
gint length,
|
|
|
|
gfloat overlap,
|
|
|
|
gfloat offset,
|
|
|
|
gfloat scale1,
|
|
|
|
gfloat scale2)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
gfloat offset255, invOverlap255;
|
2023-09-26 00:35:21 +02:00
|
|
|
gfloat frac, depth1, depth2;
|
|
|
|
gushort c1[4], c2[4];
|
|
|
|
gushort cR1[4] = { 0, 0, 0, 0 }, cR2[4] = { 0, 0, 0, 0 };
|
|
|
|
gushort cR[4], temp;
|
|
|
|
gint i, tempInt;
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
invOverlap255 = 1.0 / (MAX (overlap, 0.001) * 255);
|
|
|
|
offset255 = offset * 255;
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
{
|
|
|
|
depth1 = (gfloat) depthMap1Row[i];
|
|
|
|
depth2 = (gfloat) depthMap2Row[i];
|
|
|
|
|
|
|
|
frac = (depth2 * scale2 - (depth1 * scale1 + offset255)) * invOverlap255;
|
|
|
|
frac = 0.5 * (frac + 1.0);
|
|
|
|
frac = CLAMP(frac, 0.0, 1.0);
|
|
|
|
|
|
|
|
/* c1 -> color corresponding to source1 */
|
|
|
|
c1[0] = source1Row[4 * i ];
|
|
|
|
c1[1] = source1Row[4 * i + 1];
|
|
|
|
c1[2] = source1Row[4 * i + 2];
|
|
|
|
c1[3] = source1Row[4 * i + 3];
|
|
|
|
|
|
|
|
/* c2 -> color corresponding to source2 */
|
|
|
|
c2[0] = source2Row[4 * i ];
|
|
|
|
c2[1] = source2Row[4 * i + 1];
|
|
|
|
c2[2] = source2Row[4 * i + 2];
|
|
|
|
c2[3] = source2Row[4 * i + 3];
|
|
|
|
|
|
|
|
if (frac != 0)
|
|
|
|
{
|
|
|
|
/* cR1 -> result if c1 is completely on top */
|
|
|
|
cR1[0] = c1[3] * c1[0] + (255 - c1[3]) * c2[0];
|
|
|
|
cR1[1] = c1[3] * c1[1] + (255 - c1[3]) * c2[1];
|
|
|
|
cR1[2] = c1[3] * c1[2] + (255 - c1[3]) * c2[2];
|
|
|
|
cR1[3] = MUL255 (c1[3]) + (255 - c1[3]) * c2[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frac != 1)
|
|
|
|
{
|
|
|
|
/* cR2 -> result if c2 is completely on top */
|
|
|
|
cR2[0] = c2[3] * c2[0] + (255 - c2[3]) * c1[0];
|
|
|
|
cR2[1] = c2[3] * c2[1] + (255 - c2[3]) * c1[1];
|
|
|
|
cR2[2] = c2[3] * c2[2] + (255 - c2[3]) * c1[2];
|
|
|
|
cR2[3] = MUL255 (c2[3]) + (255 - c2[3]) * c1[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frac == 1)
|
|
|
|
{
|
|
|
|
cR[0] = cR1[0];
|
|
|
|
cR[1] = cR1[1];
|
|
|
|
cR[2] = cR1[2];
|
|
|
|
cR[3] = cR1[3];
|
|
|
|
}
|
|
|
|
else if (frac == 0)
|
|
|
|
{
|
|
|
|
cR[0] = cR2[0];
|
|
|
|
cR[1] = cR2[1];
|
|
|
|
cR[2] = cR2[2];
|
|
|
|
cR[3] = cR2[3];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tempInt = LERP (frac, cR2[0], cR1[0]);
|
|
|
|
cR[0] = CLAMP (tempInt,0,255 * 255);
|
|
|
|
tempInt = LERP (frac, cR2[1], cR1[1]);
|
|
|
|
cR[1] = CLAMP (tempInt,0,255 * 255);
|
|
|
|
tempInt = LERP (frac, cR2[2], cR1[2]);
|
|
|
|
cR[2] = CLAMP (tempInt,0,255 * 255);
|
|
|
|
tempInt = LERP (frac, cR2[3], cR1[3]);
|
|
|
|
cR[3] = CLAMP (tempInt,0,255 * 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
temp = DIV255 (cR[0]); resultRow[4 * i ] = MIN (temp, 255);
|
|
|
|
temp = DIV255 (cR[1]); resultRow[4 * i + 1] = MIN (temp, 255);
|
|
|
|
temp = DIV255 (cR[2]); resultRow[4 * i + 2] = MIN (temp, 255);
|
|
|
|
temp = DIV255 (cR[3]); resultRow[4 * i + 3] = MIN (temp, 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2023-10-30 23:55:30 +01:00
|
|
|
DepthMerge_dialog (Merge *merge,
|
|
|
|
PikaProcedure *procedure,
|
|
|
|
PikaProcedureConfig *config)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
|
|
|
GtkWidget *dialog;
|
|
|
|
gboolean run;
|
|
|
|
|
|
|
|
pika_ui_init (PLUG_IN_BINARY);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
dialog = pika_procedure_dialog_new (procedure,
|
|
|
|
PIKA_PROCEDURE_CONFIG (config),
|
|
|
|
_("Depth Merge"));
|
|
|
|
/* Preview */
|
|
|
|
merge->previewWidth = MIN (merge->selectionWidth, PREVIEW_SIZE);
|
|
|
|
merge->previewHeight = MIN (merge->selectionHeight, PREVIEW_SIZE);
|
|
|
|
merge->preview = pika_preview_area_new ();
|
|
|
|
DepthMerge_buildPreviewSourceImage (merge, config);
|
|
|
|
g_signal_connect (merge->preview, "size-allocate",
|
|
|
|
G_CALLBACK (merge_preview_size_allocate),
|
|
|
|
merge);
|
|
|
|
gtk_widget_set_size_request (merge->preview,
|
|
|
|
merge->previewWidth,
|
|
|
|
merge->previewHeight);
|
|
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
|
|
|
merge->preview, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (merge->preview);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
g_signal_connect (config, "notify",
|
|
|
|
G_CALLBACK (merge_preview_config_notify),
|
|
|
|
merge);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), NULL);
|
|
|
|
run = pika_procedure_dialog_run (PIKA_PROCEDURE_DIALOG (dialog));
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
gtk_widget_destroy (dialog);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
|
|
|
return run;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-10-30 23:55:30 +01:00
|
|
|
DepthMerge_buildPreviewSourceImage (Merge *dm,
|
|
|
|
PikaProcedureConfig *config)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
2023-10-30 23:55:30 +01:00
|
|
|
PikaDrawable *source1Drawable;
|
|
|
|
PikaDrawable *source2Drawable;
|
|
|
|
PikaDrawable *depthMap1Drawable;
|
|
|
|
PikaDrawable *depthMap2Drawable;
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"source-1", &source1Drawable,
|
|
|
|
"source-2", &source2Drawable,
|
|
|
|
"depth-map-1", &depthMap1Drawable,
|
|
|
|
"depth-map-2", &depthMap2Drawable,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
dm->previewSource1 = g_new (guchar, dm->previewWidth * dm->previewHeight * 4);
|
|
|
|
util_fillReducedBuffer (dm->previewSource1,
|
2023-09-26 00:35:21 +02:00
|
|
|
babl_format ("R'G'B'A u8"),
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewWidth,
|
|
|
|
dm->previewHeight,
|
|
|
|
source1Drawable,
|
2023-09-26 00:35:21 +02:00
|
|
|
dm->selectionX, dm->selectionY,
|
|
|
|
dm->selectionWidth, dm->selectionHeight);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewSource2 = g_new (guchar, dm->previewWidth * dm->previewHeight * 4);
|
|
|
|
util_fillReducedBuffer (dm->previewSource2,
|
2023-09-26 00:35:21 +02:00
|
|
|
babl_format ("R'G'B'A u8"),
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewWidth,
|
|
|
|
dm->previewHeight,
|
|
|
|
source2Drawable,
|
2023-09-26 00:35:21 +02:00
|
|
|
dm->selectionX, dm->selectionY,
|
|
|
|
dm->selectionWidth, dm->selectionHeight);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewDepthMap1 = g_new (guchar, dm->previewWidth * dm->previewHeight * 1);
|
|
|
|
util_fillReducedBuffer (dm->previewDepthMap1,
|
2023-09-26 00:35:21 +02:00
|
|
|
babl_format ("Y' u8"),
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewWidth,
|
|
|
|
dm->previewHeight,
|
|
|
|
depthMap1Drawable,
|
2023-09-26 00:35:21 +02:00
|
|
|
dm->selectionX, dm->selectionY,
|
|
|
|
dm->selectionWidth, dm->selectionHeight);
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewDepthMap2 = g_new (guchar, dm->previewWidth * dm->previewHeight * 1);
|
|
|
|
util_fillReducedBuffer (dm->previewDepthMap2,
|
2023-09-26 00:35:21 +02:00
|
|
|
babl_format ("Y' u8"),
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewWidth,
|
|
|
|
dm->previewHeight,
|
|
|
|
depthMap2Drawable,
|
2023-09-26 00:35:21 +02:00
|
|
|
dm->selectionX, dm->selectionY,
|
|
|
|
dm->selectionWidth, dm->selectionHeight);
|
2023-10-30 23:55:30 +01:00
|
|
|
|
|
|
|
g_clear_object (&source1Drawable);
|
|
|
|
g_clear_object (&source2Drawable);
|
|
|
|
g_clear_object (&depthMap1Drawable);
|
|
|
|
g_clear_object (&depthMap2Drawable);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-10-30 23:55:30 +01:00
|
|
|
DepthMerge_updatePreview (Merge *dm,
|
|
|
|
PikaProcedureConfig *config)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
|
|
|
gint y;
|
|
|
|
guchar *source1Row, *source2Row;
|
|
|
|
guchar *depthMap1Row, *depthMap2Row;
|
|
|
|
guchar *resultRGBA;
|
2023-10-30 23:55:30 +01:00
|
|
|
gdouble overlap = 0.0;
|
|
|
|
gdouble offset = 0.0;
|
|
|
|
gdouble scale1 = 0.0;
|
|
|
|
gdouble scale2 = 0.0;
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"overlap", &overlap,
|
|
|
|
"offset", &offset,
|
|
|
|
"scale-1", &scale1,
|
|
|
|
"scale-2", &scale2,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
resultRGBA = g_new (guchar, 4 * dm->previewWidth *
|
|
|
|
dm->previewHeight);
|
|
|
|
|
|
|
|
for (y = 0; y < dm->previewHeight; y++)
|
2023-09-26 00:35:21 +02:00
|
|
|
{
|
|
|
|
source1Row =
|
2023-10-30 23:55:30 +01:00
|
|
|
&(dm->previewSource1[ y * dm->previewWidth * 4]);
|
2023-09-26 00:35:21 +02:00
|
|
|
source2Row =
|
2023-10-30 23:55:30 +01:00
|
|
|
&(dm->previewSource2[ y * dm->previewWidth * 4]);
|
2023-09-26 00:35:21 +02:00
|
|
|
depthMap1Row =
|
2023-10-30 23:55:30 +01:00
|
|
|
&(dm->previewDepthMap1[y * dm->previewWidth ]);
|
2023-09-26 00:35:21 +02:00
|
|
|
depthMap2Row =
|
2023-10-30 23:55:30 +01:00
|
|
|
&(dm->previewDepthMap2[y * dm->previewWidth ]);
|
2023-09-26 00:35:21 +02:00
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
DepthMerge_executeRegion (config,
|
|
|
|
source1Row, source2Row, depthMap1Row, depthMap2Row,
|
|
|
|
resultRGBA + 4 * y * dm->previewWidth,
|
|
|
|
dm->previewWidth, overlap, offset, scale1, scale2);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
2023-10-30 23:55:30 +01:00
|
|
|
pika_preview_area_draw (PIKA_PREVIEW_AREA (dm->preview),
|
2023-09-26 00:35:21 +02:00
|
|
|
0, 0,
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewWidth,
|
|
|
|
dm->previewHeight,
|
2023-09-26 00:35:21 +02:00
|
|
|
PIKA_RGBA_IMAGE,
|
|
|
|
resultRGBA,
|
2023-10-30 23:55:30 +01:00
|
|
|
dm->previewWidth * 4);
|
|
|
|
gtk_widget_show (dm->preview);
|
|
|
|
g_free (resultRGBA);
|
2023-09-26 00:35:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----- Utility routines ----- */
|
|
|
|
|
|
|
|
static void
|
|
|
|
util_fillReducedBuffer (guchar *dest,
|
|
|
|
const Babl *dest_format,
|
|
|
|
gint destWidth,
|
|
|
|
gint destHeight,
|
|
|
|
PikaDrawable *sourceDrawable,
|
|
|
|
gint x0,
|
|
|
|
gint y0,
|
|
|
|
gint sourceWidth,
|
|
|
|
gint sourceHeight)
|
|
|
|
{
|
|
|
|
GeglBuffer *buffer;
|
|
|
|
guchar *sourceBuffer, *reducedRowBuffer;
|
|
|
|
guchar *sourceBufferPos, *reducedRowBufferPos;
|
|
|
|
guchar *sourceBufferRow;
|
|
|
|
gint x, y, i, yPrime;
|
|
|
|
gint destBPP;
|
|
|
|
gint *sourceRowOffsetLookup;
|
|
|
|
|
|
|
|
destBPP = babl_format_get_bytes_per_pixel (dest_format);
|
|
|
|
|
|
|
|
if (! sourceDrawable || (sourceWidth == 0) || (sourceHeight == 0))
|
|
|
|
{
|
|
|
|
for (x = 0; x < destWidth * destHeight * destBPP; x++)
|
|
|
|
dest[x] = 0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceBuffer = g_new (guchar, sourceWidth * sourceHeight * destBPP);
|
|
|
|
reducedRowBuffer = g_new (guchar, destWidth * destBPP);
|
|
|
|
sourceRowOffsetLookup = g_new (int, destWidth);
|
|
|
|
|
|
|
|
buffer = pika_drawable_get_buffer (sourceDrawable);
|
|
|
|
|
|
|
|
for (x = 0; x < destWidth; x++)
|
|
|
|
sourceRowOffsetLookup[x] = (x * (sourceWidth - 1) / (destWidth - 1)) * destBPP;
|
|
|
|
|
|
|
|
gegl_buffer_get (buffer,
|
|
|
|
GEGL_RECTANGLE (x0, y0, sourceWidth, sourceHeight), 1.0,
|
|
|
|
dest_format, sourceBuffer,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
|
|
|
|
|
|
for (y = 0; y < destHeight; y++)
|
|
|
|
{
|
|
|
|
yPrime = y * (sourceHeight - 1) / (destHeight - 1);
|
|
|
|
sourceBufferRow = &(sourceBuffer[yPrime * sourceWidth * destBPP]);
|
|
|
|
reducedRowBufferPos = reducedRowBuffer;
|
|
|
|
|
|
|
|
for (x = 0; x < destWidth; x++)
|
|
|
|
{
|
|
|
|
sourceBufferPos = sourceBufferRow + sourceRowOffsetLookup[x];
|
|
|
|
for (i = 0; i < destBPP; i++)
|
|
|
|
reducedRowBufferPos[i] = sourceBufferPos[i];
|
|
|
|
reducedRowBufferPos += destBPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy (&(dest[y * destWidth * destBPP]), reducedRowBuffer,
|
|
|
|
destWidth * destBPP);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (buffer);
|
|
|
|
|
|
|
|
g_free (sourceBuffer);
|
|
|
|
g_free (reducedRowBuffer);
|
|
|
|
g_free (sourceRowOffsetLookup);
|
|
|
|
}
|
2023-10-30 23:55:30 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* Signal handlers */
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_preview_size_allocate (GtkWidget *widget,
|
|
|
|
GtkAllocation *allocation,
|
|
|
|
Merge *dm)
|
|
|
|
{
|
|
|
|
DepthMerge_updatePreview (dm, dm->config);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_preview_config_notify (PikaProcedureConfig *config,
|
|
|
|
const GParamSpec *pspec,
|
|
|
|
Merge *dm)
|
|
|
|
{
|
|
|
|
PikaDrawable *drawable = NULL;
|
|
|
|
guchar *dest = NULL;
|
|
|
|
const Babl *format = NULL;
|
|
|
|
|
|
|
|
if (g_strcmp0 (pspec->name, "source-1") == 0)
|
|
|
|
{
|
|
|
|
g_object_get (config, "source-1", &drawable, NULL);
|
|
|
|
dest = dm->previewSource1;
|
|
|
|
format = babl_format ("R'G'B'A u8");
|
|
|
|
}
|
|
|
|
else if (g_strcmp0 (pspec->name, "source-2") == 0)
|
|
|
|
{
|
|
|
|
g_object_get (config, "source-2", &drawable, NULL);
|
|
|
|
dest = dm->previewSource2;
|
|
|
|
format = babl_format ("R'G'B'A u8");
|
|
|
|
}
|
|
|
|
else if (g_strcmp0 (pspec->name, "depth-map-1") == 0)
|
|
|
|
{
|
|
|
|
g_object_get (config, "depth-map-1", &drawable, NULL);
|
|
|
|
dest = dm->previewDepthMap1,
|
|
|
|
format = babl_format ("Y' u8");
|
|
|
|
}
|
|
|
|
else if (g_strcmp0 (pspec->name, "depth-map-2") == 0)
|
|
|
|
{
|
|
|
|
g_object_get (config, "depth-map-2", &drawable, NULL);
|
|
|
|
dest = dm->previewDepthMap2,
|
|
|
|
format = babl_format ("Y' u8");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawable != NULL)
|
|
|
|
util_fillReducedBuffer (dest, format,
|
|
|
|
dm->previewWidth,
|
|
|
|
dm->previewHeight,
|
|
|
|
drawable,
|
|
|
|
dm->selectionX, dm->selectionY,
|
|
|
|
dm->selectionWidth, dm->selectionHeight);
|
|
|
|
g_clear_object (&drawable);
|
|
|
|
|
|
|
|
DepthMerge_updatePreview (dm, dm->config);
|
|
|
|
}
|