Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gimp/plug-ins/common/   (Gimp Bildeditor Version 3.2.0©)  Datei vom 14.2.2026 mit Größe 31 kB image not shown  

Quelle  depth-merge.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * 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 <libgimp/gimp.h>
#include <libgimp/gimpui.h>

#include "libgimp/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    "gimp-depth-merge"

#define PREVIEW_SIZE    256


typedef struct _Merge      Merge;
typedef struct _MergeClass MergeClass;

struct _Merge
{
  GimpPlugIn parent_instance;

  gint       selectionX;
  gint       selectionY;
  gint       selectionWidth;
  gint       selectionHeight;
  gint       resultHasAlpha;

  GtkWidget *preview;
  gint       previewWidth;
  gint       previewHeight;

  guchar    *previewSource1;
  guchar    *previewSource2;
  guchar    *previewDepthMap1;
  guchar    *previewDepthMap2;

  GimpProcedureConfig *config;
};

struct _MergeClass
{
  GimpPlugInClass parent_class;
};


#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             (GimpPlugIn           *plug_in);
static GimpProcedure  * merge_create_procedure             (GimpPlugIn           *plug_in,
                                                           const gchar          *name);

static GimpValueArray * merge_run                          (GimpProcedure        *procedure,
                                                            GimpRunMode           run_mode,
                                                            GimpImage            *image,
                                                            GimpDrawable        **drawables,
                                                            GimpProcedureConfig  *config,
                                                            gpointer              run_data);

static gint32           DepthMerge_execute                 (Merge                *dm,
                                                            GimpDrawable         *resultDrawable,
                                                            GimpProcedureConfig  *config);
static void             DepthMerge_executeRegion           (GimpProcedureConfig  *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,
                                                            GimpProcedure        *procedure,
                                                            GimpProcedureConfig  *config);
static void             DepthMerge_buildPreviewSourceImage (Merge                *dm,
                                                            GimpProcedureConfig  *config);
static void             DepthMerge_updatePreview           (Merge                *dm,
                                                            GimpProcedureConfig  *config);


static void             util_fillReducedBuffer             (guchar               *dest,
                                                            const Babl           *dest_format,
                                                            gint                  destWidth,
                                                            gint                  destHeight,
                                                            GimpDrawable         *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       (GimpProcedureConfig  *config,
                                                            const GParamSpec     *pspec,
                                                            Merge                *dm);


G_DEFINE_TYPE (Merge, merge, GIMP_TYPE_PLUG_IN)

GIMP_MAIN (MERGE_TYPE)
DEFINE_STD_SET_I18N


static void
merge_class_init (MergeClass *klass)
{
  GObjectClass    *object_class  = G_OBJECT_CLASS (klass);
  GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);

  object_class->finalize          = merge_finalize;

  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)
{
  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);
}

static GList *
merge_query_procedures (GimpPlugIn *plug_in)
{
  return g_list_append (NULL, g_strdup (PLUG_IN_PROC));
}

