diff --git a/src/omv/imlib/bayer.c b/src/omv/imlib/bayer.c index 47bbb08ab..02b354efb 100644 --- a/src/omv/imlib/bayer.c +++ b/src/omv/imlib/bayer.c @@ -10,7 +10,7 @@ */ #include "imlib.h" -void imlib_debayer_line_to_binary(int x_start, int x_end, int y_row, uint32_t *dst_row_ptr, image_t *src) +void imlib_debayer_line(int x_start, int x_end, int y_row, void *dst_row_ptr, pixformat_t pixfmt, image_t *src) { int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1; int src_h = src->h, h_limit = src_h - 1, h_limit_m_1 = h_limit - 1; @@ -94,34 +94,157 @@ void imlib_debayer_line_to_binary(int x_start, int x_end, int y_row, uint32_t *d row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); } - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + int r_pixels_0, g_pixels_0, b_pixels_0; - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); + r_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + #else - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - #endif + int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); - int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; - IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr, i, (y0 >> 7) & 0x1); + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); - if (x != w_limit) { - IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr, i + 1, (y0 >> 23) & 0x1); + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + #else + + int r0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + r_pixels_0 = r0 | (((r0 + r2) >> 1) << 16); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + b_pixels_0 = b1 | (row_bgbg_1 & 0xFF0000); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + #else + + int r1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + r_pixels_0 = r1 | (row_bgbg_1 & 0xFF0000); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + b_pixels_0 = b0 | (((b0 + b2) >> 1) << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + #else + + int r1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + r_pixels_0 = (r1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + + int b0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + b_pixels_0 = (b2 << 16) | ((b0 + b2) >> 1); + + #endif + break; + } + default: { + r_pixels_0 = 0; + g_pixels_0 = 0; + b_pixels_0 = 0; + break; + } + } + + switch (pixfmt) { + case PIXFORMAT_BINARY: { + uint32_t *dst_row_ptr_32 = (uint32_t *) dst_row_ptr; + int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; + IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr_32, i, (y0 >> 7)); + + if (x != w_limit) { + IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr_32, i + 1, (y0 >> 23)); + } + + break; + } + case PIXFORMAT_GRAYSCALE: { + uint8_t *dst_row_ptr_8 = (uint8_t *) dst_row_ptr; + int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr_8, i, y0); + + if (x != w_limit) { + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr_8, i + 1, y0 >> 16); + } + + break; + } + case PIXFORMAT_RGB565: { + uint16_t *dst_row_ptr_16 = (uint16_t *) dst_row_ptr; + int rgb565_0 = ((r_pixels_0 << 8) & 0xf800f800) | + ((g_pixels_0 << 3) & 0x07e007e0) | + ((b_pixels_0 >> 3) & 0x001f001f); + + if (x == w_limit) { // just put bottom + IMAGE_PUT_RGB565_PIXEL_FAST(dst_row_ptr_16, i, rgb565_0); + } else { // put both + *((uint32_t *) (dst_row_ptr_16 + i)) = rgb565_0; + } + + break; + } + default: { + break; + } } } } else { // odd @@ -175,49 +298,190 @@ void imlib_debayer_line_to_binary(int x_start, int x_end, int y_row, uint32_t *d row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); } - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + int r_pixels_1, g_pixels_1, b_pixels_1; - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; + r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + #else - int g1 = (row_bgbg_1 >> 16) & 0xFF; - int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - #endif + int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; - int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; - IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr, i, (y1 >> 7) & 0x1); + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); - if (x != w_limit) { - IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr, i + 1, (y1 >> 23) & 0x1); + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + #else + + int r2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + r_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (r2 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + b_pixels_1 = ((b1 + b3) >> 1) | (b3 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + #else + + int r1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + r_pixels_1 = ((r1 + r3) >> 1) | (r3 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + b_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (b2 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + #else + + int r1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + r_pixels_1 = (((r1 + r3) >> 1) << 16) | r1; + + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + + int b2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + b_pixels_1 = (row_grgr_2 & 0xFF0000) | b2; + + #endif + break; + } + default: { + r_pixels_1 = 0; + g_pixels_1 = 0; + b_pixels_1 = 0; + break; + } + } + + switch (pixfmt) { + case PIXFORMAT_BINARY: { + uint32_t *dst_row_ptr_32 = (uint32_t *) dst_row_ptr; + int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; + IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr_32, i, (y1 >> 7)); + + if (x != w_limit) { + IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr_32, i + 1, (y1 >> 23)); + } + + break; + } + case PIXFORMAT_GRAYSCALE: { + uint8_t *dst_row_ptr_8 = (uint8_t *) dst_row_ptr; + int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr_8, i, y1); + + if (x != w_limit) { + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr_8, i + 1, y1 >> 16); + } + + break; + } + case PIXFORMAT_RGB565: { + uint16_t *dst_row_ptr_16 = (uint16_t *) dst_row_ptr; + int rgb565_1 = ((r_pixels_1 << 8) & 0xf800f800) | + ((g_pixels_1 << 3) & 0x07e007e0) | + ((b_pixels_1 >> 3) & 0x001f001f); + + if (x == w_limit) { // just put bottom + IMAGE_PUT_RGB565_PIXEL_FAST(dst_row_ptr_16, i, rgb565_1); + } else { // put both + *((uint32_t *) (dst_row_ptr_16 + i)) = rgb565_1; + } + + break; + } + default: { + break; + } } } } } -// Does no bounds checking on the destination. -void imlib_debayer_image_to_binary(image_t *dst, image_t *src) +// Does no bounds checking on the destination. Destination must be mutable. +void imlib_debayer_image(image_t *dst, image_t *src) { int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1; int src_h = src->h, h_limit = src_h - 1, h_limit_m_1 = h_limit - 1; // If the image is an odd height this will go for the last loop and we drop the last row. for (int y = 0; y < src_h; y += 2) { - uint32_t *row_ptr_e = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(dst, y); - uint32_t *row_ptr_o = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(dst, y + 1); + void *row_ptr_e = NULL, *row_ptr_o = NULL; + + switch (dst->pixfmt) { + case PIXFORMAT_BINARY: { + row_ptr_e = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(dst, y); + row_ptr_o = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(dst, y + 1); + break; + } + case PIXFORMAT_GRAYSCALE: { + row_ptr_e = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(dst, y); + row_ptr_o = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(dst, y + 1); + break; + } + case PIXFORMAT_RGB565: { + row_ptr_e = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(dst, y); + row_ptr_o = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(dst, y + 1); + break; + } + } + uint8_t *rowptr_grgr_0, *rowptr_bgbg_1, *rowptr_grgr_2, *rowptr_bgbg_3; // keep row pointers in bounds @@ -305,804 +569,308 @@ void imlib_debayer_image_to_binary(image_t *dst, image_t *src) row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); } - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + int r_pixels_0, g_pixels_0, b_pixels_0; - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); + r_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + #else - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - #endif + int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); - int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; - IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_e, x, (y0 >> 7) & 0x1); + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); - if (x != w_limit) { - IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_e, x + 1, (y0 >> 23) & 0x1); + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + #else + + int r0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + r_pixels_0 = r0 | (((r0 + r2) >> 1) << 16); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + b_pixels_0 = b1 | (row_bgbg_1 & 0xFF0000); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + #else + + int r1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + r_pixels_0 = r1 | (row_bgbg_1 & 0xFF0000); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + b_pixels_0 = b0 | (((b0 + b2) >> 1) << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + #else + + int r1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + r_pixels_0 = (r1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + + int b0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + b_pixels_0 = (b2 << 16) | ((b0 + b2) >> 1); + + #endif + break; + } + default: { + r_pixels_0 = 0; + g_pixels_0 = 0; + b_pixels_0 = 0; + break; + } + } + + switch (dst->pixfmt) { + case PIXFORMAT_BINARY: { + uint32_t *row_ptr_e_32 = (uint32_t *) row_ptr_e; + int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; + IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_e_32, x, (y0 >> 7)); + + if (x != w_limit) { + IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_e_32, x + 1, (y0 >> 23)); + } + + break; + } + case PIXFORMAT_GRAYSCALE: { + uint8_t *row_ptr_e_8 = (uint8_t *) row_ptr_e; + int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_e_8, x, y0); + + if (x != w_limit) { + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_e_8, x + 1, y0 >> 16); + } + + break; + } + case PIXFORMAT_RGB565: { + uint16_t *row_ptr_e_16 = (uint16_t *) row_ptr_e; + int rgb565_0 = ((r_pixels_0 << 8) & 0xf800f800) | + ((g_pixels_0 << 3) & 0x07e007e0) | + ((b_pixels_0 >> 3) & 0x001f001f); + + if (x == w_limit) { // just put bottom + IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_e_16, x, rgb565_0); + } else { // put both + *((uint32_t *) (row_ptr_e_16 + x)) = rgb565_0; + } + + break; + } } if (y == h_limit) { - break; + continue; } - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + int r_pixels_1, g_pixels_1, b_pixels_1; - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; + r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + #else - g1 = (row_bgbg_1 >> 16) & 0xFF; - g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - #endif + int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; - int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; - IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_o, x, (y1 >> 7) & 0x1); + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); - if (x != w_limit) { - IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_o, x + 1, (y1 >> 23) & 0x1); - } - } - } -} - -void imlib_debayer_line_to_grayscale(int x_start, int x_end, int y_row, uint8_t *dst_row_ptr, image_t *src) -{ - int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1; - int src_h = src->h, h_limit = src_h - 1, h_limit_m_1 = h_limit - 1; - - int y_row_odd = y_row & 1; - int y = (y_row / 2) * 2; - uint8_t *rowptr_grgr_0, *rowptr_bgbg_1, *rowptr_grgr_2, *rowptr_bgbg_3; - - // keep row pointers in bounds - if (y == 0) { - rowptr_bgbg_1 = src->data; - rowptr_grgr_2 = rowptr_bgbg_1 + ((src_h >= 2) ? src_w : 0); - rowptr_bgbg_3 = rowptr_bgbg_1 + ((src_h >= 3) ? (src_w * 2) : 0); - rowptr_grgr_0 = rowptr_grgr_2; - } else if (y == h_limit_m_1) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else if (y >= h_limit) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_grgr_0; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else { // get 4 neighboring rows - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_grgr_2 + src_w; - } - - // If the image is an odd width this will go for the last loop and we drop the last column. - if (!y_row_odd) { // even - for (int x = x_start, i = 0; x < x_end; x += 2, i += 2) { - uint32_t row_grgr_0, row_bgbg_1, row_grgr_2; - - // keep pixels in bounds - if (x == 0) { - if (src_w >= 4) { - row_grgr_0 = *((uint32_t *) rowptr_grgr_0); - row_bgbg_1 = *((uint32_t *) rowptr_bgbg_1); - row_grgr_2 = *((uint32_t *) rowptr_grgr_2); - } else if (src_w >= 3) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0) | (*(rowptr_grgr_0 + 2) << 16); - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1) | (*(rowptr_bgbg_1 + 2) << 16); - row_grgr_2 = *((uint16_t *) rowptr_grgr_2) | (*(rowptr_grgr_2 + 2) << 16); - } else if (src_w >= 2) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) rowptr_grgr_2); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - } else { - row_grgr_0 = *(rowptr_grgr_0) * 0x01010101; - row_bgbg_1 = *(rowptr_bgbg_1) * 0x01010101; - row_grgr_2 = *(rowptr_grgr_2) * 0x01010101; - } - // The starting point needs to be offset by 1. The below patterns are actually - // rgrg, gbgb, rgrg, and gbgb. So, shift left and backfill the missing border pixel. - row_grgr_0 = (row_grgr_0 << 8) | __UXTB_RORn(row_grgr_0, 8); - row_bgbg_1 = (row_bgbg_1 << 8) | __UXTB_RORn(row_bgbg_1, 8); - row_grgr_2 = (row_grgr_2 << 8) | __UXTB_RORn(row_grgr_2, 8); - } else if (x == w_limit_m_1) { - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 2)); - row_grgr_0 = (row_grgr_0 >> 8) | ((row_grgr_0 << 8) & 0xff000000); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 2)); - row_bgbg_1 = (row_bgbg_1 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 2)); - row_grgr_2 = (row_grgr_2 >> 8) | ((row_grgr_2 << 8) & 0xff000000); - } else if (x >= w_limit) { - row_grgr_0 = *((uint16_t *) (rowptr_grgr_0 + x - 1)); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) (rowptr_bgbg_1 + x - 1)); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) (rowptr_grgr_2 + x - 1)); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - } else { // get 4 neighboring rows - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 1)); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 1)); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else - - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); - - #endif - - int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr, i, y0); - - if (x != w_limit) { - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr, i + 1, y0 >> 16); - } - } - } else { // odd - for (int x = x_start, i = 0; x < x_end; x += 2, i += 2) { - uint32_t row_bgbg_1, row_grgr_2, row_bgbg_3; - - // keep pixels in bounds - if (x == 0) { - if (src_w >= 4) { - row_bgbg_1 = *((uint32_t *) rowptr_bgbg_1); - row_grgr_2 = *((uint32_t *) rowptr_grgr_2); - row_bgbg_3 = *((uint32_t *) rowptr_bgbg_3); - } else if (src_w >= 3) { - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1) | (*(rowptr_bgbg_1 + 2) << 16); - row_grgr_2 = *((uint16_t *) rowptr_grgr_2) | (*(rowptr_grgr_2 + 2) << 16); - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3) | (*(rowptr_bgbg_3 + 2) << 16); - } else if (src_w >= 2) { - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) rowptr_grgr_2); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { - row_bgbg_1 = *(rowptr_bgbg_1) * 0x01010101; - row_grgr_2 = *(rowptr_grgr_2) * 0x01010101; - row_bgbg_3 = *(rowptr_bgbg_3) * 0x01010101; - } - // The starting point needs to be offset by 1. The below patterns are actually - // rgrg, gbgb, rgrg, and gbgb. So, shift left and backfill the missing border pixel. - row_bgbg_1 = (row_bgbg_1 << 8) | __UXTB_RORn(row_bgbg_1, 8); - row_grgr_2 = (row_grgr_2 << 8) | __UXTB_RORn(row_grgr_2, 8); - row_bgbg_3 = (row_bgbg_3 << 8) | __UXTB_RORn(row_bgbg_3, 8); - } else if (x == w_limit_m_1) { - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 2)); - row_bgbg_1 = (row_bgbg_1 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 2)); - row_grgr_2 = (row_grgr_2 >> 8) | ((row_grgr_2 << 8) & 0xff000000); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 2)); - row_bgbg_3 = (row_bgbg_3 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - } else if (x >= w_limit) { - row_bgbg_1 = *((uint16_t *) (rowptr_bgbg_1 + x - 1)); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) (rowptr_grgr_2 + x - 1)); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) (rowptr_bgbg_3 + x - 1)); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { // get 4 neighboring rows - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 1)); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else - - int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - - int g1 = (row_bgbg_1 >> 16) & 0xFF; - int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - - int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; - - #endif - - int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr, i, y1); - - if (x != w_limit) { - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr, i + 1, y1 >> 16); - } - } - } -} - -// Does no bounds checking on the destination. -void imlib_debayer_image_to_grayscale(image_t *dst, image_t *src) -{ - int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1; - int src_h = src->h, h_limit = src_h - 1, h_limit_m_1 = h_limit - 1; - - // If the image is an odd height this will go for the last loop and we drop the last row. - for (int y = 0; y < src_h; y += 2) { - uint8_t *row_ptr_e = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(dst, y); - uint8_t *row_ptr_o = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(dst, y + 1); - uint8_t *rowptr_grgr_0, *rowptr_bgbg_1, *rowptr_grgr_2, *rowptr_bgbg_3; - - // keep row pointers in bounds - if (y == 0) { - rowptr_bgbg_1 = src->data; - rowptr_grgr_2 = rowptr_bgbg_1 + ((src_h >= 2) ? src_w : 0); - rowptr_bgbg_3 = rowptr_bgbg_1 + ((src_h >= 3) ? (src_w * 2) : 0); - rowptr_grgr_0 = rowptr_grgr_2; - } else if (y == h_limit_m_1) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else if (y >= h_limit) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_grgr_0; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else { // get 4 neighboring rows - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_grgr_2 + src_w; - } - - // If the image is an odd width this will go for the last loop and we drop the last column. - for (int x = 0; x < src_w; x += 2) { - uint32_t row_grgr_0, row_bgbg_1, row_grgr_2, row_bgbg_3; - - // keep pixels in bounds - if (x == 0) { - if (src_w >= 4) { - row_grgr_0 = *((uint32_t *) rowptr_grgr_0); - row_bgbg_1 = *((uint32_t *) rowptr_bgbg_1); - row_grgr_2 = *((uint32_t *) rowptr_grgr_2); - row_bgbg_3 = *((uint32_t *) rowptr_bgbg_3); - } else if (src_w >= 3) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0) | (*(rowptr_grgr_0 + 2) << 16); - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1) | (*(rowptr_bgbg_1 + 2) << 16); - row_grgr_2 = *((uint16_t *) rowptr_grgr_2) | (*(rowptr_grgr_2 + 2) << 16); - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3) | (*(rowptr_bgbg_3 + 2) << 16); - } else if (src_w >= 2) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) rowptr_grgr_2); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { - row_grgr_0 = *(rowptr_grgr_0) * 0x01010101; - row_bgbg_1 = *(rowptr_bgbg_1) * 0x01010101; - row_grgr_2 = *(rowptr_grgr_2) * 0x01010101; - row_bgbg_3 = *(rowptr_bgbg_3) * 0x01010101; - } - // The starting point needs to be offset by 1. The below patterns are actually - // rgrg, gbgb, rgrg, and gbgb. So, shift left and backfill the missing border pixel. - row_grgr_0 = (row_grgr_0 << 8) | __UXTB_RORn(row_grgr_0, 8); - row_bgbg_1 = (row_bgbg_1 << 8) | __UXTB_RORn(row_bgbg_1, 8); - row_grgr_2 = (row_grgr_2 << 8) | __UXTB_RORn(row_grgr_2, 8); - row_bgbg_3 = (row_bgbg_3 << 8) | __UXTB_RORn(row_bgbg_3, 8); - } else if (x == w_limit_m_1) { - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 2)); - row_grgr_0 = (row_grgr_0 >> 8) | ((row_grgr_0 << 8) & 0xff000000); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 2)); - row_bgbg_1 = (row_bgbg_1 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 2)); - row_grgr_2 = (row_grgr_2 >> 8) | ((row_grgr_2 << 8) & 0xff000000); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 2)); - row_bgbg_3 = (row_bgbg_3 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - } else if (x >= w_limit) { - row_grgr_0 = *((uint16_t *) (rowptr_grgr_0 + x - 1)); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) (rowptr_bgbg_1 + x - 1)); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) (rowptr_grgr_2 + x - 1)); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) (rowptr_bgbg_3 + x - 1)); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { // get 4 neighboring rows - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 1)); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 1)); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else - - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); - - #endif - - int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_e, x, y0); - - if (x != w_limit) { - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_e, x + 1, y0 >> 16); - } - - if (y == h_limit) { - break; - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else - - r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - - g1 = (row_bgbg_1 >> 16) & 0xFF; - g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - - b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; - - #endif - - int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_o, x, y1); - - if (x != w_limit) { - IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_o, x + 1, y1 >> 16); - } - } - } -} - -void imlib_debayer_line_to_rgb565(int x_start, int x_end, int y_row, uint16_t *dst_row_ptr, image_t *src) -{ - int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1; - int src_h = src->h, h_limit = src_h - 1, h_limit_m_1 = h_limit - 1; - - int y_row_odd = y_row & 1; - int y = (y_row / 2) * 2; - uint8_t *rowptr_grgr_0, *rowptr_bgbg_1, *rowptr_grgr_2, *rowptr_bgbg_3; - - // keep row pointers in bounds - if (y == 0) { - rowptr_bgbg_1 = src->data; - rowptr_grgr_2 = rowptr_bgbg_1 + ((src_h >= 2) ? src_w : 0); - rowptr_bgbg_3 = rowptr_bgbg_1 + ((src_h >= 3) ? (src_w * 2) : 0); - rowptr_grgr_0 = rowptr_grgr_2; - } else if (y == h_limit_m_1) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else if (y >= h_limit) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_grgr_0; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else { // get 4 neighboring rows - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_grgr_2 + src_w; - } - - // If the image is an odd width this will go for the last loop and we drop the last column. - if (!y_row_odd) { // even - for (int x = x_start, i = 0; x < x_end; x += 2, i += 2) { - uint32_t row_grgr_0, row_bgbg_1, row_grgr_2; - - // keep pixels in bounds - if (x == 0) { - if (src_w >= 4) { - row_grgr_0 = *((uint32_t *) rowptr_grgr_0); - row_bgbg_1 = *((uint32_t *) rowptr_bgbg_1); - row_grgr_2 = *((uint32_t *) rowptr_grgr_2); - } else if (src_w >= 3) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0) | (*(rowptr_grgr_0 + 2) << 16); - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1) | (*(rowptr_bgbg_1 + 2) << 16); - row_grgr_2 = *((uint16_t *) rowptr_grgr_2) | (*(rowptr_grgr_2 + 2) << 16); - } else if (src_w >= 2) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) rowptr_grgr_2); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - } else { - row_grgr_0 = *(rowptr_grgr_0) * 0x01010101; - row_bgbg_1 = *(rowptr_bgbg_1) * 0x01010101; - row_grgr_2 = *(rowptr_grgr_2) * 0x01010101; - } - // The starting point needs to be offset by 1. The below patterns are actually - // rgrg, gbgb, rgrg, and gbgb. So, shift left and backfill the missing border pixel. - row_grgr_0 = (row_grgr_0 << 8) | __UXTB_RORn(row_grgr_0, 8); - row_bgbg_1 = (row_bgbg_1 << 8) | __UXTB_RORn(row_bgbg_1, 8); - row_grgr_2 = (row_grgr_2 << 8) | __UXTB_RORn(row_grgr_2, 8); - } else if (x == w_limit_m_1) { - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 2)); - row_grgr_0 = (row_grgr_0 >> 8) | ((row_grgr_0 << 8) & 0xff000000); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 2)); - row_bgbg_1 = (row_bgbg_1 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 2)); - row_grgr_2 = (row_grgr_2 >> 8) | ((row_grgr_2 << 8) & 0xff000000); - } else if (x >= w_limit) { - row_grgr_0 = *((uint16_t *) (rowptr_grgr_0 + x - 1)); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) (rowptr_bgbg_1 + x - 1)); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) (rowptr_grgr_2 + x - 1)); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - } else { // get 4 neighboring rows - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 1)); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 1)); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else - - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); - - #endif - - int rgb565_0 = ((r_pixels_0 << 8) & 0xf800f800) | - ((g_pixels_0 << 3) & 0x07e007e0) | - ((b_pixels_0 >> 3) & 0x001f001f); - - if (x == w_limit) { // just put bottom - IMAGE_PUT_RGB565_PIXEL_FAST(dst_row_ptr, i, rgb565_0); - } else { // put both - *((uint32_t *) (dst_row_ptr + i)) = rgb565_0; - } - } - } else { // odd - for (int x = x_start, i = 0; x < x_end; x += 2, i += 2) { - uint32_t row_bgbg_1, row_grgr_2, row_bgbg_3; - - // keep pixels in bounds - if (x == 0) { - if (src_w >= 4) { - row_bgbg_1 = *((uint32_t *) rowptr_bgbg_1); - row_grgr_2 = *((uint32_t *) rowptr_grgr_2); - row_bgbg_3 = *((uint32_t *) rowptr_bgbg_3); - } else if (src_w >= 3) { - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1) | (*(rowptr_bgbg_1 + 2) << 16); - row_grgr_2 = *((uint16_t *) rowptr_grgr_2) | (*(rowptr_grgr_2 + 2) << 16); - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3) | (*(rowptr_bgbg_3 + 2) << 16); - } else if (src_w >= 2) { - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) rowptr_grgr_2); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { - row_bgbg_1 = *(rowptr_bgbg_1) * 0x01010101; - row_grgr_2 = *(rowptr_grgr_2) * 0x01010101; - row_bgbg_3 = *(rowptr_bgbg_3) * 0x01010101; - } - // The starting point needs to be offset by 1. The below patterns are actually - // rgrg, gbgb, rgrg, and gbgb. So, shift left and backfill the missing border pixel. - row_bgbg_1 = (row_bgbg_1 << 8) | __UXTB_RORn(row_bgbg_1, 8); - row_grgr_2 = (row_grgr_2 << 8) | __UXTB_RORn(row_grgr_2, 8); - row_bgbg_3 = (row_bgbg_3 << 8) | __UXTB_RORn(row_bgbg_3, 8); - } else if (x == w_limit_m_1) { - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 2)); - row_bgbg_1 = (row_bgbg_1 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 2)); - row_grgr_2 = (row_grgr_2 >> 8) | ((row_grgr_2 << 8) & 0xff000000); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 2)); - row_bgbg_3 = (row_bgbg_3 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - } else if (x >= w_limit) { - row_bgbg_1 = *((uint16_t *) (rowptr_bgbg_1 + x - 1)); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) (rowptr_grgr_2 + x - 1)); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) (rowptr_bgbg_3 + x - 1)); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { // get 4 neighboring rows - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 1)); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else - - int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - - int g1 = (row_bgbg_1 >> 16) & 0xFF; - int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - - int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; - - #endif - - int rgb565_1 = ((r_pixels_1 << 8) & 0xf800f800) | - ((g_pixels_1 << 3) & 0x07e007e0) | - ((b_pixels_1 >> 3) & 0x001f001f); - - if (x == w_limit) { // just put bottom - IMAGE_PUT_RGB565_PIXEL_FAST(dst_row_ptr, i, rgb565_1); - } else { // put both - *((uint32_t *) (dst_row_ptr + i)) = rgb565_1; - } - } - } -} - -// Does no bounds checking on the destination. -void imlib_debayer_image_to_rgb565(image_t *dst, image_t *src) -{ - int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1; - int src_h = src->h, h_limit = src_h - 1, h_limit_m_1 = h_limit - 1; - - // If the image is an odd height this will go for the last loop and we drop the last row. - for (int y = 0; y < src_h; y += 2) { - uint16_t *row_ptr_e = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(dst, y); - uint16_t *row_ptr_o = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(dst, y + 1); - uint8_t *rowptr_grgr_0, *rowptr_bgbg_1, *rowptr_grgr_2, *rowptr_bgbg_3; - - // keep row pointers in bounds - if (y == 0) { - rowptr_bgbg_1 = src->data; - rowptr_grgr_2 = rowptr_bgbg_1 + ((src_h >= 2) ? src_w : 0); - rowptr_bgbg_3 = rowptr_bgbg_1 + ((src_h >= 3) ? (src_w * 2) : 0); - rowptr_grgr_0 = rowptr_grgr_2; - } else if (y == h_limit_m_1) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else if (y >= h_limit) { - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_grgr_0; - rowptr_bgbg_3 = rowptr_bgbg_1; - } else { // get 4 neighboring rows - rowptr_grgr_0 = src->data + ((y - 1) * src_w); - rowptr_bgbg_1 = rowptr_grgr_0 + src_w; - rowptr_grgr_2 = rowptr_bgbg_1 + src_w; - rowptr_bgbg_3 = rowptr_grgr_2 + src_w; - } - - // If the image is an odd width this will go for the last loop and we drop the last column. - for (int x = 0; x < src_w; x += 2) { - uint32_t row_grgr_0, row_bgbg_1, row_grgr_2, row_bgbg_3; - - // keep pixels in bounds - if (x == 0) { - if (src_w >= 4) { - row_grgr_0 = *((uint32_t *) rowptr_grgr_0); - row_bgbg_1 = *((uint32_t *) rowptr_bgbg_1); - row_grgr_2 = *((uint32_t *) rowptr_grgr_2); - row_bgbg_3 = *((uint32_t *) rowptr_bgbg_3); - } else if (src_w >= 3) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0) | (*(rowptr_grgr_0 + 2) << 16); - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1) | (*(rowptr_bgbg_1 + 2) << 16); - row_grgr_2 = *((uint16_t *) rowptr_grgr_2) | (*(rowptr_grgr_2 + 2) << 16); - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3) | (*(rowptr_bgbg_3 + 2) << 16); - } else if (src_w >= 2) { - row_grgr_0 = *((uint16_t *) rowptr_grgr_0); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) rowptr_bgbg_1); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) rowptr_grgr_2); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) rowptr_bgbg_3); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { - row_grgr_0 = *(rowptr_grgr_0) * 0x01010101; - row_bgbg_1 = *(rowptr_bgbg_1) * 0x01010101; - row_grgr_2 = *(rowptr_grgr_2) * 0x01010101; - row_bgbg_3 = *(rowptr_bgbg_3) * 0x01010101; - } - // The starting point needs to be offset by 1. The below patterns are actually - // rgrg, gbgb, rgrg, and gbgb. So, shift left and backfill the missing border pixel. - row_grgr_0 = (row_grgr_0 << 8) | __UXTB_RORn(row_grgr_0, 8); - row_bgbg_1 = (row_bgbg_1 << 8) | __UXTB_RORn(row_bgbg_1, 8); - row_grgr_2 = (row_grgr_2 << 8) | __UXTB_RORn(row_grgr_2, 8); - row_bgbg_3 = (row_bgbg_3 << 8) | __UXTB_RORn(row_bgbg_3, 8); - } else if (x == w_limit_m_1) { - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 2)); - row_grgr_0 = (row_grgr_0 >> 8) | ((row_grgr_0 << 8) & 0xff000000); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 2)); - row_bgbg_1 = (row_bgbg_1 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 2)); - row_grgr_2 = (row_grgr_2 >> 8) | ((row_grgr_2 << 8) & 0xff000000); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 2)); - row_bgbg_3 = (row_bgbg_3 >> 8) | ((row_bgbg_1 << 8) & 0xff000000); - } else if (x >= w_limit) { - row_grgr_0 = *((uint16_t *) (rowptr_grgr_0 + x - 1)); - row_grgr_0 = (row_grgr_0 << 16) | row_grgr_0; - row_bgbg_1 = *((uint16_t *) (rowptr_bgbg_1 + x - 1)); - row_bgbg_1 = (row_bgbg_1 << 16) | row_bgbg_1; - row_grgr_2 = *((uint16_t *) (rowptr_grgr_2 + x - 1)); - row_grgr_2 = (row_grgr_2 << 16) | row_grgr_2; - row_bgbg_3 = *((uint16_t *) (rowptr_bgbg_3 + x - 1)); - row_bgbg_3 = (row_bgbg_3 << 16) | row_bgbg_3; - } else { // get 4 neighboring rows - row_grgr_0 = *((uint32_t *) (rowptr_grgr_0 + x - 1)); - row_bgbg_1 = *((uint32_t *) (rowptr_bgbg_1 + x - 1)); - row_grgr_2 = *((uint32_t *) (rowptr_grgr_2 + x - 1)); - row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else - - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); - - #endif - - int rgb565_0 = ((r_pixels_0 << 8) & 0xf800f800) | - ((g_pixels_0 << 3) & 0x07e007e0) | - ((b_pixels_0 >> 3) & 0x001f001f); - - if (x == w_limit) { // just put bottom - IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_e, x, rgb565_0); - } else { // put both - *((uint32_t *) (row_ptr_e + x)) = rgb565_0; - } - - if (y == h_limit) { - break; - } - - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else - - r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - - g1 = (row_bgbg_1 >> 16) & 0xFF; - g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - - b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; - - #endif - - int rgb565_1 = ((r_pixels_1 << 8) & 0xf800f800) | - ((g_pixels_1 << 3) & 0x07e007e0) | - ((b_pixels_1 >> 3) & 0x001f001f); - - if (x == w_limit) { // just put bottom - IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_o, x, rgb565_1); - } else { // put both - *((uint32_t *) (row_ptr_o + x)) = rgb565_1; + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + #else + + int r2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + r_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (r2 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + b_pixels_1 = ((b1 + b3) >> 1) | (b3 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + #else + + int r1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + r_pixels_1 = ((r1 + r3) >> 1) | (r3 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + b_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (b2 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + #else + + int r1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + r_pixels_1 = (((r1 + r3) >> 1) << 16) | r1; + + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + + int b2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + b_pixels_1 = (row_grgr_2 & 0xFF0000) | b2; + + #endif + break; + } + default: { + r_pixels_1 = 0; + g_pixels_1 = 0; + b_pixels_1 = 0; + break; + } + } + + switch (dst->pixfmt) { + case PIXFORMAT_BINARY: { + uint32_t *row_ptr_o_32 = (uint32_t *) row_ptr_o; + int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; + IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_o_32, x, (y1 >> 7)); + + if (x != w_limit) { + IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_o_32, x + 1, (y1 >> 23)); + } + + break; + } + case PIXFORMAT_GRAYSCALE: { + uint8_t *row_ptr_o_8 = (uint8_t *) row_ptr_o; + int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_o_8, x, y1); + + if (x != w_limit) { + IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_o_8, x + 1, y1 >> 16); + } + + break; + } + case PIXFORMAT_RGB565: { + uint16_t *row_ptr_o_16 = (uint16_t *) row_ptr_o; + int rgb565_1 = ((r_pixels_1 << 8) & 0xf800f800) | + ((g_pixels_1 << 3) & 0x07e007e0) | + ((b_pixels_1 >> 3) & 0x001f001f); + + if (x == w_limit) { // just put bottom + IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_o_16, x, rgb565_1); + } else { // put both + *((uint32_t *) (row_ptr_o_16 + x)) = rgb565_1; + } + + break; + } } } } diff --git a/src/omv/imlib/draw.c b/src/omv/imlib/draw.c index c4042b90c..d012a8154 100644 --- a/src/omv/imlib/draw.c +++ b/src/omv/imlib/draw.c @@ -2728,7 +2728,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d switch (new_src_img.pixfmt) { case PIXFORMAT_BINARY: { if (src_img->is_bayer) { - imlib_debayer_image_to_binary(&new_src_img, src_img); + imlib_debayer_image(&new_src_img, src_img); } else if (src_img->pixfmt == PIXFORMAT_JPEG) { jpeg_decompress_image_to_binary(&new_src_img, src_img); } @@ -2736,7 +2736,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d } case PIXFORMAT_GRAYSCALE: { if (src_img->is_bayer) { - imlib_debayer_image_to_grayscale(&new_src_img, src_img); + imlib_debayer_image(&new_src_img, src_img); } else if (src_img->pixfmt == PIXFORMAT_JPEG) { jpeg_decompress_image_to_grayscale(&new_src_img, src_img); } @@ -2744,7 +2744,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d } case PIXFORMAT_RGB565: { if (src_img->is_bayer) { - imlib_debayer_image_to_rgb565(&new_src_img, src_img); + imlib_debayer_image(&new_src_img, src_img); } else if (src_img->pixfmt == PIXFORMAT_JPEG) { jpeg_decompress_image_to_rgb565(&new_src_img, src_img); } @@ -2888,7 +2888,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d for (int i = src_y_index; i < src_y_index_end; i++) { uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, i) + src_x_index; int n = width; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint16_t *src_row_ptr16 = (uint16_t *) src_row_ptr; for (; n > 1; n -= 2) { @@ -2906,7 +2906,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d for (int i = src_y_index; i < src_y_index_end; i++) { uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, i) + src_x_index; int n = width; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint32_t *src_row_ptr32 = (uint32_t *) src_row_ptr; for (; n > 3; n -= 4) { @@ -2972,7 +2972,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d for (int i = src_y_index; i < src_y_index_end; i++) { uint16_t *src_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src_img, i) + src_x_index; int n = width; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint32_t *src_row_ptr32 = (uint32_t *) src_row_ptr; for (; n > 1; n -= 2) { @@ -3248,7 +3248,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d for (int i = src_y_index_p_1; i < src_y_index_end; i++) { uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, i) + src_x_index_p_1; int n = x_width_m_2; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint16_t *src_row_ptr16 = (uint16_t *) src_row_ptr; for (; n > 1; n -= 2) { @@ -3266,7 +3266,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d for (int i = src_y_index_p_1; i < src_y_index_end; i++) { uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, i) + src_x_index_p_1; int n = x_width_m_2; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint32_t *src_row_ptr32 = (uint32_t *) src_row_ptr; for (; n > 4; n -= 4) { @@ -3447,7 +3447,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d for (int i = src_y_index_p_1; i < src_y_index_end; i++) { uint16_t *src_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src_img, i) + src_x_index_p_1; int n = x_width_m_2; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint32_t *src_row_ptr32 = (uint32_t *) src_row_ptr; for (; n > 1; n -= 2) { @@ -3945,7 +3945,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d int src_x_index = next_src_x_index; int src_x_index_m_1 = src_x_index - 1; int src_x_index_p_1 = src_x_index + 1; -#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) +#if defined(ARM_MATH_DSP) uint32_t pixel_row_0[2], pixel_row_1[2], pixel_row_2[2], pixel_row_3[2]; // Column 0 = Bits[15:0] // Column 1 = Bits[31:16] @@ -4623,22 +4623,11 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d case PIXFORMAT_BAYER_ANY: { while (y_not_done) { switch (is_bayer_or_jpeg_pixfmt) { - case PIXFORMAT_BINARY: { - uint32_t *dst_row_ptr = imlib_draw_row_get_row_buffer(&imlib_draw_row_data); - imlib_debayer_line_to_binary(dst_x_start, dst_x_end, next_src_y_index, - dst_row_ptr, src_img); - break; - } - case PIXFORMAT_GRAYSCALE: { - uint8_t *dst_row_ptr = imlib_draw_row_get_row_buffer(&imlib_draw_row_data); - imlib_debayer_line_to_grayscale(dst_x_start, dst_x_end, next_src_y_index, - dst_row_ptr, src_img); - break; - } + case PIXFORMAT_BINARY: + case PIXFORMAT_GRAYSCALE: case PIXFORMAT_RGB565: { - uint16_t *dst_row_ptr = imlib_draw_row_get_row_buffer(&imlib_draw_row_data); - imlib_debayer_line_to_rgb565(dst_x_start, dst_x_end, next_src_y_index, - dst_row_ptr, src_img); + imlib_debayer_line(dst_x_start, dst_x_end, next_src_y_index, + imlib_draw_row_get_row_buffer(&imlib_draw_row_data), is_bayer_or_jpeg_pixfmt, src_img); break; } case PIXFORMAT_BAYER_ANY: { // Bayer images have the same shape as grayscale. diff --git a/src/omv/imlib/gif.c b/src/omv/imlib/gif.c index 0bdcb9f0b..b5aeb590d 100644 --- a/src/omv/imlib/gif.c +++ b/src/omv/imlib/gif.c @@ -94,7 +94,7 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay) write_byte(fp, 1 + block_size); write_byte(fp, 0x80); // clear code uint16_t pixels[block_size]; - imlib_debayer_line_to_rgb565(0, block_size, y, pixels, img); + imlib_debayer_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img); for (int x=0; xpixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); + r_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + #else - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - #endif + int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + #else + + int r0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + r_pixels_0 = r0 | (((r0 + r2) >> 1) << 16); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + b_pixels_0 = b1 | (row_bgbg_1 & 0xFF0000); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + #else + + int r1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + r_pixels_0 = r1 | (row_bgbg_1 & 0xFF0000); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + b_pixels_0 = b0 | (((b0 + b2) >> 1) << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + #else + + int r1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + r_pixels_0 = (r1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + + int b0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + b_pixels_0 = (b2 << 16) | ((b0 + b2) >> 1); + + #endif + break; + } + default: { + r_pixels_0 = 0; + g_pixels_0 = 0; + b_pixels_0 = 0; + break; + } + } int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; @@ -290,28 +378,116 @@ static void jpeg_get_mcu(image_t *src, int x_offset, int y_offset, int dx, int d CR[index_e] = v0, CR[index_e + 1] = v0 >> 16; - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + int r_pixels_1, g_pixels_1, b_pixels_1; - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; + r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + #else - g1 = (row_bgbg_1 >> 16) & 0xFF; - g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - #endif + int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; + + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + #else + + int r2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + r_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (r2 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + b_pixels_1 = ((b1 + b3) >> 1) | (b3 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + #else + + int r1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + r_pixels_1 = ((r1 + r3) >> 1) | (r3 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + b_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (b2 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + #else + + int r1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + r_pixels_1 = (((r1 + r3) >> 1) << 16) | r1; + + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + + int b2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + b_pixels_1 = (row_grgr_2 & 0xFF0000) | b2; + + #endif + break; + } + default: { + r_pixels_1 = 0; + g_pixels_1 = 0; + b_pixels_1 = 0; + break; + } + } int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; @@ -430,28 +606,116 @@ static void jpeg_get_mcu(image_t *src, int x_offset, int y_offset, int dx, int d row_bgbg_3 = *((uint32_t *) (rowptr_bgbg_3 + x - 1)); } - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_01 = __UHADD8(row_grgr_0, row_grgr_2); - int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + int r_pixels_0, g_pixels_0, b_pixels_0; - int r_pixels_0 = __UXTB16(__UHADD8(row_01, __PKHTB(row_01, row_01, 16))); - int g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_01, 8))); - int b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); - int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; - int r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); + r_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + #else - int g0 = (row_grgr_0 >> 8) & 0xFF; - int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; - int g2 = (row_grgr_2 >> 8) & 0xFF; - int g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + int r0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + r_pixels_0 = (r2 << 16) | ((r0 + r2) >> 1); - int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; - int b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); - #endif + int b1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + b_pixels_0 = (b1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + #else + + int r0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int r2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + r_pixels_0 = r0 | (((r0 + r2) >> 1) << 16); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + b_pixels_0 = b1 | (row_bgbg_1 & 0xFF0000); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16(__UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16))); + g_pixels_0 = __UXTB16_RORn(__UHADD8(row_1g, __PKHBT(row_1g, row_02, 8)), 8); + b_pixels_0 = __UXTB16_RORn(__UHADD8(row_02, __PKHBT(row_02, row_02, 16)), 8); + #else + + int r1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + r_pixels_0 = r1 | (row_bgbg_1 & 0xFF0000); + + int g0 = (row_grgr_0 >> 16) & 0xFF; + int g1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 16) & 0xFF; + g_pixels_0 = ((row_bgbg_1 >> 8) & 0xFF) | (((((g0 + g2) >> 1) + g1) >> 1) << 16); + + int b0 = (((row_grgr_0 >> 8) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 24) & 0xFF) + ((row_grgr_2 >> 24) & 0xFF)) >> 1; + b_pixels_0 = b0 | (((b0 + b2) >> 1) << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_02 = __UHADD8(row_grgr_0, row_grgr_2); + int row_1g = __UHADD8(row_bgbg_1, __PKHTB(row_bgbg_1, row_bgbg_1, 16)); + + r_pixels_0 = __UXTB16_RORn(__UHADD8(row_bgbg_1, __PKHBT(row_bgbg_1, row_bgbg_1, 16)), 8); + g_pixels_0 = __UXTB16(__UHADD8(row_1g, __PKHTB(row_1g, row_02, 8))); + b_pixels_0 = __UXTB16(__UHADD8(row_02, __PKHTB(row_02, row_02, 16))); + #else + + int r1 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_1 >> 8) & 0xFF)) >> 1; + r_pixels_0 = (r1 << 16) | ((row_bgbg_1 >> 8) & 0xFF); + + int g0 = (row_grgr_0 >> 8) & 0xFF; + int g1 = (((row_bgbg_1 >> 16) & 0xFF) + (row_bgbg_1 & 0xFF)) >> 1; + int g2 = (row_grgr_2 >> 8) & 0xFF; + g_pixels_0 = (row_bgbg_1 & 0xFF0000) | ((((g0 + g2) >> 1) + g1) >> 1); + + int b0 = ((row_grgr_0 & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int b2 = (((row_grgr_0 >> 16) & 0xFF) + ((row_grgr_2 >> 16) & 0xFF)) >> 1; + b_pixels_0 = (b2 << 16) | ((b0 + b2) >> 1); + + #endif + break; + } + default: { + r_pixels_0 = 0; + g_pixels_0 = 0; + b_pixels_0 = 0; + break; + } + } int y0 = ((r_pixels_0 * 38) + (g_pixels_0 * 75) + (b_pixels_0 * 15)) >> 7; @@ -477,28 +741,116 @@ static void jpeg_get_mcu(image_t *src, int x_offset, int y_offset, int dx, int d CR[index_e] = v0, CR[index_e + 1] = v0 >> 16; - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) - int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); - int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + int r_pixels_1, g_pixels_1, b_pixels_1; - int r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); - int g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); - int b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); - #else + switch (src->pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); - r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; - int r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; + r_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + #else - g1 = (row_bgbg_1 >> 16) & 0xFF; - g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; - int g3 = (row_bgbg_3 >> 16) & 0xFF; - int g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + int r2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + r_pixels_1 = (row_grgr_2 & 0xFF0000) | r2; - b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; - int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; - int b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); - #endif + int b1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + b_pixels_1 = (((b1 + b3) >> 1) << 16) | b1; + + #endif + break; + } + case PIXFORMAT_BAYER_GBRG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + #else + + int r2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + r_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (r2 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int b3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + b_pixels_1 = ((b1 + b3) >> 1) | (b3 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_GRBG: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16(__UHADD8(row_13, __PKHTB(row_13, row_13, 16))); + g_pixels_1 = __UXTB16(__UHADD8(row_2g, __PKHTB(row_2g, row_13, 8))); + b_pixels_1 = __UXTB16_RORn(__UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)), 8); + #else + + int r1 = ((row_bgbg_1 & 0xFF) + (row_bgbg_3 & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 16) & 0xFF) + ((row_bgbg_3 >> 16) & 0xFF)) >> 1; + r_pixels_1 = ((r1 + r3) >> 1) | (r3 << 16); + + int g1 = (row_bgbg_1 >> 8) & 0xFF; + int g2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 8) & 0xFF; + g_pixels_1 = ((((g1 + g3) >> 1) + g2) >> 1) | (row_grgr_2 & 0xFF0000); + + int b2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + b_pixels_1 = ((row_grgr_2 >> 8) & 0xFF) | (b2 << 16); + + #endif + break; + } + case PIXFORMAT_BAYER_RGGB: { + #if defined(ARM_MATH_DSP) + int row_13 = __UHADD8(row_bgbg_1, row_bgbg_3); + int row_2g = __UHADD8(row_grgr_2, __PKHBT(row_grgr_2, row_grgr_2, 16)); + + r_pixels_1 = __UXTB16_RORn(__UHADD8(row_13, __PKHBT(row_13, row_13, 16)), 8); + g_pixels_1 = __UXTB16_RORn(__UHADD8(row_2g, __PKHBT(row_2g, row_13, 8)), 8); + b_pixels_1 = __UXTB16(__UHADD8(row_grgr_2, __PKHTB(row_grgr_2, row_grgr_2, 16))); + #else + + int r1 = (((row_bgbg_1 >> 8) & 0xFF) + ((row_bgbg_3 >> 8) & 0xFF)) >> 1; + int r3 = (((row_bgbg_1 >> 24) & 0xFF) + ((row_bgbg_3 >> 24) & 0xFF)) >> 1; + r_pixels_1 = (((r1 + r3) >> 1) << 16) | r1; + + int g1 = (row_bgbg_1 >> 16) & 0xFF; + int g2 = (((row_grgr_2 >> 24) & 0xFF) + ((row_grgr_2 >> 8) & 0xFF)) >> 1; + int g3 = (row_bgbg_3 >> 16) & 0xFF; + g_pixels_1 = (((((g1 + g3) >> 1) + g2) >> 1) << 16) | ((row_grgr_2 >> 8) & 0xFF); + + int b2 = (((row_grgr_2 >> 16) & 0xFF) + (row_grgr_2 & 0xFF)) >> 1; + b_pixels_1 = (row_grgr_2 & 0xFF0000) | b2; + + #endif + break; + } + default: { + r_pixels_1 = 0; + g_pixels_1 = 0; + b_pixels_1 = 0; + break; + } + } int y1 = ((r_pixels_1 * 38) + (g_pixels_1 * 75) + (b_pixels_1 * 15)) >> 7; @@ -1025,7 +1377,7 @@ static const uint16_t UVAC_HT[256][2] = { // return true to indicate that encoding has to halt // static int jpeg_check_highwater(jpeg_buf_t *jpeg_buf) -{ +{ if ((jpeg_buf->idx+1) >= jpeg_buf->length - 256) { if (jpeg_buf->realloc == false) { // Can't realloc buffer diff --git a/src/omv/modules/py_image.c b/src/omv/modules/py_image.c index f5c2ab730..a98c3afd2 100644 --- a/src/omv/modules/py_image.c +++ b/src/omv/modules/py_image.c @@ -365,16 +365,16 @@ static void py_image_print(const mp_print_t *print, mp_obj_t self, mp_print_kind && image->pixels[0] == 0xFE && image->pixels[image->size-1] == 0xFE) { // print for ide. - print->print_strn(print->data, (const char *) image->pixels, image->bpp); + print->print_strn(print->data, (const char *) image->pixels, image->size); } else { - mp_printf(print, "{\"w\":%d, \"h\":%d, \"type\"=\"binary\", \"size\":%d}", + mp_printf(print, "{\"w\":%d, \"h\":%d, \"type\":\"%s\", \"size\":%d}", image->w, image->h, - (image->pixfmt == PIXFORMAT_BINARY) ? "Binary" : - (image->pixfmt == PIXFORMAT_GRAYSCALE) ? "Grayscale" : - (image->pixfmt == PIXFORMAT_RGB565) ? "RGB565" : - (image->pixfmt == PIXFORMAT_YUV422) ? "YUV422" : - (image->pixfmt == PIXFORMAT_JPEG) ? "JPEG" : "Bayer", + (image->pixfmt == PIXFORMAT_BINARY) ? "binary" : + (image->pixfmt == PIXFORMAT_GRAYSCALE) ? "grayscale" : + (image->pixfmt == PIXFORMAT_RGB565) ? "rgb565" : + (image->pixfmt == PIXFORMAT_YUV422) ? "yuv422" : + (image->pixfmt == PIXFORMAT_JPEG) ? "jpeg" : "bayer", image_size(image)); } } @@ -443,7 +443,7 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value case PIXFORMAT_JPEG: { if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(image->bpp, index, &slice)) { + if (!mp_seq_get_fast_slice_indexes(image->size, index, &slice)) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("only slices with step=1 (aka None) are supported")); } mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL); @@ -452,7 +452,7 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value } return result; } - mp_uint_t i = mp_get_index(self->base.type, image->bpp, index, false); + mp_uint_t i = mp_get_index(self->base.type, image->size, index, false); return mp_obj_new_int(image->data[i]); } default: @@ -552,7 +552,7 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value case PIXFORMAT_JPEG: { if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(image->bpp, index, &slice)) { + if (!mp_seq_get_fast_slice_indexes(image->size, index, &slice)) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("only slices with step=1 (aka None) are supported")); } if (MP_OBJ_IS_TYPE(value, &mp_type_list)) { @@ -571,7 +571,7 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value } return mp_const_none; } - mp_uint_t i = mp_get_index(self->base.type, image->bpp, index, false); + mp_uint_t i = mp_get_index(self->base.type, image->size, index, false); image->data[i] = mp_obj_get_int(value); return mp_const_none; } @@ -700,7 +700,7 @@ STATIC mp_obj_t py_image_get_pixel(uint n_args, const mp_obj_t *args, mp_map_t * } case PIXFORMAT_BAYER_ANY: if (arg_rgbtuple) { - uint16_t pixel; imlib_debayer_line_to_rgb565(arg_x, arg_x + 1, arg_y, &pixel, arg_img); + uint16_t pixel; imlib_debayer_line(arg_x, arg_x + 1, arg_y, &pixel, PIXFORMAT_RGB565, arg_img); mp_obj_t pixel_tuple[3]; pixel_tuple[0] = mp_obj_new_int(COLOR_RGB565_TO_R8(pixel)); pixel_tuple[1] = mp_obj_new_int(COLOR_RGB565_TO_G8(pixel)); @@ -951,6 +951,53 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, const uint16_t *default_color_pa (alpha_palette != NULL)) { mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Only bayer copying/cropping is supported!")); } else { + bool shift_right = arg_roi.x % 2; + bool shift_down = arg_roi.y % 2; + switch (dst_img.pixfmt) { + case PIXFORMAT_BAYER_BGGR: { + if (shift_right && shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_RGGB; + } else if (shift_right) { + dst_img.pixfmt = PIXFORMAT_BAYER_GBRG; + } else if (shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_GRBG; + } + break; + } + case PIXFORMAT_BAYER_GBRG: { + if (shift_right && shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_GRBG; + } else if (shift_right) { + dst_img.pixfmt = PIXFORMAT_BAYER_BGGR; + } else if (shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_RGGB; + } + break; + } + case PIXFORMAT_BAYER_GRBG: { + if (shift_right && shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_GBRG; + } else if (shift_right) { + dst_img.pixfmt = PIXFORMAT_BAYER_RGGB; + } else if (shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_BGGR; + } + break; + } + case PIXFORMAT_BAYER_RGGB: { + if (shift_right && shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_BGGR; + } else if (shift_right) { + dst_img.pixfmt = PIXFORMAT_BAYER_GRBG; + } else if (shift_down) { + dst_img.pixfmt = PIXFORMAT_BAYER_GBRG; + } + break; + } + default: { + break; + } + } hint &= ~(IMAGE_HINT_AREA | IMAGE_HINT_BICUBIC | IMAGE_HINT_BILINEAR | @@ -1098,7 +1145,7 @@ static mp_obj_t py_image_compress(uint n_args, const mp_obj_t *args, mp_map_t *k fb_alloc_mark(); image_t out = { .w=arg_img->w, .h=arg_img->h, .pixfmt=PIXFORMAT_JPEG, .size=0, .data=NULL }; // alloc in jpeg compress PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!"); - PY_ASSERT_TRUE_MSG(out.bpp <= image_size(arg_img), "Can't compress in place!"); + PY_ASSERT_TRUE_MSG(out.size <= image_size(arg_img), "Can't compress in place!"); memcpy(arg_img->data, out.data, out.size); arg_img->size = out.size; fb_alloc_free_till_mark(); diff --git a/src/omv/ports/stm32/modules/py_tv.c b/src/omv/ports/stm32/modules/py_tv.c index 78e9dabd1..9567f9604 100644 --- a/src/omv/ports/stm32/modules/py_tv.c +++ b/src/omv/ports/stm32/modules/py_tv.c @@ -615,7 +615,7 @@ static void spi_tv_draw_image_cb_convert_grayscale(uint8_t *row_pointer_i, uint8 static void spi_tv_draw_image_cb_convert_rgb565(uint16_t *row_pointer_i, uint8_t *row_pointer_o) { for (int i = 0, j = 0; i < TV_WIDTH; i += 2, j += 3) { - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) + #if defined(ARM_MATH_DSP) int pixels = *((uint32_t *) (row_pointer_i + i)); int r_pixels = ((pixels >> 8) & 0xf800f8) | ((pixels >> 13) & 0x70007);