mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #1122 from kwagyeman/kwabena/cleanup_to_ops
Kwabena/cleanup to ops
This commit is contained in:
commit
730efc65aa
@ -439,7 +439,14 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
|
|||||||
|
|
||||||
void imlib_draw_row_setup(imlib_draw_row_data_t *data)
|
void imlib_draw_row_setup(imlib_draw_row_data_t *data)
|
||||||
{
|
{
|
||||||
size_t image_row_size = image_size(data->dst_img) / data->dst_img->h;
|
image_t temp;
|
||||||
|
temp.w = data->dst_img->w;
|
||||||
|
temp.h = data->dst_img->h;
|
||||||
|
temp.bpp = data->src_img_bpp;
|
||||||
|
|
||||||
|
// Image Row Size should be the width of the destination image
|
||||||
|
// but with the bpp of the source image.
|
||||||
|
size_t image_row_size = image_size(&temp) / data->dst_img->h;
|
||||||
|
|
||||||
data->toggle = 0;
|
data->toggle = 0;
|
||||||
data->row_buffer[0] = fb_alloc(image_row_size, FB_ALLOC_NO_HINT);
|
data->row_buffer[0] = fb_alloc(image_row_size, FB_ALLOC_NO_HINT);
|
||||||
@ -2663,6 +2670,29 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
|||||||
color_palette = NULL;
|
color_palette = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool no_scaling_nearest_neighbor = (dst_delta_x == 1)
|
||||||
|
&& (dst_x_start == 0) && (src_x_start == 0)
|
||||||
|
&& (src_x_frac == 65536) && (src_y_frac == 65536);
|
||||||
|
|
||||||
|
// If we are scaling just make a deep copy.
|
||||||
|
bool is_scaling = (hint & (IMAGE_HINT_AREA | IMAGE_HINT_BICUBIC | IMAGE_HINT_BILINEAR))
|
||||||
|
|| (!no_scaling_nearest_neighbor);
|
||||||
|
|
||||||
|
// Otherwise, we only have to do a deep copy if the image is growing.
|
||||||
|
size_t src_img_row_bytes = image_size(src_img) / src_img->h;
|
||||||
|
size_t dst_img_row_bytes = image_size(dst_img) / dst_img->h;
|
||||||
|
|
||||||
|
// In-place (by definition mutually exclusive to the above)...
|
||||||
|
if ((dst_img->data == src_img->data) && (is_scaling || (src_img_row_bytes < dst_img_row_bytes))) {
|
||||||
|
size_t size = image_size(src_img);
|
||||||
|
new_src_img.w = src_img->w; // same width as source image
|
||||||
|
new_src_img.h = src_img->h; // same height as source image
|
||||||
|
new_src_img.bpp = src_img->bpp;
|
||||||
|
new_src_img.data = fb_alloc(size, FB_ALLOC_NO_HINT);
|
||||||
|
memcpy(new_src_img.data, src_img->data, size);
|
||||||
|
src_img = &new_src_img;
|
||||||
|
}
|
||||||
|
|
||||||
imlib_draw_row_data_t imlib_draw_row_data;
|
imlib_draw_row_data_t imlib_draw_row_data;
|
||||||
imlib_draw_row_data.dst_img = dst_img;
|
imlib_draw_row_data.dst_img = dst_img;
|
||||||
imlib_draw_row_data.src_img_bpp = src_img->bpp;
|
imlib_draw_row_data.src_img_bpp = src_img->bpp;
|
||||||
@ -4360,52 +4390,162 @@ void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int d
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((dst_delta_x == 1) && (dst_x_start == 0) && (src_x_start == 0) && (src_x_frac == 65536) && (src_y_frac == 65536)) { // copy
|
} else if (no_scaling_nearest_neighbor) { // copy
|
||||||
switch (src_img->bpp) {
|
if (dst_img->data == src_img->data) { // In-Place
|
||||||
case IMAGE_BPP_BINARY: {
|
switch (src_img->bpp) {
|
||||||
while (y_not_done) {
|
case IMAGE_BPP_BINARY: {
|
||||||
uint32_t *src_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
while (y_not_done) {
|
||||||
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
uint32_t *src_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||||
imlib_draw_row(dst_x_start, dst_x_end, dst_y, &imlib_draw_row_data);
|
// Must be called per loop to get the address of the temp buffer to blend with
|
||||||
|
uint32_t *dst_row_ptr = (uint32_t *) imlib_draw_row_get_row_buffer(&imlib_draw_row_data);
|
||||||
|
|
||||||
// Increment offsets
|
// X loop iteration variables
|
||||||
dst_y += dst_delta_y;
|
int dst_x = dst_x_reset;
|
||||||
src_y_accum += src_y_frac;
|
long src_x_accum = src_x_accum_reset;
|
||||||
next_src_y_index = src_y_accum >> 16;
|
int next_src_x_index = src_x_accum >> 16;
|
||||||
y_not_done = ++y < dst_y_end;
|
int x = dst_x_start;
|
||||||
} // while y
|
bool x_not_done = x < dst_x_end;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_GRAYSCALE: {
|
|
||||||
while (y_not_done) {
|
|
||||||
uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
|
||||||
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
|
||||||
imlib_draw_row(dst_x_start, dst_x_end, dst_y, &imlib_draw_row_data);
|
|
||||||
|
|
||||||
// Increment offsets
|
while (x_not_done) {
|
||||||
dst_y += dst_delta_y;
|
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(src_row_ptr, next_src_x_index);
|
||||||
src_y_accum += src_y_frac;
|
IMAGE_PUT_BINARY_PIXEL_FAST(dst_row_ptr, dst_x, pixel);
|
||||||
next_src_y_index = src_y_accum >> 16;
|
|
||||||
y_not_done = ++y < dst_y_end;
|
|
||||||
} // while y
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_RGB565: {
|
|
||||||
while (y_not_done) {
|
|
||||||
uint16_t *src_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
|
||||||
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
|
||||||
imlib_draw_row(dst_x_start, dst_x_end, dst_y, &imlib_draw_row_data);
|
|
||||||
|
|
||||||
// Increment offsets
|
// Increment offsets
|
||||||
dst_y += dst_delta_y;
|
dst_x += dst_delta_x;
|
||||||
src_y_accum += src_y_frac;
|
src_x_accum += src_x_frac;
|
||||||
next_src_y_index = src_y_accum >> 16;
|
next_src_x_index = src_x_accum >> 16;
|
||||||
y_not_done = ++y < dst_y_end;
|
x_not_done = ++x < dst_x_end;
|
||||||
} // while y
|
} // while x
|
||||||
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 IMAGE_BPP_GRAYSCALE: {
|
||||||
|
while (y_not_done) {
|
||||||
|
uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_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
|
||||||
|
uint8_t *dst_row_ptr = (uint8_t *) imlib_draw_row_get_row_buffer(&imlib_draw_row_data);
|
||||||
|
|
||||||
|
// X loop iteration variables
|
||||||
|
int dst_x = dst_x_reset;
|
||||||
|
long src_x_accum = src_x_accum_reset;
|
||||||
|
int next_src_x_index = src_x_accum >> 16;
|
||||||
|
int x = dst_x_start;
|
||||||
|
bool x_not_done = x < dst_x_end;
|
||||||
|
|
||||||
|
while (x_not_done) {
|
||||||
|
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(src_row_ptr, next_src_x_index);
|
||||||
|
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(dst_row_ptr, dst_x, pixel);
|
||||||
|
|
||||||
|
// Increment offsets
|
||||||
|
dst_x += dst_delta_x;
|
||||||
|
src_x_accum += src_x_frac;
|
||||||
|
next_src_x_index = src_x_accum >> 16;
|
||||||
|
x_not_done = ++x < dst_x_end;
|
||||||
|
} // while x
|
||||||
|
|
||||||
|
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 IMAGE_BPP_RGB565: {
|
||||||
|
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
|
||||||
|
uint16_t *dst_row_ptr = (uint16_t *) imlib_draw_row_get_row_buffer(&imlib_draw_row_data);
|
||||||
|
|
||||||
|
// X loop iteration variables
|
||||||
|
int dst_x = dst_x_reset;
|
||||||
|
long src_x_accum = src_x_accum_reset;
|
||||||
|
int next_src_x_index = src_x_accum >> 16;
|
||||||
|
int x = dst_x_start;
|
||||||
|
bool x_not_done = x < dst_x_end;
|
||||||
|
|
||||||
|
while (x_not_done) {
|
||||||
|
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(src_row_ptr, next_src_x_index);
|
||||||
|
IMAGE_PUT_RGB565_PIXEL_FAST(dst_row_ptr, dst_x, pixel);
|
||||||
|
|
||||||
|
// Increment offsets
|
||||||
|
dst_x += dst_delta_x;
|
||||||
|
src_x_accum += src_x_frac;
|
||||||
|
next_src_x_index = src_x_accum >> 16;
|
||||||
|
x_not_done = ++x < dst_x_end;
|
||||||
|
} // while x
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default: {
|
} else { // Out-of-Place
|
||||||
break;
|
switch (src_img->bpp) {
|
||||||
|
case IMAGE_BPP_BINARY: {
|
||||||
|
while (y_not_done) {
|
||||||
|
uint32_t *src_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||||
|
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
||||||
|
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 IMAGE_BPP_GRAYSCALE: {
|
||||||
|
while (y_not_done) {
|
||||||
|
uint8_t *src_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||||
|
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
||||||
|
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 IMAGE_BPP_RGB565: {
|
||||||
|
while (y_not_done) {
|
||||||
|
uint16_t *src_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(src_img, next_src_y_index);
|
||||||
|
imlib_draw_row_put_row_buffer(&imlib_draw_row_data, src_row_ptr);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // nearest neighbor
|
} else { // nearest neighbor
|
||||||
|
|||||||
@ -867,435 +867,156 @@ static mp_obj_t py_image_midpoint_pooled(uint n_args, const mp_obj_t *args, mp_m
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_pooled_obj, 3, py_image_midpoint_pooled);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_pooled_obj, 3, py_image_midpoint_pooled);
|
||||||
#endif // IMLIB_ENABLE_MIDPOINT_POOLING
|
#endif // IMLIB_ENABLE_MIDPOINT_POOLING
|
||||||
|
|
||||||
|
static mp_obj_t py_image_to(int bpp, 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(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);
|
||||||
|
|
||||||
|
float arg_y_scale = 1.f;
|
||||||
|
bool got_y_scale = py_helper_keyword_float_maybe(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), &arg_y_scale);
|
||||||
|
|
||||||
|
rectangle_t arg_roi;
|
||||||
|
py_helper_keyword_rectangle_roi(src_img, n_args, args, 3, kw_args, &arg_roi);
|
||||||
|
|
||||||
|
int arg_rgb_channel = py_helper_keyword_int(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
|
||||||
|
if ((arg_rgb_channel < -1) || (2 < arg_rgb_channel)) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("-1 <= rgb_channel <= 2!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int arg_alpha = py_helper_keyword_int(n_args, args, 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_alpha), 256);
|
||||||
|
if ((arg_alpha < 0) || (256 < arg_alpha)) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("0 <= alpha <= 256!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t *color_palette = py_helper_keyword_color_palette(n_args, args, 6, kw_args, default_color_palette);
|
||||||
|
const uint8_t *alpha_palette = py_helper_keyword_alpha_palette(n_args, args, 7, kw_args, NULL);
|
||||||
|
|
||||||
|
image_hint_t hint = py_helper_keyword_int(n_args, args, 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0);
|
||||||
|
|
||||||
|
int arg_x_size;
|
||||||
|
bool got_x_size = py_helper_keyword_int_maybe(n_args, args, 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_size), &arg_x_size);
|
||||||
|
|
||||||
|
int arg_y_size;
|
||||||
|
bool got_y_size = py_helper_keyword_int_maybe(n_args, args, 10, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_size), &arg_y_size);
|
||||||
|
|
||||||
|
if (got_x_scale && got_x_size) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Choose either x_scale or x_size not both!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_y_scale && got_y_size) {
|
||||||
|
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Choose either y_scale or y_size not both!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_x_size) {
|
||||||
|
arg_x_scale = arg_x_size / ((float) arg_roi.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_y_size) {
|
||||||
|
arg_y_scale = arg_y_size / ((float) arg_roi.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!got_x_scale) && (!got_x_size) && got_y_size) {
|
||||||
|
arg_x_scale = arg_y_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!got_y_scale) && (!got_y_size) && got_x_size) {
|
||||||
|
arg_y_scale = arg_x_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t copy_obj = py_helper_keyword_object(n_args, args, 11, kw_args,
|
||||||
|
MP_OBJ_NEW_QSTR(copy_to_fb ? MP_QSTR_copy_to_fb : MP_QSTR_copy), NULL);
|
||||||
|
bool copy = false;
|
||||||
|
image_t *arg_other = copy_to_fb ? NULL : src_img;
|
||||||
|
|
||||||
|
if (copy_obj) {
|
||||||
|
if (mp_obj_is_integer(copy_obj)) {
|
||||||
|
copy = mp_obj_get_int(copy_obj);
|
||||||
|
} else {
|
||||||
|
arg_other = py_helper_arg_to_image_mutable(copy_obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_fb && copy) {
|
||||||
|
fb_update_jpeg_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
image_t dst_img;
|
||||||
|
dst_img.w = fast_floorf(arg_roi.w * arg_x_scale);
|
||||||
|
dst_img.h = fast_floorf(arg_roi.h * arg_y_scale);
|
||||||
|
dst_img.bpp = (bpp >= 0) ? bpp : src_img->bpp;
|
||||||
|
|
||||||
|
if (copy) {
|
||||||
|
if (copy_to_fb) {
|
||||||
|
py_helper_set_to_framebuffer(&dst_img);
|
||||||
|
} else {
|
||||||
|
dst_img.data = xalloc(image_size(&dst_img));
|
||||||
|
}
|
||||||
|
} else if (arg_other) {
|
||||||
|
bool fb = py_helper_is_equal_to_framebuffer(arg_other);
|
||||||
|
size_t size = fb ? framebuffer_get_buffer_size() : image_size(arg_other);
|
||||||
|
PY_ASSERT_TRUE_MSG((image_size(&dst_img) <= size),
|
||||||
|
"The new image won't fit in the target frame buffer!");
|
||||||
|
// DO NOT MODIFY arg_other YET (as it could point to src_img)!
|
||||||
|
dst_img.data = arg_other->data;
|
||||||
|
py_helper_update_framebuffer(&dst_img);
|
||||||
|
} else {
|
||||||
|
dst_img.data = xalloc(image_size(&dst_img));
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_alloc_mark();
|
||||||
|
imlib_draw_image(&dst_img, src_img, 0, 0, arg_x_scale, arg_y_scale, &arg_roi,
|
||||||
|
arg_rgb_channel, arg_alpha, color_palette, alpha_palette,
|
||||||
|
(hint & (~IMAGE_HINT_CENTER)) | IMAGE_HINT_BLACK_BACKGROUND, NULL, NULL);
|
||||||
|
fb_alloc_free_till_mark();
|
||||||
|
|
||||||
|
if (arg_other) {
|
||||||
|
arg_other->w = dst_img.w;
|
||||||
|
arg_other->h = dst_img.h;
|
||||||
|
arg_other->bpp = dst_img.bpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return py_image_from_struct(&dst_img);
|
||||||
|
}
|
||||||
|
|
||||||
static mp_obj_t py_image_to_bitmap(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_to_bitmap(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]);
|
return py_image_to(IMAGE_BPP_BINARY, NULL, false, n_args, args, kw_args);
|
||||||
bool copy = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_copy), false);
|
|
||||||
int channel = py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
|
|
||||||
|
|
||||||
image_t out;
|
|
||||||
out.w = arg_img->w;
|
|
||||||
out.h = arg_img->h;
|
|
||||||
out.bpp = IMAGE_BPP_BINARY;
|
|
||||||
out.data = copy ? xalloc(image_size(&out)) : arg_img->data;
|
|
||||||
|
|
||||||
switch(arg_img->bpp) {
|
|
||||||
case IMAGE_BPP_BINARY: {
|
|
||||||
if (copy) memcpy(out.data, arg_img->data, image_size(&out));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_GRAYSCALE: {
|
|
||||||
PY_ASSERT_TRUE_MSG((out.w >= (sizeof(uint32_t)/sizeof(uint8_t))) || copy,
|
|
||||||
"Can't convert to bitmap in place!");
|
|
||||||
fb_alloc_mark();
|
|
||||||
uint32_t *out_row_ptr = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(&out), FB_ALLOC_NO_HINT);
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)));
|
|
||||||
}
|
|
||||||
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&out, y),
|
|
||||||
out_row_ptr, IMAGE_BINARY_LINE_LEN_BYTES(&out));
|
|
||||||
}
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_RGB565: {
|
|
||||||
PY_ASSERT_TRUE_MSG((out.w >= (sizeof(uint32_t)/sizeof(uint16_t))) || copy,
|
|
||||||
"Can't convert to bitmap in place!");
|
|
||||||
fb_alloc_mark();
|
|
||||||
uint32_t *out_row_ptr = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(&out), FB_ALLOC_NO_HINT);
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
|
|
||||||
switch (channel) {
|
|
||||||
case 0: {
|
|
||||||
pixel = COLOR_RGB565_TO_R5(pixel) > (((COLOR_R5_MAX - COLOR_R5_MIN) / 2) + COLOR_R5_MIN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
pixel = COLOR_RGB565_TO_G6(pixel) > (((COLOR_G6_MAX - COLOR_G6_MIN) / 2) + COLOR_G6_MIN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
pixel = COLOR_RGB565_TO_B5(pixel) > (((COLOR_B5_MAX - COLOR_B5_MIN) / 2) + COLOR_B5_MIN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
pixel = COLOR_RGB565_TO_BINARY(pixel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
|
|
||||||
}
|
|
||||||
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&out, y),
|
|
||||||
out_row_ptr, IMAGE_BINARY_LINE_LEN_BYTES(&out));
|
|
||||||
}
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!copy) {
|
|
||||||
arg_img->bpp = IMAGE_BPP_BINARY;
|
|
||||||
py_helper_update_framebuffer(&out);
|
|
||||||
}
|
|
||||||
|
|
||||||
return py_image_from_struct(&out);
|
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_bitmap_obj, 1, py_image_to_bitmap);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_bitmap_obj, 1, py_image_to_bitmap);
|
||||||
|
|
||||||
static mp_obj_t py_image_to_grayscale(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_to_grayscale(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]);
|
return py_image_to(IMAGE_BPP_GRAYSCALE, NULL, false, n_args, args, kw_args);
|
||||||
bool copy = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_copy), false);
|
|
||||||
int channel = py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
|
|
||||||
|
|
||||||
image_t out;
|
|
||||||
out.w = arg_img->w;
|
|
||||||
out.h = arg_img->h;
|
|
||||||
out.bpp = IMAGE_BPP_GRAYSCALE;
|
|
||||||
out.data = copy ? xalloc(image_size(&out)) : arg_img->data;
|
|
||||||
|
|
||||||
switch(arg_img->bpp) {
|
|
||||||
case IMAGE_BPP_BINARY: {
|
|
||||||
if (copy || (!py_helper_is_equal_to_framebuffer(&out))) {
|
|
||||||
PY_ASSERT_TRUE_MSG((out.w == 1) || copy,
|
|
||||||
"Can't convert to grayscale in place!");
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
COLOR_BINARY_TO_GRAYSCALE(IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
image_t temp;
|
|
||||||
memcpy(&temp, arg_img, sizeof(image_t));
|
|
||||||
fb_alloc_mark();
|
|
||||||
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
|
|
||||||
memcpy(temp.data, arg_img->data, image_size(&temp));
|
|
||||||
py_helper_set_to_framebuffer(&out);
|
|
||||||
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&temp, y);
|
|
||||||
uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
COLOR_BINARY_TO_GRAYSCALE(IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_GRAYSCALE: {
|
|
||||||
if (copy) memcpy(out.data, arg_img->data, image_size(&out));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_RGB565: {
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
|
|
||||||
switch (channel) {
|
|
||||||
case 0: {
|
|
||||||
pixel = COLOR_RGB565_TO_R8(pixel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
pixel = COLOR_RGB565_TO_G8(pixel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
pixel = COLOR_RGB565_TO_B8(pixel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
pixel = COLOR_RGB565_TO_GRAYSCALE(pixel);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x, pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!copy) {
|
|
||||||
arg_img->bpp = IMAGE_BPP_GRAYSCALE;
|
|
||||||
py_helper_update_framebuffer(&out);
|
|
||||||
}
|
|
||||||
|
|
||||||
return py_image_from_struct(&out);
|
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_grayscale_obj, 1, py_image_to_grayscale);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_grayscale_obj, 1, py_image_to_grayscale);
|
||||||
|
|
||||||
static mp_obj_t py_image_to_rgb565(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_to_rgb565(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]);
|
return py_image_to(IMAGE_BPP_RGB565, NULL, false, n_args, args, kw_args);
|
||||||
bool copy = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_copy), false);
|
|
||||||
int channel = py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
|
|
||||||
|
|
||||||
image_t out;
|
|
||||||
out.w = arg_img->w;
|
|
||||||
out.h = arg_img->h;
|
|
||||||
out.bpp = IMAGE_BPP_RGB565;
|
|
||||||
out.data = copy ? xalloc(image_size(&out)) : arg_img->data;
|
|
||||||
|
|
||||||
switch(arg_img->bpp) {
|
|
||||||
case IMAGE_BPP_BINARY: {
|
|
||||||
if (copy || (!py_helper_is_equal_to_framebuffer(&out))) {
|
|
||||||
PY_ASSERT_TRUE_MSG((out.w == 1) || copy,
|
|
||||||
"Can't convert to grayscale in place!");
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
imlib_yuv_to_rgb(IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) * COLOR_GRAYSCALE_MAX, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
image_t temp;
|
|
||||||
memcpy(&temp, arg_img, sizeof(image_t));
|
|
||||||
fb_alloc_mark();
|
|
||||||
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
|
|
||||||
memcpy(temp.data, arg_img->data, image_size(&temp));
|
|
||||||
py_helper_set_to_framebuffer(&out);
|
|
||||||
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&temp, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
imlib_yuv_to_rgb(IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) * COLOR_GRAYSCALE_MAX, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_GRAYSCALE: {
|
|
||||||
if (copy || (!py_helper_is_equal_to_framebuffer(&out))) {
|
|
||||||
PY_ASSERT_TRUE_MSG(copy,
|
|
||||||
"Can't convert to rgb565 in place!");
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
imlib_yuv_to_rgb(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x), 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
image_t temp;
|
|
||||||
memcpy(&temp, arg_img, sizeof(image_t));
|
|
||||||
fb_alloc_mark();
|
|
||||||
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
|
|
||||||
memcpy(temp.data, arg_img->data, image_size(&temp));
|
|
||||||
py_helper_set_to_framebuffer(&out);
|
|
||||||
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&temp, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
imlib_yuv_to_rgb(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x), 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_RGB565: {
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
|
|
||||||
switch (channel) {
|
|
||||||
case 0: {
|
|
||||||
pixel = COLOR_R5_G6_B5_TO_RGB565(COLOR_RGB565_TO_R5(pixel), 0, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
pixel = COLOR_R5_G6_B5_TO_RGB565(0, COLOR_RGB565_TO_G6(pixel), 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
pixel = COLOR_R5_G6_B5_TO_RGB565(0, 0, COLOR_RGB565_TO_B5(pixel));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!copy) {
|
|
||||||
arg_img->bpp = IMAGE_BPP_RGB565;
|
|
||||||
py_helper_update_framebuffer(&out);
|
|
||||||
}
|
|
||||||
|
|
||||||
return py_image_from_struct(&out);
|
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_rgb565_obj, 1, py_image_to_rgb565);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_rgb565_obj, 1, py_image_to_rgb565);
|
||||||
|
|
||||||
static mp_obj_t py_image_to_rainbow(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_to_rainbow(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]);
|
return py_image_to(IMAGE_BPP_RGB565, rainbow_table, false, n_args, args, kw_args);
|
||||||
bool copy = py_helper_keyword_int(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_copy), false);
|
|
||||||
int channel = py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
|
|
||||||
int palette = py_helper_keyword_int(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), COLOR_PALETTE_RAINBOW);
|
|
||||||
const uint16_t *color_palette = NULL;
|
|
||||||
|
|
||||||
if (palette == COLOR_PALETTE_RAINBOW) {
|
|
||||||
color_palette = rainbow_table;
|
|
||||||
} else if (palette == COLOR_PALETTE_IRONBOW) {
|
|
||||||
color_palette = ironbow_table;
|
|
||||||
} else {
|
|
||||||
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid color palette!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
image_t out;
|
|
||||||
out.w = arg_img->w;
|
|
||||||
out.h = arg_img->h;
|
|
||||||
out.bpp = IMAGE_BPP_RGB565;
|
|
||||||
out.data = copy ? xalloc(image_size(&out)) : arg_img->data;
|
|
||||||
|
|
||||||
switch(arg_img->bpp) {
|
|
||||||
case IMAGE_BPP_BINARY: {
|
|
||||||
if (copy || (!py_helper_is_equal_to_framebuffer(&out))) {
|
|
||||||
PY_ASSERT_TRUE_MSG((out.w == 1) || copy,
|
|
||||||
"Can't convert to rainbow in place!");
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
color_palette[IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) * COLOR_GRAYSCALE_MAX]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
image_t temp;
|
|
||||||
memcpy(&temp, arg_img, sizeof(image_t));
|
|
||||||
fb_alloc_mark();
|
|
||||||
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
|
|
||||||
memcpy(temp.data, arg_img->data, image_size(&temp));
|
|
||||||
py_helper_set_to_framebuffer(&out);
|
|
||||||
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&temp, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
color_palette[IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) * COLOR_GRAYSCALE_MAX]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_GRAYSCALE: {
|
|
||||||
if (copy || (!py_helper_is_equal_to_framebuffer(&out))) {
|
|
||||||
PY_ASSERT_TRUE_MSG(copy,
|
|
||||||
"Can't convert to rainbow in place!");
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
color_palette[IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
image_t temp;
|
|
||||||
memcpy(&temp, arg_img, sizeof(image_t));
|
|
||||||
fb_alloc_mark();
|
|
||||||
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
|
|
||||||
memcpy(temp.data, arg_img->data, image_size(&temp));
|
|
||||||
py_helper_set_to_framebuffer(&out);
|
|
||||||
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&temp, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
|
|
||||||
color_palette[IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_RGB565: {
|
|
||||||
for (int y = 0, yy = out.h; y < yy; y++) {
|
|
||||||
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, y);
|
|
||||||
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&out, y);
|
|
||||||
for (int x = 0, xx = out.w; x < xx; x++) {
|
|
||||||
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
|
|
||||||
switch (channel) {
|
|
||||||
case 0: {
|
|
||||||
pixel = color_palette[COLOR_RGB565_TO_R8(pixel)];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
pixel = color_palette[COLOR_RGB565_TO_G8(pixel)];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
pixel = color_palette[COLOR_RGB565_TO_B8(pixel)];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
pixel = color_palette[COLOR_RGB565_TO_GRAYSCALE(pixel)];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, pixel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!copy) {
|
|
||||||
arg_img->bpp = IMAGE_BPP_RGB565;
|
|
||||||
py_helper_update_framebuffer(&out);
|
|
||||||
}
|
|
||||||
|
|
||||||
return py_image_from_struct(&out);
|
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_rainbow_obj, 1, py_image_to_rainbow);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_to_rainbow_obj, 1, py_image_to_rainbow);
|
||||||
|
|
||||||
|
static mp_obj_t py_image_copy(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||||
|
{
|
||||||
|
return py_image_to(-1, NULL, true, n_args, args, kw_args);
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_copy_obj, 1, py_image_copy);
|
||||||
|
|
||||||
|
static mp_obj_t py_image_crop(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||||
|
{
|
||||||
|
return py_image_to(-1, NULL, false, n_args, args, kw_args);
|
||||||
|
}
|
||||||
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_crop_obj, 1, py_image_crop);
|
||||||
|
|
||||||
static mp_obj_t py_image_jpeg_encode_for_ide(mp_obj_t img_obj)
|
static mp_obj_t py_image_jpeg_encode_for_ide(mp_obj_t img_obj)
|
||||||
{
|
{
|
||||||
image_t *arg_img = py_image_cobj(img_obj);
|
image_t *arg_img = py_image_cobj(img_obj);
|
||||||
@ -1434,153 +1155,6 @@ static mp_obj_t py_image_compressed_for_ide(uint n_args, const mp_obj_t *args, m
|
|||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_compressed_for_ide_obj, 1, py_image_compressed_for_ide);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_compressed_for_ide_obj, 1, py_image_compressed_for_ide);
|
||||||
|
|
||||||
static mp_obj_t py_image_copy_int(uint n_args, const mp_obj_t *args, mp_map_t *kw_args, bool mode)
|
|
||||||
{
|
|
||||||
// mode == false -> copy behavior
|
|
||||||
// mode == true -> crop/scale behavior
|
|
||||||
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
|
|
||||||
|
|
||||||
rectangle_t roi;
|
|
||||||
py_helper_keyword_rectangle_roi(arg_img, n_args, args, 1, kw_args, &roi);
|
|
||||||
|
|
||||||
float arg_x_scale =
|
|
||||||
py_helper_keyword_float(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), 1.0f);
|
|
||||||
PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!");
|
|
||||||
|
|
||||||
float arg_y_scale =
|
|
||||||
py_helper_keyword_float(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f);
|
|
||||||
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
|
|
||||||
|
|
||||||
mp_obj_t copy_to_fb_obj = py_helper_keyword_object(n_args, args, 4, kw_args,
|
|
||||||
MP_OBJ_NEW_QSTR(mode ? MP_QSTR_copy : MP_QSTR_copy_to_fb), NULL);
|
|
||||||
bool copy_to_fb = false;
|
|
||||||
image_t *arg_other = mode ? arg_img : NULL;
|
|
||||||
|
|
||||||
if (copy_to_fb_obj) {
|
|
||||||
if (mp_obj_is_integer(copy_to_fb_obj)) {
|
|
||||||
if (!mode) {
|
|
||||||
copy_to_fb = mp_obj_get_int(copy_to_fb_obj);
|
|
||||||
} else if (mp_obj_get_int(copy_to_fb_obj)) {
|
|
||||||
arg_other = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
arg_other = py_helper_arg_to_image_mutable(copy_to_fb_obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_to_fb) {
|
|
||||||
fb_update_jpeg_buffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
image_t image;
|
|
||||||
image.w = fast_floorf(roi.w * arg_x_scale);
|
|
||||||
PY_ASSERT_TRUE_MSG(image.w >= 1, "Output image width is 0!");
|
|
||||||
image.h = fast_floorf(roi.h * arg_y_scale);
|
|
||||||
PY_ASSERT_TRUE_MSG(image.h >= 1, "Output image height is 0!");
|
|
||||||
image.bpp = arg_img->bpp;
|
|
||||||
image.data = NULL;
|
|
||||||
|
|
||||||
if (copy_to_fb) {
|
|
||||||
py_helper_set_to_framebuffer(&image);
|
|
||||||
} else if (arg_other) {
|
|
||||||
PY_ASSERT_TRUE_MSG((image_size(&image) <= image_size(arg_other)), "The new image won't fit in the target frame buffer!");
|
|
||||||
image.data = arg_other->data;
|
|
||||||
} else {
|
|
||||||
image.data = xalloc(image_size(&image));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool in_place = arg_img->data == image.data;
|
|
||||||
image_t temp;
|
|
||||||
|
|
||||||
if (in_place) {
|
|
||||||
memcpy(&temp, arg_img, sizeof(image_t));
|
|
||||||
fb_alloc_mark();
|
|
||||||
temp.data = fb_alloc(image_size(&temp), FB_ALLOC_NO_HINT);
|
|
||||||
memcpy(temp.data, arg_img->data, image_size(&temp));
|
|
||||||
arg_img = &temp;
|
|
||||||
if (copy_to_fb) {
|
|
||||||
py_helper_set_to_framebuffer(&image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float over_xscale = IM_DIV(1.0, arg_x_scale), over_yscale = IM_DIV(1.0f, arg_y_scale);
|
|
||||||
|
|
||||||
switch(arg_img->bpp) {
|
|
||||||
case IMAGE_BPP_BINARY: {
|
|
||||||
for (int y = 0, yy = image.h; y < yy; y++) {
|
|
||||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(arg_img, fast_floorf(y * over_yscale) + roi.y);
|
|
||||||
uint32_t *row_ptr_2 = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&image, y);
|
|
||||||
for (int x = 0, xx = image.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_2, x,
|
|
||||||
IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, fast_floorf(x * over_xscale) + roi.x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_GRAYSCALE: {
|
|
||||||
for (int y = 0, yy = image.h; y < yy; y++) {
|
|
||||||
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(arg_img, fast_floorf(y * over_yscale) + roi.y);
|
|
||||||
uint8_t *row_ptr_2 = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&image, y);
|
|
||||||
for (int x = 0, xx = image.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_2, x,
|
|
||||||
IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, fast_floorf(x * over_xscale) + roi.x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IMAGE_BPP_RGB565: {
|
|
||||||
for (int y = 0, yy = image.h; y < yy; y++) {
|
|
||||||
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, fast_floorf(y * over_yscale) + roi.y);
|
|
||||||
uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&image, y);
|
|
||||||
for (int x = 0, xx = image.w; x < xx; x++) {
|
|
||||||
IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_2, x,
|
|
||||||
IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, fast_floorf(x * over_xscale) + roi.x));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_place) {
|
|
||||||
fb_alloc_free_till_mark();
|
|
||||||
}
|
|
||||||
|
|
||||||
py_helper_update_framebuffer(&image);
|
|
||||||
|
|
||||||
if (copy_to_fb) {
|
|
||||||
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
|
|
||||||
|
|
||||||
if (py_helper_is_equal_to_framebuffer(arg_img)) {
|
|
||||||
arg_img->w = image.w;
|
|
||||||
arg_img->h = image.h;
|
|
||||||
arg_img->bpp = image.bpp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (arg_other) {
|
|
||||||
arg_other->w = image.w;
|
|
||||||
arg_other->h = image.h;
|
|
||||||
arg_other->bpp = image.bpp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return py_image_from_struct(&image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static mp_obj_t py_image_copy(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
|
||||||
{
|
|
||||||
return py_image_copy_int(n_args, args, kw_args, false);
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_copy_obj, 1, py_image_copy);
|
|
||||||
|
|
||||||
static mp_obj_t py_image_crop(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
|
||||||
{
|
|
||||||
return py_image_copy_int(n_args, args, kw_args, true);
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_crop_obj, 1, py_image_crop);
|
|
||||||
|
|
||||||
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
|
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
|
||||||
static mp_obj_t py_image_save(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
static mp_obj_t py_image_save(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user