static inline void
update_histogram (DespeckleHistogram *hist,
                  const guchar       *src,
                  gint                width,
                  gint                bpp,
                  gint                xmin,
                  gint                ymin,
                  gint                xmax,
                  gint                ymax)
{
  /* assuming that radious of the box can change no more than one
     pixel in each call */
  /* assuming that box is moving either right or down */

  del_vals (hist,
            src, width, bpp, hist->xmin, hist->ymin, xmin - 1, hist->ymax);
  del_vals (hist, src, width, bpp, xmin, hist->ymin, xmax, ymin - 1);
  del_vals (hist, src, width, bpp, xmin, ymax + 1, xmax, hist->ymax);

  add_vals (hist, src, width, bpp, hist->xmax + 1, ymin, xmax, ymax);
  add_vals (hist, src, width, bpp, xmin, ymin, hist->xmax, hist->ymin - 1);
  add_vals (hist,
            src, width, bpp, hist->xmin, hist->ymax + 1, hist->xmax, ymax);

  hist->xmin = xmin;
  hist->ymin = ymin;
  hist->xmax = xmax;
  hist->ymax = ymax;
}
Exemple #2
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct htable_obj ht, ht2;
	struct obj val[NUM_VALS], *result;
	unsigned int dne;
	void *p;
	struct htable_obj_iter iter;

	plan_tests(29);
	for (i = 0; i < NUM_VALS; i++)
		val[i].key = i;
	dne = i;

	htable_obj_init(&ht);
	ok1(ht.raw.max == 0);
	ok1(ht.raw.bits == 0);

	/* We cannot find an entry which doesn't exist. */
	ok1(!htable_obj_get(&ht, &dne));

	/* Fill it, it should increase in size. */
	add_vals(&ht, val, NUM_VALS);
	ok1(ht.raw.bits == NUM_BITS + 1);
	ok1(ht.raw.max < (1 << ht.raw.bits));

	/* Mask should be set. */
	ok1(ht.raw.common_mask != 0);
	ok1(ht.raw.common_mask != -1);
	ok1(check_mask(&ht.raw, val, NUM_VALS));

	/* Find all. */
	find_vals(&ht, val, NUM_VALS);
	ok1(!htable_obj_get(&ht, &dne));

	/* Walk once, should get them all. */
	i = 0;
	for (p = htable_obj_first(&ht,&iter); p; p = htable_obj_next(&ht, &iter))
		i++;
	ok1(i == NUM_VALS);
	i = 0;
	for (p = htable_obj_prev(&ht,&iter); p; p = htable_obj_prev(&ht, &iter))
		i++;
	ok1(i == NUM_VALS);

	/* Delete all. */
	del_vals(&ht, val, NUM_VALS);
	ok1(!htable_obj_get(&ht, &val[0].key));

	/* Worst case, a "pointer" which doesn't have any matching bits. */
	htable_add(&ht.raw, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]);
	htable_obj_add(&ht, &val[NUM_VALS-1]);
	ok1(ht.raw.common_mask == 0);
	ok1(ht.raw.common_bits == 0);
	/* Delete the bogus one before we trip over it. */
	htable_del(&ht.raw, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]);

	/* Add the rest. */
	add_vals(&ht, val, NUM_VALS-1);

	/* Check we can find them all. */
	find_vals(&ht, val, NUM_VALS);
	ok1(!htable_obj_get(&ht, &dne));

	/* Check copy. */
	ok1(htable_obj_copy(&ht2, &ht));

	/* Delete them all by key. */
	del_vals_bykey(&ht, val, NUM_VALS);
	del_vals_bykey(&ht2, val, NUM_VALS);

	/* Write two of the same value. */
	val[1] = val[0];
	htable_obj_add(&ht, &val[0]);
	htable_obj_add(&ht, &val[1]);
	i = 0;

	result = htable_obj_getfirst(&ht, &i, &iter);
	ok1(result == &val[0] || result == &val[1]);
	if (result == &val[0]) {
		ok1(htable_obj_getnext(&ht, &i, &iter) == &val[1]);
		ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);

		/* Deleting first should make us iterate over the other. */
		ok1(htable_obj_del(&ht, &val[0]));
		ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[1]);
		ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);
	} else {
		ok1(htable_obj_getnext(&ht, &i, &iter) == &val[0]);
		ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);

		/* Deleting first should make us iterate over the other. */
		ok1(htable_obj_del(&ht, &val[1]));
		ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[0]);
		ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);
	}

	htable_obj_clear(&ht);
	htable_obj_clear(&ht2);
	return exit_status();
}
Exemple #3
0
int main(int argc, char *argv[])
{
	unsigned int i;
	uintptr_t perfect_bit;
	struct htable ht;
	uint64_t val[NUM_VALS];
	uint64_t dne;
	void *p;
	struct htable_iter iter;

	plan_tests(29);
	for (i = 0; i < NUM_VALS; i++)
		val[i] = i;
	dne = i;

	htable_init(&ht, hash, NULL);
	ok1(ht.max == 0);
	ok1(ht.bits == 0);

	/* We cannot find an entry which doesn't exist. */
	ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne));

	/* This should increase it once. */
	add_vals(&ht, val, 0, 1);
	ok1(ht.bits == 1);
	ok1(ht.max == 1);
	ok1(ht.common_mask == -1);

	/* Mask should be set. */
	ok1(check_mask(&ht, val, 1));

	/* This should increase it again. */
	add_vals(&ht, val, 1, 1);
	ok1(ht.bits == 2);
	ok1(ht.max == 3);

	/* Mask should be set. */
	ok1(ht.common_mask != 0);
	ok1(ht.common_mask != -1);
	ok1(check_mask(&ht, val, 2));

	/* Now do the rest. */
	add_vals(&ht, val, 2, NUM_VALS - 2);

	/* Find all. */
	find_vals(&ht, val, NUM_VALS);
	ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne));

	/* Walk once, should get them all. */
	i = 0;
	for (p = htable_first(&ht,&iter); p; p = htable_next(&ht, &iter))
		i++;
	ok1(i == NUM_VALS);

	/* Delete all. */
	del_vals(&ht, val, NUM_VALS);
	ok1(!htable_get(&ht, hash(&val[0], NULL), objcmp, &val[0]));

	/* Worst case, a "pointer" which doesn't have any matching bits. */
	htable_add(&ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]);
	htable_add(&ht, hash(&val[NUM_VALS-1], NULL), &val[NUM_VALS-1]);
	ok1(ht.common_mask == 0);
	ok1(ht.common_bits == 0);
	/* Get rid of bogus pointer before we trip over it! */
	htable_del(&ht, 0, (void *)~(uintptr_t)&val[NUM_VALS-1]);

	/* Add the rest. */
	add_vals(&ht, val, 0, NUM_VALS-1);

	/* Check we can find them all. */
	find_vals(&ht, val, NUM_VALS);
	ok1(!htable_get(&ht, hash(&dne, NULL), objcmp, &dne));

	/* Corner cases: wipe out the perfect bit using bogus pointer. */
	htable_clear(&ht);
	htable_add(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1]));
	ok1(ht.perfect_bit);
	perfect_bit = ht.perfect_bit;
	htable_add(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1]
				   | perfect_bit));
	ok1(ht.perfect_bit == 0);
	htable_del(&ht, 0, (void *)((uintptr_t)&val[NUM_VALS-1] | perfect_bit));

	/* Enlarging should restore it... */
	add_vals(&ht, val, 0, NUM_VALS-1);

	ok1(ht.perfect_bit != 0);
	htable_clear(&ht);

	return exit_status();
}
static void
despeckle_median (guchar   *src,
                  guchar   *dst,
                  gint      width,
                  gint      height,
                  gint      bpp,
                  gint      radius,
                  gboolean  preview)
{
  guint  progress;
  guint  max_progress;
  gint   x, y;
  gint   input_radius = radius;
  gint   pos;
  gint   ymin;
  gint   ymax;
  gint   xmin;
  gint   xmax;

  memset (&histogram, 0, sizeof(histogram));
  progress     = 0;
  max_progress = width * height;

  if (! preview)
    gimp_progress_init(_("Despeckle"));


  for (y = 0; y < height; y++)
    {
      x = 0;
      ymin = MAX (0, y - radius);
      ymax = MIN (height - 1, y + radius);
      xmin = MAX (0, x - radius);
      xmax = MIN (width - 1, x + radius);
      hist0   = 0;
      histrest = 0;
      hist255 = 0;
      histogram_clean (&histogram);
      histogram.xmin = xmin;
      histogram.ymin = ymin;
      histogram.xmax = xmax;
      histogram.ymax = ymax;
      add_vals (&histogram,
                src, width, bpp,
                histogram.xmin, histogram.ymin, histogram.xmax, histogram.ymax);

      for (x = 0; x < width; x++)
        {
          const guchar *pixel;

          ymin = MAX (0, y - radius); /* update ymin, ymax when radius changed (FILTER_ADAPTIVE) */
          ymax = MIN (height - 1, y + radius);
          xmin = MAX (0, x - radius);
          xmax = MIN (width - 1, x + radius);

          update_histogram (&histogram,
                            src, width, bpp, xmin, ymin, xmax, ymax);

          pos = (x + (y * width)) * bpp;
          pixel = histogram_get_median (&histogram, src + pos);

          if (filter_type & FILTER_RECURSIVE)
            {
              del_val (&histogram, src, width, bpp, x, y);
              pixel_copy (src + pos, pixel, bpp);
              add_val (&histogram, src, width, bpp, x, y);
            }

          pixel_copy (dst + pos, pixel, bpp);

          /*
           * Check the histogram and adjust the diameter accordingly...
           */
          if (filter_type & FILTER_ADAPTIVE)
            {
              if (hist0 >= radius || hist255 >= radius)
                {
                  if (radius < input_radius)
                    radius++;
                }
              else if (radius > 1)
                {
                  radius--;
                }
            }
        }

      progress += width;

      if (! preview && y % 32 == 0)
        gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
    }

  if (! preview)
    gimp_progress_update (1.0);
}