/** finds median in unsorted set by sorting only minimum required */ static f_pixel get_median(const box* b, hist_item achv[]) { const uint median_start = (b->colors-1)/2; hist_item_sort_range(&(achv[b->ind]), b->colors, median_start, b->colors&1 ? 1 : 2); if (b->colors&1) return achv[b->ind + median_start].acolor; return averagepixels(2, &achv[b->ind + median_start], 1.0); }
/** finds median in unsorted set by sorting only minimum required */ static f_pixel get_median(const struct box *b, hist_item achv[]) { const unsigned int median_start = (b->colors-1)/2; hist_item_sort_range(&(achv[b->ind]), b->colors, median_start); if (b->colors&1) return achv[b->ind + median_start].acolor; // technically the second color is not guaranteed to be sorted correctly // but most of the time it is good enough to be useful return averagepixels(2, &achv[b->ind + median_start], 1.0, (f_pixel){0.5,0.5,0.5,0.5}); }
/** this is a simple qsort that completely sorts only elements between sort_start and +sort_len. Used to find median of the set. */ static void hist_item_sort_range(hist_item *base, unsigned int len, int sort_start, const int sort_len) { do { const unsigned int l = qsort_partition(base, len), r = l+1; if (sort_start+sort_len > 0 && (signed)l >= sort_start && l > 0) { hist_item_sort_range(base, l, sort_start, sort_len); } if (len > r && r < sort_start+sort_len && (signed)len > sort_start) { base += r; len -= r; sort_start -= r; // tail-recursive "call" } else return; } while(1); }