Blame operations/workshop/hstack.c

Packit bc1512
/* This file is an image processing operation for GEGL
Packit bc1512
 *
Packit bc1512
 * GEGL is free software; you can redistribute it and/or
Packit bc1512
 * modify it under the terms of the GNU Lesser General Public
Packit bc1512
 * License as published by the Free Software Foundation; either
Packit bc1512
 * version 3 of the License, or (at your option) any later version.
Packit bc1512
 *
Packit bc1512
 * GEGL is distributed in the hope that it will be useful,
Packit bc1512
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bc1512
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bc1512
 * Lesser General Public License for more details.
Packit bc1512
 *
Packit bc1512
 * You should have received a copy of the GNU Lesser General Public
Packit bc1512
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit bc1512
 *
Packit bc1512
 * Copyright 2007 Øyvind Kolås <oeyvindk@hig.no>
Packit bc1512
 */
Packit bc1512
Packit bc1512
#include "config.h"
Packit bc1512
#include <glib/gi18n-lib.h>
Packit bc1512
Packit bc1512
Packit bc1512
#ifdef GEGL_CHANT_PROPERTIES
Packit bc1512
Packit bc1512
    /* No properties */
Packit bc1512
Packit bc1512
#else
Packit bc1512
Packit bc1512
#define GEGL_CHANT_TYPE_COMPOSER
Packit bc1512
#define GEGL_CHANT_C_FILE       "hstack.c"
Packit bc1512
Packit bc1512
#include "gegl-chant.h"
Packit bc1512
#include <math.h>
Packit bc1512
Packit bc1512
static void prepare (GeglOperation *operation)
Packit bc1512
{
Packit bc1512
  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
Packit bc1512
}
Packit bc1512
Packit bc1512
static GeglRectangle
Packit bc1512
get_bounding_box (GeglOperation *operation)
Packit bc1512
{
Packit bc1512
  GeglRectangle  result = {0,0,0,0};
Packit bc1512
  GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation,
Packit bc1512
                                                                     "input");
Packit bc1512
  GeglRectangle *aux_rect = gegl_operation_source_get_bounding_box (operation,
Packit bc1512
                                                                      "aux");
Packit bc1512
Packit bc1512
  if (!in_rect || !aux_rect)
Packit bc1512
    return result;
Packit bc1512
Packit bc1512
  result = *in_rect;
Packit bc1512
  if (result.width  != 0 &&
Packit bc1512
      result.height != 0)
Packit bc1512
    {
Packit bc1512
      result.width += aux_rect->width;
Packit bc1512
      if (aux_rect->height > result.height)
Packit bc1512
        result.height = aux_rect->height;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  return result;
Packit bc1512
}
Packit bc1512
Packit bc1512
static GeglRectangle
Packit bc1512
get_required_for_output (GeglOperation       *self,
Packit bc1512
                       const gchar         *input_pad,
Packit bc1512
                       const GeglRectangle *roi)
