From f6136477fd2e74ba7e2c32b4373dcb6a1a633344 Mon Sep 17 00:00:00 2001 From: Larry Bank Date: Mon, 30 Mar 2020 02:18:43 +0200 Subject: [PATCH] optimized more image filters --- src/omv/img/filter.c | 356 ++++++++++++++++++++++++++++--------------- 1 file changed, 237 insertions(+), 119 deletions(-) diff --git a/src/omv/img/filter.c b/src/omv/img/filter.c index 958537552..2794c5eb3 100644 --- a/src/omv/img/filter.c +++ b/src/omv/img/filter.c @@ -939,9 +939,14 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres buf.w = img->w; buf.h = brows; buf.bpp = img->bpp; - + uint8_t *u8BiasTable; 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) { case IMAGE_BPP_BINARY: { 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; - 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))); + if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) { + for (int j = -ksize; j <= ksize; j++) { + 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++) { - int pixel = IMAGE_GET_BINARY_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); + for (int k = -ksize; k <= ksize; k++) { + int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, + IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + min &= 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; + 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++) { - 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++) { - 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); + for (int k = -ksize; k <= ksize; k++) { + int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, + IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + if (pixel < min) min = pixel; + else if (pixel > max) max = pixel; + } } } - int pixel = fast_floorf((min*min_bias)+(max*max_bias)); + int pixel = min + u8BiasTable[max-min]; if (threshold) { 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 g_min = COLOR_G6_MAX, g_max = COLOR_G6_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++) { - 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))); - int r_pixel = COLOR_RGB565_TO_R5(pixel); - int g_pixel = COLOR_RGB565_TO_G6(pixel); - int b_pixel = COLOR_RGB565_TO_B5(pixel); - r_min = IM_MIN(r_min, r_pixel); - r_max = IM_MAX(r_max, r_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); + 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))); + 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; + } } } - int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_floorf((r_min*min_bias)+(r_max*max_bias)), - fast_floorf((g_min*min_bias)+(g_max*max_bias)), - fast_floorf((b_min*min_bias)+(b_max*max_bias))); + r_min += u8BiasTable[r_max-r_min]; + g_min += u8BiasTable[g_max-g_min]; + b_min += u8BiasTable[b_max-b_min]; + int pixel = COLOR_R5_G6_B5_TO_RGB565(r_min, g_min, b_min); if (threshold) { 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; } } + fb_free(); } #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.h = brows; buf.bpp = img->bpp; + const int32_t m_int = (int32_t)(65536.0 * m); // m is 1/kernel_weight switch(img->bpp) { 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; - 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))); + if (x >= ksize && x < img->w-ksize && y >= ksize && y < img->h-ksize) { + for (int j = -ksize; j <= ksize; j++) { + 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++) { - acc += krn[ptr++] * IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, - IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + for (int k = -ksize; k <= ksize; k++) { + acc += krn[ptr++] * IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, + IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + } } } - - int pixel = IM_MAX(IM_MIN(fast_floorf(acc * m) + b, COLOR_BINARY_MAX), COLOR_BINARY_MIN); + int32_t tmp = (acc * m_int) >> 16; + int pixel = tmp + b; + if (pixel < 0) pixel = 0; + else if (pixel > 1) pixel = 1; if (threshold) { 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. } - int acc = 0, ptr = 0; + int32_t acc = 0, ptr = 0; - 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))); + 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++) { + 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++) { - acc += krn[ptr++] * IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, - IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + for (int k = -ksize; k <= ksize; k++) { + acc += krn[ptr++] * IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, + IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + } } } - - int pixel = IM_MAX(IM_MIN(fast_floorf(acc * m) + b, COLOR_GRAYSCALE_MAX), COLOR_GRAYSCALE_MIN); + int32_t tmp = (acc * m_int)>>16; + int pixel = tmp + b; + if (pixel > COLOR_GRAYSCALE_MAX) pixel = COLOR_GRAYSCALE_MAX; + else if (pixel < 0) pixel = 0; if (threshold) { 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. } - 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++) { - 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); + 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); + 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); + } + } + } 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); + } } } - - int pixel = COLOR_R5_G6_B5_TO_RGB565(IM_MAX(IM_MIN(fast_floorf(r_acc * m) + b, COLOR_R5_MAX), COLOR_R5_MIN), - IM_MAX(IM_MIN(fast_floorf(g_acc * m) + b, COLOR_G6_MAX), COLOR_G6_MIN), - IM_MAX(IM_MIN(fast_floorf(b_acc * m) + b, COLOR_B5_MAX), COLOR_B5_MIN)); + tmp = (r_acc * m_int) >> 16; + r_acc = tmp + b; + if (r_acc > COLOR_R5_MAX) r_acc = COLOR_R5_MAX; + 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 (((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) { case IMAGE_BPP_BINARY: { 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); 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; @@ -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); float i_acc = 0, w_acc = 0; - + int ptr = 0; 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))); @@ -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++) { int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr, 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; 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: { 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); 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; @@ -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); 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++) { - 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++) { - int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, - 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; + for (int k = -ksize; k <= ksize; k++) { + int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr, + IM_MIN(IM_MAX(x + k, 0), (img->w - 1))); + float w = gi_lut[(this_pixel - pixel)] * gs_lut[ptr++]; + 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: { 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 *g_gi_lut = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(float), 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_ptr = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(float) *2, 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 *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); 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); for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; 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); + g_gi_lut[-i] = g_gi_lut[i] = gaussian(i * g_max_color, color_sigma); } 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 g_i_acc = 0, g_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++) { - 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))); - 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[(n * (j + ksize)) + (k + ksize)]; - float r_w = r_gi_lut[abs(r_this_pixel - r_pixel)] * gs; - float g_w = g_gi_lut[abs(g_this_pixel - g_pixel)] * gs; - float b_w = b_gi_lut[abs(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; + 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))); + 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; + } } } @@ -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(); break; } default: {