static GimpProcedure *
merge_create_procedure (GimpPlugIn  *plug_in,
                        const gchar *name)
{
  GimpProcedure *procedure = NULL;

  if (! strcmp (name, PLUG_IN_PROC))
    {
      procedure = gimp_image_procedure_new (plug_in, name,
                                            GIMP_PDB_PROC_TYPE_PLUGIN,
                                            merge_run, NULL, NULL);

      gimp_procedure_set_image_types (procedure, "RGB*, GRAY*");
      gimp_procedure_set_sensitivity_mask (procedure,
                                           GIMP_PROCEDURE_SENSITIVE_DRAWABLE);

      gimp_procedure_set_menu_label (procedure, _("_Depth Merge..."));
      gimp_procedure_add_menu_path (procedure, "<Image>/Filters/Combine");

      gimp_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);
      gimp_procedure_set_attribution (procedure,
                                      "Sean Cier",
                                      "Sean Cier",
                                      PLUG_IN_VERSION);

      gimp_procedure_add_drawable_argument (procedure, "source-1",
                                            _("Source _1"),
                                            _("Source 1"),
                                            TRUE,
                                            G_PARAM_READWRITE);

      gimp_procedure_add_drawable_argument (procedure, "depth-map-1",
                                            _("_Depth map 1"),
                                            _("Depth map 1"),
                                            TRUE,
                                            G_PARAM_READWRITE);

      gimp_procedure_add_drawable_argument (procedure, "source-2",
                                            _("Source _2"),
                                            _("Source 2"),
                                            TRUE,
                                            G_PARAM_READWRITE);

      gimp_procedure_add_drawable_argument (procedure, "depth-map-2",
                                            _("Depth _map 2"),
                                            _("Depth map 2"),
                                            TRUE,
                                            G_PARAM_READWRITE);

      gimp_procedure_add_double_argument (procedure, "overlap",
                                          _("O_verlap"),
                                          _("Overlap"),
                                          0, 2, 0,
                                          G_PARAM_READWRITE);

      gimp_procedure_add_double_argument (procedure, "offset",
                                          _("O_ffset"),
                                          _("Depth relative offset"),
                                          -1, 1, 0,
                                          G_PARAM_READWRITE);

      gimp_procedure_add_double_argument (procedure, "scale-1",
                                          _("Sc_ale 1"),
                                          _("Depth relative scale 1"),
                                          -1, 1, 1,
                                          G_PARAM_READWRITE);

      gimp_procedure_add_double_argument (procedure, "scale-2",
                                          _("Scal_e 2"),
                                          _("Depth relative scale 2"),
                                          -1, 1, 1,
                                          G_PARAM_READWRITE);
    }

  return procedure;
}

static GimpValueArray *
merge_run (GimpProcedure        *procedure,
           GimpRunMode           run_mode,
           GimpImage            *image,
           GimpDrawable        **drawables,
           GimpProcedureConfig  *config,
           gpointer              run_data)
{
  GimpDrawable *drawable;
  Merge        *merge = MERGE (gimp_procedure_get_plug_in (procedure));

  gegl_init (NULL, NULL);

  if (gimp_core_object_array_get_length ((GObject **) drawables) != 1)
    {
      GError *error = NULL;

      g_set_error (&error, GIMP_PLUG_IN_ERROR, 0,
                   _("Procedure '%s' only works with one drawable."),
                   PLUG_IN_PROC);

      return gimp_procedure_new_return_values (procedure,
                                               GIMP_PDB_CALLING_ERROR,
                                               error);
    }
  else
    {
      drawable = drawables[0];
    }

  merge->config = config;
  if (! gimp_drawable_mask_intersect (drawable,
                                      &(merge->selectionX), &(merge->selectionY),
                                      &(merge->selectionWidth),
                                      &(merge->selectionHeight)))
    return gimp_procedure_new_return_values (procedure,
                                             GIMP_PDB_EXECUTION_ERROR,
                                             g_error_new_literal (GIMP_PLUG_IN_ERROR, 0,
                                                                  _("The selection does not intersect with the input drawable.")));

  if (run_mode == GIMP_RUN_INTERACTIVE)
    {
      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 gimp_procedure_new_return_values (procedure,
                                                 GIMP_PDB_CANCEL,
                                                 NULL);
    }

  if (! DepthMerge_execute (merge, drawable, config))
    return gimp_procedure_new_return_values (procedure,
                                             GIMP_PDB_EXECUTION_ERROR, NULL);
  else if (run_mode != GIMP_RUN_NONINTERACTIVE)
    gimp_displays_flush ();

  return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}

/* ----- DepthMerge ----- */

