Esempio n. 1
0
static void
snn_percentile (GeglBuffer *src,
                GeglBuffer *dst,
                gdouble     radius,
                gdouble     percentile,
                gint        pairs)
{
  gint    x, y;
  gint    offset;
  gfloat *src_buf;
  gfloat *dst_buf;
  RankList list = {0};

  src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4);
  dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 4);

  gegl_buffer_get (src, NULL, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

  offset = 0;
  percentile/= 100.0;

  for (y=0; y<gegl_buffer_get_height (dst); y++)
    for (x=0; x<gegl_buffer_get_width (dst); x++)
      {
        gint u,v;
        gfloat *center_pix = src_buf + offset * 4;

        list_clear (&list);

        /* iterate through the upper left quater of pixels */
        for (v=-radius;v<=0;v++)
          for (u=-radius;u<= (pairs==1?radius:0);u++)
            {
              gfloat *selected_pix = center_pix;
              gfloat  best_diff = 1000.0;
              gint    i;

              /* skip computations for the center pixel */
              if (u != 0 &&
                  v != 0)
                {
                  /* compute the coordinates of the symmetric pairs for
                   * this locaiton in the quadrant
                   */
                  gint xs[4] = {x+u, x-u, x-u, x+u};
                  gint ys[4] = {y+v, y-v, y+v, y-v};

                  /* check which member of the symmetric quadruple to use */
                  for (i=0;i<pairs*2;i++)
                    {
                      if (xs[i] >= 0 && xs[i] < gegl_buffer_get_width (src) &&
                          ys[i] >= 0 && ys[i] < gegl_buffer_get_height (src))
                        {
                          gfloat *tpix = src_buf + (xs[i]+ys[i]*gegl_buffer_get_width (src))*4;
                          gfloat diff = colordiff (tpix, center_pix);
                          if (diff < best_diff)
                            {
                              best_diff = diff;
                              selected_pix = tpix;
                            }
                        }
                    }
                }

              list_add (&list, rgb2luminance(selected_pix), selected_pix);

              if (u==0 && v==0)
                break; /* to avoid doubly processing when using only 1 pair */
            }
        {
          gfloat *result = list_percentile (&list, percentile);
          for (u=0; u<4; u++)
            dst_buf[offset*4+u] = result[u];
        }
        offset++;
      }
  gegl_buffer_set (dst, NULL, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
  g_free (src_buf);
  g_free (dst_buf);
}
static void
snn_mean (GeglBuffer          *src,
          GeglBuffer          *dst,
          const GeglRectangle *dst_rect,
          gdouble              dradius,
          gint                 pairs)
{
  gint x,y;
  gint offset;
  gfloat *src_buf;
  gfloat *dst_buf;
  gint radius = dradius;
  gint src_width = gegl_buffer_get_width (src);
  gint src_height = gegl_buffer_get_height (src);

  src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4);
  dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 4);

  gegl_buffer_get (src, NULL, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

  offset = 0;

  for (y=0; y<dst_rect->height; y++)
    {
      gfloat *center_pix;

      center_pix = src_buf + ((radius) + (y+radius)* src_width)*4;

      for (x=0; x<dst_rect->width; x++)
        {
          gint u,v;

          gfloat  accumulated[4]={0,};
          gint    count=0;

          /* iterate through the upper left quater of pixels */
          for (v=-radius;v<=0;v++)
            for (u=-radius;u<= (pairs==1?radius:0);u++)
              {
                gfloat *selected_pix = center_pix;
                gfloat  best_diff = 1000.0;
                gint    i;

                /* skip computations for the center pixel */
                if (u != 0 &&
                    v != 0)
                  {
                    /* compute the coordinates of the symmetric pairs for
                     * this locaiton in the quadrant
                     */
                    gint xs[4], ys[4];

                    xs[0] = x+u+radius;
                    xs[1] = x-u+radius;
                    xs[2] = x-u+radius;
                    xs[3] = x+u+radius;
                    ys[0] = y+v+radius;
                    ys[1] = y-v+radius;
                    ys[2] = y+v+radius;
                    ys[3] = y-v+radius;

                    /* check which member of the symmetric quadruple to use */
                    for (i=0;i<pairs*2;i++)
                      {
                        if (xs[i] >= 0 && xs[i] < src_width &&
                            ys[i] >= 0 && ys[i] < src_height)
                          {
                            gfloat *tpix = src_buf + (xs[i]+ys[i]* src_width)*4;
                            gfloat diff = colordiff (tpix, center_pix);
                            if (diff < best_diff)
                              {
                                best_diff = diff;
                                selected_pix = tpix;
                              }
                          }
                      }
                  }

                /* accumulate the components of the best sample from
                 * the symmetric quadruple
                 */
                for (i=0;i<4;i++)
                  {
                    accumulated[i] += selected_pix[i];
                  }
                count++;

                if (u==0 && v==0)
                  break; /* to avoid doubly processing when using only 1 pair */
              }
          for (u=0; u<4; u++)
            dst_buf[offset*4+u] = accumulated[u]/count;
          offset++;

          center_pix += 4;
        }
    }
  gegl_buffer_set (dst, dst_rect, 0, babl_format ("RGBA float"), dst_buf,
                   GEGL_AUTO_ROWSTRIDE);
  g_free (src_buf);
  g_free (dst_buf);
}