Merge pull request #1944 from kwagyeman/kwabena/faster_transpose

imlib: Speed up transpose by 5X.
This commit is contained in:
Ibrahim Abdelkader 2023-10-03 12:26:38 +03:00 committed by GitHub
commit a2bd75a727
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 6 deletions

View File

@ -251,6 +251,27 @@ void image_copy(image_t *dst, image_t *src) {
memcpy(dst, src, sizeof(image_t)); 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) { size_t image_size(image_t *ptr) {
switch (ptr->pixfmt) { switch (ptr->pixfmt) {
case PIXFORMAT_BINARY: { case PIXFORMAT_BINARY: {

View File

@ -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_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); void image_copy(image_t *dst, image_t *src);
size_t image_line_size(image_t *ptr);
size_t image_size(image_t *ptr); size_t image_size(image_t *ptr);
bool image_get_mask_pixel(image_t *ptr, int x, int y); bool image_get_mask_pixel(image_t *ptr, int x, int y);

View File

@ -148,12 +148,51 @@ void imlib_replace(image_t *img,
other = &temp; other = &temp;
} }
// 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; imlib_replace_line_op_state_t state;
state.hmirror = hmirror; state.hmirror = hmirror;
state.vflip = vflip; state.vflip = vflip;
state.mask = mask; state.mask = mask;
state.transpose = transpose; state.transpose = transpose;
imlib_image_operation(img, path, other, scalar, imlib_replace_line_op, &state); imlib_image_operation(img, path, other, scalar, imlib_replace_line_op, &state);
}
if (in_place) { if (in_place) {
fb_free(); fb_free();