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; }
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(); }
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); }