static gint32
DepthMerge_execute (Merge               *dm,
                    GimpDrawable        *resultDrawable,
                    GimpProcedureConfig *config)
{
  int           x, y;
  GeglBuffer   *source1_buffer   = NULL;
  GeglBuffer   *source2_buffer   = NULL;
  GeglBuffer   *depthMap1_buffer = NULL;
  GeglBuffer   *depthMap2_buffer = NULL;
  GeglBuffer   *result_buffer    = NULL;
  guchar       *source1Row,   *source2Row;
  guchar       *depthMap1Row, *depthMap2Row;
  guchar       *resultRow;
  guchar       *tempRow;

  GimpDrawable *source1Drawable = NULL;
  GimpDrawable *source2Drawable = NULL;
  GimpDrawable *depthMap1Drawable = NULL;
  GimpDrawable *depthMap2Drawable = NULL;
  gdouble       overlap = 0.0;
  gdouble       offset = 0.0;
  gdouble       scale1 = 0.0;
  gdouble       scale2 = 0.0;

  gimp_progress_init (_("Depth-merging"));

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

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

  if (source1Drawable)
    {
      source1_buffer = gimp_drawable_get_buffer (source1Drawable);
    }
  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;
        }
    }

  if (source2Drawable)
    {
      source2_buffer = gimp_drawable_get_buffer (source2Drawable);
    }
  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;
        }
    }

  if (depthMap1Drawable)
    {
      depthMap1_buffer = gimp_drawable_get_buffer (depthMap1Drawable);
    }
  else
    {
      for (x = 0; x < dm->selectionWidth; x++)
        depthMap1Row[x] = 0;
    }

  if (depthMap2Drawable)
    {
      depthMap2_buffer = gimp_drawable_get_buffer (depthMap2Drawable);
    }
  else
    {
      for (x = 0; x < dm->selectionWidth; x++)
        depthMap2Row[x] = 0;
    }

  result_buffer = gimp_drawable_get_shadow_buffer (resultDrawable);

  for (y = dm->selectionY; y < (dm->selectionY + dm->selectionHeight); y++)
    {
      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,
                                source1Row, source2Row, depthMap1Row, depthMap2Row,
                                resultRow,
                                dm->selectionWidth, overlap, offset, scale1, scale2);

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

      gimp_progress_update ((double)(y-dm->selectionY) /
                            (double)(dm->selectionHeight - 1));
    }

  g_clear_object (&source1Drawable);
  g_clear_object (&source2Drawable);
  g_clear_object (&depthMap1Drawable);
  g_clear_object (&depthMap2Drawable);
  g_free (resultRow);
  g_free (source1Row);
  g_free (source2Row);
  g_free (depthMap1Row);
  g_free (depthMap2Row);
  g_free (tempRow);

  gimp_progress_update (1.0);

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

  gimp_drawable_merge_shadow (resultDrawable, TRUE);
  gimp_drawable_update (resultDrawable,
                        dm->selectionX, dm->selectionY,
                        dm->selectionWidth, dm->selectionHeight);

  return TRUE;
}

static void
DepthMerge_executeRegion (GimpProcedureConfig *config,
                          guchar              *source1Row,
                          guchar              *source2Row,
                          guchar              *depthMap1Row,
                          guchar              *depthMap2Row,
                          guchar              *resultRow,
                          gint                 length,
                          gfloat               overlap,
                          gfloat               offset,
                          gfloat               scale1,
                          gfloat               scale2)
{
  gfloat  offset255, invOverlap255;
  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;

  invOverlap255 = 1.0 / (MAX (overlap, 0.001) * 255);
  offset255     = offset * 255;

  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
DepthMerge_dialog (Merge               *merge,
                   GimpProcedure       *procedure,
                   GimpProcedureConfig *config)
{
  GtkWidget *dialog;
  gboolean   run;

  gimp_ui_init (PLUG_IN_BINARY);

  dialog = gimp_procedure_dialog_new (procedure,
                                      GIMP_PROCEDURE_CONFIG (config),
                                      _("Depth Merge"));
  /* Preview */
  merge->previewWidth  = MIN (merge->selectionWidth,  PREVIEW_SIZE);
  merge->previewHeight = MIN (merge->selectionHeight, PREVIEW_SIZE);
  merge->preview = gimp_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);

  g_signal_connect (config, "notify",
                    G_CALLBACK (merge_preview_config_notify),
                    merge);

  gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), NULL);
  run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));

  gtk_widget_destroy (dialog);

  return run;
}

