예제 #1
0
static void
process_random_covariant (GeglBuffer *input,
                          GeglBuffer *output,
                          const GeglRectangle *result,
                          guint *channel_bits)
{
    GeglRectangle        line_rect;
    guint16             *line_buf;
    guint                channel_mask [4];
    guint                y;

    line_rect.x = result->x;
    line_rect.y = result->y;
    line_rect.width = result->width;
    line_rect.height = 1;

    line_buf = g_new (guint16, line_rect.width * 4);

    generate_channel_masks (channel_bits, channel_mask);

    for (y = 0; y < result->height; y++)
    {
        guint x;

        gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
                         GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

        for (x = 0; x < result->width; x++)
        {
            guint16 *pixel = &line_buf [x * 4];
            guint    ch;
            gint     r = g_random_int_range (-65536, 65536);

            for (ch = 0; ch < 4; ch++)
            {
                gdouble value;
                gdouble value_clamped;
                gdouble quantized;

                value         = pixel [ch] + (r / (1 << channel_bits [ch]));
                value_clamped = CLAMP (value, 0.0, 65535.0);
                quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);

                pixel [ch] = (guint16) quantized;
            }
        }

        gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
        line_rect.y++;
    }

    g_free (line_buf);
}
예제 #2
0
static void
process_bayer (GeglBuffer *input,
               GeglBuffer *output,
               const GeglRectangle *result,
               guint *channel_bits)
{
  GeglRectangle        line_rect;
  guint16             *line_buf;
  guint                channel_mask [4];
  guint                y;

  line_rect.x = result->x;
  line_rect.y = result->y;
  line_rect.width = result->width;
  line_rect.height = 1;

  line_buf = g_new (guint16, line_rect.width * 4);

  generate_channel_masks (channel_bits, channel_mask);

  for (y = 0; y < result->height; y++)
  {
    guint x;

    gegl_buffer_get (input, 1.0, &line_rect, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);

    for (x = 0; x < result->width; x++)
    {
      guint16 *pixel = &line_buf [x * 4];
      guint    ch;

      for (ch = 0; ch < 4; ch++)
      {
        gdouble value;
        gdouble value_clamped;
        gdouble quantized;

        value         = pixel [ch] + ((bayer_matrix_8x8 [(y % 8) * 8 + (x % 8)] - 32) * 65536.0 / 65.0) / (1 << (channel_bits [ch] - 1));
        value_clamped = CLAMP (value, 0.0, 65535.0);
        quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);

        pixel [ch] = (guint16) quantized;
      }
    }

    gegl_buffer_set (output, &line_rect, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
    line_rect.y++;
  }

  g_free (line_buf);
}
예제 #3
0
static void
process_standard (GeglBuffer          *input,
                  GeglBuffer          *output,
                  const GeglRectangle *result,
                  guint               *channel_bits,
                  GeglRandom          *rand,
                  GeglDitherStrategy   dither_strategy)
{
  GeglBufferIterator *gi;
  guint               channel_mask [4];

  generate_channel_masks (channel_bits, channel_mask);

  gi = gegl_buffer_iterator_new (input, result, 0, babl_format ("R'G'B'A u16"),
                                 GEGL_ACCESS_READ, GEGL_ABYSS_NONE);

  gegl_buffer_iterator_add (gi, output, result, 0, babl_format ("R'G'B'A u16"),
                            GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);

  while (gegl_buffer_iterator_next (gi))
    {
      guint    y;
      for (y = 0; y < gi->roi->height; y++)
        {
          switch (dither_strategy)
            {
            case GEGL_DITHER_NONE:
              process_row_no_dither (gi, channel_mask, channel_bits, y);
              break;
            case GEGL_DITHER_RANDOM:
              process_row_random (gi, channel_mask, channel_bits, y, rand);
              break;
            case GEGL_DITHER_RESILIENT:
              process_row_resilient (gi, channel_mask, channel_bits, y, rand);
              break;
            case GEGL_DITHER_RANDOM_COVARIANT:
              process_row_random_covariant (gi, channel_mask, channel_bits, y, rand);
              break;
            case GEGL_DITHER_BAYER:
              process_row_bayer (gi, channel_mask, channel_bits, y);
              break;
            case GEGL_DITHER_FLOYD_STEINBERG:
              /* Done separately */
              break;
            default:
              process_row_no_dither (gi, channel_mask, channel_bits, y);
            }
        }
    }
}
예제 #4
0
static void
process_no_dither (GeglBuffer *input,
                   GeglBuffer *output,
                   const GeglRectangle *result,
                   guint *channel_bits)
{
    GeglRectangle        line_rect;
    guint16             *line_buf;
    guint                channel_mask [4];
    guint                y;

    line_rect.x = result->x;
    line_rect.y = result->y;
    line_rect.width = result->width;
    line_rect.height = 1;

    line_buf = g_new (guint16, line_rect.width * 4);

    generate_channel_masks (channel_bits, channel_mask);

    for (y = 0; y < result->height; y++)
    {
        guint x;

        gegl_buffer_get (input, &line_rect, 1.0, babl_format ("RGBA u16"), line_buf,
                         GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

        for (x = 0; x < result->width; x++)
        {
            guint16 *pixel = &line_buf [x * 4];
            guint    ch;

            for (ch = 0; ch < 4; ch++)
            {
                pixel [ch] = quantize_value (pixel [ch], channel_bits [ch], channel_mask [ch]);
            }
        }

        gegl_buffer_set (output, &line_rect, 0, babl_format ("RGBA u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
        line_rect.y++;
    }

    g_free (line_buf);
}
예제 #5
0
static void
process_floyd_steinberg (GeglBuffer          *input,
                         GeglBuffer          *output,
                         const GeglRectangle *result,
                         guint               *channel_bits)
{
  GeglRectangle  line_rect;
  guint16       *line_buf;
  gdouble       *error_buf [2];
  guint          channel_mask [4];
  gint           y;

  line_rect.x      = result->x;
  line_rect.y      = result->y;
  line_rect.width  = result->width;
  line_rect.height = 1;

  line_buf      = g_new  (guint16, line_rect.width * 4);
  error_buf [0] = g_new0 (gdouble, line_rect.width * 4);
  error_buf [1] = g_new0 (gdouble, line_rect.width * 4);

  generate_channel_masks (channel_bits, channel_mask);

  for (y = 0; y < result->height; y++)
    {
      gdouble  *error_buf_swap;
      gint      step;
      gint      start_x;
      gint      end_x;
      gint      x;

      /* Serpentine scanning; reverse direction every row */

      if (y & 1)
        {
          start_x = result->width - 1;
          end_x   = -1;
          step    = -1;
        }
      else
        {
          start_x = 0;
          end_x   = result->width;
          step    = 1;
        }

      /* Pull input row */

      gegl_buffer_get (input, &line_rect, 1.0, babl_format ("R'G'B'A u16"), line_buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      /* Process the row */

      for (x = start_x; x != end_x; x += step)
        {
          guint16  *pixel = &line_buf [x * 4];
          guint     ch;

          for (ch = 0; ch < 4; ch++)
            {
              gdouble value;
              gdouble value_clamped;
              gdouble quantized;
              gdouble qerror;

              value         = pixel [ch] + error_buf [0] [x * 4 + ch];
              value_clamped = CLAMP (value, 0.0, 65535.0);
              quantized     = quantize_value ((guint) (value_clamped + 0.5), channel_bits [ch], channel_mask [ch]);
              qerror        = value - quantized;

              pixel [ch] = (guint16) quantized;

              /* Distribute the error */

              error_buf [1] [x * 4 + ch] += qerror * 5.0 / 16.0;  /* Down */

              if (x + step >= 0 && x + step < result->width)
                {
                  error_buf [0] [(x + step) * 4 + ch] += qerror * 6.0 / 16.0;  /* Ahead */
                  error_buf [1] [(x + step) * 4 + ch] += qerror * 1.0 / 16.0;  /* Down, ahead */
                }

              if (x - step >= 0 && x - step < result->width)
                {
                  error_buf [1] [(x - step) * 4 + ch] += qerror * 3.0 / 16.0;  /* Down, behind */
                }
            }
        }

      /* Swap error accumulation rows */

      error_buf_swap = error_buf [0];
      error_buf [0]  = error_buf [1];
      error_buf [1]  = error_buf_swap;

      /* Clear error buffer for next-plus-one line */

      memset (error_buf [1], 0, line_rect.width * 4 * sizeof (gdouble));

      /* Push output row */

      gegl_buffer_set (output, &line_rect, 0, babl_format ("R'G'B'A u16"), line_buf, GEGL_AUTO_ROWSTRIDE);
      line_rect.y++;
    }

  g_free (line_buf);
  g_free (error_buf [0]);
  g_free (error_buf [1]);
}