Blame operations/workshop/color-reduction.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 2008 Hans Petter Jansson <hpj@copyleft.no>
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 (red_bits,   _("Red bits"),   1, 16, 16, _("Number of bits for red channel"))
Packit Service 2781ba
gegl_chant_int (green_bits, _("Green bits"), 1, 16, 16, _("Number of bits for green channel"))
Packit Service 2781ba
gegl_chant_int (blue_bits,  _("Blue bits"),  1, 16, 16, _("Number of bits for blue channel"))
Packit Service 2781ba
gegl_chant_int (alpha_bits, _("Alpha bits"), 1, 16, 16, _("Number of bits for alpha channel"))
Packit Service 2781ba
gegl_chant_string (dither_type, _("Dither"), "none",
Packit Service 2781ba
              _("Dithering strategy (none, random, random-covariant, bayer, floyd-steinberg)"))
Packit Service 2781ba
Packit Service 2781ba
#else
Packit Service 2781ba
Packit Service 2781ba
#define GEGL_CHANT_TYPE_FILTER
Packit Service 2781ba
#define GEGL_CHANT_C_FILE       "color-reduction.c"
Packit Service 2781ba
Packit Service 2781ba
#include "gegl-chant.h"
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
prepare (GeglOperation *operation)
Packit Service 2781ba
{
Packit Service 2781ba
  gegl_operation_set_format (operation, "input", babl_format ("RGBA u16"));
Packit Service 2781ba
  gegl_operation_set_format (operation, "output", babl_format ("RGBA u16"));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
generate_channel_masks (guint *channel_bits, guint *channel_mask)
Packit Service 2781ba
{
Packit Service 2781ba
  gint i;
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < 4; i++)
Packit Service 2781ba
    channel_mask [i] = ~((1 << (16 - channel_bits [i])) - 1);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static guint
Packit Service 2781ba
quantize_value (guint value, guint n_bits, guint mask)
Packit Service 2781ba
{
Packit Service 2781ba
  gint i;
Packit Service 2781ba
Packit Service 2781ba
  value &= mask;
Packit Service 2781ba
Packit Service 2781ba
  for (i = n_bits; i < 16; i += n_bits)
Packit Service 2781ba
    value |= value >> i;
Packit Service 2781ba
Packit Service 2781ba
  return value;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
process_floyd_steinberg (GeglBuffer *input,
Packit Service 2781ba
                         GeglBuffer *output,
Packit Service 2781ba
                         const GeglRectangle *result,
Packit Service 2781ba
                         guint *channel_bits)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle        line_rect;
Packit Service 2781ba
  guint16             *line_buf;
Packit Service 2781ba
  gdouble             *error_buf [2];
Packit Service 2781ba
  guint                channel_mask [4];
Packit Service 2781ba
  gint                 y;
Packit Service 2781ba
Packit Service 2781ba
  line_rect.x      = result->x;
Packit Service 2781ba
  line_rect.y      = result->y;
Packit Service 2781ba
  line_rect.width  = result->width;
Packit Service 2781ba
  line_rect.height = 1;
Packit Service 2781ba
Packit Service 2781ba
  line_buf      = g_new  (guint16, line_rect.width * 4);
Packit Service 2781ba
  error_buf [0] = g_new0 (gdouble, line_rect.width * 4);
Packit Service 2781ba
  error_buf [1] = g_new0 (gdouble, line_rect.width * 4);
Packit Service 2781ba
Packit Service 2781ba
  generate_channel_masks (channel_bits, channel_mask);
Packit Service 2781ba
Packit Service 2781ba
  for (y = 0; y < result->height; y++)
Packit Service 2781ba
  {
Packit Service 2781ba
    gdouble  *error_buf_swap;
Packit Service 2781ba
    gint      step;
Packit Service 2781ba
    gint      start_x;
Packit Service 2781ba
    gint      end_x;
Packit Service 2781ba
    gint      x;
Packit Service 2781ba
Packit Service 2781ba
    /* Serpentine scanning; reverse direction every row */
Packit Service 2781ba
Packit Service 2781ba
    if (y & 1)
Packit Service 2781ba
    {
Packit Service 2781ba
      start_x = result->width - 1;
Packit Service 2781ba
      end_x   = -1;
Packit Service 2781ba
      step    = -1;
Packit Service 2781ba
    }
Packit Service 2781ba
    else
Packit Service 2781ba
    {
Packit Service 2781ba
      start_x = 0;
Packit Service 2781ba
      end_x   = result->width;
Packit Service 2781ba
      step    = 1;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
    /* Pull input row */
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
Packit Service 2781ba
                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
    /* Process the row */
Packit Service 2781ba
Packit Service 2781ba
    for (x = start_x; x != end_x; x += step)
Packit Service 2781ba
    {
Packit Service 2781ba
      guint16  *pixel = &line_buf [x * 4];
Packit Service 2781ba
      guint     ch;
Packit Service 2781ba
Packit Service 2781ba
      for (ch = 0; ch < 4; ch++)
Packit Service 2781ba
      {
Packit Service 2781ba
        gdouble value;
Packit Service 2781ba
        gdouble value_clamped;
Packit Service 2781ba
        gdouble quantized;
Packit Service 2781ba
        gdouble qerror;
Packit Service 2781ba
Packit Service 2781ba
        value         = pixel [ch] + error_buf [0] [x * 4 + ch];
Packit Service 2781ba
        value_clamped = CLAMP (value, 0.0, 65535.0);
Packit Service 2781ba
        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
Packit Service 2781ba
        qerror        = value - quantized;
Packit Service 2781ba
Packit Service 2781ba
        pixel [ch] = (guint16) quantized;
Packit Service 2781ba
Packit Service 2781ba
        /* Distribute the error */
Packit Service 2781ba
Packit Service 2781ba
        error_buf [1] [x * 4 + ch] += qerror * 5.0 / 16.0;  /* Down */
Packit Service 2781ba
Packit Service 2781ba
        if (x + step >= 0 && x + step < result->width)
Packit Service 2781ba
        {
Packit Service 2781ba
          error_buf [0] [(x + step) * 4 + ch] += qerror * 6.0 / 16.0;  /* Ahead */
Packit Service 2781ba
          error_buf [1] [(x + step) * 4 + ch] += qerror * 1.0 / 16.0;  /* Down, ahead */
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
        if (x - step >= 0 && x - step < result->width)
Packit Service 2781ba
        {
Packit Service 2781ba
          error_buf [1] [(x - step) * 4 + ch] += qerror * 3.0 / 16.0;  /* Down, behind */
Packit Service 2781ba
        }
Packit Service 2781ba
      }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
    /* Swap error accumulation rows */
Packit Service 2781ba
Packit Service 2781ba
    error_buf_swap = error_buf [0];
Packit Service 2781ba
    error_buf [0]  = error_buf [1];
Packit Service 2781ba
    error_buf [1]  = error_buf_swap;
Packit Service 2781ba
Packit Service 2781ba
    /* Clear error buffer for next-plus-one line */
Packit Service 2781ba
Packit Service 2781ba
    memset (error_buf [1], 0, line_rect.width * 4 * sizeof (gdouble));
Packit Service 2781ba
Packit Service 2781ba
    /* Push output row */
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
    line_rect.y++;
Packit Service 2781ba
  }
Packit Service 2781ba
Packit Service 2781ba
  g_free (line_buf);
Packit Service 2781ba
  g_free (error_buf [0]);
Packit Service 2781ba
  g_free (error_buf [1]);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static const gdouble bayer_matrix_8x8 [] =
Packit Service 2781ba
{
Packit Service 2781ba
   1, 49, 13, 61,  4, 52, 16, 64,
Packit Service 2781ba
  33, 17, 45, 29, 36, 20, 48, 32,
Packit Service 2781ba
   9, 57,  5, 53, 12, 60,  8, 56,
Packit Service 2781ba
  41, 25, 37, 21, 44, 28, 40, 24,
Packit Service 2781ba
   3, 51, 15, 63,  2, 50, 14, 62,
Packit Service 2781ba
  35, 19, 47, 31, 34, 18, 46, 30,
Packit Service 2781ba
  11, 59,  7, 55, 10, 58,  6, 54,
Packit Service 2781ba
  43, 27, 39, 23, 42, 26, 38, 22
Packit Service 2781ba
};
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
process_bayer (GeglBuffer *input,
Packit Service 2781ba
               GeglBuffer *output,
Packit Service 2781ba
               const GeglRectangle *result,
Packit Service 2781ba
               guint *channel_bits)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle        line_rect;
Packit Service 2781ba
  guint16             *line_buf;
Packit Service 2781ba
  guint                channel_mask [4];
Packit Service 2781ba
  guint                y;
Packit Service 2781ba
Packit Service 2781ba
  line_rect.x = result->x;
Packit Service 2781ba
  line_rect.y = result->y;
Packit Service 2781ba
  line_rect.width = result->width;
Packit Service 2781ba
  line_rect.height = 1;
Packit Service 2781ba
Packit Service 2781ba
  line_buf = g_new (guint16, line_rect.width * 4);
Packit Service 2781ba
Packit Service 2781ba
  generate_channel_masks (channel_bits, channel_mask);
Packit Service 2781ba
Packit Service 2781ba
  for (y = 0; y < result->height; y++)
Packit Service 2781ba
  {
Packit Service 2781ba
    guint x;
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
Packit Service 2781ba
                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
    for (x = 0; x < result->width; x++)
Packit Service 2781ba
    {
Packit Service 2781ba
      guint16 *pixel = &line_buf [x * 4];
Packit Service 2781ba
      guint    ch;
Packit Service 2781ba
Packit Service 2781ba
      for (ch = 0; ch < 4; ch++)
Packit Service 2781ba
      {
Packit Service 2781ba
        gdouble value;
Packit Service 2781ba
        gdouble value_clamped;
Packit Service 2781ba
        gdouble quantized;
Packit Service 2781ba
Packit Service 2781ba
        value         = pixel [ch] + ((bayer_matrix_8x8 [(y % 8) * 8 + (x % 8)] - 32) * 65536.0 / 65.0) / (1 << (channel_bits [ch] - 1));
Packit Service 2781ba
        value_clamped = CLAMP (value, 0.0, 65535.0);
Packit Service 2781ba
        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
Packit Service 2781ba
Packit Service 2781ba
        pixel [ch] = (guint16) quantized;
Packit Service 2781ba
      }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
    line_rect.y++;
Packit Service 2781ba
  }
Packit Service 2781ba
Packit Service 2781ba
  g_free (line_buf);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
process_random_covariant (GeglBuffer *input,
Packit Service 2781ba
                          GeglBuffer *output,
Packit Service 2781ba
                          const GeglRectangle *result,
Packit Service 2781ba
                          guint *channel_bits)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle        line_rect;
Packit Service 2781ba
  guint16             *line_buf;
Packit Service 2781ba
  guint                channel_mask [4];
Packit Service 2781ba
  guint                y;
Packit Service 2781ba
Packit Service 2781ba
  line_rect.x = result->x;
Packit Service 2781ba
  line_rect.y = result->y;
Packit Service 2781ba
  line_rect.width = result->width;
Packit Service 2781ba
  line_rect.height = 1;
Packit Service 2781ba
Packit Service 2781ba
  line_buf = g_new (guint16, line_rect.width * 4);
Packit Service 2781ba
Packit Service 2781ba
  generate_channel_masks (channel_bits, channel_mask);
Packit Service 2781ba
Packit Service 2781ba
  for (y = 0; y < result->height; y++)
Packit Service 2781ba
  {
Packit Service 2781ba
    guint x;
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
Packit Service 2781ba
                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
    for (x = 0; x < result->width; x++)
Packit Service 2781ba
    {
Packit Service 2781ba
      guint16 *pixel = &line_buf [x * 4];
Packit Service 2781ba
      guint    ch;
Packit Service 2781ba
      gint     r = g_random_int_range (-65536, 65536);
Packit Service 2781ba
Packit Service 2781ba
      for (ch = 0; ch < 4; ch++)
Packit Service 2781ba
      {
Packit Service 2781ba
        gdouble value;
Packit Service 2781ba
        gdouble value_clamped;
Packit Service 2781ba
        gdouble quantized;
Packit Service 2781ba
Packit Service 2781ba
        value         = pixel [ch] + (r / (1 << channel_bits [ch]));
Packit Service 2781ba
        value_clamped = CLAMP (value, 0.0, 65535.0);
Packit Service 2781ba
        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
Packit Service 2781ba
Packit Service 2781ba
        pixel [ch] = (guint16) quantized;
Packit Service 2781ba
      }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
    line_rect.y++;
Packit Service 2781ba
  }
Packit Service 2781ba
Packit Service 2781ba
  g_free (line_buf);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
process_random (GeglBuffer *input,
Packit Service 2781ba
                GeglBuffer *output,
Packit Service 2781ba
                const GeglRectangle *result,
Packit Service 2781ba
                guint *channel_bits)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle        line_rect;
Packit Service 2781ba
  guint16             *line_buf;
Packit Service 2781ba
  guint                channel_mask [4];
Packit Service 2781ba
  guint                y;
Packit Service 2781ba
Packit Service 2781ba
  line_rect.x = result->x;
Packit Service 2781ba
  line_rect.y = result->y;
Packit Service 2781ba
  line_rect.width = result->width;
Packit Service 2781ba
  line_rect.height = 1;
Packit Service 2781ba
Packit Service 2781ba
  line_buf = g_new (guint16, line_rect.width * 4);
Packit Service 2781ba
Packit Service 2781ba
  generate_channel_masks (channel_bits, channel_mask);
Packit Service 2781ba
Packit Service 2781ba
  for (y = 0; y < result->height; y++)
Packit Service 2781ba
  {
Packit Service 2781ba
    guint x;
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
Packit Service 2781ba
                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
    for (x = 0; x < result->width; x++)
Packit Service 2781ba
    {
Packit Service 2781ba
      guint16 *pixel = &line_buf [x * 4];
Packit Service 2781ba
      guint    ch;
Packit Service 2781ba
Packit Service 2781ba
      for (ch = 0; ch < 4; ch++)
Packit Service 2781ba
      {
Packit Service 2781ba
        gdouble value;
Packit Service 2781ba
        gdouble value_clamped;
Packit Service 2781ba
        gdouble quantized;
Packit Service 2781ba
Packit Service 2781ba
        value         = pixel [ch] + (g_random_int_range (-65536, 65536) / (1 << channel_bits [ch]));
Packit Service 2781ba
        value_clamped = CLAMP (value, 0.0, 65535.0);
Packit Service 2781ba
        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
Packit Service 2781ba
Packit Service 2781ba
        pixel [ch] = (guint16) quantized;
Packit Service 2781ba
      }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
    line_rect.y++;
Packit Service 2781ba
  }
Packit Service 2781ba
Packit Service 2781ba
  g_free (line_buf);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
process_no_dither (GeglBuffer *input,
Packit Service 2781ba
                   GeglBuffer *output,
Packit Service 2781ba
                   const GeglRectangle *result,
Packit Service 2781ba
                   guint *channel_bits)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle        line_rect;
Packit Service 2781ba
  guint16             *line_buf;
Packit Service 2781ba
  guint                channel_mask [4];
Packit Service 2781ba
  guint                y;
Packit Service 2781ba
Packit Service 2781ba
  line_rect.x = result->x;
Packit Service 2781ba
  line_rect.y = result->y;
Packit Service 2781ba
  line_rect.width = result->width;
Packit Service 2781ba
  line_rect.height = 1;
Packit Service 2781ba
Packit Service 2781ba
  line_buf = g_new (guint16, line_rect.width * 4);
Packit Service 2781ba
Packit Service 2781ba
  generate_channel_masks (channel_bits, channel_mask);
Packit Service 2781ba
Packit Service 2781ba
  for (y = 0; y < result->height; y++)
Packit Service 2781ba
  {
Packit Service 2781ba
    guint x;
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
Packit Service 2781ba
                     GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
    for (x = 0; x < result->width; x++)
Packit Service 2781ba
    {
Packit Service 2781ba
      guint16 *pixel = &line_buf [x * 4];
Packit Service 2781ba
      guint    ch;
Packit Service 2781ba
Packit Service 2781ba
      for (ch = 0; ch < 4; ch++)
Packit Service 2781ba
      {
Packit Service 2781ba
        pixel [ch] = quantize_value (pixel [ch], channel_bits [ch], channel_mask [ch]);
Packit Service 2781ba
      }
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
    gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
Packit Service 2781ba
    line_rect.y++;
Packit Service 2781ba
  }
Packit Service 2781ba
Packit Service 2781ba
  g_free (line_buf);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_required_for_output (GeglOperation        *self,
Packit Service 2781ba
                         const gchar         *input_pad,
Packit Service 2781ba
                         const GeglRectangle *roi)
Packit Service 2781ba
{
Packit Service 2781ba
  return *gegl_operation_source_get_bounding_box (self, "input");
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_cached_region (GeglOperation       *self,
Packit Service 2781ba
                   const GeglRectangle *roi)
Packit Service 2781ba
{
Packit Service 2781ba
  return *gegl_operation_source_get_bounding_box (self, "input");
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
  guint       channel_bits [4];
Packit Service 2781ba
Packit Service 2781ba
  channel_bits [0] = o->red_bits;
Packit Service 2781ba
  channel_bits [1] = o->green_bits;
Packit Service 2781ba
  channel_bits [2] = o->blue_bits;
Packit Service 2781ba
  channel_bits [3] = o->alpha_bits;
Packit Service 2781ba
Packit Service 2781ba
  if (!o->dither_type)
Packit Service 2781ba
    process_no_dither (input, output, result, channel_bits);
Packit Service 2781ba
  else if (!strcasecmp (o->dither_type, "random"))
Packit Service 2781ba
    process_random (input, output, result, channel_bits);
Packit Service 2781ba
  else if (!strcasecmp (o->dither_type, "random-covariant"))
Packit Service 2781ba
    process_random_covariant (input, output, result, channel_bits);
Packit Service 2781ba
  else if (!strcasecmp (o->dither_type, "bayer"))
Packit Service 2781ba
    process_bayer (input, output, result, channel_bits);
Packit Service 2781ba
  else if (!strcasecmp (o->dither_type, "floyd-steinberg"))
Packit Service 2781ba
    process_floyd_steinberg (input, output, result, channel_bits);
Packit Service 2781ba
  else
Packit Service 2781ba
    process_no_dither (input, output, result, channel_bits);
Packit Service 2781ba
Packit Service 2781ba
  return TRUE;
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
  operation_class->prepare = prepare;
Packit Service 2781ba
  operation_class->get_required_for_output = get_required_for_output;
Packit Service 2781ba
  operation_class->get_cached_region = get_cached_region;
Packit Service 2781ba
  filter_class->process = process;
Packit Service 2781ba
Packit Service 2781ba
  gegl_operation_class_set_keys (operation_class,
Packit Service 2781ba
    "name"        , "gegl:color-reduction",
Packit Service 2781ba
    "categories"  , "misc",
Packit Service 2781ba
    "description" ,
Packit Service 2781ba
            _("Reduces the number of bits per channel (colors and alpha), with optional dithering"),
Packit Service 2781ba
            NULL);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
#endif