Merge pull request #2788 from kwagyeman/kwabena/add_transform
Some checks are pending
🔥 Firmware Build / build-firmware (ARDUINO_GIGA) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_33_BLE_SENSE) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NANO_RP2040_CONNECT) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_NICLA_VISION) (push) Waiting to run
🔥 Firmware Build / build-firmware (ARDUINO_PORTENTA_H7) (push) Waiting to run
🔥 Firmware Build / build-firmware (DOCKER) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV2) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV4P) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMVPT) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_AE3) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_N6) (push) Waiting to run
🔥 Firmware Build / build-firmware (OPENMV_RT1060) (push) Waiting to run
🔥 Firmware Build / code-size-report (push) Blocked by required conditions
🔥 Firmware Build / stable-release (push) Blocked by required conditions
🔥 Firmware Build / development-release (push) Blocked by required conditions

ports: Add GPU matrix support.
This commit is contained in:
Ibrahim Abdelkader 2025-08-02 13:36:29 +03:00 committed by GitHub
commit a04fb78cab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 120 additions and 45 deletions

View File

@ -50,5 +50,6 @@ int omv_gpu_draw_image(image_t *src_img,
int alpha,
const uint16_t *color_palette,
const uint8_t *alpha_palette,
image_hint_t hint);
image_hint_t hint,
float *transform);
#endif // __OMV_GPU_H__

View File

@ -484,7 +484,7 @@ static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
imlib_draw_image(&fb_image, &temp, 0, 0, 1.0f, 1.0f, NULL, -1, 255,
(csi->pixformat == PIXFORMAT_RGB565) ? csi->color_palette : NULL, NULL,
IMAGE_HINT_BILINEAR | IMAGE_HINT_CENTER | IMAGE_HINT_SCALE_ASPECT_EXPAND,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
fb_alloc_free_till_mark();
framebuffer_init_image(fb, image);

View File

@ -11995,7 +11995,7 @@ void imlib_find_apriltags(list_t *out, image_t *ptr, rectangle_t *roi, apriltag_
img.h = roi->h;
img.pixfmt = PIXFORMAT_GRAYSCALE;
img.data = fb_alloc(image_size(&img), FB_ALLOC_NO_HINT);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL, NULL);
image_u8_t im;
im.width = roi->w;
@ -12111,7 +12111,7 @@ void imlib_find_rects(list_t *out, image_t *ptr, rectangle_t *roi, uint32_t thre
img.h = roi->h;
img.pixfmt = PIXFORMAT_GRAYSCALE;
img.data = fb_alloc(image_size(&img), FB_ALLOC_NO_HINT);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL, NULL);
image_u8_t im;
im.width = roi->w;

View File

@ -200,7 +200,8 @@ void imlib_binary(image_t *out, image_t *img, list_t *thresholds, bool invert, b
dst_row_override = fb_alloc0(image_line_size(out), FB_ALLOC_CACHE_ALIGN);
}
imlib_draw_image(out, &bmp, 0, 0, 1.0f, 1.0f, NULL, -1, 255, NULL, NULL, 0, callback, mask, dst_row_override);
imlib_draw_image(out, &bmp, 0, 0, 1.0f, 1.0f, NULL, -1, 255, NULL, NULL, 0,
NULL, callback, mask, dst_row_override);
if (dst_row_override) {
fb_free(); // dst_row_override
@ -1256,7 +1257,7 @@ static void imlib_hat(image_t *img, int ksize, int threshold, image_t *mask, bin
op(&temp, ksize, threshold, mask);
void *dst_row_override = fb_alloc0(image_line_size(img), FB_ALLOC_CACHE_ALIGN);
imlib_draw_image(img, &temp, 0, 0, 1.0f, 1.0f, NULL, -1, 255, NULL, NULL, 0,
imlib_difference_line_op, mask, dst_row_override);
NULL, imlib_difference_line_op, mask, dst_row_override);
fb_free(); // dst_row_override
fb_free(); // temp.data
}

View File

@ -6016,7 +6016,7 @@ void imlib_find_datamatrices(list_t *out, image_t *ptr, rectangle_t *roi, int ef
img.h = roi->h;
img.pixfmt = PIXFORMAT_GRAYSCALE;
img.data = grayscale_image;
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL, NULL);
}
umm_init_x(fb_avail());