static void
DepthMerge_buildPreviewSourceImage (Merge               *dm,
                                    GimpProcedureConfig *config)
{
  GimpDrawable *source1Drawable;
  GimpDrawable *source2Drawable;
  GimpDrawable *depthMap1Drawable;
  GimpDrawable *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,
                          babl_format ("R'G'B'A u8"),
                          dm->previewWidth,
                          dm->previewHeight,
                          source1Drawable,
                          dm->selectionX, dm->selectionY,
                          dm->selectionWidth, dm->selectionHeight);

  dm->previewSource2 = g_new (guchar, dm->previewWidth * dm->previewHeight * 4);
  util_fillReducedBuffer (dm->previewSource2,
                          babl_format ("R'G'B'A u8"),
                          dm->previewWidth,
                          dm->previewHeight,
                          source2Drawable,
                          dm->selectionX, dm->selectionY,
                          dm->selectionWidth, dm->selectionHeight);

  dm->previewDepthMap1 = g_new (guchar, dm->previewWidth * dm->previewHeight * 1);
  util_fillReducedBuffer (dm->previewDepthMap1,
                          babl_format ("Y' u8"),
                          dm->previewWidth,
                          dm->previewHeight,
                          depthMap1Drawable,
                          dm->selectionX, dm->selectionY,
                          dm->selectionWidth, dm->selectionHeight);

  dm->previewDepthMap2 = g_new (guchar, dm->previewWidth * dm->previewHeight * 1);
  util_fillReducedBuffer (dm->previewDepthMap2,
                          babl_format ("Y' u8"),
                          dm->previewWidth,
                          dm->previewHeight,
                          depthMap2Drawable,
                          dm->selectionX, dm->selectionY,
                          dm->selectionWidth, dm->selectionHeight);

  g_clear_object (&source1Drawable);
  g_clear_object (&source2Drawable);
  g_clear_object (&depthMap1Drawable);
  g_clear_object (&depthMap2Drawable);
}

static void
DepthMerge_updatePreview (Merge               *dm,
                          GimpProcedureConfig *config)
{
  gint    y;
  guchar *source1Row, *source2Row;
  guchar *depthMap1Row, *depthMap2Row;
  guchar *resultRGBA;
  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++)
    {
      source1Row =
        &(dm->previewSource1[  y * dm->previewWidth * 4]);
      source2Row =
        &(dm->previewSource2[  y * dm->previewWidth * 4]);
      depthMap1Row =
        &(dm->previewDepthMap1[y * dm->previewWidth    ]);
      depthMap2Row =
        &(dm->previewDepthMap2[y * dm->previewWidth    ]);

      DepthMerge_executeRegion (config,
                                source1Row, source2Row, depthMap1Row, depthMap2Row,
                                resultRGBA + 4 * y * dm->previewWidth,
                                dm->previewWidth, overlap, offset, scale1, scale2);
    }

  gimp_preview_area_draw (GIMP_PREVIEW_AREA (dm->preview),
                          0, 0,
                          dm->previewWidth,
                          dm->previewHeight,
                          GIMP_RGBA_IMAGE,
                          resultRGBA,
                          dm->previewWidth * 4);
  gtk_widget_show (dm->preview);
  g_free (resultRGBA);
}


/* ----- Utility routines ----- */

static void
util_fillReducedBuffer (guchar       *dest,
                        const Babl   *dest_format,
                        gint          destWidth,
                        gint          destHeight,
                        GimpDrawable *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 = gimp_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);
}


/* 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 (GimpProcedureConfig *config,
                             const GParamSpec    *pspec,
                             Merge               *dm)
{
  GimpDrawable *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);
}

Messung
CHZG
829610092

¤ Dauer der Verarbeitung: 0.12 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.