diff --git a/src/omv/imlib/draw.c b/src/omv/imlib/draw.c index 421c64fb8..7eef59393 100644 --- a/src/omv/imlib/draw.c +++ b/src/omv/imlib/draw.c @@ -2733,22 +2733,22 @@ void imlib_draw_row(int x_start, int x_end, int y_row, imlib_draw_row_data_t *da } // False == Image is black, True == rect valid -bool imlib_draw_image_rectangle(image_t *dst_img, - image_t *src_img, - int dst_x_start, - int dst_y_start, - float x_scale, - float y_scale, - rectangle_t *roi, - int alpha, - const uint8_t *alpha_palette, - image_hint_t hint, - int *x0, - int *x1, - int *y0, - int *y1) { +void imlib_draw_image_get_bounds(image_t *dst_img, + image_t *src_img, + int dst_x_start, + int dst_y_start, + float x_scale, + float y_scale, + rectangle_t *roi, + int alpha, + const uint8_t *alpha_palette, + image_hint_t hint, + point_t *p0, + point_t *p1) { + p0->x = -1; + if (!alpha) { - return false; + return; } if (alpha_palette) { @@ -2758,7 +2758,7 @@ bool imlib_draw_image_rectangle(image_t *dst_img, } if (i == 256) { // zero alpha palette - return false; + return; } } @@ -2779,13 +2779,13 @@ bool imlib_draw_image_rectangle(image_t *dst_img, } if (dst_x_start >= dst_img->w) { - return false; + return; } int src_x_dst_width = src_width_scaled - src_x_start; if (src_x_dst_width <= 0) { - return false; + return; } // Clamp start y to image bounds. @@ -2796,13 +2796,13 @@ bool imlib_draw_image_rectangle(image_t *dst_img, } if (dst_y_start >= dst_img->h) { - return false; + return; } int src_y_dst_height = src_height_scaled - src_y_start; if (src_y_dst_height <= 0) { - return false; + return; } // Clamp end x to image bounds. @@ -2817,12 +2817,12 @@ bool imlib_draw_image_rectangle(image_t *dst_img, dst_y_end = dst_img->h; } - *x0 = dst_x_start; - *x1 = dst_x_end; - *y0 = dst_y_start; - *y1 = dst_y_end; + p0->x = dst_x_start; + p1->x = dst_x_end; + p0->y = dst_y_start; + p1->y = dst_y_end; - return true; + return; } void imlib_draw_image(image_t *dst_img, diff --git a/src/omv/imlib/imlib.h b/src/omv/imlib/imlib.h index 2ae00327d..db881c2d0 100644 --- a/src/omv/imlib/imlib.h +++ b/src/omv/imlib/imlib.h @@ -1274,20 +1274,18 @@ void imlib_draw_row_deinit_all(); void *imlib_draw_row_get_row_buffer(imlib_draw_row_data_t *data); void imlib_draw_row_put_row_buffer(imlib_draw_row_data_t *data, void *row_buffer); void imlib_draw_row(int x_start, int x_end, int y_row, imlib_draw_row_data_t *data); -bool imlib_draw_image_rectangle(image_t *dst_img, - image_t *src_img, - int dst_x_start, - int dst_y_start, - float x_scale, - float y_scale, - rectangle_t *roi, - int alpha, - const uint8_t *alpha_palette, - image_hint_t hint, - int *x0, - int *x1, - int *y0, - int *y1); +void imlib_draw_image_get_bounds(image_t *dst_img, + image_t *src_img, + int dst_x_start, + int dst_y_start, + float x_scale, + float y_scale, + rectangle_t *roi, + int alpha, + const uint8_t *alpha_palette, + image_hint_t hint, + point_t *p0, + point_t *p1); void imlib_flood_fill_int(image_t *out, image_t *img, int x, int y, int seed_threshold, int floating_threshold, flood_fill_call_back_t cb, void *data); diff --git a/src/omv/imlib/mjpeg.c b/src/omv/imlib/mjpeg.c index f501aaf23..86b275aeb 100644 --- a/src/omv/imlib/mjpeg.c +++ b/src/omv/imlib/mjpeg.c @@ -134,23 +134,24 @@ void mjpeg_write(FIL *fp, int width, int height, uint32_t *frames, uint32_t *byt int center_x = fast_floorf((width - (roi->w * scale)) / 2); int center_y = fast_floorf((height - (roi->h * scale)) / 2); - int x0, x1, y0, y1; - bool black = !imlib_draw_image_rectangle(&temp, img, center_x, center_y, scale, scale, roi, - alpha, alpha_palette, hint, &x0, &x1, &y0, &y1); + point_t p0, p1; + imlib_draw_image_get_bounds(&temp, img, center_x, center_y, scale, scale, roi, + alpha, alpha_palette, hint, &p0, &p1); + bool black = p0.x == -1; if (black) { // zero the whole image memset(temp.data, 0, temp.w * temp.h * sizeof(uint16_t)); } else { // Zero the top rows - if (y0) { - memset(temp.data, 0, temp.w * y0 * sizeof(uint16_t)); + if (p0.y) { + memset(temp.data, 0, temp.w * p0.y * sizeof(uint16_t)); } - if (x0) { - for (int i = y0; i < y1; i++) { + if (p0.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero left - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp, i), 0, x0 * sizeof(uint16_t)); + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp, i), 0, p0.x * sizeof(uint16_t)); } } @@ -159,18 +160,18 @@ void mjpeg_write(FIL *fp, int width, int height, uint32_t *frames, uint32_t *byt (hint & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL); - if (temp.w - x1) { - for (int i = y0; i < y1; i++) { + if (temp.w - p1.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero right - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp, i) + x1, - 0, (temp.w - x1) * sizeof(uint16_t)); + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp, i) + p1.x, + 0, (temp.w - p1.x) * sizeof(uint16_t)); } } // Zero the bottom rows - if (temp.h - y1) { - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp, y1), - 0, temp.w * (temp.h - y1) * sizeof(uint16_t)); + if (temp.h - p1.y) { + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp, p1.y), + 0, temp.w * (temp.h - p1.y) * sizeof(uint16_t)); } } } diff --git a/src/omv/modules/py_spi_display.c b/src/omv/modules/py_spi_display.c index aa12f1ca8..16c57be1a 100644 --- a/src/omv/modules/py_spi_display.c +++ b/src/omv/modules/py_spi_display.c @@ -172,9 +172,10 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_ dst_img.h = self->height; dst_img.pixfmt = PIXFORMAT_RGB565; - int x0, x1, y0, y1; - bool black = !imlib_draw_image_rectangle(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, - y_scale, roi, alpha, alpha_palette, hint, &x0, &x1, &y0, &y1); + point_t p0, p1; + imlib_draw_image_get_bounds(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, + y_scale, roi, alpha, alpha_palette, hint, &p0, &p1); + bool black = p0.x == -1; if (!self->triple_buffer) { dst_img.data = fb_alloc0(self->width * sizeof(uint16_t), FB_ALLOC_NO_HINT); @@ -190,7 +191,7 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_ } } else { // Zero the top rows - for (int i = 0; i < y0; i++) { + for (int i = 0; i < p0.y; i++) { spi_transmit_16(self, dst_img.data, self->width); } @@ -202,11 +203,11 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_ x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, spi_display_draw_image_cb, dst_img.data); // Zero the bottom rows - if (y1 < self->height) { + if (p1.y < self->height) { memset(dst_img.data, 0, self->width * sizeof(uint16_t)); } - for (int i = y1; i < self->height; i++) { + for (int i = p1.y; i < self->height; i++) { spi_transmit_16(self, dst_img.data, self->width); } } @@ -229,14 +230,14 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_ memset(dst_img.data, 0, self->width * self->height * sizeof(uint16_t)); } else { // Zero the top rows - if (y0) { - memset(dst_img.data, 0, self->width * y0 * sizeof(uint16_t)); + if (p0.y) { + memset(dst_img.data, 0, self->width * p0.y * sizeof(uint16_t)); } - if (x0) { - for (int i = y0; i < y1; i++) { + if (p0.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero left - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i), 0, x0 * sizeof(uint16_t)); + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i), 0, p0.x * sizeof(uint16_t)); } } @@ -244,17 +245,18 @@ static void spi_display_write(py_display_obj_t *self, image_t *src_img, int dst_ x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL); - if (self->width - x1) { - for (int i = y0; i < y1; i++) { + if (self->width - p1.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero right - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i) + x1, 0, (self->width - x1) * sizeof(uint16_t)); + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i) + p1.x, 0, + (self->width - p1.x) * sizeof(uint16_t)); } } // Zero the bottom rows - if (self->height - y1) { - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, y1), - 0, self->width * (self->height - y1) * sizeof(uint16_t)); + if (self->height - p1.y) { + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, p1.y), + 0, self->width * (self->height - p1.y) * sizeof(uint16_t)); } } diff --git a/src/omv/modules/py_tv.c b/src/omv/modules/py_tv.c index 1ea04a527..f7cd5aaa2 100644 --- a/src/omv/modules/py_tv.c +++ b/src/omv/modules/py_tv.c @@ -588,9 +588,10 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f dst_img.h = TV_HEIGHT; dst_img.pixfmt = rgb565 ? PIXFORMAT_RGB565 : PIXFORMAT_GRAYSCALE; - int x0, x1, y0, y1; - bool black = !imlib_draw_image_rectangle(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, - roi, alpha, alpha_palette, hint, &x0, &x1, &y0, &y1); + point_t p0, p1; + imlib_draw_image_get_bounds(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, + roi, alpha, alpha_palette, hint, &p0, &p1); + bool black = p0.x == -1; if (!tv_triple_buffer) { dst_img.data = fb_alloc0(TV_WIDTH_RGB565, FB_ALLOC_NO_HINT); @@ -604,7 +605,7 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f } } else { // Zero the top rows - for (int i = 0; i < y0; i++) { + for (int i = 0; i < p0.y; i++) { SpiTransmitReceivePacket(dst_img.data, NULL, PICLINE_LENGTH_BYTES, false); } @@ -614,11 +615,11 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f cb, dst_img.data); // Zero the bottom rows - if (y1 < TV_HEIGHT) { + if (p1.y < TV_HEIGHT) { memset(dst_img.data, 0, TV_WIDTH_RGB565); } - for (int i = y1; i < TV_HEIGHT; i++) { + for (int i = p1.y; i < TV_HEIGHT; i++) { SpiTransmitReceivePacket(dst_img.data, NULL, PICLINE_LENGTH_BYTES, false); } } @@ -641,14 +642,14 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f memset(dst_img.data, 0, TV_WIDTH * TV_HEIGHT * sizeof(uint16_t)); } else { // Zero the top rows - if (y0) { - memset(dst_img.data, 0, TV_WIDTH * y0 * sizeof(uint16_t)); + if (p0.y) { + memset(dst_img.data, 0, TV_WIDTH * p0.y * sizeof(uint16_t)); } - if (x0) { - for (int i = y0; i < y1; i++) { + if (p0.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero left - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i), 0, x0 * sizeof(uint16_t)); + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i), 0, p0.x * sizeof(uint16_t)); } } @@ -656,18 +657,18 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL); - if (TV_WIDTH - x1) { - for (int i = y0; i < y1; i++) { + if (TV_WIDTH - p1.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero right - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i) + x1, 0, - (TV_WIDTH - x1) * sizeof(uint16_t)); + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, i) + p1.x, 0, + (TV_WIDTH - p1.x) * sizeof(uint16_t)); } } // Zero the bottom rows - if (TV_HEIGHT - y1) { - memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, y1), 0, - TV_WIDTH * (TV_HEIGHT - y1) * sizeof(uint16_t)); + if (TV_HEIGHT - p1.y) { + memset(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, p1.y), 0, + TV_WIDTH * (TV_HEIGHT - p1.y) * sizeof(uint16_t)); } } @@ -682,14 +683,14 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f memset(dst_img.data, 0, TV_WIDTH * TV_HEIGHT * sizeof(uint8_t)); } else { // Zero the top rows - if (y0) { - memset(dst_img.data, 0, TV_WIDTH * y0 * sizeof(uint8_t)); + if (p0.y) { + memset(dst_img.data, 0, TV_WIDTH * p0.y * sizeof(uint8_t)); } - if (x0) { - for (int i = y0; i < y1; i++) { + if (p0.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero left - memset(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&dst_img, i), 0, x0 * sizeof(uint8_t)); + memset(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&dst_img, i), 0, p0.x * sizeof(uint8_t)); } } @@ -697,18 +698,18 @@ static void spi_tv_display(image_t *src_img, int dst_x_start, int dst_y_start, f rgb_channel, alpha, color_palette, alpha_palette, hint | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL); - if (TV_WIDTH - x1) { - for (int i = y0; i < y1; i++) { + if (TV_WIDTH - p1.x) { + for (int i = p0.y; i < p1.y; i++) { // Zero right - memset(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&dst_img, i) + x1, 0, - (TV_WIDTH - x1) * sizeof(uint8_t)); + memset(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&dst_img, i) + p1.x, 0, + (TV_WIDTH - p1.x) * sizeof(uint8_t)); } } // Zero the bottom rows - if (TV_HEIGHT - y1) { - memset(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&dst_img, y1), 0, - TV_WIDTH * (TV_HEIGHT - y1) * sizeof(uint8_t)); + if (TV_HEIGHT - p1.y) { + memset(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&dst_img, p1.y), 0, + TV_WIDTH * (TV_HEIGHT - p1.y) * sizeof(uint8_t)); } } diff --git a/src/omv/ports/stm32/modules/py_display.c b/src/omv/ports/stm32/modules/py_display.c index c48327a4b..211d65095 100644 --- a/src/omv/ports/stm32/modules/py_display.c +++ b/src/omv/ports/stm32/modules/py_display.c @@ -409,9 +409,10 @@ static void display_write(py_display_obj_t *self, image_t *src_img, int dst_x_st dst_img.h = self->height; dst_img.pixfmt = PIXFORMAT_RGB565; - int x0, x1, y0, y1; - bool black = !imlib_draw_image_rectangle(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, - roi, alpha, alpha_palette, hint, &x0, &x1, &y0, &y1); + point_t p0, p1; + imlib_draw_image_get_bounds(&dst_img, src_img, dst_x_start, dst_y_start, x_scale, y_scale, + roi, alpha, alpha_palette, hint, &p0, &p1); + bool black = p0.x == -1; // For triple buffering we are never drawing where tail or head (which may instantly update to // to be equal to tail) is. @@ -422,15 +423,15 @@ static void display_write(py_display_obj_t *self, image_t *src_img, int dst_x_st dst_img.data = (uint8_t *) self->framebuffers[tail]; // Set default values for the layer to display the whole framebuffer. - display.framebuffer_layers[tail].WindowX0 = black ? 0 : x0; - display.framebuffer_layers[tail].WindowX1 = black ? self->width : x1; - display.framebuffer_layers[tail].WindowY0 = black ? 0 : y0; - display.framebuffer_layers[tail].WindowY1 = black ? self->height : y1; + display.framebuffer_layers[tail].WindowX0 = black ? 0 : p0.x; + display.framebuffer_layers[tail].WindowX1 = black ? self->width : p1.x; + display.framebuffer_layers[tail].WindowY0 = black ? 0 : p0.y; + display.framebuffer_layers[tail].WindowY1 = black ? self->height : p1.y; display.framebuffer_layers[tail].Alpha = black ? 0 : fast_roundf((alpha * 255) / 256.f); display.framebuffer_layers[tail].FBStartAdress = - black ? ((uint32_t) dst_img.data) : ((uint32_t) (IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, y0) + x0)); + black ? ((uint32_t) dst_img.data) : ((uint32_t) (IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&dst_img, p0.y) + p0.x)); display.framebuffer_layers[tail].ImageWidth = black ? self->width : dst_img.w; - display.framebuffer_layers[tail].ImageHeight = black ? self->height : (y1 - y0); + display.framebuffer_layers[tail].ImageHeight = black ? self->height : (p1.y - p0.y); // Set alpha to 256 here as we will use the layer alpha to blend the image into the background color of black for free. if (!black) {