From 8fb6dfd88b3bf0fdec00478be461b89e067f0118 Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Mon, 2 Oct 2023 18:37:40 -0700 Subject: [PATCH] imlib: Speed up transpose by 5X. --- src/omv/imlib/imlib.c | 21 +++++++++++++++++ src/omv/imlib/imlib.h | 1 + src/omv/imlib/mathop.c | 51 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/omv/imlib/imlib.c b/src/omv/imlib/imlib.c index f19238ed8..5feca2dab 100644 --- a/src/omv/imlib/imlib.c +++ b/src/omv/imlib/imlib.c @@ -251,6 +251,27 @@ void image_copy(image_t *dst, image_t *src) { memcpy(dst, src, sizeof(image_t)); } +size_t image_line_size(image_t *ptr) { + switch (ptr->pixfmt) { + case PIXFORMAT_BINARY: { + return IMAGE_BINARY_LINE_LEN_BYTES(ptr); + } + case PIXFORMAT_GRAYSCALE: + case PIXFORMAT_BAYER_ANY: { + // re-use + return IMAGE_GRAYSCALE_LINE_LEN_BYTES(ptr); + } + case PIXFORMAT_RGB565: + case PIXFORMAT_YUV_ANY: { + // re-use + return IMAGE_RGB565_LINE_LEN_BYTES(ptr); + } + default: { + return 0; + } + } +} + size_t image_size(image_t *ptr) { switch (ptr->pixfmt) { case PIXFORMAT_BINARY: { diff --git a/src/omv/imlib/imlib.h b/src/omv/imlib/imlib.h index 90f0d03e0..1f945665b 100644 --- a/src/omv/imlib/imlib.h +++ b/src/omv/imlib/imlib.h @@ -514,6 +514,7 @@ typedef struct image { void image_init(image_t *ptr, int w, int h, pixformat_t pixfmt, uint32_t size, void *pixels); void image_copy(image_t *dst, image_t *src); +size_t image_line_size(image_t *ptr); size_t image_size(image_t *ptr); bool image_get_mask_pixel(image_t *ptr, int x, int y); diff --git a/src/omv/imlib/mathop.c b/src/omv/imlib/mathop.c index 9ad2c6619..727d26ede 100644 --- a/src/omv/imlib/mathop.c +++ b/src/omv/imlib/mathop.c @@ -148,12 +148,51 @@ void imlib_replace(image_t *img, other = &temp; } - imlib_replace_line_op_state_t state; - state.hmirror = hmirror; - state.vflip = vflip; - state.mask = mask; - state.transpose = transpose; - imlib_image_operation(img, path, other, scalar, imlib_replace_line_op, &state); + // To improve transpose performance we will split the operation up into chunks that fit in + // onchip RAM. These chunks will then be copied to the target buffer in an efficent manner. + if (path == NULL && other && transpose) { + uint32_t size; + void *data = fb_alloc_all(&size, FB_ALLOC_PREFER_SPEED); + // line_num stores how many lines we can do at a time with on-chip RAM. + int line_num = size / image_line_size(other); + // Transposed chunks will be copied to the output image... + uint8_t *img_data = img->data; + int t_line_size = (image_line_size(img) * img->h) / img->w; + // Work top to bottom transposing as many lines at a time in a chunk of the image. + for (int i = 0, ii = other->h; i < ii; i += line_num) { + line_num = IM_MIN(line_num, (ii - i)); + // Make an image that is a slice of the input image. + image_t in = {.w = other->w, .h = line_num, .pixfmt = other->pixfmt}; + in.data = other->data + (image_line_size(other) * i); + // Make an image that will hold the transposed output. + image_t out = in; + out.data = data; + // Transpose the slice of the input image. + imlib_replace_line_op_state_t state; + state.hmirror = hmirror; + state.vflip = vflip; + state.mask = mask; + state.transpose = true; + imlib_image_operation(&out, NULL, &in, 0, imlib_replace_line_op, &state); + out.w = line_num; + out.h = other->w; + // Copy lines of the chunk to the target image. + int out_line_size = image_line_size(&out); + for (int j = 0, jj = out.h; j < jj; j++) { + memcpy(img_data + (t_line_size * j), out.data + (out_line_size * j), out_line_size); + } + // Slide the offset for the first line over by the size of the slice we transposed. + img_data += out_line_size; + } + fb_free(); // fb_alloc_all + } else { + imlib_replace_line_op_state_t state; + state.hmirror = hmirror; + state.vflip = vflip; + state.mask = mask; + state.transpose = transpose; + imlib_image_operation(img, path, other, scalar, imlib_replace_line_op, &state); + } if (in_place) { fb_free();