Blame operations/workshop/demosaic-bimedian.c

Packit Service 2781ba
/* This file is an image processing operation for GEGL
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is free software; you can redistribute it and/or
Packit Service 2781ba
 * modify it under the terms of the GNU Lesser General Public
Packit Service 2781ba
 * License as published by the Free Software Foundation; either
Packit Service 2781ba
 * version 3 of the License, or (at your option) any later version.
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is distributed in the hope that it will be useful,
Packit Service 2781ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2781ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2781ba
 * Lesser General Public License for more details.
Packit Service 2781ba
 *
Packit Service 2781ba
 * You should have received a copy of the GNU Lesser General Public
Packit Service 2781ba
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit Service 2781ba
 *
Packit Service 2781ba
 * Copyright 2006 Øyvind Kolås <pippin@gimp.org>
Packit Service 2781ba
 * Copyright 2008 Bradley Broom <bmbroom@gmail.com>
Packit Service 2781ba
 */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
#include <glib/gi18n-lib.h>
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
#ifdef GEGL_CHANT_PROPERTIES
Packit Service 2781ba
Packit Service 2781ba
gegl_chant_int (pattern, _("Bayer pattern"), 0, 3, 0,
Packit Service 2781ba
                _("Bayer pattern used, 0 seems to work for some nikon files, 2 for some Fuji files."))
Packit Service 2781ba
Packit Service 2781ba
#else
Packit Service 2781ba
Packit Service 2781ba
#define GEGL_CHANT_TYPE_AREA_FILTER
Packit Service 2781ba
#define GEGL_CHANT_C_FILE       "demosaic-bimedian.c"
Packit Service 2781ba
Packit Service 2781ba
#include "gegl-chant.h"
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
/* Returns the median of four floats. We define the median as the average of
Packit Service 2781ba
 * the central two elements.
Packit Service 2781ba
 */