View File

@ -2817,6 +2817,7 @@ void imlib_draw_image(image_t *dst_img,
const uint16_t *color_palette,
const uint8_t *alpha_palette,
image_hint_t hint,
float *transform,
imlib_draw_row_callback_t callback,
void *callback_arg,
void *dst_row_override) {
@ -2998,7 +2999,7 @@ void imlib_draw_image(image_t *dst_img,
new_src_img.pixfmt = color_palette ? PIXFORMAT_RGB565 : PIXFORMAT_GRAYSCALE;
new_src_img.data = fb_alloc(image_size(&new_src_img), FB_ALLOC_CACHE_ALIGN);
imlib_draw_image(&new_src_img, src_img, 0, 0, 1.f, 1.f, NULL,
rgb_channel, 255, color_palette, NULL, 0, NULL, NULL, NULL);
rgb_channel, 255, color_palette, NULL, 0, NULL, NULL, NULL, NULL);
src_img = &new_src_img;
rgb_channel = -1;
color_palette = NULL;
@ -3056,7 +3057,7 @@ void imlib_draw_image(image_t *dst_img,
(hint & (IMAGE_HINT_BILINEAR | IMAGE_HINT_BLACK_BACKGROUND));
if (!omv_gpu_draw_image(src_img, &src_rect, dst_img, &dst_rect,
alpha, color_palette, alpha_palette, gpu_hints)) {
alpha, color_palette, alpha_palette, gpu_hints, transform)) {
goto exit_cleanup;
}
}
@ -3122,14 +3123,14 @@ void imlib_draw_image(image_t *dst_img,
t_src_img.pixfmt = src_img->pixfmt;
// Are we scaling?
if ((src_x_frac != 65536) || (src_y_frac != 65536)) {
if ((src_x_frac != 65536) || (src_y_frac != 65536) || transform) {
t_src_img.w = t_roi.w = src_height_scaled; // was transposed
t_src_img.h = t_roi.h = src_width_scaled; // was transposed
t_src_img.data = fb_alloc(image_size(&t_src_img), FB_ALLOC_CACHE_ALIGN);
imlib_draw_image(&t_src_img, src_img, 0, 0, x_scale, y_scale, roi,
-1, 255, NULL, NULL,
hint & (IMAGE_HINT_AREA | IMAGE_HINT_BILINEAR | IMAGE_HINT_BICUBIC),
NULL, NULL, NULL);
transform, NULL, NULL, NULL);
} else {
memcpy(&t_roi, roi, sizeof(rectangle_t));
t_src_img.w = src_img->w;
@ -3223,7 +3224,7 @@ void imlib_draw_image(image_t *dst_img,
imlib_draw_image(dst_img, &out, dst_x_start_backup + i, dst_y_start_backup, 1.f, 1.f, NULL,
rgb_channel, alpha, color_palette, alpha_palette,
hint & IMAGE_HINT_BLACK_BACKGROUND,
callback, callback_arg, dst_row_override);
NULL, callback, callback_arg, dst_row_override);
}
fb_free(); // fb_alloc_all

View File

@ -290,8 +290,8 @@ void framebuffer_update_jpeg_buffer(image_t *src) {
dst.h = fast_floorf(src->h * scale);
if (image_size(&dst) <= max_size) {
imlib_draw_image(&dst, src, 0, 0, scale, scale, NULL, -1, 255, NULL, NULL,
IMAGE_HINT_BILINEAR | IMAGE_HINT_BLACK_BACKGROUND, NULL,
NULL, NULL);
IMAGE_HINT_BILINEAR | IMAGE_HINT_BLACK_BACKGROUND,
NULL, NULL, NULL, NULL);
compress = false;
}
}

View File

@ -1381,6 +1381,7 @@ void imlib_draw_image(image_t *dst_img,
const uint16_t *color_palette,
const uint8_t *alpha_palette,
image_hint_t hint,
float *transform,
imlib_draw_row_callback_t callback,
void *callback_arg,
void *dst_row_override);

View File

@ -2699,7 +2699,7 @@ void imlib_lsd_find_line_segments(list_t *out,
img.h = roi->h;
img.pixfmt = PIXFORMAT_GRAYSCALE;
img.data = grayscale_image;
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL, NULL);
umm_init_x(fb_avail());

