Add grayscale median

This commit is contained in:
iabdalkader 2014-03-16 22:24:47 +02:00
parent 822cd035b2
commit fb928482b4

View File

@ -22,46 +22,61 @@
typedef struct {
int n;
int r[32];
int g[64];
int b[32];
} color_histo_t;
union {
int h[2];
struct {
int r[32];
int g[64];
int b[32];
};
};
} histo_t;
void del_pixels(image_t * im, int row, int col, int size, color_histo_t *h)
void del_pixels(image_t * im, int row, int col, int size, histo_t *h)
{
int i;
uint16_t c;
if (col < 0 || col >= im->w) return;
for (i = row - size; i <= row + size && i < im->h; i++) {
if (i < 0) continue;
c = SWAP(((uint16_t*)im->pixels)[i*im->w+col]);
h->r[R(c)]--;
h->g[G(c)]--;
h->b[B(c)]--;
h->n--;
if (im->bpp==1) {
for (int i = row - size; i <= row + size && i < im->h; i++) {
if (i < 0) continue;
h->h[im->pixels[i*im->w+col]]--;
h->n--;
}
} else {
for (int i = row - size; i <= row + size && i < im->h; i++) {
if (i < 0) continue;
uint16_t c = SWAP(((uint16_t*)im->pixels)[i*im->w+col]);
h->r[R(c)]--;
h->g[G(c)]--;
h->b[B(c)]--;
h->n--;
}
}
}
void add_pixels(image_t * im, int row, int col, int size, color_histo_t *h)
void add_pixels(image_t * im, int row, int col, int size, histo_t *h)
{
int i;
uint16_t c;
if (col < 0 || col >= im->w) return;
for (i = row - size; i <= row + size && i < im->h; i++) {
if (i < 0) continue;
c = SWAP(((uint16_t*)im->pixels)[i*im->w+col]);
h->r[R(c)]++;
h->g[G(c)]++;
h->b[B(c)]++;
h->n++;
if (im->bpp==1) {
for (int i = row - size; i <= row + size && i < im->h; i++) {
if (i < 0) continue;
h->h[im->pixels[i*im->w+col]]++;
h->n++;
}
} else {
for (int i = row - size; i <= row + size && i < im->h; i++) {
if (i < 0) continue;
uint16_t c = SWAP(((uint16_t*)im->pixels)[i*im->w+col]);
h->r[R(c)]++;
h->g[G(c)]++;
h->b[B(c)]++;
h->n++;
}
}
}
void init_histo(image_t *im, int row, int size, color_histo_t *h)
void init_histo(image_t *im, int row, int size, histo_t *h)
{
memset(h, 0, sizeof(color_histo_t));
//memset(h, 0, sizeof(histo_t));
h->n = 0;
h->h[0] = h->h[1]=0;
for (int j = 0; j < size && j < im->w; j++) {
add_pixels(im, row, j, size, h);
}
@ -74,13 +89,15 @@ uint16_t median(const int *x, int n)
return i;
}
void imlib_median_filter(image_t *in, int size)
void median_filter_rgb(image_t *in, int size)
{
uint16_t r,g,b;
color_histo_t *h = xalloc(sizeof(*h));
uint16_t *data = (uint16_t*) (in->data+(in->w * in->h*2));
int k_rows = size+1;
histo_t *h = xalloc(sizeof(*h));
uint16_t *data = xalloc(in->w * k_rows * sizeof(*data));
for (int row = 0; row<in->h; row ++) {
for (int row = 0; row<in->h; row++) {
for (int col = 0; col<in->w; col++) {
if (!col) {
init_histo(in, row, size, h);
@ -91,9 +108,70 @@ void imlib_median_filter(image_t *in, int size)
r = median(h->r, h->n);
g = median(h->g, h->n);
b = median(h->b, h->n);
data[row*in->w+col] = SWAP(((r << 11) | (g << 5) | b));
data[(row%k_rows)*in->w+col] = SWAP(((r << 11) | (g << 5) | b));
}
if ((row+1)%k_rows==0) {
memcpy((uint16_t*)in->data+((row/k_rows)*k_rows*in->w), data, (k_rows*in->w*sizeof(*data)));
}
}
memcpy(in->data, data, (in->w*in->h*2));
xfree(h);
xfree(data);
}
#if 0
void median_filter_gs(image_t *in, int size)
{
histo_t *h = xalloc(sizeof(*h));
uint8_t *data = (uint8_t*) (in->data+(in->w * in->h*2));
for (int row = 0; row<in->h; row ++) {
for (int col = 0; col<in->w; col++) {
if (!col) {
init_histo(in, row, size, h);
} else {
del_pixels(in, row, col - size, size, h);
add_pixels(in, row, col + size, size, h);
}
data[row*in->w+col]=(uint8_t)median(h->h, h->n);
}
}
memcpy(in->data, data, (in->w*in->h));
}
#else
void median_filter_gs(image_t *in, int size)
{
int k_rows = (2*size+1)*2;
histo_t *h = xalloc(sizeof(*h));
uint8_t *data = xalloc(in->w * k_rows * sizeof(*data));
for (int row = 0; row<in->h; row ++) {
for (int col = 0; col<in->w; col++) {
if (!col) {
init_histo(in, row, size, h);
} else if ((col-size) > 0 && (col+size) < in->w) {
del_pixels(in, row, col - size, size, h);
add_pixels(in, row, col + size, size, h);
}
data[(row%k_rows)*in->w+col] = (uint8_t)median(h->h, h->n);
}
if ((row+1)%k_rows==0) {
memcpy(in->data+((row/k_rows)*k_rows*in->w), data, (k_rows*in->w*sizeof(*data)));
}
}
xfree(h);
xfree(data);
}
#endif
void imlib_median_filter(image_t *in, int size)
{
if (in->bpp == 1) {
//median_filter_test(in, size);
median_filter_gs(in, size);
} else {
median_filter_rgb(in, size);
}
}