Merge pull request #745 from bitbank2/master

optimized more image filters
This commit is contained in:
Ibrahim Abd Elkader 2020-03-30 21:29:33 +02:00 committed by GitHub
commit 1746744c28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -939,9 +939,14 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
buf.w = img->w; buf.w = img->w;
buf.h = brows; buf.h = brows;
buf.bpp = img->bpp; buf.bpp = img->bpp;
uint8_t *u8BiasTable;
float max_bias = bias, min_bias = 1.0f - bias; float max_bias = bias, min_bias = 1.0f - bias;
u8BiasTable = fb_alloc(256, FB_ALLOC_NO_HINT);
for (int i=0; i<256; i++) {
u8BiasTable[i] = (uint8_t)fast_floorf((float)i * bias);
}
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT); buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT);
@ -958,15 +963,26 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
int min = COLOR_BINARY_MAX, max = COLOR_BINARY_MIN; int min = COLOR_BINARY_MAX, max = COLOR_BINARY_MIN;
for (int j = -ksize; j <= ksize; j++) { if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, for (int j = -ksize; j <= ksize; j++) {
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,x+k);
min &= pixel;
max |= pixel;
}
}
} else {
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) { for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
min = IM_MIN(min, pixel); min &= pixel;
max = IM_MAX(max, pixel); max |= pixel;
}
} }
} }
@ -1014,20 +1030,30 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
} }
int min = COLOR_GRAYSCALE_MAX, max = COLOR_GRAYSCALE_MIN; int min = COLOR_GRAYSCALE_MAX, max = COLOR_GRAYSCALE_MIN;
if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
for (int j = -ksize; j <= ksize; j++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,x+k);
if (pixel < min) min = pixel;
else if (pixel > max) max = pixel;
}
}
} else {
for (int j = -ksize; j <= ksize; j++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int j = -ksize; j <= ksize; j++) { for (int k = -ksize; k <= ksize; k++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
if (pixel < min) min = pixel;
for (int k = -ksize; k <= ksize; k++) { else if (pixel > max) max = pixel;
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, }
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
min = IM_MIN(min, pixel);
max = IM_MAX(max, pixel);
} }
} }
int pixel = fast_floorf((min*min_bias)+(max*max_bias)); int pixel = min + u8BiasTable[max-min];
if (threshold) { if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) { if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1073,29 +1099,47 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
int r_min = COLOR_R5_MAX, r_max = COLOR_R5_MIN; int r_min = COLOR_R5_MAX, r_max = COLOR_R5_MIN;
int g_min = COLOR_G6_MAX, g_max = COLOR_G6_MIN; int g_min = COLOR_G6_MAX, g_max = COLOR_G6_MIN;
int b_min = COLOR_B5_MAX, b_max = COLOR_B5_MIN; int b_min = COLOR_B5_MAX, b_max = COLOR_B5_MIN;
if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
for (int j = -ksize; j <= ksize; j++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,x+k);
int r_pixel = COLOR_RGB565_TO_R5(pixel);
int g_pixel = COLOR_RGB565_TO_G6(pixel);
int b_pixel = COLOR_RGB565_TO_B5(pixel);
if (r_pixel < r_min) r_min = r_pixel;
else if (r_pixel > r_max) r_max = r_pixel;
if (g_pixel < g_min) g_min = g_pixel;
else if (g_pixel > g_max) g_max = g_pixel;
if (b_pixel < b_min) b_min = b_pixel;
else if (b_pixel > b_max) b_max = b_pixel;
}
}
} else {
for (int j = -ksize; j <= ksize; j++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int j = -ksize; j <= ksize; j++) { for (int k = -ksize; k <= ksize; k++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
int r_pixel = COLOR_RGB565_TO_R5(pixel);
for (int k = -ksize; k <= ksize; k++) { int g_pixel = COLOR_RGB565_TO_G6(pixel);
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr, int b_pixel = COLOR_RGB565_TO_B5(pixel);
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); if (r_pixel < r_min) r_min = r_pixel;
int r_pixel = COLOR_RGB565_TO_R5(pixel); else if (r_pixel > r_max) r_max = r_pixel;
int g_pixel = COLOR_RGB565_TO_G6(pixel); if (g_pixel < g_min) g_min = g_pixel;
int b_pixel = COLOR_RGB565_TO_B5(pixel); else if (g_pixel > g_max) g_max = g_pixel;
r_min = IM_MIN(r_min, r_pixel); if (b_pixel < b_min) b_min = b_pixel;
r_max = IM_MAX(r_max, r_pixel); else if (b_pixel > b_max) b_max = b_pixel;
g_min = IM_MIN(g_min, g_pixel); }
g_max = IM_MAX(g_max, g_pixel);
b_min = IM_MIN(b_min, b_pixel);
b_max = IM_MAX(b_max, b_pixel);
} }
} }
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_floorf((r_min*min_bias)+(r_max*max_bias)), r_min += u8BiasTable[r_max-r_min];
fast_floorf((g_min*min_bias)+(g_max*max_bias)), g_min += u8BiasTable[g_max-g_min];
fast_floorf((b_min*min_bias)+(b_max*max_bias))); b_min += u8BiasTable[b_max-b_min];
int pixel = COLOR_R5_G6_B5_TO_RGB565(r_min, g_min, b_min);
if (threshold) { if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) { if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
@ -1129,6 +1173,7 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
break; break;
} }
} }
fb_free();
} }
#endif // IMLIB_ENABLE_MIDPOINT #endif // IMLIB_ENABLE_MIDPOINT
@ -1141,6 +1186,7 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
buf.w = img->w; buf.w = img->w;
buf.h = brows; buf.h = brows;
buf.bpp = img->bpp; buf.bpp = img->bpp;
const int32_t m_int = (int32_t)(65536.0 * m); // m is 1/kernel_weight
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
@ -1158,17 +1204,28 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
int acc = 0, ptr = 0; int acc = 0, ptr = 0;
for (int j = -ksize; j <= ksize; j++) { if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, for (int j = -ksize; j <= ksize; j++) {
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
acc += krn[ptr++] * IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,x+k);
}
}
} else {
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) { for (int k = -ksize; k <= ksize; k++) {
acc += krn[ptr++] * IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, acc += krn[ptr++] * IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
}
} }
} }
int32_t tmp = (acc * m_int) >> 16;
int pixel = IM_MAX(IM_MIN(fast_floorf(acc * m) + b, COLOR_BINARY_MAX), COLOR_BINARY_MIN); int pixel = tmp + b;
if (pixel < 0) pixel = 0;
else if (pixel > 1) pixel = 1;
if (threshold) { if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) { if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1211,19 +1268,30 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
continue; // Short circuit. continue; // Short circuit.
} }
int acc = 0, ptr = 0; int32_t acc = 0, ptr = 0;
for (int j = -ksize; j <= ksize; j++) { if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, for (int j = -ksize; j <= ksize; j++) {
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
acc += krn[ptr++] * IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,x+k);
}
}
} else {
for (int j = -ksize; j <= ksize; j++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) { for (int k = -ksize; k <= ksize; k++) {
acc += krn[ptr++] * IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, acc += krn[ptr++] * IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
}
} }
} }
int32_t tmp = (acc * m_int)>>16;
int pixel = IM_MAX(IM_MIN(fast_floorf(acc * m) + b, COLOR_GRAYSCALE_MAX), COLOR_GRAYSCALE_MIN); int pixel = tmp + b;
if (pixel > COLOR_GRAYSCALE_MAX) pixel = COLOR_GRAYSCALE_MAX;
else if (pixel < 0) pixel = 0;
if (threshold) { if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) { if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1266,24 +1334,45 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
continue; // Short circuit. continue; // Short circuit.
} }
int r_acc = 0, g_acc = 0, b_acc = 0, ptr = 0; int32_t tmp, r_acc = 0, g_acc = 0, b_acc = 0, ptr = 0;
for (int j = -ksize; j <= ksize; j++) { if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, for (int j = -ksize; j <= ksize; j++) {
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
for (int k = -ksize; k <= ksize; k++) { int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,x+k);
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr, r_acc += krn[ptr] * COLOR_RGB565_TO_R5(pixel);
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); g_acc += krn[ptr] * COLOR_RGB565_TO_G6(pixel);
r_acc += krn[ptr] * COLOR_RGB565_TO_R5(pixel); b_acc += krn[ptr++] * COLOR_RGB565_TO_B5(pixel);
g_acc += krn[ptr] * COLOR_RGB565_TO_G6(pixel); }
b_acc += krn[ptr++] * COLOR_RGB565_TO_B5(pixel); }
} else {
for (int j = -ksize; j <= ksize; j++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
r_acc += krn[ptr] * COLOR_RGB565_TO_R5(pixel);
g_acc += krn[ptr] * COLOR_RGB565_TO_G6(pixel);
b_acc += krn[ptr++] * COLOR_RGB565_TO_B5(pixel);
}
} }
} }
tmp = (r_acc * m_int) >> 16;
int pixel = COLOR_R5_G6_B5_TO_RGB565(IM_MAX(IM_MIN(fast_floorf(r_acc * m) + b, COLOR_R5_MAX), COLOR_R5_MIN), r_acc = tmp + b;
IM_MAX(IM_MIN(fast_floorf(g_acc * m) + b, COLOR_G6_MAX), COLOR_G6_MIN), if (r_acc > COLOR_R5_MAX) r_acc = COLOR_R5_MAX;
IM_MAX(IM_MIN(fast_floorf(b_acc * m) + b, COLOR_B5_MAX), COLOR_B5_MIN)); else if (r_acc < 0) r_acc = 0;
tmp = (g_acc * m_int) >> 16;
g_acc = tmp + b;
if (g_acc > COLOR_G6_MAX) g_acc = COLOR_G6_MAX;
else if (g_acc < 0) g_acc = 0;
tmp = (b_acc * m_int) >> 16;
b_acc = tmp + b;
if (b_acc > COLOR_B5_MAX) b_acc = COLOR_B5_MAX;
else if (b_acc < 0) b_acc = 0;
int pixel = COLOR_R5_G6_B5_TO_RGB565(r_acc, g_acc, b_acc);
if (threshold) { if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) { if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
@ -1341,11 +1430,11 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT); buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT);
float *gi_lut = fb_alloc((COLOR_BINARY_MAX - COLOR_BINARY_MIN + 1) * sizeof(float), FB_ALLOC_NO_HINT); float *gi_lut_ptr = fb_alloc((COLOR_BINARY_MAX - COLOR_BINARY_MIN + 1) * sizeof(float) *2, FB_ALLOC_NO_HINT);
float *gi_lut = &gi_lut_ptr[1];
float max_color = IM_DIV(1.0f, COLOR_BINARY_MAX - COLOR_BINARY_MIN); float max_color = IM_DIV(1.0f, COLOR_BINARY_MAX - COLOR_BINARY_MIN);
for (int i = COLOR_BINARY_MIN; i <= COLOR_BINARY_MAX; i++) { for (int i = COLOR_BINARY_MIN; i <= COLOR_BINARY_MAX; i++) {
gi_lut[i] = gaussian(i * max_color, color_sigma); gi_lut[-i] = gi_lut[i] = gaussian(i * max_color, color_sigma);
} }
int n = (ksize * 2) + 1; int n = (ksize * 2) + 1;
@ -1370,7 +1459,7 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
int this_pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x); int this_pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x);
float i_acc = 0, w_acc = 0; float i_acc = 0, w_acc = 0;
int ptr = 0;
for (int j = -ksize; j <= ksize; j++) { for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
@ -1378,7 +1467,7 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
for (int k = -ksize; k <= ksize; k++) { for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
float w = gi_lut[abs(this_pixel - pixel)] * gs_lut[(n * (j + ksize)) + (k + ksize)]; float w = gi_lut[(this_pixel - pixel)] * gs_lut[ptr++];
i_acc += pixel * w; i_acc += pixel * w;
w_acc += w; w_acc += w;
} }
@ -1418,11 +1507,11 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
buf.data = fb_alloc(IMAGE_GRAYSCALE_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT); buf.data = fb_alloc(IMAGE_GRAYSCALE_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT);
float *gi_lut = fb_alloc((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN + 1) * sizeof(float), FB_ALLOC_NO_HINT); float *gi_lut_ptr = fb_alloc((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN + 1) * sizeof(float) * 2, FB_ALLOC_NO_HINT);
float *gi_lut = &gi_lut_ptr[256]; // point to the middle
float max_color = IM_DIV(1.0f, COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN); float max_color = IM_DIV(1.0f, COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN);
for (int i = COLOR_GRAYSCALE_MIN; i <= COLOR_GRAYSCALE_MAX; i++) { for (int i = COLOR_GRAYSCALE_MIN; i <= COLOR_GRAYSCALE_MAX; i++) {
gi_lut[i] = gaussian(i * max_color, color_sigma); gi_lut[-i] = gi_lut[i] = gaussian(i * max_color, color_sigma);
} }
int n = (ksize * 2) + 1; int n = (ksize * 2) + 1;
@ -1447,17 +1536,29 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
int this_pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x); int this_pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x);
float i_acc = 0, w_acc = 0; float i_acc = 0, w_acc = 0;
int ptr = 0;
if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
for (int j = -ksize; j <= ksize; j++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y+j);
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, x+k);
float w = gi_lut[this_pixel - pixel] * gs_lut[ptr++];
i_acc += pixel * w;
w_acc += w;
}
}
} else {
for (int j = -ksize; j <= ksize; j++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int j = -ksize; j <= ksize; j++) { for (int k = -ksize; k <= ksize; k++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
float w = gi_lut[(this_pixel - pixel)] * gs_lut[ptr++];
for (int k = -ksize; k <= ksize; k++) { i_acc += pixel * w;
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, w_acc += w;
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); }
float w = gi_lut[abs(this_pixel - pixel)] * gs_lut[(n * (j + ksize)) + (k + ksize)];
i_acc += pixel * w;
w_acc += w;
} }
} }
@ -1495,23 +1596,19 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
} }
case IMAGE_BPP_RGB565: { case IMAGE_BPP_RGB565: {
buf.data = fb_alloc(IMAGE_RGB565_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT); buf.data = fb_alloc(IMAGE_RGB565_LINE_LEN_BYTES(img) * brows, FB_ALLOC_NO_HINT);
float *r_gi_lut = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(float), FB_ALLOC_NO_HINT); float *rb_gi_ptr = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(float) *2, FB_ALLOC_NO_HINT);
float *g_gi_lut = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(float), FB_ALLOC_NO_HINT); float *g_gi_ptr = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(float) *2, FB_ALLOC_NO_HINT);
float *b_gi_lut = fb_alloc((COLOR_B5_MAX - COLOR_B5_MIN + 1) * sizeof(float), FB_ALLOC_NO_HINT); float *rb_gi_lut = &rb_gi_ptr[32]; // center
float *g_gi_lut = &g_gi_ptr[64];
float r_max_color = IM_DIV(1.0f, COLOR_R5_MAX - COLOR_R5_MIN); float r_max_color = IM_DIV(1.0f, COLOR_R5_MAX - COLOR_R5_MIN);
for (int i = COLOR_R5_MIN; i <= COLOR_R5_MAX; i++) { for (int i = COLOR_R5_MIN; i <= COLOR_R5_MAX; i++) {
r_gi_lut[i] = gaussian(i * r_max_color, color_sigma); rb_gi_lut[-i] = rb_gi_lut[i] = gaussian(i * r_max_color, color_sigma);
} }
float g_max_color = IM_DIV(1.0f, COLOR_G6_MAX - COLOR_G6_MIN); float g_max_color = IM_DIV(1.0f, COLOR_G6_MAX - COLOR_G6_MIN);
for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; i++) { for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; i++) {
g_gi_lut[i] = gaussian(i * g_max_color, color_sigma); g_gi_lut[-i] = g_gi_lut[i] = gaussian(i * g_max_color, color_sigma);
}
float b_max_color = IM_DIV(1.0f, COLOR_B5_MAX - COLOR_B5_MIN);
for (int i = COLOR_B5_MIN; i <= COLOR_B5_MAX; i++) {
b_gi_lut[i] = gaussian(i * b_max_color, color_sigma);
} }
int n = (ksize * 2) + 1; int n = (ksize * 2) + 1;
@ -1541,27 +1638,49 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
float r_i_acc = 0, r_w_acc = 0; float r_i_acc = 0, r_w_acc = 0;
float g_i_acc = 0, g_w_acc = 0; float g_i_acc = 0, g_w_acc = 0;
float b_i_acc = 0, b_w_acc = 0; float b_i_acc = 0, b_w_acc = 0;
int ptr = 0;
if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) {
for (int j = -ksize; j <= ksize; j++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,y+j);
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,x+k);
int r_pixel = COLOR_RGB565_TO_R5(pixel);
int g_pixel = COLOR_RGB565_TO_G6(pixel);
int b_pixel = COLOR_RGB565_TO_B5(pixel);
float gs = gs_lut[ptr++];
float r_w = rb_gi_lut[(r_this_pixel - r_pixel)] * gs;
float g_w = g_gi_lut[(g_this_pixel - g_pixel)] * gs;
float b_w = rb_gi_lut[(b_this_pixel - b_pixel)] * gs;
r_i_acc += r_pixel * r_w;
r_w_acc += r_w;
g_i_acc += g_pixel * g_w;
g_w_acc += g_w;
b_i_acc += b_pixel * b_w;
b_w_acc += b_w;
}
}
} else { // check boundary conditions
for (int j = -ksize; j <= ksize; j++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int j = -ksize; j <= ksize; j++) { for (int k = -ksize; k <= ksize; k++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1))); IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
int r_pixel = COLOR_RGB565_TO_R5(pixel);
for (int k = -ksize; k <= ksize; k++) { int g_pixel = COLOR_RGB565_TO_G6(pixel);
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr, int b_pixel = COLOR_RGB565_TO_B5(pixel);
IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); float gs = gs_lut[ptr++];
int r_pixel = COLOR_RGB565_TO_R5(pixel); float r_w = rb_gi_lut[(r_this_pixel - r_pixel)] * gs;
int g_pixel = COLOR_RGB565_TO_G6(pixel); float g_w = g_gi_lut[(g_this_pixel - g_pixel)] * gs;
int b_pixel = COLOR_RGB565_TO_B5(pixel); float b_w = rb_gi_lut[(b_this_pixel - b_pixel)] * gs;
float gs = gs_lut[(n * (j + ksize)) + (k + ksize)]; r_i_acc += r_pixel * r_w;
float r_w = r_gi_lut[abs(r_this_pixel - r_pixel)] * gs; r_w_acc += r_w;
float g_w = g_gi_lut[abs(g_this_pixel - g_pixel)] * gs; g_i_acc += g_pixel * g_w;
float b_w = b_gi_lut[abs(b_this_pixel - b_pixel)] * gs; g_w_acc += g_w;
r_i_acc += r_pixel * r_w; b_i_acc += b_pixel * b_w;
r_w_acc += r_w; b_w_acc += b_w;
g_i_acc += g_pixel * g_w; }
g_w_acc += g_w;
b_i_acc += b_pixel * b_w;
b_w_acc += b_w;
} }
} }
@ -1598,7 +1717,6 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
fb_free(); fb_free();
fb_free(); fb_free();
fb_free(); fb_free();
fb_free();
break; break;
} }
default: { default: {