Packit bc1512
{
Packit bc1512
  GeglRectangle request = *roi;
Packit bc1512
Packit bc1512
  if (!strcmp (input_pad, "aux"))
Packit bc1512
    {
Packit bc1512
      GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (self,
Packit bc1512
                                                                         "input");
Packit bc1512
      GeglRectangle *aux_rect = gegl_operation_source_get_bounding_box (self,
Packit bc1512
                                                                         "aux");
Packit bc1512
Packit bc1512
      if (request.width != 0 &&
Packit bc1512
          request.height != 0)
Packit bc1512
        {
Packit bc1512
          request.x -= in_rect->width + aux_rect->x;
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
Packit bc1512
  return request;
Packit bc1512
}
Packit bc1512
Packit bc1512
static GeglRectangle
Packit bc1512
get_invalidated_by_change (GeglOperation       *self,
Packit bc1512
                           const gchar         *input_pad,
Packit bc1512
                           const GeglRectangle *region)
Packit bc1512
{
Packit bc1512
  if (!strcmp ("input_pad", "input"))
Packit bc1512
    {
Packit bc1512
      return *region;
Packit bc1512
    }
Packit bc1512
  else
Packit bc1512
    {
Packit bc1512
      /*region.x -= radius * 2;*/
Packit bc1512
    }
Packit bc1512
  return *region;
Packit bc1512
}
Packit bc1512
Packit bc1512
static gboolean
Packit bc1512
process (GeglOperation       *operation,
Packit bc1512
         GeglBuffer          *input,
Packit bc1512
         GeglBuffer          *aux,
Packit bc1512
         GeglBuffer          *output,
Packit bc1512
         const GeglRectangle *result,
Packit bc1512
         gint                 level)
Packit bc1512
{
Packit bc1512
  GeglBuffer            *temp_in;
Packit bc1512
  GeglBuffer            *temp_aux;
Packit bc1512
Packit bc1512
  /* FIXME: just pass the originals buffers if the result rectangle does not
Packit bc1512
   * include both input buffers
Packit bc1512
   */
Packit bc1512
Packit bc1512
  temp_in = gegl_buffer_create_sub_buffer (input, result);
Packit bc1512
  temp_aux = gegl_buffer_create_sub_buffer (aux, result);
Packit bc1512
Packit bc1512
    {
Packit bc1512
      gfloat *buf  = g_new0 (gfloat, result->width * result->height * 4);
Packit bc1512
      gfloat *bufB = g_new0 (gfloat, result->width * result->height * 4);
Packit bc1512
Packit bc1512
      gegl_buffer_get (temp_in,  NULL, 1.0, babl_format ("RGBA float"), buf,
Packit bc1512
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit bc1512
      gegl_buffer_get (temp_aux, NULL, 1.0, babl_format ("RGBA float"), bufB, GEGL_AUTO_ROWSTRIDE,
Packit bc1512
                       GEGL_ABYSS_NONE);
Packit bc1512
        {
Packit bc1512
          gint offset=0;
Packit bc1512
          gint x,y;
Packit bc1512
          for (y=0;y
Packit bc1512
            for (x=0;x
Packit bc1512
              {
Packit bc1512
                if (x + result->x >= gegl_buffer_get_width (input))
Packit bc1512
                  {
Packit bc1512
                    buf[offset+0]=bufB[offset+0];
Packit bc1512
                    buf[offset+1]=bufB[offset+1];
Packit bc1512
                    buf[offset+2]=bufB[offset+2];
Packit bc1512
                    buf[offset+3]=bufB[offset+3];
Packit bc1512
                  }
Packit bc1512
                offset+=4;
Packit bc1512
              }
Packit bc1512
        }
Packit bc1512
      gegl_buffer_set (output, NULL, 0, babl_format ("RGBA float"), buf,
Packit bc1512
                       GEGL_AUTO_ROWSTRIDE);
Packit bc1512
Packit bc1512
      g_free (buf);
Packit bc1512
      g_free (bufB);
Packit bc1512
    }
Packit bc1512
  g_object_unref (temp_in);
Packit bc1512
  g_object_unref (temp_aux);
Packit bc1512
Packit bc1512
  return  TRUE;
Packit bc1512
}
Packit bc1512
Packit bc1512
Packit bc1512
static void
Packit bc1512
gegl_chant_class_init (GeglChantClass *klass)
Packit bc1512
{
Packit bc1512
  GeglOperationClass         *operation_class;
Packit bc1512
  GeglOperationComposerClass *composer_class;
Packit bc1512
Packit bc1512
  operation_class = GEGL_OPERATION_CLASS (klass);
Packit bc1512
  composer_class  = GEGL_OPERATION_COMPOSER_CLASS (klass);
Packit bc1512
Packit bc1512
  composer_class->process = process;
Packit bc1512
  operation_class->prepare = prepare;
Packit bc1512
  operation_class->get_bounding_box = get_bounding_box;
Packit bc1512
  operation_class->get_invalidated_by_change = get_invalidated_by_change;
Packit bc1512
  operation_class->get_required_for_output = get_required_for_output;
Packit bc1512
Packit bc1512
  gegl_operation_class_set_keys (operation_class,
Packit bc1512
  "name"        , "gegl:hstack",
Packit bc1512
  "categories"  , "misc",
Packit bc1512
  "description" ,
Packit bc1512
        _("Horizontally stack inputs, (in \"output\" \"aux\" is placed to the right of \"input\")"),
Packit bc1512
        NULL);
Packit bc1512
}
Packit bc1512
Packit bc1512
#endif