mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add yuv image processing support
This commit is contained in:
parent
291e8f0ada
commit
bf447e5599
@ -91,6 +91,7 @@ SRCS += $(addprefix imlib/, \
|
||||
stats.c \
|
||||
template.c \
|
||||
xyz_tab.c \
|
||||
yuv.c \
|
||||
zbar.c \
|
||||
)
|
||||
|
||||
|
||||
@ -179,6 +179,8 @@ typedef enum {
|
||||
#define SENSOR_HW_FLAGS_BAYER_GBRG (SUBFORMAT_ID_GBRG)
|
||||
#define SENSOR_HW_FLAGS_BAYER_GRBG (SUBFORMAT_ID_GRBG)
|
||||
#define SENSOR_HW_FLAGS_BAYER_RGGB (SUBFORMAT_ID_RGGB)
|
||||
#define SENSOR_HW_FLAGS_YUV422 (SUBFORMAT_ID_YUV422)
|
||||
#define SENSOR_HW_FLAGS_YVU422 (SUBFORMAT_ID_YVU422)
|
||||
|
||||
typedef void (*vsync_cb_t)(uint32_t vsync);
|
||||
typedef void (*frame_cb_t)();
|
||||
@ -203,6 +205,7 @@ typedef struct _sensor {
|
||||
uint32_t rgb_swap:1; // Byte-swap 2BPP RGB formats after capture.
|
||||
uint32_t yuv_swap:1; // Byte-swap 2BPP YUV formats after capture.
|
||||
uint32_t bayer:3; // Bayer/CFA pattern.
|
||||
uint32_t yuv_order:1; // YUV/YVU order.
|
||||
} hw_flags;
|
||||
|
||||
const uint16_t *color_palette; // Color palette used for color lookup.
|
||||
|
||||
@ -520,11 +520,11 @@ __weak int sensor_set_pixformat(pixformat_t pixformat)
|
||||
}
|
||||
|
||||
// Some sensor drivers automatically switch to BAYER to reduce the frame size if it does not fit in RAM.
|
||||
// If the current format is BAYER (1BPP), and the target format is RGB-565 (2BPP) and the frame does not
|
||||
// If the current format is BAYER (1BPP), and the target format is color and (2BPP), and the frame does not
|
||||
// fit in RAM it will just be switched back again to BAYER, so we keep the current format unchanged.
|
||||
uint32_t size = framebuffer_get_buffer_size();
|
||||
if ((sensor.pixformat == PIXFORMAT_BAYER)
|
||||
&& (pixformat == PIXFORMAT_RGB565)
|
||||
&& ((pixformat == PIXFORMAT_RGB565) || (pixformat == PIXFORMAT_YUV422))
|
||||
&& (MAIN_FB()->u * MAIN_FB()->v * 2 > size)
|
||||
&& (MAIN_FB()->u * MAIN_FB()->v * 1 <= size)) {
|
||||
return 0;
|
||||
@ -1033,7 +1033,7 @@ __weak int sensor_set_special_effect(sde_t sde)
|
||||
if (sensor.set_special_effect == NULL) {
|
||||
return SENSOR_ERROR_CTL_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
// Call the sensor specific function.
|
||||
if (sensor.set_special_effect(&sensor, sde) != 0) {
|
||||
return SENSOR_ERROR_CTL_FAILED;
|
||||
@ -1124,7 +1124,7 @@ __weak int sensor_auto_crop_framebuffer()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sensor.pixformat == PIXFORMAT_RGB565) {
|
||||
if ((sensor.pixformat == PIXFORMAT_RGB565) || (sensor.pixformat == PIXFORMAT_YUV422)) {
|
||||
// Switch to bayer for the quick 2x savings.
|
||||
sensor_set_pixformat(PIXFORMAT_BAYER);
|
||||
bpp = 1;
|
||||
|
||||
@ -2444,11 +2444,20 @@ void imlib_draw_row(int x_start, int x_end, int y_row, imlib_draw_row_data_t *da
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
uint8_t *dst8 = (data->dst_row_override
|
||||
? ((uint8_t *) data->dst_row_override)
|
||||
: IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(data->dst_img, y_row)) + x_start;
|
||||
: IMAGE_COMPUTE_BAYER_PIXEL_ROW_PTR(data->dst_img, y_row)) + x_start;
|
||||
uint8_t *src8 = ((uint8_t *) data->row_buffer[!data->toggle]) + x_start;
|
||||
unaligned_memcpy(dst8, src8, (x_end - x_start) * sizeof(uint8_t));
|
||||
break;
|
||||
}
|
||||
// Only yuv422 copying/cropping is supported.
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
uint16_t *dst16 = (data->dst_row_override
|
||||
? ((uint16_t *) data->dst_row_override)
|
||||
: IMAGE_COMPUTE_YUV_PIXEL_ROW_PTR(data->dst_img, y_row)) + x_start;
|
||||
uint16_t *src16 = ((uint16_t *) data->row_buffer[!data->toggle]) + x_start;
|
||||
unaligned_memcpy(dst16, src16, (x_end - x_start) * sizeof(uint16_t));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
@ -2673,7 +2682,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
// rgb_channel extracted / color_palette applied image
|
||||
image_t new_src_img;
|
||||
|
||||
if (((hint & IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST) && (rgb_channel != -1) && IMAGE_IS_COLOR(src_img))
|
||||
if (((hint & IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST) && (rgb_channel != -1) && src_img->is_color)
|
||||
|| ((hint & IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST) && color_palette)) {
|
||||
new_src_img.w = src_img_w; // same width as source image
|
||||
new_src_img.h = src_img_h; // same height as source image
|
||||
@ -2687,11 +2696,10 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
|
||||
// Special destination?
|
||||
bool is_jpeg = (src_img->pixfmt == PIXFORMAT_JPEG);
|
||||
bool is_bayer_or_jpeg = src_img->is_bayer || is_jpeg;
|
||||
// Best format to convert bayer/jpeg image to.
|
||||
int is_bayer_or_jpeg_pixfmt = (rgb_channel != -1) ? PIXFORMAT_RGB565 :
|
||||
(color_palette ? PIXFORMAT_GRAYSCALE :
|
||||
dst_img->pixfmt);
|
||||
// Best format to convert yuv/bayer/jpeg image to.
|
||||
int new_not_mutable_pixfmt = (rgb_channel != -1) ? PIXFORMAT_RGB565 :
|
||||
(color_palette ? PIXFORMAT_GRAYSCALE :
|
||||
dst_img->pixfmt);
|
||||
|
||||
bool no_scaling_nearest_neighbor = (dst_delta_x == 1)
|
||||
&& (dst_x_start == 0) && (src_x_start == 0)
|
||||
@ -2707,21 +2715,23 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
|
||||
// Do we need to convert the image?
|
||||
bool is_bayer_color_conversion = src_img->is_bayer && !dst_img->is_bayer;
|
||||
bool is_yuv_color_conversion = src_img->is_yuv && !dst_img->is_yuv;
|
||||
bool is_color_conversion = is_bayer_color_conversion || is_yuv_color_conversion;
|
||||
|
||||
// Force a deep copy if we cannot use the image in-place.
|
||||
bool need_deep_copy = (dst_img->data == src_img->data)
|
||||
&& (is_scaling || (src_img_row_bytes < dst_img_row_bytes) || is_bayer_color_conversion);
|
||||
&& (is_scaling || (src_img_row_bytes < dst_img_row_bytes) || is_color_conversion);
|
||||
|
||||
// Force a deep copy if we are scaling.
|
||||
bool is_bayer_scaling = is_bayer_color_conversion && is_scaling;
|
||||
bool is_color_conversion_scaling = is_color_conversion && is_scaling;
|
||||
|
||||
// Make a deep copy of the source image.
|
||||
if (need_deep_copy || is_bayer_scaling || is_jpeg) {
|
||||
if (need_deep_copy || is_color_conversion_scaling || is_jpeg) {
|
||||
new_src_img.w = src_img->w; // same width as source image
|
||||
new_src_img.h = src_img->h; // same height as source image
|
||||
|
||||
if (is_bayer_or_jpeg) {
|
||||
new_src_img.pixfmt = is_bayer_or_jpeg_pixfmt;
|
||||
if (!src_img->is_mutable) {
|
||||
new_src_img.pixfmt = new_not_mutable_pixfmt;
|
||||
size_t size = image_size(&new_src_img);
|
||||
new_src_img.data = fb_alloc(size, FB_ALLOC_NO_HINT);
|
||||
|
||||
@ -2729,7 +2739,9 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
case PIXFORMAT_BINARY: {
|
||||
if (src_img->is_bayer) {
|
||||
imlib_debayer_image(&new_src_img, src_img);
|
||||
} else if (src_img->pixfmt == PIXFORMAT_JPEG) {
|
||||
} else if (src_img->is_yuv) {
|
||||
imlib_deyuv_image(&new_src_img, src_img);
|
||||
} else if (is_jpeg) {
|
||||
jpeg_decompress_image_to_binary(&new_src_img, src_img);
|
||||
}
|
||||
break;
|
||||
@ -2737,7 +2749,9 @@ 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(&new_src_img, src_img);
|
||||
} else if (src_img->pixfmt == PIXFORMAT_JPEG) {
|
||||
} else if (src_img->is_yuv) {
|
||||
imlib_deyuv_image(&new_src_img, src_img);
|
||||
} else if (is_jpeg) {
|
||||
jpeg_decompress_image_to_grayscale(&new_src_img, src_img);
|
||||
}
|
||||
break;
|
||||
@ -2745,12 +2759,15 @@ 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(&new_src_img, src_img);
|
||||
} else if (src_img->pixfmt == PIXFORMAT_JPEG) {
|
||||
} else if (src_img->is_yuv) {
|
||||
imlib_deyuv_image(&new_src_img, src_img);
|
||||
} else if (is_jpeg) {
|
||||
jpeg_decompress_image_to_rgb565(&new_src_img, src_img);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
case PIXFORMAT_BAYER_ANY:
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
memcpy(new_src_img.data, src_img->data, size);
|
||||
break;
|
||||
}
|
||||
@ -2770,7 +2787,7 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
|
||||
imlib_draw_row_data_t imlib_draw_row_data;
|
||||
imlib_draw_row_data.dst_img = dst_img;
|
||||
imlib_draw_row_data.src_img_pixfmt = is_bayer_or_jpeg ? is_bayer_or_jpeg_pixfmt : src_img->pixfmt;
|
||||
imlib_draw_row_data.src_img_pixfmt = (!src_img->is_mutable) ? new_not_mutable_pixfmt : src_img->pixfmt;
|
||||
imlib_draw_row_data.rgb_channel = rgb_channel;
|
||||
imlib_draw_row_data.alpha = alpha;
|
||||
imlib_draw_row_data.color_palette = color_palette;
|
||||
@ -4538,7 +4555,9 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
} // while y
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
// Re-use RGB565 for yuv.
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
while (y_not_done) {
|
||||
uint16_t *src_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||
// Must be called per loop to get the address of the temp buffer to blend with
|
||||
@ -4622,16 +4641,44 @@ 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:
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
case PIXFORMAT_RGB565: {
|
||||
switch (new_not_mutable_pixfmt) {
|
||||
case PIXFORMAT_MUTABLE_ANY: {
|
||||
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);
|
||||
imlib_draw_row_get_row_buffer(&imlib_draw_row_data),
|
||||
new_not_mutable_pixfmt, src_img);
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY: { // Bayer images have the same shape as grayscale.
|
||||
uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||
case PIXFORMAT_BAYER_ANY: { // Bayer images have the same shape as GRAYSCALE.
|
||||
uint8_t *src_row_ptr = IMAGE_COMPUTE_BAYER_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imlib_draw_row(dst_x_start, dst_x_end, dst_y, &imlib_draw_row_data);
|
||||
|
||||
// Increment offsets
|
||||
dst_y += dst_delta_y;
|
||||
src_y_accum += src_y_frac;
|
||||
next_src_y_index = src_y_accum >> 16;
|
||||
y_not_done = ++y < dst_y_end;
|
||||
} // while y
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
while (y_not_done) {
|
||||
switch (new_not_mutable_pixfmt) {
|
||||
case PIXFORMAT_MUTABLE_ANY: {
|
||||
imlib_deyuv_line(dst_x_start, dst_x_end, next_src_y_index,
|
||||
imlib_draw_row_get_row_buffer(&imlib_draw_row_data),
|
||||
new_not_mutable_pixfmt, src_img);
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_YUV_ANY: { // YUV images have the same shape as RGB565.
|
||||
uint16_t *src_row_ptr = IMAGE_COMPUTE_YUV_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
||||
break;
|
||||
}
|
||||
@ -4743,7 +4790,9 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
||||
} // while y
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
// Re-use RGB565 for yuv.
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
while (y_not_done) {
|
||||
int src_y_index = next_src_y_index;
|
||||
uint16_t *src_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src_img, src_y_index);
|
||||
|
||||
@ -88,13 +88,17 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay)
|
||||
write_byte(fp, (red<<5) | (green<<2) | blue);
|
||||
}
|
||||
}
|
||||
} else if (IM_IS_BAYER(img)) {
|
||||
} else if (img->is_bayer || img->is_yuv) {
|
||||
for (int y=0; y<blocks; y++) {
|
||||
int block_size = IM_MIN(BLOCK_SIZE, bytes - (y*BLOCK_SIZE));
|
||||
write_byte(fp, 1 + block_size);
|
||||
write_byte(fp, 0x80); // clear code
|
||||
uint16_t pixels[block_size];
|
||||
imlib_debayer_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img);
|
||||
if (img->is_bayer) {
|
||||
imlib_debayer_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img);
|
||||
} else {
|
||||
imlib_deyuv_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img);
|
||||
}
|
||||
for (int x=0; x<block_size; x++) {
|
||||
int r = COLOR_RGB565_TO_R8(pixels[x]);
|
||||
int g = COLOR_RGB565_TO_G8(pixels[x]);
|
||||
@ -105,7 +109,6 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
write_data(fp, (uint8_t []) {0x01, 0x81, 0x00}, 3); // end code
|
||||
|
||||
file_buffer_off(fp);
|
||||
|
||||
@ -260,15 +260,14 @@ size_t image_size(image_t *ptr)
|
||||
case PIXFORMAT_BINARY: {
|
||||
return IMAGE_BINARY_LINE_LEN_BYTES(ptr) * ptr->h;
|
||||
}
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
case PIXFORMAT_BAYER_ANY: { // re-use
|
||||
return IMAGE_GRAYSCALE_LINE_LEN_BYTES(ptr) * ptr->h;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_YUV_ANY: { // re-use
|
||||
return IMAGE_RGB565_LINE_LEN_BYTES(ptr) * ptr->h;
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
return ptr->w * ptr->h;
|
||||
}
|
||||
case PIXFORMAT_JPEG: {
|
||||
return ptr->size;
|
||||
}
|
||||
|
||||
@ -341,20 +341,22 @@ typedef enum {
|
||||
PIXFORMAT_ID_BINARY = 1,
|
||||
PIXFORMAT_ID_GRAY = 2,
|
||||
PIXFORMAT_ID_RGB565 = 3,
|
||||
PIXFORMAT_ID_YUV422 = 4,
|
||||
PIXFORMAT_ID_BAYER = 5,
|
||||
PIXFORMAT_ID_BAYER = 4,
|
||||
PIXFORMAT_ID_YUV422 = 5,
|
||||
PIXFORMAT_ID_JPEG = 6,
|
||||
/* Note: Update PIXFORMAT_IS_VALID when adding new formats */
|
||||
} pixformat_id_t;
|
||||
|
||||
// Pixel sub-format IDs.
|
||||
typedef enum {
|
||||
SUBFORMAT_ID_GRAY8 = 0,
|
||||
SUBFORMAT_ID_GRAY16 = 1,
|
||||
SUBFORMAT_ID_BGGR = 0, // !!! Note: Make sure bayer sub-formats don't !!!
|
||||
SUBFORMAT_ID_GBRG = 1, // !!! overflow the sensor.hw_flags.bayer field !!!
|
||||
SUBFORMAT_ID_GRBG = 2,
|
||||
SUBFORMAT_ID_RGGB = 3,
|
||||
SUBFORMAT_ID_GRAY8 = 0,
|
||||
SUBFORMAT_ID_GRAY16 = 1,
|
||||
SUBFORMAT_ID_YUV422 = 0,
|
||||
SUBFORMAT_ID_YVU422 = 1,
|
||||
/* Note: Update PIXFORMAT_IS_VALID when adding new formats */
|
||||
} subformat_id_t;
|
||||
|
||||
@ -364,45 +366,58 @@ typedef enum {
|
||||
PIXFORMAT_BPP_GRAY8 = 1,
|
||||
PIXFORMAT_BPP_GRAY16 = 2,
|
||||
PIXFORMAT_BPP_RGB565 = 2,
|
||||
PIXFORMAT_BPP_YUV422 = 2,
|
||||
PIXFORMAT_BPP_BAYER = 1,
|
||||
PIXFORMAT_BPP_YUV422 = 2,
|
||||
/* Note: Update PIXFORMAT_IS_VALID when adding new formats */
|
||||
} pixformat_bpp_t;
|
||||
|
||||
// Pixel format flags.
|
||||
#define PIXFORMAT_FLAGS_Y (1 << 28) // YUV format.
|
||||
#define PIXFORMAT_FLAGS_M (1 << 27) // Mutable format.
|
||||
#define PIXFORMAT_FLAGS_C (1 << 26) // Colored format.
|
||||
#define PIXFORMAT_FLAGS_J (1 << 25) // Compressed format (JPEG/PNG).
|
||||
#define PIXFORMAT_FLAGS_R (1 << 24) // RAW/Bayer format.
|
||||
#define PIXFORMAT_FLAGS_CY (PIXFORMAT_FLAGS_C | PIXFORMAT_FLAGS_Y)
|
||||
#define PIXFORMAT_FLAGS_CM (PIXFORMAT_FLAGS_C | PIXFORMAT_FLAGS_M)
|
||||
#define PIXFORMAT_FLAGS_CR (PIXFORMAT_FLAGS_C | PIXFORMAT_FLAGS_R)
|
||||
#define PIXFORMAT_FLAGS_CJ (PIXFORMAT_FLAGS_C | PIXFORMAT_FLAGS_J)
|
||||
#define IMLIB_IMAGE_MAX_SIZE(x) ((x) & 0xFFFFFFFF)
|
||||
|
||||
// Each pixel format encodes flags, pixel format id and bpp as follows:
|
||||
// 31......28 27 26 25 24 23..........16 15...........8 7.............0
|
||||
// <RESERVED> MF CF JF RF <PIXFORMAT_ID> <SUBFORMAT_ID> <BYTES_PER_PIX>
|
||||
// 31......29 28 27 26 25 24 23..........16 15...........8 7.............0
|
||||
// <RESERVED> YF MF CF JF RF <PIXFORMAT_ID> <SUBFORMAT_ID> <BYTES_PER_PIX>
|
||||
// NOTE: Bit 31-30 must Not be used for pixformat_t to be used as mp_int_t.
|
||||
typedef enum {
|
||||
PIXFORMAT_INVALID = (0),
|
||||
PIXFORMAT_BINARY = (PIXFORMAT_FLAGS_M | (PIXFORMAT_ID_BINARY << 16) | (0 << 8) | PIXFORMAT_BPP_BINARY ),
|
||||
PIXFORMAT_GRAYSCALE = (PIXFORMAT_FLAGS_M | (PIXFORMAT_ID_GRAY << 16) | (SUBFORMAT_ID_GRAY8 << 8) | PIXFORMAT_BPP_GRAY8 ),
|
||||
PIXFORMAT_RGB565 = (PIXFORMAT_FLAGS_CM | (PIXFORMAT_ID_RGB565 << 16) | (0 << 8) | PIXFORMAT_BPP_RGB565 ),
|
||||
PIXFORMAT_YUV422 = (PIXFORMAT_FLAGS_CM | (PIXFORMAT_ID_YUV422 << 16) | (0 << 8) | PIXFORMAT_BPP_YUV422 ),
|
||||
PIXFORMAT_BAYER = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_BGGR << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_BGGR = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_BGGR << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_GBRG = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_GBRG << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_GRBG = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_GRBG << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_RGGB = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_RGGB << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_JPEG = (PIXFORMAT_FLAGS_J | (PIXFORMAT_ID_JPEG << 16) | (0 << 8) | 0 ),
|
||||
PIXFORMAT_BINARY = (PIXFORMAT_FLAGS_M | (PIXFORMAT_ID_BINARY << 16) | (0 << 8) | PIXFORMAT_BPP_BINARY ),
|
||||
PIXFORMAT_GRAYSCALE = (PIXFORMAT_FLAGS_M | (PIXFORMAT_ID_GRAY << 16) | (SUBFORMAT_ID_GRAY8 << 8) | PIXFORMAT_BPP_GRAY8 ),
|
||||
PIXFORMAT_RGB565 = (PIXFORMAT_FLAGS_CM | (PIXFORMAT_ID_RGB565 << 16) | (0 << 8) | PIXFORMAT_BPP_RGB565 ),
|
||||
PIXFORMAT_BAYER = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_BGGR << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_BGGR = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_BGGR << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_GBRG = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_GBRG << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_GRBG = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_GRBG << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_BAYER_RGGB = (PIXFORMAT_FLAGS_CR | (PIXFORMAT_ID_BAYER << 16) | (SUBFORMAT_ID_RGGB << 8) | PIXFORMAT_BPP_BAYER ),
|
||||
PIXFORMAT_YUV422 = (PIXFORMAT_FLAGS_CY | (PIXFORMAT_ID_YUV422 << 16) | (SUBFORMAT_ID_YUV422 << 8) | PIXFORMAT_BPP_YUV422 ),
|
||||
PIXFORMAT_YVU422 = (PIXFORMAT_FLAGS_CY | (PIXFORMAT_ID_YUV422 << 16) | (SUBFORMAT_ID_YVU422 << 8) | PIXFORMAT_BPP_YUV422 ),
|
||||
PIXFORMAT_JPEG = (PIXFORMAT_FLAGS_CJ | (PIXFORMAT_ID_JPEG << 16) | (0 << 8) | 0 ),
|
||||
PIXFORMAT_LAST = 0xFFFFFFFFU,
|
||||
} pixformat_t;
|
||||
|
||||
#define PIXFORMAT_MUTABLE_ANY \
|
||||
PIXFORMAT_BINARY: \
|
||||
case PIXFORMAT_GRAYSCALE: \
|
||||
case PIXFORMAT_RGB565 \
|
||||
|
||||
#define PIXFORMAT_BAYER_ANY \
|
||||
PIXFORMAT_BAYER_BGGR: \
|
||||
case PIXFORMAT_BAYER_GBRG: \
|
||||
case PIXFORMAT_BAYER_GRBG: \
|
||||
case PIXFORMAT_BAYER_RGGB \
|
||||
|
||||
#define PIXFORMAT_YUV_ANY \
|
||||
PIXFORMAT_YUV422: \
|
||||
case PIXFORMAT_YVU422 \
|
||||
|
||||
#define IMLIB_PIXFORMAT_IS_VALID(x) \
|
||||
((x == PIXFORMAT_BINARY) \
|
||||
|| (x == PIXFORMAT_GRAYSCALE) \
|
||||
@ -411,6 +426,8 @@ typedef enum {
|
||||
|| (x == PIXFORMAT_BAYER_GBRG) \
|
||||
|| (x == PIXFORMAT_BAYER_GRBG) \
|
||||
|| (x == PIXFORMAT_BAYER_RGGB) \
|
||||
|| (x == PIXFORMAT_YUV422) \
|
||||
|| (x == PIXFORMAT_YVU422) \
|
||||
|| (x == PIXFORMAT_JPEG)) \
|
||||
|
||||
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
@ -425,7 +442,8 @@ struct { \
|
||||
uint32_t is_compressed :1; \
|
||||
uint32_t is_color :1; \
|
||||
uint32_t is_mutable :1; \
|
||||
uint32_t /*reserved*/ :4; \
|
||||
uint32_t is_yuv :1; \
|
||||
uint32_t /*reserved*/ :3; \
|
||||
}; \
|
||||
uint32_t pixfmt; \
|
||||
}; \
|
||||
@ -436,7 +454,8 @@ struct { \
|
||||
struct { \
|
||||
union { \
|
||||
struct { \
|
||||
uint32_t /*reserved*/ :4; \
|
||||
uint32_t /*reserved*/ :3; \
|
||||
uint32_t is_yuv :1; \
|
||||
uint32_t is_mutable :1; \
|
||||
uint32_t is_color :1; \
|
||||
uint32_t is_compressed :1; \
|
||||
@ -468,10 +487,6 @@ void image_copy(image_t *dst, image_t *src);
|
||||
size_t image_size(image_t *ptr);
|
||||
bool image_get_mask_pixel(image_t *ptr, int x, int y);
|
||||
|
||||
#define IMAGE_IS_MUTABLE(image) (image->is_mutable)
|
||||
#define IMAGE_IS_COLOR(image) (image->is_color)
|
||||
#define IMAGE_IS_MUTABLE_BAYER(image) (image->is_mutable || image->is_bayer)
|
||||
|
||||
#define IMAGE_BINARY_LINE_LEN(image) (((image)->w + UINT32_T_MASK) >> UINT32_T_SHIFT)
|
||||
#define IMAGE_BINARY_LINE_LEN_BYTES(image) (IMAGE_BINARY_LINE_LEN(image) * sizeof(uint32_t))
|
||||
|
||||
@ -550,6 +565,40 @@ bool image_get_mask_pixel(image_t *ptr, int x, int y);
|
||||
((uint16_t *) _image->data)[(_image->w * _y) + _x] = _v; \
|
||||
})
|
||||
|
||||
#define IMAGE_GET_YUV_PIXEL(image, x, y) \
|
||||
({ \
|
||||
__typeof__ (image) _image = (image); \
|
||||
__typeof__ (x) _x = (x); \
|
||||
__typeof__ (y) _y = (y); \
|
||||
((uint16_t *) _image->data)[(_image->w * _y) + _x]; \
|
||||
})
|
||||
|
||||
#define IMAGE_PUT_YUV_PIXEL(image, x, y, v) \
|
||||
({ \
|
||||
__typeof__ (image) _image = (image); \
|
||||
__typeof__ (x) _x = (x); \
|
||||
__typeof__ (y) _y = (y); \
|
||||
__typeof__ (v) _v = (v); \
|
||||
((uint16_t *) _image->data)[(_image->w * _y) + _x] = _v; \
|
||||
})
|
||||
|
||||
#define IMAGE_GET_BAYER_PIXEL(image, x, y) \
|
||||
({ \
|
||||
__typeof__ (image) _image = (image); \
|
||||
__typeof__ (x) _x = (x); \
|
||||
__typeof__ (y) _y = (y); \
|
||||
((uint8_t *) _image->data)[(_image->w * _y) + _x]; \
|
||||
})
|
||||
|
||||
#define IMAGE_PUT_BAYER_PIXEL(image, x, y, v) \
|
||||
({ \
|
||||
__typeof__ (image) _image = (image); \
|
||||
__typeof__ (x) _x = (x); \
|
||||
__typeof__ (y) _y = (y); \
|
||||
__typeof__ (v) _v = (v); \
|
||||
((uint8_t *) _image->data)[(_image->w * _y) + _x] = _v; \
|
||||
})
|
||||
|
||||
// Fast Stuff //
|
||||
|
||||
#define IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(image, y) \
|
||||
@ -634,6 +683,20 @@ bool image_get_mask_pixel(image_t *ptr, int x, int y);
|
||||
_row_ptr[_x] = _v; \
|
||||
})
|
||||
|
||||
#define IMAGE_COMPUTE_BAYER_PIXEL_ROW_PTR(image, y) \
|
||||
({ \
|
||||
__typeof__ (image) _image = (image); \
|
||||
__typeof__ (y) _y = (y); \
|
||||
((uint8_t *) _image->data) + (_image->w * _y); \
|
||||
})
|
||||
|
||||
#define IMAGE_COMPUTE_YUV_PIXEL_ROW_PTR(image, y) \
|
||||
({ \
|
||||
__typeof__ (image) _image = (image); \
|
||||
__typeof__ (y) _y = (y); \
|
||||
((uint16_t *) _image->data) + (_image->w * _y); \
|
||||
})
|
||||
|
||||
// Old Image Macros - Will be refactor and removed. But, only after making sure through testing new macros work.
|
||||
|
||||
// Image kernels
|
||||
@ -1016,6 +1079,10 @@ void imlib_fill_image_from_float(image_t *img, int w, int h, float *data, float
|
||||
void imlib_debayer_line(int x_start, int x_end, int y_row, void *dst_row_ptr, pixformat_t pixfmt, image_t *src);
|
||||
void imlib_debayer_image(image_t *dst, image_t *src);
|
||||
|
||||
// YUV Image Processing
|
||||
void imlib_deyuv_line(int x_start, int x_end, int y_row, void *dst_row_ptr, pixformat_t pixfmt, image_t *src);
|
||||
void imlib_deyuv_image(image_t *dst, image_t *src);
|
||||
|
||||
/* Color space functions */
|
||||
int8_t imlib_rgb565_to_l(uint16_t pixel);
|
||||
int8_t imlib_rgb565_to_a(uint16_t pixel);
|
||||
|
||||
@ -148,7 +148,9 @@ static void jpeg_get_mcu(image_t *src, int x_offset, int y_offset, int dx, int d
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
if ((dx != MCU_W) || (dy != MCU_H)) { // partial MCU, fill with 0's to start
|
||||
memset(Y0, 0, JPEG_444_YCBCR_MCU_SIZE);
|
||||
memset(Y0, 0, JPEG_444_GS_MCU_SIZE);
|
||||
memset(CB, 0, JPEG_444_GS_MCU_SIZE);
|
||||
memset(CR, 0, JPEG_444_GS_MCU_SIZE);
|
||||
}
|
||||
|
||||
for (int y = y_offset, yy = y + dy, index = 0; y < yy; y++) {
|
||||
@ -220,9 +222,79 @@ static void jpeg_get_mcu(image_t *src, int x_offset, int y_offset, int dx, int d
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
if ((dx != MCU_W) || (dy != MCU_H)) { // partial MCU, fill with 0's to start
|
||||
memset(Y0, 0, JPEG_444_GS_MCU_SIZE);
|
||||
memset(CB, 0, JPEG_444_GS_MCU_SIZE);
|
||||
memset(CR, 0, JPEG_444_GS_MCU_SIZE);
|
||||
}
|
||||
|
||||
int shift = (src->pixfmt == PIXFORMAT_YUV422) ? 24 : 8;
|
||||
|
||||
for (int y = y_offset, yy = y + dy, index = 0; y < yy; y++) {
|
||||
uint32_t *rp = (uint32_t *) (IMAGE_COMPUTE_YUV_PIXEL_ROW_PTR(src, y) + x_offset);
|
||||
|
||||
for (int x = 0, xx = dx - 1; x < xx; x += 2, index += 2) {
|
||||
int pixels = *rp++;
|
||||
|
||||
#if (OMV_HARDWARE_JPEG == 0)
|
||||
pixels ^= 0x80808080;
|
||||
#endif
|
||||
|
||||
Y0[index] = pixels, Y0[index + 1] = pixels >> 16;
|
||||
|
||||
int cb = pixels >> shift;
|
||||
CB[index] = cb, CB[index + 1] = cb;
|
||||
|
||||
int cr = pixels >> (32 - shift);
|
||||
CR[index] = cr, CR[index + 1] = cr;
|
||||
}
|
||||
|
||||
if (dx & 1) {
|
||||
int pixel = *((uint16_t *) rp);
|
||||
|
||||
#if (OMV_HARDWARE_JPEG == 0)
|
||||
pixel ^= 0x8080;
|
||||
#endif
|
||||
|
||||
Y0[index] = pixel;
|
||||
|
||||
if (index % MCU_W) {
|
||||
if (shift == 8) {
|
||||
CR[index] = CR[index - 1];
|
||||
CB[index++] = pixel >> 8;
|
||||
} else {
|
||||
CB[index] = CB[index - 1];
|
||||
CR[index++] = pixel >> 8;
|
||||
}
|
||||
} else {
|
||||
if (shift == 8) {
|
||||
CB[index] = pixel >> 8;
|
||||
#if (OMV_HARDWARE_JPEG == 0)
|
||||
CR[index++] = 0;
|
||||
#else
|
||||
CR[index++] = 0x80;
|
||||
#endif
|
||||
} else {
|
||||
#if (OMV_HARDWARE_JPEG == 0)
|
||||
CB[index] = 0;
|
||||
#else
|
||||
CB[index] = 0x80;
|
||||
#endif
|
||||
CR[index++] = pixel >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index += MCU_W - dx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
if ((dx != MCU_W) || (dy != MCU_H)) { // partial MCU, fill with 0's to start
|
||||
memset(Y0, 0, JPEG_444_YCBCR_MCU_SIZE);
|
||||
memset(Y0, 0, JPEG_444_GS_MCU_SIZE);
|
||||
memset(CB, 0, JPEG_444_GS_MCU_SIZE);
|
||||
memset(CR, 0, JPEG_444_GS_MCU_SIZE);
|
||||
}
|
||||
|
||||
int src_w = src->w, w_limit = src_w - 1, w_limit_m_1 = w_limit - 1;
|
||||
@ -987,6 +1059,7 @@ bool jpeg_compress(image_t *src, image_t *dst, int quality, bool realloc)
|
||||
break;
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_BAYER_ANY:
|
||||
case PIXFORMAT_YUV_ANY:
|
||||
mcu_size = JPEG_444_YCBCR_MCU_SIZE;
|
||||
JPEG_Info.ColorSpace = JPEG_YCBCR_COLORSPACE;
|
||||
JPEG_Info.ChromaSubsampling = JPEG_444_SUBSAMPLING;
|
||||
|
||||
127
src/omv/imlib/yuv.c
Normal file
127
src/omv/imlib/yuv.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
*
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* Deyuv Functions
|
||||
*/
|
||||
#include "imlib.h"
|
||||
|
||||
void imlib_deyuv_line(int x_start, int x_end, int y_row, void *dst_row_ptr, pixformat_t pixfmt, image_t *src)
|
||||
{
|
||||
int shift = (src->pixfmt == PIXFORMAT_YUV422) ? 16 : 0;
|
||||
int src_w = src->w, w_limit = src_w - 1;
|
||||
|
||||
uint16_t *rowptr_yuv = ((uint16_t *) src->data) + (y_row * 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 = x_start; x < x_end; x += 2) {
|
||||
int32_t row_yuv; // signed
|
||||
|
||||
// keep pixels in bounds
|
||||
if (x >= w_limit) {
|
||||
if (src_w >= 2) {
|
||||
uint32_t temp = *((uint32_t *) (rowptr_yuv + x - 1));
|
||||
row_yuv = ((temp & 0xff00) << 16) | (temp & 0xff0000) | (temp >> 16);
|
||||
} else {
|
||||
row_yuv = *((uint16_t *) (rowptr_yuv + x));
|
||||
row_yuv = ((row_yuv & 0xff) << 16) | 0x80000000;
|
||||
}
|
||||
} else {
|
||||
row_yuv = *((uint32_t *) (rowptr_yuv + x));
|
||||
}
|
||||
|
||||
int y0 = row_yuv & 0xff, y1 = (row_yuv >> 16) & 0xff;
|
||||
|
||||
switch (pixfmt) {
|
||||
case PIXFORMAT_BINARY: {
|
||||
uint32_t *row_ptr_32 = (uint32_t *) dst_row_ptr;
|
||||
IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_32, x, (y0 >> 7));
|
||||
|
||||
if (x != w_limit) {
|
||||
IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_32, x + 1, (y1 >> 7));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
uint8_t *row_ptr_8 = (uint8_t *) dst_row_ptr;
|
||||
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_8, x, y0);
|
||||
|
||||
if (x != w_limit) {
|
||||
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_8, x + 1, y1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
uint16_t *row_ptr_16 = (uint16_t *) dst_row_ptr;
|
||||
|
||||
// R = Y + (1.40200 * U)
|
||||
// G = Y - (0.34414 * V) - (0.71414 * U)
|
||||
// B = Y + (1.77200 * V)
|
||||
|
||||
// R = Y + ((179 * U) >> 7)
|
||||
// G = Y - (((44 * V) - (91 * U)) >> 7)
|
||||
// B = Y + ((227 * V) >> 7)
|
||||
|
||||
row_yuv ^= 0x80008000;
|
||||
|
||||
int u = (row_yuv << shift) >> 24; // signed bit extraction
|
||||
int v = (row_yuv << (16 - shift)) >> 24; // signed bit extraction
|
||||
|
||||
int ry = (179 * u) >> 7;
|
||||
int gy = ((44 * v) + (91 * u)) >> 7;
|
||||
int by = (227 * v) >> 7;
|
||||
|
||||
int r0 = y0 + ry, g0 = y0 - gy, b0 = y0 + by;
|
||||
r0 = IM_MIN(IM_MAX(r0, COLOR_R8_MIN), COLOR_R8_MAX);
|
||||
g0 = IM_MIN(IM_MAX(g0, COLOR_G8_MIN), COLOR_G8_MAX);
|
||||
b0 = IM_MIN(IM_MAX(b0, COLOR_B8_MIN), COLOR_B8_MAX);
|
||||
int rgb565_0 = COLOR_R8_G8_B8_TO_RGB565(r0, g0, b0);
|
||||
IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_16, x, rgb565_0);
|
||||
|
||||
if (x != w_limit) {
|
||||
int r1 = y1 + ry, g1 = y1 - gy, b1 = y1 + by;
|
||||
r1 = IM_MIN(IM_MAX(r1, COLOR_R8_MIN), COLOR_R8_MAX);
|
||||
g1 = IM_MIN(IM_MAX(g1, COLOR_G8_MIN), COLOR_G8_MAX);
|
||||
b1 = IM_MIN(IM_MAX(b1, COLOR_B8_MIN), COLOR_B8_MAX);
|
||||
int rgb565_1 = COLOR_R8_G8_B8_TO_RGB565(r1, g1, b1);
|
||||
IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_16, x + 1, rgb565_1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void imlib_deyuv_image(image_t *dst, image_t *src)
|
||||
{
|
||||
for (int y = 0, src_w = src->w, src_h = src->h; y < src_h; y++) {
|
||||
void *row_ptr = NULL;
|
||||
|
||||
switch (dst->pixfmt) {
|
||||
case PIXFORMAT_BINARY: {
|
||||
row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(dst, y);
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(dst, y);
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(dst, y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imlib_deyuv_line(0, src_w, y, row_ptr, dst->pixfmt, src);
|
||||
}
|
||||
}
|
||||
@ -1082,7 +1082,7 @@ mp_obj_t py_fir_snapshot(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
if (mp_obj_is_integer(copy_to_fb_obj)) {
|
||||
copy_to_fb = mp_obj_get_int(copy_to_fb_obj);
|
||||
} else {
|
||||
arg_other = py_helper_arg_to_image_mutable_bayer(copy_to_fb_obj);
|
||||
arg_other = py_helper_arg_to_image_not_compressed(copy_to_fb_obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,21 +27,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(py_func_unavailable_obj, 0, py_func_unavailable);
|
||||
image_t *py_helper_arg_to_image_mutable(const mp_obj_t arg)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(arg);
|
||||
PY_ASSERT_TRUE_MSG(IMAGE_IS_MUTABLE(arg_img), "Image is not mutable!");
|
||||
PY_ASSERT_TRUE_MSG(arg_img->is_mutable, "Image is not mutable!");
|
||||
return arg_img;
|
||||
}
|
||||
|
||||
image_t *py_helper_arg_to_image_mutable_bayer(const mp_obj_t arg)
|
||||
image_t *py_helper_arg_to_image_not_compressed(const mp_obj_t arg)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(arg);
|
||||
PY_ASSERT_TRUE_MSG(IMAGE_IS_MUTABLE_BAYER(arg_img), "Image is not mutable!");
|
||||
return arg_img;
|
||||
}
|
||||
|
||||
image_t *py_helper_arg_to_image_mutable_bayer_jpeg(const mp_obj_t arg)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(arg);
|
||||
PY_ASSERT_TRUE_MSG(IMLIB_PIXFORMAT_IS_VALID(arg_img->pixfmt), "Image is not mutable!");
|
||||
PY_ASSERT_FALSE_MSG(arg_img->is_compressed, "Image is compressed!");
|
||||
return arg_img;
|
||||
}
|
||||
|
||||
@ -52,13 +45,6 @@ image_t *py_helper_arg_to_image_grayscale(const mp_obj_t arg)
|
||||
return arg_img;
|
||||
}
|
||||
|
||||
image_t *py_helper_arg_to_image_color(const mp_obj_t arg)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(arg);
|
||||
PY_ASSERT_TRUE_MSG(arg_img->pixfmt == PIXFORMAT_RGB565, "Image is not RGB565!");
|
||||
return arg_img;
|
||||
}
|
||||
|
||||
image_t *py_helper_keyword_to_image_mutable(uint n_args, const mp_obj_t *args, uint arg_index,
|
||||
mp_map_t *kw_args, mp_obj_t kw, image_t *default_val)
|
||||
{
|
||||
|
||||
@ -13,10 +13,8 @@
|
||||
#include "imlib.h"
|
||||
extern const mp_obj_fun_builtin_var_t py_func_unavailable_obj;
|
||||
image_t *py_helper_arg_to_image_mutable(const mp_obj_t arg);
|
||||
image_t *py_helper_arg_to_image_mutable_bayer(const mp_obj_t arg);
|
||||
image_t *py_helper_arg_to_image_mutable_bayer_jpeg(const mp_obj_t arg);
|
||||
image_t *py_helper_arg_to_image_not_compressed(const mp_obj_t arg);
|
||||
image_t *py_helper_arg_to_image_grayscale(const mp_obj_t arg);
|
||||
image_t *py_helper_arg_to_image_color(const mp_obj_t arg);
|
||||
image_t *py_helper_keyword_to_image_mutable(uint n_args, const mp_obj_t *args, uint arg_index,
|
||||
mp_map_t *kw_args, mp_obj_t kw, image_t *default_val);
|
||||
image_t *py_helper_keyword_to_image_mutable_mask(uint n_args, const mp_obj_t *args, uint arg_index,
|
||||
|
||||
@ -312,8 +312,8 @@ STATIC mp_obj_t py_image_it_iternext(mp_obj_t self_in)
|
||||
return row;
|
||||
}
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY:
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
if (self->cur >= img->h) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
} else {
|
||||
@ -325,7 +325,8 @@ STATIC mp_obj_t py_image_it_iternext(mp_obj_t self_in)
|
||||
return row;
|
||||
}
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
if (self->cur >= img->h) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
} else {
|
||||
@ -373,8 +374,13 @@ static void py_image_print(const mp_print_t *print, mp_obj_t self, mp_print_kind
|
||||
(image->pixfmt == PIXFORMAT_BINARY) ? "binary" :
|
||||
(image->pixfmt == PIXFORMAT_GRAYSCALE) ? "grayscale" :
|
||||
(image->pixfmt == PIXFORMAT_RGB565) ? "rgb565" :
|
||||
(image->pixfmt == PIXFORMAT_BAYER_BGGR) ? "bayer_bggr" :
|
||||
(image->pixfmt == PIXFORMAT_BAYER_GBRG) ? "bayer_gbrg" :
|
||||
(image->pixfmt == PIXFORMAT_BAYER_GRBG) ? "bayer_grbg" :
|
||||
(image->pixfmt == PIXFORMAT_BAYER_RGGB) ? "bayer_rggb" :
|
||||
(image->pixfmt == PIXFORMAT_YUV422) ? "yuv422" :
|
||||
(image->pixfmt == PIXFORMAT_JPEG) ? "jpeg" : "bayer",
|
||||
(image->pixfmt == PIXFORMAT_YVU422) ? "yvu422" :
|
||||
(image->pixfmt == PIXFORMAT_JPEG) ? "jpeg" : "unknown",
|
||||
image_size(image));
|
||||
}
|
||||
}
|
||||
@ -401,8 +407,8 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
mp_uint_t i = mp_get_index(self->base.type, image->w * image->h, index, false);
|
||||
return mp_obj_new_int(IMAGE_GET_BINARY_PIXEL(image, i % image->w, i / image->w));
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY:
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_bound_slice_t slice;
|
||||
if (!mp_seq_get_fast_slice_indexes(image->w * image->h, index, &slice)) {
|
||||
@ -419,7 +425,8 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
uint8_t p = IMAGE_GET_GRAYSCALE_PIXEL(image, i % image->w, i / image->w);
|
||||
return mp_obj_new_int(p);
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_bound_slice_t slice;
|
||||
if (!mp_seq_get_fast_slice_indexes(image->w * image->h, index, &slice)) {
|
||||
@ -428,17 +435,27 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL);
|
||||
for (mp_uint_t i = 0; i < result->len; i++) {
|
||||
uint16_t p = IMAGE_GET_RGB565_PIXEL(image, (slice.start + i) % image->w, (slice.start + i) / image->w);
|
||||
result->items[i] = mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(COLOR_RGB565_TO_R8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_G8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_B8(p))});
|
||||
if (image->is_yuv) {
|
||||
result->items[i] = mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(p & 0xff),
|
||||
mp_obj_new_int((p >> 8) & 0xff)});
|
||||
} else {
|
||||
result->items[i] = mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(COLOR_RGB565_TO_R8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_G8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_B8(p))});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
mp_uint_t i = mp_get_index(self->base.type, image->w * image->h, index, false);
|
||||
uint16_t p = IMAGE_GET_RGB565_PIXEL(image, i % image->w, i / image->w);
|
||||
return mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(COLOR_RGB565_TO_R8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_G8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_B8(p))});
|
||||
if (image->is_yuv) {
|
||||
return mp_obj_new_tuple(2, (mp_obj_t []) {mp_obj_new_int(p & 0xff),
|
||||
mp_obj_new_int((p >> 8) & 0xff)});
|
||||
} else {
|
||||
return mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(COLOR_RGB565_TO_R8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_G8(p)),
|
||||
mp_obj_new_int(COLOR_RGB565_TO_B8(p))});
|
||||
}
|
||||
}
|
||||
case PIXFORMAT_JPEG: {
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
@ -486,8 +503,8 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
IMAGE_PUT_BINARY_PIXEL(image, i % image->w, i / image->w, mp_obj_get_int(value));
|
||||
return mp_const_none;
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY:
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_bound_slice_t slice;
|
||||
if (!mp_seq_get_fast_slice_indexes(image->w * image->h, index, &slice)) {
|
||||
@ -515,7 +532,8 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
IMAGE_PUT_GRAYSCALE_PIXEL(image, i % image->w, i / image->w, p);
|
||||
return mp_const_none;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_YUV_ANY: {
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_bound_slice_t slice;
|
||||
if (!mp_seq_get_fast_slice_indexes(image->w * image->h, index, &slice)) {
|
||||
@ -528,16 +546,36 @@ static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
PY_ASSERT_TRUE_MSG(value_l_len == (slice.stop - slice.start), "cannot grow or shrink image");
|
||||
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
|
||||
mp_obj_t *value_2;
|
||||
mp_obj_get_array_fixed_n(value_l[i], 3, &value_2);
|
||||
uint16_t p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]), mp_obj_get_int(value_2[1]), mp_obj_get_int(value_2[2]));
|
||||
IMAGE_PUT_RGB565_PIXEL(image, (slice.start + i) % image->w, (slice.start + i) / image->w, p);
|
||||
uint16_t p;
|
||||
if (image->is_yuv) {
|
||||
mp_obj_get_array_fixed_n(value_l[i], 2, &value_2);
|
||||
p = (mp_obj_get_int(value_2[0]) & 0xff) |
|
||||
(mp_obj_get_int(value_2[1]) & 0xff) << 8;
|
||||
} else {
|
||||
mp_obj_get_array_fixed_n(value_l[i], 3, &value_2);
|
||||
p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]),
|
||||
mp_obj_get_int(value_2[1]),
|
||||
mp_obj_get_int(value_2[2]));
|
||||
}
|
||||
IMAGE_PUT_RGB565_PIXEL(image, (slice.start + i) % image->w,
|
||||
(slice.start + i) / image->w, p);
|
||||
}
|
||||
} else {
|
||||
mp_obj_t *value_2;
|
||||
mp_obj_get_array_fixed_n(value, 3, &value_2);
|
||||
uint16_t p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]), mp_obj_get_int(value_2[1]), mp_obj_get_int(value_2[2]));
|
||||
uint16_t p;
|
||||
if (image->is_yuv) {
|
||||
mp_obj_get_array_fixed_n(value, 2, &value_2);
|
||||
p = (mp_obj_get_int(value_2[0]) & 0xff) |
|
||||
(mp_obj_get_int(value_2[1]) & 0xff) << 8;
|
||||
} else {
|
||||
mp_obj_get_array_fixed_n(value, 3, &value_2);
|
||||
p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]),
|
||||
mp_obj_get_int(value_2[1]),
|
||||
mp_obj_get_int(value_2[2]));
|
||||
}
|
||||
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
|
||||
IMAGE_PUT_RGB565_PIXEL(image, (slice.start + i) % image->w, (slice.start + i) / image->w, p);
|
||||
IMAGE_PUT_RGB565_PIXEL(image, (slice.start + i) % image->w,
|
||||
(slice.start + i) / image->w, p);
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
@ -626,6 +664,8 @@ static mp_obj_t py_image_format(mp_obj_t img_obj)
|
||||
return mp_obj_new_int(PIXFORMAT_RGB565);
|
||||
case PIXFORMAT_BAYER_ANY:
|
||||
return mp_obj_new_int(PIXFORMAT_BAYER);
|
||||
case PIXFORMAT_YUV_ANY:
|
||||
return mp_obj_new_int(PIXFORMAT_YUV422);
|
||||
default:
|
||||
return mp_obj_new_int(PIXFORMAT_JPEG);
|
||||
}
|
||||
@ -647,7 +687,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_bytearray_obj, py_image_bytearray);
|
||||
|
||||
STATIC mp_obj_t py_image_get_pixel(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
image_t *arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
|
||||
const mp_obj_t *arg_vec;
|
||||
uint offset = py_helper_consume_array(n_args, args, 1, 2, &arg_vec);
|
||||
@ -707,7 +747,18 @@ STATIC mp_obj_t py_image_get_pixel(uint n_args, const mp_obj_t *args, mp_map_t *
|
||||
pixel_tuple[2] = mp_obj_new_int(COLOR_RGB565_TO_B8(pixel));
|
||||
return mp_obj_new_tuple(3, pixel_tuple);
|
||||
} else {
|
||||
return mp_obj_new_int(IMAGE_GET_GRAYSCALE_PIXEL(arg_img, arg_x, arg_y)); // Correct!
|
||||
return mp_obj_new_int(IMAGE_GET_BAYER_PIXEL(arg_img, arg_x, arg_y));
|
||||
}
|
||||
case PIXFORMAT_YUV_ANY:
|
||||
if (arg_rgbtuple) {
|
||||
uint16_t pixel; imlib_deyuv_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));
|
||||
pixel_tuple[2] = mp_obj_new_int(COLOR_RGB565_TO_B8(pixel));
|
||||
return mp_obj_new_tuple(3, pixel_tuple);
|
||||
} else {
|
||||
return mp_obj_new_int(IMAGE_GET_YUV_PIXEL(arg_img, arg_x, arg_y));
|
||||
}
|
||||
default: return mp_const_none;
|
||||
}
|
||||
@ -716,7 +767,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_get_pixel_obj, 2, py_image_get_pixel)
|
||||
|
||||
STATIC mp_obj_t py_image_set_pixel(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
image_t *arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
|
||||
const mp_obj_t *arg_vec;
|
||||
uint offset = py_helper_consume_array(n_args, args, 1, 2, &arg_vec);
|
||||
@ -735,18 +786,16 @@ STATIC mp_obj_t py_image_set_pixel(uint n_args, const mp_obj_t *args, mp_map_t *
|
||||
IMAGE_PUT_BINARY_PIXEL(arg_img, arg_x, arg_y, arg_c);
|
||||
return args[0];
|
||||
}
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
case PIXFORMAT_BAYER_ANY: { // re-use
|
||||
IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, arg_x, arg_y, arg_c);
|
||||
return args[0];
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_YUV_ANY: { // re-use
|
||||
IMAGE_PUT_RGB565_PIXEL(arg_img, arg_x, arg_y, arg_c);
|
||||
return args[0];
|
||||
}
|
||||
case PIXFORMAT_BAYER_ANY: {
|
||||
IMAGE_PUT_GRAYSCALE_PIXEL(arg_img, arg_x, arg_y, arg_c); // Correct!
|
||||
return args[0];
|
||||
}
|
||||
default: return args[0];
|
||||
}
|
||||
}
|
||||
@ -861,7 +910,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_pooled_obj, 3, py_image_midp
|
||||
static mp_obj_t py_image_to(pixformat_t pixfmt, const uint16_t *default_color_palette, bool copy_to_fb,
|
||||
uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *src_img = py_helper_arg_to_image_mutable_bayer_jpeg(args[0]);
|
||||
image_t *src_img = py_image_cobj(args[0]);
|
||||
|
||||
float arg_x_scale = 1.f;
|
||||
bool got_x_scale = py_helper_keyword_float_maybe(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), &arg_x_scale);
|
||||
@ -926,7 +975,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, const uint16_t *default_color_pa
|
||||
if (mp_obj_is_integer(copy_obj)) {
|
||||
copy = mp_obj_get_int(copy_obj);
|
||||
} else {
|
||||
arg_other = py_helper_arg_to_image_mutable_bayer(copy_obj);
|
||||
arg_other = py_helper_arg_to_image_not_compressed(copy_obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1004,6 +1053,24 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, const uint16_t *default_color_pa
|
||||
IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST |
|
||||
IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST);
|
||||
}
|
||||
} else if (dst_img.is_yuv) {
|
||||
if (((arg_x_scale != 1) && (arg_x_scale != -1)) ||
|
||||
((arg_y_scale != 1) && (arg_y_scale != -1)) ||
|
||||
(arg_rgb_channel != -1) ||
|
||||
(arg_alpha != 256) ||
|
||||
(color_palette != NULL) ||
|
||||
(alpha_palette != NULL)) {
|
||||
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Only YUV422 copying/cropping is supported!"));
|
||||
} else {
|
||||
if (arg_roi.x % 2) {
|
||||
dst_img.pixfmt = (dst_img.pixfmt == PIXFORMAT_YUV422) ? PIXFORMAT_YVU422 : PIXFORMAT_YUV422;
|
||||
}
|
||||
hint &= ~(IMAGE_HINT_AREA |
|
||||
IMAGE_HINT_BICUBIC |
|
||||
IMAGE_HINT_BILINEAR |
|
||||
IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST |
|
||||
IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST);
|
||||
}
|
||||
} else if (dst_img.pixfmt == PIXFORMAT_JPEG) {
|
||||
if ((arg_x_scale != 1) ||
|
||||
(arg_y_scale != 1) ||
|
||||
@ -1138,7 +1205,7 @@ static mp_obj_t py_image_compress(uint n_args, const mp_obj_t *args, mp_map_t *k
|
||||
{
|
||||
if (IM_IS_JPEG((image_t *) py_image_cobj(args[0]))) return args[0];
|
||||
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
image_t *arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
int arg_q = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_quality), 50);
|
||||
PY_ASSERT_TRUE_MSG((1 <= arg_q) && (arg_q <= 100), "Error: 1 <= quality <= 100!");
|
||||
|
||||
@ -1158,7 +1225,7 @@ static mp_obj_t py_image_compress_for_ide(uint n_args, const mp_obj_t *args, mp_
|
||||
{
|
||||
if (IM_IS_JPEG((image_t *) py_image_cobj(args[0]))) return py_image_jpeg_encode_for_ide(args[0]);
|
||||
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
image_t *arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
int arg_q = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_quality), 50);
|
||||
PY_ASSERT_TRUE_MSG((1 <= arg_q) && (arg_q <= 100), "Error: 1 <= quality <= 100!");
|
||||
|
||||
@ -1186,7 +1253,7 @@ static mp_obj_t py_image_compressed(uint n_args, const mp_obj_t *args, mp_map_t
|
||||
return py_image_from_struct(&out);
|
||||
}
|
||||
|
||||
arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
int arg_q = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_quality), 50);
|
||||
PY_ASSERT_TRUE_MSG((1 <= arg_q) && (arg_q <= 100), "Error: 1 <= quality <= 100!");
|
||||
|
||||
@ -1206,7 +1273,7 @@ static mp_obj_t py_image_compressed_for_ide(uint n_args, const mp_obj_t *args, m
|
||||
{
|
||||
if (IM_IS_JPEG((image_t *) py_image_cobj(args[0]))) return py_image_jpeg_encoded_for_ide(args[0]);
|
||||
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
image_t *arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
int arg_q = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_quality), 50);
|
||||
PY_ASSERT_TRUE_MSG((1 <= arg_q) && (arg_q <= 100), "Error: 1 <= quality <= 100!");
|
||||
|
||||
@ -1258,7 +1325,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_flush_obj, py_image_flush);
|
||||
|
||||
STATIC mp_obj_t py_image_clear(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
|
||||
image_t *arg_img = py_helper_arg_to_image_not_compressed(args[0]);
|
||||
|
||||
image_t *arg_msk =
|
||||
py_helper_keyword_to_image_mutable_mask(n_args, args, 1, kw_args);
|
||||
@ -1515,7 +1582,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_edges_obj, 2, py_image_draw_edge
|
||||
STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
|
||||
image_t *arg_other = py_helper_arg_to_image_mutable_bayer(args[1]);
|
||||
image_t *arg_other = py_helper_arg_to_image_not_compressed(args[1]);
|
||||
|
||||
const mp_obj_t *arg_vec;
|
||||
uint offset = py_helper_consume_array(n_args, args, 2, 2, &arg_vec);
|
||||
@ -5226,7 +5293,7 @@ static const mp_obj_type_t py_apriltag_type = {
|
||||
|
||||
static mp_obj_t py_image_find_apriltags(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer_jpeg(args[0]);
|
||||
image_t *arg_img = py_image_cobj(args[0]);
|
||||
|
||||
rectangle_t roi;
|
||||
py_helper_keyword_rectangle_roi(arg_img, n_args, args, 1, kw_args, &roi);
|
||||
@ -6905,8 +6972,8 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_BINARY), MP_ROM_INT(PIXFORMAT_BINARY)}, /* 1BPP/BINARY*/
|
||||
{MP_ROM_QSTR(MP_QSTR_GRAYSCALE), MP_ROM_INT(PIXFORMAT_GRAYSCALE)},/* 1BPP/GRAYSCALE*/
|
||||
{MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(PIXFORMAT_RGB565)}, /* 2BPP/RGB565*/
|
||||
{MP_ROM_QSTR(MP_QSTR_YUV422), MP_ROM_INT(PIXFORMAT_YUV422)}, /* 2BPP/YUV422*/
|
||||
{MP_ROM_QSTR(MP_QSTR_BAYER), MP_ROM_INT(PIXFORMAT_BAYER)}, /* 1BPP/RAW*/
|
||||
{MP_ROM_QSTR(MP_QSTR_YUV422), MP_ROM_INT(PIXFORMAT_YUV422)}, /* 2BPP/YUV422*/
|
||||
{MP_ROM_QSTR(MP_QSTR_JPEG), MP_ROM_INT(PIXFORMAT_JPEG)}, /* JPEG/COMPRESSED*/
|
||||
{MP_ROM_QSTR(MP_QSTR_AREA), MP_ROM_INT(IMAGE_HINT_AREA)},
|
||||
{MP_ROM_QSTR(MP_QSTR_BILINEAR), MP_ROM_INT(IMAGE_HINT_BILINEAR)},
|
||||
|
||||
@ -991,8 +991,8 @@ STATIC const mp_map_elem_t globals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BINARY), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_BINARY)}, /* 1BPP/BINARY*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GRAYSCALE), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_GRAYSCALE)},/* 1BPP/GRAYSCALE*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RGB565), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_RGB565)}, /* 2BPP/RGB565*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_YUV422), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_YUV422)}, /* 2BPP/YUV422*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BAYER), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_BAYER)}, /* 1BPP/RAW*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_YUV422), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_YUV422)}, /* 2BPP/YUV422*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_JPEG), MP_OBJ_NEW_SMALL_INT(PIXFORMAT_JPEG)}, /* JPEG/COMPRESSED*/
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OV2640), MP_OBJ_NEW_SMALL_INT(OV2640_ID)},
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OV5640), MP_OBJ_NEW_SMALL_INT(OV5640_ID)},
|
||||
|
||||
@ -172,6 +172,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/imlib/, \
|
||||
stats.o \
|
||||
template.o \
|
||||
xyz_tab.o \
|
||||
yuv.o \
|
||||
zbar.o \
|
||||
)
|
||||
|
||||
|
||||
@ -168,6 +168,7 @@ target_sources(${MICROPY_TARGET} PRIVATE
|
||||
${TOP_DIR}/${OMV_DIR}/imlib/stats.c
|
||||
${TOP_DIR}/${OMV_DIR}/imlib/template.c
|
||||
${TOP_DIR}/${OMV_DIR}/imlib/xyz_tab.c
|
||||
${TOP_DIR}/${OMV_DIR}/imlib/yuv.c
|
||||
${TOP_DIR}/${OMV_DIR}/imlib/zbar.c
|
||||
|
||||
${TOP_DIR}/${OMV_DIR}/ports/${PORT}/main.c
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "py_lcd_cec.h"
|
||||
#include "py_lcd_touch.h"
|
||||
#include "py_helper.h"
|
||||
#include "py_image.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include STM32_HAL_H
|
||||
@ -1606,7 +1607,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_lcd_get_point_y_position_obj, py_lcd_get_poi
|
||||
|
||||
STATIC mp_obj_t py_lcd_display(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer_jpeg(args[0]);
|
||||
image_t *arg_img = py_image_cobj(args[0]);
|
||||
|
||||
int arg_x_off = 0;
|
||||
int arg_y_off = 0;
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include "spi.h"
|
||||
|
||||
#include "py_helper.h"
|
||||
#include "py_image.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include STM32_HAL_H
|
||||
|
||||
@ -679,7 +680,7 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f
|
||||
const uint16_t *color_palette, const uint8_t *alpha_palette,
|
||||
image_hint_t hint)
|
||||
{
|
||||
bool rgb565 = ((rgb_channel == -1) && IMAGE_IS_COLOR(src_img)) || color_palette;
|
||||
bool rgb565 = ((rgb_channel == -1) && src_img->is_color) || color_palette;
|
||||
imlib_draw_row_callback_t cb = rgb565 ? spi_tv_draw_image_cb_rgb565 : spi_tv_draw_image_cb_grayscale;
|
||||
|
||||
image_t dst_img;
|
||||
@ -957,7 +958,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(py_tv_channel_obj, 0, 1, py_tv_channe
|
||||
|
||||
STATIC mp_obj_t py_tv_display(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||
{
|
||||
image_t *arg_img = py_helper_arg_to_image_mutable_bayer_jpeg(args[0]);
|
||||
image_t *arg_img = py_image_cobj(args[0]);
|
||||
|
||||
int arg_x_off = 0;
|
||||
int arg_y_off = 0;
|
||||
|
||||
@ -206,6 +206,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/imlib/, \
|
||||
stats.o \
|
||||
template.o \
|
||||
xyz_tab.o \
|
||||
yuv.o \
|
||||
zbar.o \
|
||||
)
|
||||
|
||||
|
||||
@ -627,7 +627,8 @@ void DCMI_DMAConvCpltUser(uint32_t addr)
|
||||
#if (OMV_ENABLE_SENSOR_MDMA == 1)
|
||||
mdma_memcpy(buffer, dst16, src16, sizeof(uint16_t), sensor.transpose);
|
||||
#else
|
||||
if (sensor.hw_flags.rgb_swap) {
|
||||
if ((sensor.pixformat == PIXFORMAT_RGB565 && sensor.hw_flags.rgb_swap)
|
||||
|| (sensor.pixformat == PIXFORMAT_YUV422 && sensor.hw_flags.yuv_swap)) {
|
||||
if (!sensor.transpose) {
|
||||
unaligned_memcpy_rev16(dst16, src16, MAIN_FB()->u);
|
||||
} else {
|
||||
@ -668,7 +669,8 @@ static void mdma_config(MDMA_InitTypeDef *init, sensor_t *sensor, uint32_t bytes
|
||||
init->SourceBlockAddressOffset = 0;
|
||||
init->DestBlockAddressOffset = 0;
|
||||
|
||||
if ((sensor->pixformat == PIXFORMAT_RGB565) && sensor->hw_flags.rgb_swap) {
|
||||
if ((sensor->pixformat == PIXFORMAT_RGB565 && sensor->hw_flags.rgb_swap)
|
||||
|| (sensor->pixformat == PIXFORMAT_YUV422 && sensor->hw_flags.yuv_swap)) {
|
||||
init->Endianness = MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE;
|
||||
} else {
|
||||
init->Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE;
|
||||
@ -963,7 +965,6 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
|
||||
#endif
|
||||
break;
|
||||
case PIXFORMAT_RGB565:
|
||||
case PIXFORMAT_YUV422:
|
||||
MAIN_FB()->pixfmt = PIXFORMAT_RGB565;
|
||||
#if (OMV_ENABLE_SENSOR_MDMA == 1)
|
||||
// Flush data for MDMA
|
||||
@ -978,6 +979,17 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
|
||||
SCB_InvalidateDCache_by_Addr(buffer->data, w * h);
|
||||
#endif
|
||||
break;
|
||||
case PIXFORMAT_YUV422: {
|
||||
bool yuv_order = sensor->hw_flags.yuv_order == SENSOR_HW_FLAGS_YUV422;
|
||||
int even = yuv_order ? PIXFORMAT_YUV422 : PIXFORMAT_YVU422;
|
||||
int odd = yuv_order ? PIXFORMAT_YVU422 : PIXFORMAT_YUV422;
|
||||
MAIN_FB()->pixfmt = (MAIN_FB()->x % 2) ? odd : even;
|
||||
#if (OMV_ENABLE_SENSOR_MDMA == 1)
|
||||
// Flush data for MDMA
|
||||
SCB_InvalidateDCache_by_Addr(buffer->data, w * h * sizeof(uint16_t));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_JPEG: {
|
||||
int32_t size = 0;
|
||||
if (sensor->chip_id == OV5640_ID) {
|
||||
@ -998,7 +1010,6 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
|
||||
SCB_InvalidateDCache_by_Addr(buffer->data, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Clean trailing data after 0xFFD9 at the end of the jpeg byte stream.
|
||||
MAIN_FB()->pixfmt = PIXFORMAT_JPEG;
|
||||
MAIN_FB()->size = jpeg_clean_trailing_bytes(size, buffer->data);
|
||||
|
||||
@ -748,7 +748,7 @@ static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
|
||||
break;
|
||||
case PIXFORMAT_BAYER:
|
||||
// Make sure odd/even row are switched to work with our bayer conversion.
|
||||
ret |= cambus_writeb(&sensor->bus, sensor->slv_addr,
|
||||
ret |= cambus_writeb(&sensor->bus, sensor->slv_addr,
|
||||
REG_SYNC_MODE, REG_SYNC_MODE_DEF | REG_SYNC_MODE_ROW_SWITCH);
|
||||
ret |= cambus_writeb(&sensor->bus, sensor->slv_addr,
|
||||
REG_OUTPUT_FMT, REG_OUTPUT_SET_FMT(reg, REG_OUTPUT_FMT_BAYER));
|
||||
@ -881,6 +881,7 @@ int gc2145_init(sensor_t *sensor)
|
||||
sensor->hw_flags.jpege = 0;
|
||||
sensor->hw_flags.gs_bpp = 2;
|
||||
sensor->hw_flags.rgb_swap = 1;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1013,6 +1013,7 @@ int mt9m114_init(sensor_t *sensor)
|
||||
sensor->hw_flags.gs_bpp = 2;
|
||||
sensor->hw_flags.rgb_swap = 0;
|
||||
sensor->hw_flags.bayer = SENSOR_HW_FLAGS_BAYER_GBRG;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -857,6 +857,7 @@ int ov2640_init(sensor_t *sensor)
|
||||
sensor->hw_flags.jpeg_mode = 3;
|
||||
sensor->hw_flags.gs_bpp = 2;
|
||||
sensor->hw_flags.rgb_swap = 0;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1383,6 +1383,7 @@ int ov5640_init(sensor_t *sensor)
|
||||
sensor->hw_flags.jpeg_mode = 4;
|
||||
sensor->hw_flags.gs_bpp = 1;
|
||||
sensor->hw_flags.rgb_swap = 0;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -454,6 +454,7 @@ int ov7670_init(sensor_t *sensor)
|
||||
sensor->hw_flags.jpege = 0;
|
||||
sensor->hw_flags.gs_bpp = 2;
|
||||
sensor->hw_flags.rgb_swap = 1;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -624,6 +624,7 @@ int ov7725_init(sensor_t *sensor)
|
||||
sensor->hw_flags.jpege = 0;
|
||||
sensor->hw_flags.gs_bpp = 2;
|
||||
sensor->hw_flags.rgb_swap = 1;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -540,6 +540,7 @@ int ov9650_init(sensor_t *sensor)
|
||||
sensor->hw_flags.jpege = 0;
|
||||
sensor->hw_flags.gs_bpp = 2;
|
||||
sensor->hw_flags.rgb_swap = 1;
|
||||
sensor->hw_flags.yuv_order = SENSOR_HW_FLAGS_YVU422;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user