Merge pull request #763 from matsondawson/add_custom_palettes_to_draw_image

Add custom palettes to draw image with demo
This commit is contained in:
Ibrahim Abd Elkader 2020-04-29 18:57:22 +02:00 committed by GitHub
commit ff54696163
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 4 deletions

View File

@ -0,0 +1,43 @@
# Draw Image Example with custom color palette
#
# This example shows off how to draw images in the frame buffer with a custom generated color palette.
import sensor, image, time, pyb
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE) # or GRAYSCALE...
sensor.set_framesize(sensor.QQVGA) # or QQVGA...
sensor.skip_frames(time = 2000)
clock = time.clock()
# the color palette is actually an image, this allows you to use image ops to create palettes
# the image must have 256 entries i.e. 256x1, 64x4, 16x16 and have the format rgb565
# Initialise palette source colors into an image
palette_source_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 0, 255)]
palette_source_color_image = image.Image(len(palette_source_colors), 1, sensor.RGB565)
for i, color in enumerate(palette_source_colors):
palette_source_color_image[i] = color
# Scale the image to palette width and smooth them
palette = image.Image(256,1, sensor.RGB565)
palette.draw_image(palette_source_color_image, 0, 0, x_scale=palette.width() / palette_source_color_image.width())
palette.mean(int(palette.width() / palette_source_color_image.width()/2))
while(True):
clock.tick()
img = sensor.snapshot()
# Get a copy of grayscale image before converting to color
img_copy = img.copy()
img.to_rgb565()
palette_boundary_inset = int(sensor.width() / 40)
palette_scale_x = (sensor.width() - palette_boundary_inset * 2) / palette.width()
img.draw_image(img_copy, 0, 0, color_palette=palette)
img.draw_image(palette, palette_boundary_inset, palette_boundary_inset, x_scale=palette_scale_x, y_scale=8)
img.draw_rectangle(palette_boundary_inset, palette_boundary_inset, int(palette.width()*palette_scale_x), 8, color=(255,255,255), thickness=1)
print(clock.fps())

View File

@ -67,6 +67,12 @@ image_t *py_helper_keyword_to_image_mutable_mask(uint n_args, const mp_obj_t *ar
return py_helper_keyword_to_image_mutable(n_args, args, arg_index, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mask), NULL);
}
image_t *py_helper_keyword_to_image_mutable_color_palette(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args)
{
return py_helper_keyword_to_image_mutable(n_args, args, arg_index, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), NULL);
}
void py_helper_keyword_rectangle(image_t *img, uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, rectangle_t *r)
{
@ -124,6 +130,20 @@ int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index,
return default_val;
}
int py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value)
{
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP);
if (kw_arg) {
return mp_obj_get_int_maybe(kw_arg->value, value);
} else if (n_args > arg_index) {
return mp_obj_get_int_maybe(args[arg_index], value);
}
return false;
}
float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float default_val)
{

View File

@ -21,12 +21,16 @@ image_t *py_helper_keyword_to_image_mutable(uint n_args, const mp_obj_t *args, u
mp_map_t *kw_args, mp_obj_t kw, image_t *default_val);
image_t *py_helper_keyword_to_image_mutable_mask(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args);
image_t *py_helper_keyword_to_image_mutable_color_palette(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args);
void py_helper_keyword_rectangle(image_t *img, uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, rectangle_t *r);
void py_helper_keyword_rectangle_roi(image_t *img, uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, rectangle_t *r);
int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int default_val);
int py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value);
float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float default_val);
void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index,

View File

@ -1931,11 +1931,11 @@ STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t
PY_ASSERT_TRUE_MSG((0 <= arg_alpha) && (arg_alpha <= 256), "Error: 0 <= alpha <= 256!");
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, offset + 3, kw_args);
int palette = py_helper_keyword_int(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), -1);
const uint16_t *color_palette = NULL;
if (palette != -1) {
int palette;
if (py_helper_keyword_int_maybe(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), &palette)) {
if (palette == COLOR_PALETTE_RAINBOW) {
color_palette = rainbow_table;
} else if (palette == COLOR_PALETTE_IRONBOW) {
@ -1943,7 +1943,17 @@ STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid color palette!"));
}
} else {
image_t *arg_palette = py_helper_keyword_to_image_mutable_color_palette(n_args, args, offset + 4, kw_args);
if (arg_palette) {
if (arg_palette->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Palette must be an RGB565 format image!"));
if ((arg_palette->w * arg_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Palette image must have 256 pixels!"));
color_palette = (uint16_t*)arg_palette->data;
}
}
if (color_palette) {
if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify color palette when passing a grayscale image!"));
}