diff --git a/lib/imlib/bayer.c b/lib/imlib/bayer.c index 7c45f6cf9..2b93a0423 100644 --- a/lib/imlib/bayer.c +++ b/lib/imlib/bayer.c @@ -559,6 +559,10 @@ static inline v128_t vdebayer_to_cr(vrgb_pixels_t pixels) { return pixels.r; } +// FIXME: This needs to be placed in the DTCM. .bss is in the DTCM on Alif. But, this is not portable. +// Move this to a proper DTCM section for other platforms. +static uint8_t gamma_lut[256]; + // In the case of vectors larger than 32-bits the pattern is repeated for every 32-bits. // // pixels.r = MSB [0, R1, 0, R0] LSB pixels where each pixel is 8-bits. @@ -569,6 +573,9 @@ static inline v128_t vdebayer_to_cr(vrgb_pixels_t pixels) { static inline vrgb_pixels_t vdebayer_apply_rb_gain(vrgb_pixels_t pixels, uint32_t red_gain, uint32_t blue_gain) { pixels.r = vusat_s16_narrow_u8_lo(pixels.r, vmul_n_u32(pixels.r, red_gain), 5); pixels.b = vusat_s16_narrow_u8_lo(pixels.b, vmul_n_u32(pixels.b, blue_gain), 5); + pixels.r = vldr_u8_gather(gamma_lut, pixels.r); + pixels.g = vldr_u8_gather(gamma_lut, pixels.g); + pixels.b = vldr_u8_gather(gamma_lut, pixels.b); return pixels; } @@ -2291,13 +2298,19 @@ static void vdebayer_rggb_to_rgb565_awb_quarter(image_t *src, image_t *dst, uint // GRAYSCALE: src->data == dst->data // RGB565: src->data == dst->data + image_size(src) // YUV422: Not supported -void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out) { +void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out, + float brightness, float contrast, float gamma) { uint32_t red_gain = IM_DIV(g_out * 32, r_out); red_gain = IM_MIN(red_gain, 128U); uint32_t blue_gain = IM_DIV(g_out * 32, b_out); blue_gain = IM_MIN(blue_gain, 128U); + for (int i = 0; i < 256; i++) { + int v = fast_roundf(((fast_powf(i * (1.0f / 255.0f), gamma) * contrast) + brightness) * 255.0f); + gamma_lut[i] = IM_CLAMP(v, 0, 255); + } + if (fast) { switch (src->pixfmt) { case PIXFORMAT_BAYER_BGGR: { diff --git a/lib/imlib/imlib.h b/lib/imlib/imlib.h index a3a87ff74..d622dd4e7 100644 --- a/lib/imlib/imlib.h +++ b/lib/imlib/imlib.h @@ -1207,7 +1207,8 @@ pixformat_t imlib_bayer_shift(pixformat_t pixfmt, int x, int y, bool transpose); void imlib_debayer_ycbcr(image_t *src, rectangle_t *roi, int8_t *Y0, int8_t *CB, int8_t *CR); void imlib_debayer_line(int x_start, int x_end, int y_row, void *dst_row_ptr, pixformat_t pixfmt, image_t *src); void imlib_debayer_image(image_t *dst, image_t *src); -void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out); +void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out, + float brightness, float contrast, float gamma); // YUV Image Processing pixformat_t imlib_yuv_shift(pixformat_t pixfmt, int x); diff --git a/lib/imlib/simd.h b/lib/imlib/simd.h index ffc195c9e..d31e5adf9 100644 --- a/lib/imlib/simd.h +++ b/lib/imlib/simd.h @@ -1514,6 +1514,19 @@ static inline v128_t vldr_u8_pred(const uint8_t *p, v128_predicate_t pred) { #endif } +static inline v128_t vldr_u8_gather(const uint8_t *p, v128_t offsets) { + #if (__ARM_ARCH >= 8) + return (v128_t) vldrbq_gather_offset(p, offsets.u8); + #else + v128_t v0; + v0.u8[0] = *(p + offsets.u8[0]); + v0.u8[1] = *(p + offsets.u8[1]); + v0.u8[2] = *(p + offsets.u8[2]); + v0.u8[3] = *(p + offsets.u8[3]); + return v0; + #endif +} + static inline v128_t vldr_u8_widen_u32_gather_pred(const uint8_t *p, v128_t offsets, v128_predicate_t pred) { diff --git a/ports/alif/omv_csi.c b/ports/alif/omv_csi.c index 3b392abde..c4b0568c3 100644 --- a/ports/alif/omv_csi.c +++ b/ports/alif/omv_csi.c @@ -404,7 +404,7 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) { } // Debayer frame. - imlib_debayer_image_awb(dst_image, &src_image, false, r_stat, g_stat, b_stat); + imlib_debayer_image_awb(dst_image, &src_image, false, r_stat, g_stat, b_stat, 0.0f, 1.0f, 0.5f); } return 0; }