Packit Service 2781ba
static inline gfloat
Packit Service 2781ba
m4 (gfloat a, gfloat b, gfloat c, gfloat d)
Packit Service 2781ba
{
Packit Service 2781ba
  gfloat t;
Packit Service 2781ba
Packit Service 2781ba
  /* Sort ab */
Packit Service 2781ba
  if (a > b)
Packit Service 2781ba
    {
Packit Service 2781ba
      t = b;
Packit Service 2781ba
      b = a;
Packit Service 2781ba
      a = t;
Packit Service 2781ba
    }
Packit Service 2781ba
  /* Sort abc */
Packit Service 2781ba
  if (b > c)
Packit Service 2781ba
    {
Packit Service 2781ba
      t = c;
Packit Service 2781ba
      c = b;
Packit Service 2781ba
      if (a > t)
Packit Service 2781ba
        {
Packit Service 2781ba
          b = a;
Packit Service 2781ba
          a = t;
Packit Service 2781ba
        }
Packit Service 2781ba
      else
Packit Service 2781ba
    b = t;
Packit Service 2781ba
    }
Packit Service 2781ba
  /* Return average of central two elements. */
Packit Service 2781ba
  if (d >= c) /* Sorted order would be abcd */
Packit Service 2781ba
    return (b + c) / 2.0;
Packit Service 2781ba
  else if (d >= a) /* Sorted order would be either abdc or adbc */
Packit Service 2781ba
    return (b + d) / 2.0;
Packit Service 2781ba
  else /* Sorted order would be dabc */
Packit Service 2781ba
    return (a + b) / 2.0;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/* Defines to make the row/col offsets below obvious. */
Packit Service 2781ba
#define ROW src_rect->width
Packit Service 2781ba
#define COL 1
Packit Service 2781ba
Packit Service 2781ba
/* We expect src_extent to have a one pixel border around all four sides
Packit Service 2781ba
 * of dst_extent.
Packit Service 2781ba
 */
Packit Service 2781ba
static void
Packit Service 2781ba
demosaic (GeglChantO          *op,
Packit Service 2781ba
          GeglBuffer          *src,
Packit Service 2781ba
          const GeglRectangle *src_rect,
Packit Service 2781ba
          GeglBuffer          *dst,
Packit Service 2781ba
          const GeglRectangle *dst_rect)
Packit Service 2781ba
{
Packit Service 2781ba
  gint x,y;
Packit Service 2781ba
  gint offset, doffset;
Packit Service 2781ba
  gfloat *src_buf;
Packit Service 2781ba
  gfloat *dst_buf;
Packit Service 2781ba
Packit Service 2781ba
  src_buf = g_new0 (gfloat, src_rect->width * src_rect->height * 1);
Packit Service 2781ba
  dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 3);
Packit Service 2781ba
Packit Service 2781ba
  gegl_buffer_get (src, src_rect, 1.0, babl_format ("Y float"), src_buf,
Packit Service 2781ba
                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
  offset = ROW + COL;
Packit Service 2781ba
  doffset = 0;
Packit Service 2781ba
  for (y=dst_rect->y; y<dst_rect->height + dst_rect->y; y++)
Packit Service 2781ba
    {
Packit Service 2781ba
      for (x=dst_rect->x; x<dst_rect->width + dst_rect->x; x++)
Packit Service 2781ba
        {
Packit Service 2781ba
          gfloat red=0.0;
Packit Service 2781ba
          gfloat green=0.0;
Packit Service 2781ba
          gfloat blue=0.0;
Packit Service 2781ba
Packit Service 2781ba
          if ((y + op->pattern%2)%2==0)
Packit Service 2781ba
            {
Packit Service 2781ba
              if ((x+op->pattern/2)%2==1)
Packit Service 2781ba
                {
Packit Service 2781ba
                  /* GRG
Packit Service 2781ba
                   * BGB
Packit Service 2781ba
                   * GRG
Packit Service 2781ba
                   */
Packit Service 2781ba
                  blue =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
Packit Service 2781ba
                  green=src_buf[offset];
Packit Service 2781ba
                  red  =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
Packit Service 2781ba
                }
Packit Service 2781ba
              else
Packit Service 2781ba
                {
Packit Service 2781ba
                  /* RGR
Packit Service 2781ba
                   * GBG
Packit Service 2781ba
                   * RGR
Packit Service 2781ba
                   */
Packit Service 2781ba
                  blue =src_buf[offset];
Packit Service 2781ba
                  green=m4(src_buf[offset-ROW], src_buf[offset-COL],
Packit Service 2781ba
                           src_buf[offset+COL], src_buf[offset+ROW]);
Packit Service 2781ba
                  red  =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
Packit Service 2781ba
                           src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
Packit Service 2781ba
                }
Packit Service 2781ba
            }
Packit Service 2781ba
          else
Packit Service 2781ba
            {
Packit Service 2781ba
              if ((x+op->pattern/2)%2==1)
Packit Service 2781ba
                {
Packit Service 2781ba
                  /* BGB
Packit Service 2781ba
                   * GRG
Packit Service 2781ba
                   * BGB
Packit Service 2781ba
                   */
Packit Service 2781ba
                  blue =m4(src_buf[offset-ROW-COL], src_buf[offset-ROW+COL],
Packit Service 2781ba
                       src_buf[offset+ROW-COL], src_buf[offset+ROW+COL]);
Packit Service 2781ba
                  green=m4(src_buf[offset-ROW], src_buf[offset-COL],
Packit Service 2781ba
                       src_buf[offset+COL], src_buf[offset+ROW]);
Packit Service 2781ba
                  red  =src_buf[offset];
Packit Service 2781ba
                }
Packit Service 2781ba
              else
Packit Service 2781ba
                {
Packit Service 2781ba
                  /* GBG
Packit Service 2781ba
                   * RGR
Packit Service 2781ba
                   * GBG
Packit Service 2781ba
                   */
Packit Service 2781ba
                  blue =(src_buf[offset-ROW]+src_buf[offset+ROW])/2.0;
Packit Service 2781ba
                  green=src_buf[offset];
Packit Service 2781ba
                  red  =(src_buf[offset-COL]+src_buf[offset+COL])/2.0;
Packit Service 2781ba
                }
Packit Service 2781ba
            }
Packit Service 2781ba
Packit Service 2781ba
          dst_buf [doffset*3+0] = red;
Packit Service 2781ba
          dst_buf [doffset*3+1] = green;
Packit Service 2781ba
          dst_buf [doffset*3+2] = blue;
Packit Service 2781ba
Packit Service 2781ba
          offset++;
Packit Service 2781ba
          doffset++;
Packit Service 2781ba
        }
Packit Service 2781ba
      offset+=2;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  gegl_buffer_set (dst, dst_rect, 0, babl_format ("RGB float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
  g_free (src_buf);
Packit Service 2781ba
  g_free (dst_buf);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
/* Specify required extra pixels around dst_extent: one pixel on every side.
Packit Service 2781ba
 */
Packit Service 2781ba
static void prepare (GeglOperation *operation)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation);
Packit Service 2781ba
  area->right = area->bottom = 1;
Packit Service 2781ba
  area->left  = area->top    = 1;
Packit Service 2781ba
Packit Service 2781ba
  gegl_operation_set_format (operation, "output", babl_format ("RGB float"));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
static gboolean
Packit Service 2781ba
process (GeglOperation       *operation,
Packit Service 2781ba
         GeglBuffer          *input,
Packit Service 2781ba
         GeglBuffer          *output,
Packit Service 2781ba
         const GeglRectangle *result,
Packit Service 2781ba
         gint                 level)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
Packit Service 2781ba
  GeglRectangle src_rect = gegl_operation_get_required_for_output (operation, "input", result);
Packit Service 2781ba
Packit Service 2781ba
  demosaic (o, input, &src_rect, output, result);
Packit Service 2781ba
Packit Service 2781ba
  return  TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_chant_class_init (GeglChantClass *klass)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass       *operation_class;
Packit Service 2781ba
  GeglOperationFilterClass *filter_class;
Packit Service 2781ba
Packit Service 2781ba
  operation_class = GEGL_OPERATION_CLASS (klass);
Packit Service 2781ba
  filter_class    = GEGL_OPERATION_FILTER_CLASS (klass);
Packit Service 2781ba
Packit Service 2781ba
  filter_class->process    = process;
Packit Service 2781ba
  operation_class->prepare = prepare;
Packit Service 2781ba
Packit Service 2781ba
  gegl_operation_class_set_keys (operation_class,
Packit Service 2781ba
    "name"        , "gegl:demosaic-bimedian",
Packit Service 2781ba
    "categories"  , "blur",
Packit Service 2781ba
    "description" ,
Packit Service 2781ba
          _("Performs a grayscale2color demosaicing of an image, using bimedian interpolation."),
Packit Service 2781ba
          NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#endif