View File

@ -175,7 +175,7 @@ void mjpeg_write(FIL *fp, int width, int height, uint32_t *frames, uint32_t *byt
imlib_draw_image(&temp, img, center_x, center_y, scale, scale, roi,
rgb_channel, alpha, color_palette, alpha_palette,
(hint & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (temp.w - p1.x) {
for (int i = p0.y; i < p1.y; i++) {

View File

@ -2984,7 +2984,7 @@ void imlib_find_qrcodes(list_t *out, image_t *ptr, rectangle_t *roi)
img.h = roi->h;
img.pixfmt = PIXFORMAT_GRAYSCALE;
img.data = grayscale_image;
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL, NULL);
quirc_end(controller);
list_init(out, sizeof(find_qrcodes_list_lnk_data_t));

View File

@ -182,8 +182,8 @@ void imlib_get_similarity(image_t *img,
void *dst_row_override = fb_alloc0(image_line_size(img), FB_ALLOC_CACHE_ALIGN);
imlib_draw_image(img, other, x_start, y_start, x_scale, y_scale, roi,
rgb_channel, alpha, color_palette, alpha_palette,
hint, imlib_similarity_line_op, &state, dst_row_override);
rgb_channel, alpha, color_palette, alpha_palette, hint,
NULL, imlib_similarity_line_op, &state, dst_row_override);
*avg = state.similarity_sum / blocks;
*std = fast_sqrtf((state.similarity_sum_2 / blocks) - ((*avg) * (*avg)));

View File

@ -8733,7 +8733,7 @@ void imlib_find_barcodes(list_t *out, image_t *ptr, rectangle_t *roi)
img.h = roi->h;
img.pixfmt = PIXFORMAT_GRAYSCALE;
img.data = grayscale_image;
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL);
imlib_draw_image(&img, ptr, 0, 0, 1.f, 1.f, roi, -1, 255, NULL, NULL, 0, NULL, NULL, NULL, NULL);
}
umm_init_x(fb_avail());

View File

@ -224,7 +224,7 @@ static mp_obj_t py_csi_snapshot(size_t n_args, const mp_obj_t *pos_args, mp_map_
image_t *other = py_helper_arg_to_image(args[ARG_image].u_obj, ARG_IMAGE_MUTABLE);
fb_alloc_mark();
imlib_draw_image(other, &image, 0, 0, 1.f, 1.f, NULL, -1, 255, NULL, NULL,
IMAGE_HINT_SCALE_ASPECT_IGNORE, NULL, NULL, NULL);
IMAGE_HINT_SCALE_ASPECT_IGNORE, NULL, NULL, NULL, NULL);
fb_alloc_free_till_mark();
return mp_const_none;
}

View File

@ -832,7 +832,7 @@ mp_obj_t py_fir_draw_ir(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
imlib_draw_image(dst_img, &src_img, args[ARG_x].u_int, args[ARG_y].u_int, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
args[ARG_hint].u_int, NULL, NULL, NULL);
args[ARG_hint].u_int, NULL, NULL, NULL, NULL);
fb_alloc_free_till_mark();
return mp_const_none;
@ -971,7 +971,8 @@ mp_obj_t py_fir_snapshot(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
imlib_draw_image(&dst_img, &src_img, 0, 0, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
(args[ARG_hint].u_int & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL, NULL);
(args[ARG_hint].u_int & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND,
NULL, NULL, NULL, NULL);
fb_alloc_free_till_mark();

View File

@ -28,6 +28,9 @@
#include "framebuffer.h"
#include "py_helper.h"
#include "py_assert.h"
#if defined(MODULE_ULAB_ENABLED)
#include "ndarray.h"
#endif // MODULE_ULAB_ENABLED
#if MICROPY_PY_CSI
#include "omv_csi.h"
#endif
@ -104,6 +107,40 @@ const void *py_helper_arg_to_palette(const mp_obj_t arg, uint32_t pixfmt) {
return palette;
}
void *py_helper_arg_to_transform(const mp_obj_t arg) {
if (arg == mp_const_none) {
return NULL;
}
#if defined(MODULE_ULAB_ENABLED) && defined(OPENMV_N6)
if (!MP_OBJ_IS_TYPE(arg, &ulab_ndarray_type)) {
mp_raise_msg(&mp_type_TypeError, MP_ERROR_TEXT("Expected a ndarray"));
}
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(arg);
if (ndarray->dtype != NDARRAY_FLOAT) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Expected a ndarray with dtype float"));
}
if (!ndarray_is_dense(ndarray)) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Expected a dense ndarray"));
}
if (ndarray->ndim != 2) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Expected a 2D ndarray"));
}
if ((ndarray->shape[ULAB_MAX_DIMS-2] != 3) || (ndarray->shape[ULAB_MAX_DIMS-1] != 3)) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid matrix shape!"));
}
return ndarray->array;
#else
mp_raise_msg(&mp_type_TypeError, MP_ERROR_TEXT("Transform operations are not supported!"));
#endif // MODULE_ULAB_ENABLED
}
rectangle_t py_helper_arg_to_roi(const mp_obj_t arg, const image_t *img) {
rectangle_t roi = {0, 0, img->w, img->h};
if (arg != mp_const_none) {

View File

@ -38,6 +38,7 @@ typedef enum py_helper_arg_image_flags {
extern const mp_obj_fun_builtin_var_t py_func_unavailable_obj;
image_t *py_helper_arg_to_image(const mp_obj_t arg, uint32_t flags);
const void *py_helper_arg_to_palette(const mp_obj_t arg, uint32_t pixfmt);
void *py_helper_arg_to_transform(const mp_obj_t arg);
rectangle_t py_helper_arg_to_roi(const mp_obj_t arg, const image_t *img);
void py_helper_arg_to_scale(const mp_obj_t arg_x_scale, const mp_obj_t arg_y_scale,
float *x_scale, float *y_scale);

View File

@ -987,7 +987,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {
ARG_x_scale, ARG_y_scale, ARG_roi, ARG_channel, ARG_alpha, ARG_color_palette, ARG_alpha_palette,
ARG_hint, ARG_copy, ARG_copy_to_fb, ARG_quality, ARG_subsampling
ARG_hint, ARG_transform, ARG_copy, ARG_copy_to_fb, ARG_quality, ARG_subsampling
};
const mp_arg_t allowed_args[] = {
{ MP_QSTR_x_scale, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
@ -998,6 +998,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
{ MP_QSTR_color_palette, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = default_color_palette} },
{ MP_QSTR_alpha_palette, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_hint, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0 } },
{ MP_QSTR_transform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_copy, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = default_copy} },
{ MP_QSTR_copy_to_fb, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} },
{ MP_QSTR_quality, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 90} },
@ -1035,6 +1036,8 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
IMAGE_HINT_SCALE_ASPECT_EXPAND |
IMAGE_HINT_SCALE_ASPECT_IGNORE)) | IMAGE_HINT_BLACK_BACKGROUND;
float *transform = py_helper_arg_to_transform(args[ARG_transform].u_obj);
if (args[ARG_copy_to_fb].u_bool) {
framebuffer_t *fb = framebuffer_get(0);
image_t tmp;
@ -1114,7 +1117,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
imlib_draw_image(&temp, src_img, 0, 0, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
args[ARG_hint].u_int, NULL, NULL, NULL);
args[ARG_hint].u_int, NULL, NULL, NULL, NULL);
}
if (((dst_img.pixfmt == PIXFORMAT_JPEG) &&
@ -1155,7 +1158,7 @@ static mp_obj_t py_image_to(pixformat_t pixfmt, mp_rom_obj_t default_color_palet
fb_alloc_mark();
imlib_draw_image(&dst_img, src_img, 0, 0, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
args[ARG_hint].u_int, NULL, NULL, NULL);
args[ARG_hint].u_int, transform, NULL, NULL, NULL);
fb_alloc_free_till_mark();
}
@ -1704,7 +1707,7 @@ static mp_obj_t py_image_line_op(size_t n_args, const mp_obj_t *pos_args, mp_map
imlib_draw_row_callback_t callback) {
enum {
ARG_image, ARG_x, ARG_y, ARG_x_scale, ARG_y_scale, ARG_roi,
ARG_channel, ARG_alpha, ARG_color_palette, ARG_alpha_palette, ARG_hint, ARG_mask
ARG_channel, ARG_alpha, ARG_color_palette, ARG_alpha_palette, ARG_hint, ARG_transform, ARG_mask
};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_image, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
@ -1718,6 +1721,7 @@ static mp_obj_t py_image_line_op(size_t n_args, const mp_obj_t *pos_args, mp_map
{ MP_QSTR_color_palette, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_alpha_palette, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_hint, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0 } },
{ MP_QSTR_transform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_mask, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
};
@ -1781,6 +1785,8 @@ static mp_obj_t py_image_line_op(size_t n_args, const mp_obj_t *pos_args, mp_map
const uint16_t *color_palette = py_helper_arg_to_palette(args[ARG_color_palette].u_obj, PIXFORMAT_RGB565);
const uint8_t *alpha_palette = py_helper_arg_to_palette(args[ARG_alpha_palette].u_obj, PIXFORMAT_GRAYSCALE);
float *transform = py_helper_arg_to_transform(args[ARG_transform].u_obj);
image_t *mask = NULL;
if (args[ARG_mask].u_obj != mp_const_none) {
mask = py_helper_arg_to_image(args[ARG_mask].u_obj, ARG_IMAGE_MUTABLE | ARG_IMAGE_ALLOC);
@ -1799,7 +1805,7 @@ static mp_obj_t py_image_line_op(size_t n_args, const mp_obj_t *pos_args, mp_map
imlib_draw_image(image, other, args[ARG_x].u_int, args[ARG_y].u_int, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
args[ARG_hint].u_int, callback, mask, dst_row_override);
args[ARG_hint].u_int, transform, callback, mask, dst_row_override);
fb_alloc_free_till_mark();
return pos_args[0];

View File

@ -247,7 +247,7 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_
// Transmits left/right parts already zeroed...
imlib_draw_image(&dst_img, src_img, dst_x_start, dst_y_start,
x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette,
hint | IMAGE_HINT_BLACK_BACKGROUND, spi_display_draw_image_cb, self, dst_img.data);
hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, spi_display_draw_image_cb, self, dst_img.data);
// Zero the bottom rows
if (p1.y < self->height) {
@ -290,7 +290,7 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_
imlib_draw_image(&dst_img, src_img, dst_x_start, dst_y_start,
x_scale, y_scale, roi, rgb_channel, alpha, color_palette,
alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL, NULL);
alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL, NULL, NULL);
if (self->width - p1.x) {
for (int i = p0.y; i < p1.y; i++) {

View File

@ -479,7 +479,7 @@ mp_obj_t py_tof_draw_depth(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
imlib_draw_image(dst_img, &src_img, args[ARG_x].u_int, args[ARG_y].u_int, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
args[ARG_hint].u_int, NULL, NULL, NULL);
args[ARG_hint].u_int, NULL, NULL, NULL, NULL);
fb_alloc_free_till_mark();
return mp_const_none;
@ -584,7 +584,8 @@ mp_obj_t py_tof_snapshot(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a
imlib_draw_image(&dst_img, &src_img, 0, 0, x_scale, y_scale, &roi,
args[ARG_channel].u_int, args[ARG_alpha].u_int, color_palette, alpha_palette,
(args[ARG_hint].u_int & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL, NULL);
(args[ARG_hint].u_int & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND,
NULL, NULL, NULL, NULL);
fb_alloc_free_till_mark();

View File

@ -634,7 +634,7 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f
// Transmits left/right parts already zeroed...
imlib_draw_image(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, roi,
rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND,
cb, NULL, dst_img.data);
NULL, cb, NULL, dst_img.data);
// Zero the bottom rows
if (p1.y < TV_HEIGHT) {
@ -677,7 +677,7 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f
imlib_draw_image(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, roi,
rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (TV_WIDTH - p1.x) {
for (int i = p0.y; i < p1.y; i++) {
@ -718,7 +718,7 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f
imlib_draw_image(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, roi,
rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (TV_WIDTH - p1.x) {
for (int i = p0.y; i < p1.y; i++) {

View File

@ -373,7 +373,7 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
rectangle_t srect = { fb->x, fb->y, fb->u, fb->v };
rectangle_t drect = { 0, 0, fb->u, fb->v };
if (omv_gpu_draw_image(&src_cimage, &srect, &dst_cimage, &drect, 255, NULL, NULL, 0) != 0) {
if (omv_gpu_draw_image(&src_cimage, &srect, &dst_cimage, &drect, 255, NULL, NULL, 0, NULL) != 0) {
return OMV_CSI_ERROR_IO_ERROR;
}
}

View File

@ -129,9 +129,10 @@ int omv_gpu_draw_image(image_t *src_img,
int alpha,
const uint16_t *color_palette,
const uint8_t *alpha_palette,
image_hint_t hint) {
// Belnding is not supported yet.
if (color_palette || alpha_palette) {
image_hint_t hint,
float *transform) {
// Belnding is not supported yet and transformations are not supported.
if (color_palette || alpha_palette || transform) {
return -1;
}
OMV_PROFILE_START();

View File

@ -448,7 +448,7 @@ static void display_write(py_display_obj_t *self, image_t *src_img, int dst_x_st
if (!black) {
imlib_draw_image(&dst_img, src_img, dst_x_start, dst_y_start,
x_scale, y_scale, roi, rgb_channel, 255, color_palette,
alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL, NULL);
alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL, NULL, NULL);
}
#ifdef __DCACHE_PRESENT

View File

@ -93,7 +93,8 @@ int omv_gpu_draw_image(image_t *src_img,
int alpha,
const uint16_t *color_palette,
const uint8_t *alpha_palette,
image_hint_t hint) {
image_hint_t hint,
float *transform) {
OMV_PROFILE_START();
// GPU2D can only draw on RGB565/GRAYSCALE buffers.
@ -119,6 +120,22 @@ int omv_gpu_draw_image(image_t *src_img,
return -1;
}
float dx0 = dst_rect->x;
float dy0 = dst_rect->y;
float dx1 = dst_rect->x + dst_rect->w;
float dy1 = dst_rect->y;
float dx2 = dst_rect->x + dst_rect->w;
float dy2 = dst_rect->y + dst_rect->h;
float dx3 = dst_rect->x;
float dy3 = dst_rect->y + dst_rect->h;
if (transform) {
nema_mat3x3_mul_vec(*((nema_matrix3x3_t *) transform), &dx0, &dy0);
nema_mat3x3_mul_vec(*((nema_matrix3x3_t *) transform), &dx1, &dy1);
nema_mat3x3_mul_vec(*((nema_matrix3x3_t *) transform), &dx2, &dy2);
nema_mat3x3_mul_vec(*((nema_matrix3x3_t *) transform), &dx3, &dy3);
}
// Create command list.
#if OMV_GPU_NEMA_MM_STATIC
nema_buffer_t bo = {
@ -156,9 +173,10 @@ int omv_gpu_draw_image(image_t *src_img,
uint32_t dst_bf = (hint & IMAGE_HINT_BLACK_BACKGROUND) ? NEMA_BF_ZERO : NEMA_BF_INVSRCALPHA;
nema_set_blend_blit(nema_blending_mode(NEMA_BF_SRCALPHA, dst_bf, blops));
nema_set_const_color(nema_rgba(0, 0, 0, alpha));
nema_set_clip(dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
nema_blit_subrect_fit(dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h,
src_rect->x, src_rect->y, src_rect->w, src_rect->h);
nema_set_clip(0, 0, dst_img->w, dst_img->h);
nema_enable_aa(true, true, true, true);
nema_blit_subrect_quad_fit(dx0, dy0, dx1, dy1, dx2, dy2, dx3, dy3,
src_rect->x, src_rect->y, src_rect->w, src_rect->h);
SCB_CleanInvalidateDCache_by_Addr(dst_img->data, image_size(dst_img));
SCB_CleanDCache_by_Addr(src_img->data, image_size(src_img));
@ -191,7 +209,8 @@ int omv_gpu_draw_image(image_t *src_img,
int alpha,
const uint16_t *color_palette,
const uint8_t *alpha_palette,
image_hint_t hint) {
image_hint_t hint,
float *transform) {
OMV_PROFILE_START();
// DMA2D can only draw on RGB565 buffers and the destination/source buffers must be accessible by DMA.
@ -224,6 +243,11 @@ int omv_gpu_draw_image(image_t *src_img,
}
#endif
// DMA2D cannot do matrix transformations.
if (transform) {
return -1;
}
DMA2D_HandleTypeDef dma2d = {
.Instance = DMA2D,
.Init.ColorMode = DMA2D_OUTPUT_RGB565,