| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  | typedef struct _Merge      Merge; | 
					
						
							|  |  |  | typedef struct _MergeClass MergeClass; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  | struct _Merge | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   PikaPlugIn parent_instance; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   gint       selectionX; | 
					
						
							|  |  |  |   gint       selectionY; | 
					
						
							|  |  |  |   gint       selectionWidth; | 
					
						
							|  |  |  |   gint       selectionHeight; | 
					
						
							|  |  |  |   gint       resultHasAlpha; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   GtkWidget *preview; | 
					
						
							|  |  |  |   gint       previewWidth; | 
					
						
							|  |  |  |   gint       previewHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   guchar    *previewSource1; | 
					
						
							|  |  |  |   guchar    *previewSource2; | 
					
						
							|  |  |  |   guchar    *previewDepthMap1; | 
					
						
							|  |  |  |   guchar    *previewDepthMap2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   PikaProcedureConfig *config; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _MergeClass | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PikaPlugInClass parent_class; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |   GObjectClass    *object_class  = G_OBJECT_CLASS (klass); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |   PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   object_class->finalize          = merge_finalize; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07: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-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |                         const gchar *name) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |                               _("Source _1"), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                               "Source 1", | 
					
						
							|  |  |  |                               TRUE, | 
					
						
							|  |  |  |                               G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       PIKA_PROC_ARG_DRAWABLE (procedure, "depth-map-1", | 
					
						
							|  |  |  |                               _("_Depth map 1"), | 
					
						
							|  |  |  |                               "Depth map 1", | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                               TRUE, | 
					
						
							|  |  |  |                               G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       PIKA_PROC_ARG_DRAWABLE (procedure, "source-2", | 
					
						
							|  |  |  |                               _("Source _2"), | 
					
						
							|  |  |  |                               "Source 2", | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                               TRUE, | 
					
						
							|  |  |  |                               G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       PIKA_PROC_ARG_DRAWABLE (procedure, "depth-map-2", | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                               _("Depth _map 2"), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                               "Depth map 2", | 
					
						
							|  |  |  |                               TRUE, | 
					
						
							|  |  |  |                               G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       PIKA_PROC_ARG_DOUBLE (procedure, "overlap", | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                             _("O_verlap"), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                             "Overlap", | 
					
						
							|  |  |  |                             0, 2, 0, | 
					
						
							|  |  |  |                             G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       PIKA_PROC_ARG_DOUBLE (procedure, "offset", | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                             _("O_ffset"), | 
					
						
							|  |  |  |                             _("Depth relative offset"), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                             -1, 1, 0, | 
					
						
							|  |  |  |                             G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       PIKA_PROC_ARG_DOUBLE (procedure, "scale-1", | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                             _("Sc_ale 1"), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                             "Depth relative scale 1", | 
					
						
							|  |  |  |                             -1, 1, 1, | 
					
						
							|  |  |  |                             G_PARAM_READWRITE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       PIKA_PROC_ARG_DOUBLE (procedure, "scale-2", | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                             _("Scal_e 2"), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |            PikaProcedureConfig  *config, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |            gpointer              run_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PikaDrawable *drawable; | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   Merge        *merge = MERGE (pika_procedure_get_plug_in (procedure)); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ----- DepthMerge ----- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gint32 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  | DepthMerge_execute (Merge               *dm, | 
					
						
							|  |  |  |                     PikaDrawable        *resultDrawable, | 
					
						
							|  |  |  |                     PikaProcedureConfig *config) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | { | 
					
						
							|  |  |  |   int           x, y; | 
					
						
							|  |  |  |   GeglBuffer   *source1_buffer   = NULL; | 
					
						
							|  |  |  |   GeglBuffer   *source2_buffer   = NULL; | 
					
						
							|  |  |  |   GeglBuffer   *depthMap1_buffer = NULL; | 
					
						
							|  |  |  |   GeglBuffer   *depthMap2_buffer = NULL; | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   GeglBuffer   *result_buffer    = NULL; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |   guchar       *source1Row,   *source2Row; | 
					
						
							|  |  |  |   guchar       *depthMap1Row, *depthMap2Row; | 
					
						
							|  |  |  |   guchar       *resultRow; | 
					
						
							|  |  |  |   guchar       *tempRow; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  |   pika_progress_init (_("Depth-merging")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |   if (source1Drawable) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       source1_buffer = pika_drawable_get_buffer (source1Drawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |   if (source2Drawable) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       source2_buffer = pika_drawable_get_buffer (source2Drawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |   if (depthMap1Drawable) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       depthMap1_buffer = pika_drawable_get_buffer (depthMap1Drawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (x = 0; x < dm->selectionWidth; x++) | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |         depthMap1Row[x] = 0; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   if (depthMap2Drawable) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       depthMap2_buffer = pika_drawable_get_buffer (depthMap2Drawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (x = 0; x < dm->selectionWidth; x++) | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |         depthMap2Row[x] = 0; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   result_buffer = pika_drawable_get_shadow_buffer (resultDrawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (y = dm->selectionY; y < (dm->selectionY + dm->selectionHeight); y++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  |                                 source1Row, source2Row, depthMap1Row, depthMap2Row, | 
					
						
							|  |  |  |                                 resultRow, | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                                 dm->selectionWidth, overlap, offset, scale1, scale2); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |   g_clear_object (&source1Drawable); | 
					
						
							|  |  |  |   g_clear_object (&source2Drawable); | 
					
						
							|  |  |  |   g_clear_object (&depthMap1Drawable); | 
					
						
							|  |  |  |   g_clear_object (&depthMap2Drawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   pika_drawable_merge_shadow (resultDrawable, TRUE); | 
					
						
							|  |  |  |   pika_drawable_update (resultDrawable, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                         dm->selectionX, dm->selectionY, | 
					
						
							|  |  |  |                         dm->selectionWidth, dm->selectionHeight); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   gfloat  offset255, invOverlap255; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  |   invOverlap255 = 1.0 / (MAX (overlap, 0.001) * 255); | 
					
						
							|  |  |  |   offset255     = offset * 255; | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07:00
										 |  |  | DepthMerge_dialog (Merge               *merge, | 
					
						
							|  |  |  |                    PikaProcedure       *procedure, | 
					
						
							|  |  |  |                    PikaProcedureConfig *config) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | { | 
					
						
							|  |  |  |   GtkWidget *dialog; | 
					
						
							|  |  |  |   gboolean   run; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pika_ui_init (PLUG_IN_BINARY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   g_signal_connect (config, "notify", | 
					
						
							|  |  |  |                     G_CALLBACK (merge_preview_config_notify), | 
					
						
							|  |  |  |                     merge); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), NULL); | 
					
						
							|  |  |  |   run = pika_procedure_dialog_run (PIKA_PROCEDURE_DIALOG (dialog)); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   gtk_widget_destroy (dialog); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return run; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  | DepthMerge_buildPreviewSourceImage (Merge               *dm, | 
					
						
							|  |  |  |                                     PikaProcedureConfig *config) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  |                           babl_format ("R'G'B'A u8"), | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                           dm->previewWidth, | 
					
						
							|  |  |  |                           dm->previewHeight, | 
					
						
							|  |  |  |                           source1Drawable, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           dm->selectionX, dm->selectionY, | 
					
						
							|  |  |  |                           dm->selectionWidth, dm->selectionHeight); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   dm->previewSource2 = g_new (guchar, dm->previewWidth * dm->previewHeight * 4); | 
					
						
							|  |  |  |   util_fillReducedBuffer (dm->previewSource2, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           babl_format ("R'G'B'A u8"), | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                           dm->previewWidth, | 
					
						
							|  |  |  |                           dm->previewHeight, | 
					
						
							|  |  |  |                           source2Drawable, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           dm->selectionX, dm->selectionY, | 
					
						
							|  |  |  |                           dm->selectionWidth, dm->selectionHeight); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   dm->previewDepthMap1 = g_new (guchar, dm->previewWidth * dm->previewHeight * 1); | 
					
						
							|  |  |  |   util_fillReducedBuffer (dm->previewDepthMap1, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           babl_format ("Y' u8"), | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                           dm->previewWidth, | 
					
						
							|  |  |  |                           dm->previewHeight, | 
					
						
							|  |  |  |                           depthMap1Drawable, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           dm->selectionX, dm->selectionY, | 
					
						
							|  |  |  |                           dm->selectionWidth, dm->selectionHeight); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   dm->previewDepthMap2 = g_new (guchar, dm->previewWidth * dm->previewHeight * 1); | 
					
						
							|  |  |  |   util_fillReducedBuffer (dm->previewDepthMap2, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           babl_format ("Y' u8"), | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                           dm->previewWidth, | 
					
						
							|  |  |  |                           dm->previewHeight, | 
					
						
							|  |  |  |                           depthMap2Drawable, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           dm->selectionX, dm->selectionY, | 
					
						
							|  |  |  |                           dm->selectionWidth, dm->selectionHeight); | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   g_clear_object (&source1Drawable); | 
					
						
							|  |  |  |   g_clear_object (&source2Drawable); | 
					
						
							|  |  |  |   g_clear_object (&depthMap1Drawable); | 
					
						
							|  |  |  |   g_clear_object (&depthMap2Drawable); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  | DepthMerge_updatePreview (Merge               *dm, | 
					
						
							|  |  |  |                           PikaProcedureConfig *config) | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | { | 
					
						
							|  |  |  |   gint    y; | 
					
						
							|  |  |  |   guchar *source1Row, *source2Row; | 
					
						
							|  |  |  |   guchar *depthMap1Row, *depthMap2Row; | 
					
						
							|  |  |  |   guchar *resultRGBA; | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07: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-25 15:35:21 -07:00
										 |  |  |     { | 
					
						
							|  |  |  |       source1Row = | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |         &(dm->previewSource1[  y * dm->previewWidth * 4]); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |       source2Row = | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |         &(dm->previewSource2[  y * dm->previewWidth * 4]); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |       depthMap1Row = | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |         &(dm->previewDepthMap1[y * dm->previewWidth    ]); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |       depthMap2Row = | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |         &(dm->previewDepthMap2[y * dm->previewWidth    ]); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |       DepthMerge_executeRegion (config, | 
					
						
							|  |  |  |                                 source1Row, source2Row, depthMap1Row, depthMap2Row, | 
					
						
							|  |  |  |                                 resultRGBA + 4 * y * dm->previewWidth, | 
					
						
							|  |  |  |                                 dm->previewWidth, overlap, offset, scale1, scale2); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |   pika_preview_area_draw (PIKA_PREVIEW_AREA (dm->preview), | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           0, 0, | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                           dm->previewWidth, | 
					
						
							|  |  |  |                           dm->previewHeight, | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07:00
										 |  |  |                           PIKA_RGBA_IMAGE, | 
					
						
							|  |  |  |                           resultRGBA, | 
					
						
							| 
									
										
										
										
											2023-10-30 15:55:30 -07:00
										 |  |  |                           dm->previewWidth * 4); | 
					
						
							|  |  |  |   gtk_widget_show (dm->preview); | 
					
						
							|  |  |  |   g_free (resultRGBA); | 
					
						
							| 
									
										
										
										
											2023-09-25 15:35:21 -07: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 15:55:30 -07: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); | 
					
						
							|  |  |  | } |