mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-21 06:53:01 +08:00
fix conflicts
This commit is contained in:
commit
e7afc94cde
@ -1100,10 +1100,8 @@ static void indev_drag(lv_indev_proc_t * proc)
|
||||
if(proc->types.pointer.drag_limit_out == 0) {
|
||||
proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x;
|
||||
proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y;
|
||||
}
|
||||
|
||||
/*Enough move?*/
|
||||
if(proc->types.pointer.drag_limit_out == 0) {
|
||||
/*Enough move?*/
|
||||
bool hor_en = false;
|
||||
bool ver_en = false;
|
||||
if(allowed_dirs == LV_DRAG_DIR_HOR || allowed_dirs == LV_DRAG_DIR_BOTH) {
|
||||
@ -1182,9 +1180,20 @@ static void indev_drag(lv_indev_proc_t * proc)
|
||||
}
|
||||
}
|
||||
|
||||
/*In the inactive direction `drag_sum` is kept zero*/
|
||||
if(proc->types.pointer.drag_sum.x) act_x += proc->types.pointer.vect.x;
|
||||
if(proc->types.pointer.drag_sum.y) act_y += proc->types.pointer.vect.y;
|
||||
/*Move the object*/
|
||||
if(allowed_dirs == LV_DRAG_DIR_HOR ||
|
||||
allowed_dirs == LV_DRAG_DIR_BOTH ||
|
||||
(allowed_dirs == LV_DRAG_DIR_ONE &&
|
||||
LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y))) {
|
||||
act_x += proc->types.pointer.vect.x;
|
||||
}
|
||||
if(allowed_dirs == LV_DRAG_DIR_VER ||
|
||||
allowed_dirs == LV_DRAG_DIR_BOTH ||
|
||||
(allowed_dirs == LV_DRAG_DIR_ONE &&
|
||||
LV_MATH_ABS(proc->types.pointer.drag_sum.x) < LV_MATH_ABS(proc->types.pointer.drag_sum.y))) {
|
||||
act_y += proc->types.pointer.vect.y;
|
||||
}
|
||||
|
||||
lv_obj_set_pos(drag_obj, act_x, act_y);
|
||||
proc->types.pointer.drag_in_prog = 1;
|
||||
|
||||
|
@ -204,6 +204,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
|
||||
new_obj->drag = 0;
|
||||
new_obj->drag_throw = 0;
|
||||
new_obj->drag_parent = 0;
|
||||
new_obj->drag_dir = 0;
|
||||
new_obj->hidden = 0;
|
||||
new_obj->top = 0;
|
||||
new_obj->protect = LV_PROTECT_NONE;
|
||||
|
@ -525,7 +525,12 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
|
||||
|
||||
#if MASK_AREA_DEBUG
|
||||
static lv_color_t debug_color = LV_COLOR_RED;
|
||||
lv_draw_fill(&obj_ext_mask, &obj_ext_mask, debug_color, LV_OPA_50);
|
||||
LV_STYLE_CREATE(style_debug, &lv_style_plain);
|
||||
style_debug.body.main_color = debug_color;
|
||||
style_debug.body.grad_color = debug_color;
|
||||
style_debug.body.border.width = 2;
|
||||
style_debug.body.border.color.full = (debug_color.full + 0x13) * 9;
|
||||
lv_draw_rect(&obj_ext_mask, &obj_ext_mask, &style_debug, LV_OPA_50);
|
||||
debug_color.full *= 17;
|
||||
debug_color.full += 0xA1;
|
||||
#endif
|
||||
|
@ -26,10 +26,10 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src,
|
||||
const lv_style_t * style, lv_opa_t opa_scale);
|
||||
const lv_style_t * style, uint16_t angle, lv_opa_t opa_scale);
|
||||
|
||||
static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa,
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style);
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -52,7 +52,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
* @param opa_scale scale down all opacities by the factor
|
||||
*/
|
||||
void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style,
|
||||
lv_opa_t opa_scale)
|
||||
uint16_t angle, lv_opa_t opa_scale)
|
||||
{
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
@ -62,7 +62,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
}
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_img_draw_core(coords, mask, src, style, opa_scale);
|
||||
res = lv_img_draw_core(coords, mask, src, style, angle, opa_scale);
|
||||
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
@ -72,400 +72,12 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color)
|
||||
{
|
||||
lv_color_t p_color = LV_COLOR_BLACK;
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is too large (out of canvas)");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is too large (out of canvas)");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
memcpy(&p_color, &buf_u8[px], sizeof(lv_color_t));
|
||||
#if LV_COLOR_SIZE == 32
|
||||
p_color.ch.alpha = 0xFF; /*Only the color should be get so use a deafult alpha value*/
|
||||
#endif
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8, 16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
* so the possible real width are 4, 8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
* so the possible real width are 2, 4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
p_color.full = buf_u8[px];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
p_color = color;
|
||||
}
|
||||
return p_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is too large (out of canvas)");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is too large (out of canvas)");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
return buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
return px_opa ? LV_OPA_TRANSP : LV_OPA_COVER;
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
return opa_table[px_opa];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255};
|
||||
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
return opa_table[px_opa];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
return buf_u8[px];
|
||||
}
|
||||
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
memcpy(&buf_u8[px], &c, px_size);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
memcpy(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/
|
||||
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
* so the possible real width are 4, 8 ,12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = c.full;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = opa;
|
||||
}
|
||||
}
|
||||
|
||||
bool lv_img_get_px_rotated(lv_img_dsc_t * img, uint16_t angle, lv_color_t color, lv_point_t * point, lv_point_t * pivot, lv_color_t * res_color, lv_opa_t * res_opa)
|
||||
{
|
||||
|
||||
int32_t sinma = lv_trigo_sin(-angle);
|
||||
int32_t cosma = lv_trigo_sin(-angle + 90); /* cos */
|
||||
|
||||
/*Get the target point relative coordinates to the pivot*/
|
||||
int32_t xt = point->x - pivot->x;
|
||||
int32_t yt = point->y - pivot->y;
|
||||
|
||||
/*Get the source pixel from the upscaled image*/
|
||||
int32_t xs = ((cosma * xt - sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + pivot->x * 256;
|
||||
int32_t ys = ((sinma * xt + cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + pivot->y * 256;
|
||||
|
||||
/*Get the integer part of the source pixel*/
|
||||
int xs_int = xs >> 8;
|
||||
int ys_int = ys >> 8;
|
||||
|
||||
if(xs_int >= img->header.w) return false;
|
||||
else if(xs_int < 0) return false;
|
||||
|
||||
if(ys_int >= img->header.h) return false;
|
||||
else if(ys_int < 0) return false;
|
||||
|
||||
/*Get the fractional part of the source pixel*/
|
||||
int xs_fract = xs & 0xff;
|
||||
int ys_fract = ys & 0xff;
|
||||
|
||||
/* If the fractional < 0x70 mix the source pixel with the left/top pixel
|
||||
* If the fractional > 0x90 mix the source pixel with the right/bottom pixel
|
||||
* In the 0x70..0x90 range use the unchanged source pixel */
|
||||
|
||||
int xn; /*x neightboor*/
|
||||
lv_opa_t xr; /*x mix ratio*/
|
||||
if(xs_fract < 0x70) {
|
||||
xn = xs_int - 1;
|
||||
xr = xs_fract * 2;
|
||||
} else if(xs_fract > 0x90) {
|
||||
xn = xs_int + 1;
|
||||
xr = (0xFF - xs_fract) * 2;
|
||||
} else {
|
||||
xn = xs_int;
|
||||
xr = 0xFF;
|
||||
}
|
||||
|
||||
/*Handle under/overflow*/
|
||||
if(xn >= img->header.w) return false;
|
||||
else if(xn < 0) return false;
|
||||
|
||||
int yn; /*y neightboor*/
|
||||
lv_opa_t yr; /*y mix ratio*/
|
||||
if(ys_fract < 0x70) {
|
||||
yn = ys_int - 1;
|
||||
yr = ys_fract * 2;
|
||||
} else if(ys_fract > 0x90) {
|
||||
yn = ys_int + 1;
|
||||
yr = (0xFF - ys_fract) * 2;
|
||||
} else {
|
||||
yn = ys_int;
|
||||
yr = 0xFF;
|
||||
}
|
||||
|
||||
/*Handle under/overflow*/
|
||||
if(yn >= img->header.h) return false;
|
||||
else if(yn < 0) return false;
|
||||
|
||||
/*Get the mixture of the original source and the neightboor pixels in both directions*/
|
||||
/*Get the mixture of the original source and the neightboor pixels in both directions*/
|
||||
lv_color_t c_dest_int = lv_img_buf_get_px_color(img, xs_int, ys_int, color);
|
||||
|
||||
if(lv_img_color_format_is_chroma_keyed(img->header.cf)) {
|
||||
lv_color_t ct = LV_COLOR_TRANSP;
|
||||
if(c_dest_int.full == ct.full) return false;
|
||||
}
|
||||
|
||||
lv_color_t c_dest_xn = lv_img_buf_get_px_color(img, xn, ys_int, color);
|
||||
lv_color_t c_dest_yn = lv_img_buf_get_px_color(img, xs_int, yn, color);
|
||||
|
||||
lv_color_t x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr);
|
||||
lv_color_t y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr);
|
||||
*res_color = lv_color_mix(x_dest, y_dest, LV_OPA_50);
|
||||
|
||||
/*Get result pixel opacity*/
|
||||
if(lv_img_color_format_has_alpha(img->header.cf)) {
|
||||
lv_opa_t opa_int = lv_img_buf_get_px_alpha(img, xs_int, ys_int);
|
||||
lv_opa_t opa_xn = lv_img_buf_get_px_alpha(img, xn, ys_int);
|
||||
lv_opa_t opa_yn = lv_img_buf_get_px_alpha(img, xs_int, yn);
|
||||
lv_opa_t opa_x = (opa_int * xr + (opa_xn * (255 - xr))) >> 8;
|
||||
lv_opa_t opa_y = (opa_int * yr + (opa_yn * (255 - yr))) >> 8;
|
||||
|
||||
*res_opa = (opa_x + opa_y) / 2;
|
||||
if(*res_opa <= LV_OPA_MIN) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c)
|
||||
{
|
||||
if((dsc->header.cf == LV_IMG_CF_ALPHA_1BIT && id > 1) || (dsc->header.cf == LV_IMG_CF_ALPHA_2BIT && id > 3) ||
|
||||
(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT && id > 15) || (dsc->header.cf == LV_IMG_CF_ALPHA_8BIT)) {
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: invalid 'id'");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(c);
|
||||
uint8_t * buf = (uint8_t *)dsc->data;
|
||||
memcpy(&buf[id * sizeof(c32)], &c32, sizeof(c32));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pixel size of a color format in bits
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return the pixel size in bits
|
||||
*/
|
||||
uint8_t lv_img_color_format_get_px_size(lv_img_cf_t cf)
|
||||
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf)
|
||||
{
|
||||
uint8_t px_size = 0;
|
||||
|
||||
@ -494,7 +106,7 @@ uint8_t lv_img_color_format_get_px_size(lv_img_cf_t cf)
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: chroma keyed; false: not chroma keyed
|
||||
*/
|
||||
bool lv_img_color_format_is_chroma_keyed(lv_img_cf_t cf)
|
||||
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf)
|
||||
{
|
||||
bool is_chroma_keyed = false;
|
||||
|
||||
@ -520,7 +132,7 @@ bool lv_img_color_format_is_chroma_keyed(lv_img_cf_t cf)
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: has alpha channel; false: doesn't have alpha channel
|
||||
*/
|
||||
bool lv_img_color_format_has_alpha(lv_img_cf_t cf)
|
||||
bool lv_img_cf_has_alpha(lv_img_cf_t cf)
|
||||
{
|
||||
bool has_alpha = false;
|
||||
|
||||
@ -572,77 +184,54 @@ lv_img_src_t lv_img_src_get_type(const void * src)
|
||||
return img_src_type;
|
||||
}
|
||||
|
||||
lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
/* Allocate image descriptor */
|
||||
lv_img_dsc_t *dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
|
||||
if(dsc == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(dsc, 0, sizeof(lv_img_dsc_t));
|
||||
|
||||
/* Get image data size */
|
||||
dsc->data_size = lv_img_buf_get_img_size(w, h, cf);
|
||||
if(dsc->data_size == 0) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate raw buffer */
|
||||
dsc->data = lv_mem_alloc(dsc->data_size);
|
||||
if(dsc->data == NULL) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
memset((uint8_t *)dsc->data, 0, dsc->data_size);
|
||||
|
||||
/* Fill in header */
|
||||
dsc->header.always_zero = 0;
|
||||
dsc->header.w = w;
|
||||
dsc->header.h = h;
|
||||
dsc->header.cf = cf;
|
||||
return dsc;
|
||||
}
|
||||
|
||||
void lv_img_buf_free(lv_img_dsc_t *dsc)
|
||||
{
|
||||
if(dsc != NULL) {
|
||||
if(dsc->data != NULL)
|
||||
lv_mem_free(dsc->data);
|
||||
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR: return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA: return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h);
|
||||
case LV_IMG_CF_ALPHA_1BIT: return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_2BIT: return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_4BIT: return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_8BIT: return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_1BIT: return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_2BIT: return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_4BIT: return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_8BIT: return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src,
|
||||
const lv_style_t * style, lv_opa_t opa_scale)
|
||||
const lv_style_t * style, uint16_t angle, lv_opa_t opa_scale)
|
||||
{
|
||||
lv_area_t map_area_rot;
|
||||
lv_area_copy(&map_area_rot, coords);
|
||||
if(angle) {
|
||||
/*Get the exact area which is required to show the rotated image*/
|
||||
lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1;
|
||||
lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1;
|
||||
|
||||
lv_area_t norm;
|
||||
norm.x1 = + coords->x1 - pivot_x;
|
||||
norm.y1 = + coords->y1 - pivot_y;
|
||||
norm.x2 = + coords->x2 - pivot_x;
|
||||
norm.y2 = + coords->y2 - pivot_y;
|
||||
|
||||
int16_t sinma = lv_trigo_sin(-angle);
|
||||
int16_t cosma = lv_trigo_sin(-angle + 90);
|
||||
|
||||
lv_point_t lt;
|
||||
lv_point_t rt;
|
||||
lv_point_t lb;
|
||||
lv_point_t rb;
|
||||
lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x;
|
||||
lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y;
|
||||
|
||||
rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x;
|
||||
rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y;
|
||||
|
||||
lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x;
|
||||
lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y;
|
||||
|
||||
rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x;
|
||||
rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y;
|
||||
|
||||
map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x);
|
||||
map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x);
|
||||
map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y);
|
||||
map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y);
|
||||
}
|
||||
|
||||
lv_area_t mask_com; /*Common area of mask and coords*/
|
||||
bool union_ok;
|
||||
union_ok = lv_area_intersect(&mask_com, mask, coords);
|
||||
union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot);
|
||||
if(union_ok == false) {
|
||||
return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn
|
||||
successfully.*/
|
||||
@ -655,18 +244,18 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
|
||||
if(cdsc == NULL) return LV_RES_INV;
|
||||
|
||||
bool chroma_keyed = lv_img_color_format_is_chroma_keyed(cdsc->dec_dsc.header.cf);
|
||||
bool alpha_byte = lv_img_color_format_has_alpha(cdsc->dec_dsc.header.cf);
|
||||
bool chroma_keyed = lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf);
|
||||
bool alpha_byte = lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf);
|
||||
|
||||
if(cdsc->dec_dsc.error_msg != NULL) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_rect(coords, &mask_com, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, &mask_com, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
}
|
||||
/* The decoder open could open the image and gave the entire uncompressed image.
|
||||
* Just draw it!*/
|
||||
else if(cdsc->dec_dsc.img_data) {
|
||||
lv_draw_map(coords, mask, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style);
|
||||
lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle);
|
||||
}
|
||||
/* The whole uncompressed image is not available. Try to read it line-by-line*/
|
||||
else {
|
||||
@ -689,7 +278,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
lv_draw_buf_release(buf);
|
||||
return LV_RES_INV;
|
||||
}
|
||||
lv_draw_map(&line, mask, buf, opa, chroma_keyed, alpha_byte, style);
|
||||
lv_draw_map(&line, &mask_com, buf, opa, chroma_keyed, alpha_byte, style, 0);
|
||||
line.y1++;
|
||||
line.y2++;
|
||||
y++;
|
||||
@ -711,20 +300,15 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
* @param style style of the image
|
||||
*/
|
||||
static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa,
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style)
|
||||
bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle)
|
||||
{
|
||||
|
||||
if(opa < LV_OPA_MIN) return;
|
||||
if(opa > LV_OPA_MAX) opa = LV_OPA_COVER;
|
||||
|
||||
/* Use the clip area as draw area*/
|
||||
lv_area_t draw_area;
|
||||
bool union_ok;
|
||||
|
||||
/* Get clipped map area which is the real draw area.
|
||||
* It is always the same or inside `map_area` */
|
||||
union_ok = lv_area_intersect(&draw_area, map_area, clip_area);
|
||||
|
||||
/*If there are common part of the three area then draw to the vdb*/
|
||||
if(union_ok == false) return;
|
||||
lv_area_copy(&draw_area, clip_area);
|
||||
|
||||
lv_disp_t * disp = lv_refr_get_disp_refreshing();
|
||||
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
|
||||
@ -740,7 +324,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
uint8_t other_mask_cnt = lv_draw_mask_get_cnt();
|
||||
|
||||
/*The simplest case just copy the pixels into the VDB*/
|
||||
if(other_mask_cnt == 0 && chroma_key == false && alpha_byte == false && opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) {
|
||||
if(angle == 0 && other_mask_cnt == 0 && chroma_key == false && alpha_byte == false && opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) {
|
||||
lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, style->image.blend_mode);
|
||||
}
|
||||
/*In the other cases every pixel need to be checked one-by-one*/
|
||||
@ -748,15 +332,14 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
/*The pixel size in byte is different if an alpha byte is added too*/
|
||||
uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t);
|
||||
|
||||
|
||||
|
||||
/*Build the image and a mask line-by-line*/
|
||||
uint32_t mask_buf_size = lv_area_get_size(&draw_area) > LV_HOR_RES_MAX ? lv_area_get_size(&draw_area) : LV_HOR_RES_MAX;
|
||||
uint32_t mask_buf_size = lv_area_get_size(&draw_area) > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : lv_area_get_size(&draw_area);
|
||||
lv_color_t * map2 = lv_draw_buf_get(mask_buf_size * sizeof(lv_color_t));
|
||||
lv_opa_t * mask_buf = lv_draw_buf_get(mask_buf_size);
|
||||
|
||||
/*Go to the first displayed pixel of the map*/
|
||||
lv_coord_t map_w = lv_area_get_width(map_area);
|
||||
lv_coord_t map_h = lv_area_get_height(map_area);
|
||||
const uint8_t * map_buf_tmp = map_p;
|
||||
map_buf_tmp += map_w * (draw_area.y1 - (map_area->y1 - disp_area->y1)) * px_size_byte;
|
||||
map_buf_tmp += (draw_area.x1 - (map_area->x1 - disp_area->x1)) * px_size_byte;
|
||||
@ -779,8 +362,16 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
memset(mask_buf, 0xFF, mask_buf_size);
|
||||
}
|
||||
|
||||
|
||||
lv_img_rotate_dsc_t rotate_dsc = {};
|
||||
if(angle) {
|
||||
lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR;
|
||||
if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
|
||||
lv_img_buf_rotate_init(&rotate_dsc, angle, map_p, map_w, map_h, cf, map_w/2, map_h / 2, LV_COLOR_BLACK);
|
||||
}
|
||||
lv_draw_mask_res_t mask_res;
|
||||
mask_res = (alpha_byte || chroma_key) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
lv_coord_t x;
|
||||
lv_coord_t y;
|
||||
for(y = 0; y < lv_area_get_height(&draw_area); y++) {
|
||||
@ -788,26 +379,41 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
px_i_start = px_i;
|
||||
|
||||
for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) {
|
||||
if(alpha_byte) {
|
||||
lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
mask_buf[px_i] = px_opa;
|
||||
if(px_opa < LV_OPA_MIN) continue;
|
||||
} else {
|
||||
mask_buf[px_i] = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
if(angle == 0) {
|
||||
if(alpha_byte) {
|
||||
lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
mask_buf[px_i] = px_opa;
|
||||
if(px_opa < LV_OPA_MIN) continue;
|
||||
} else {
|
||||
mask_buf[px_i] = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
#if LV_COLOR_DEPTH == 8
|
||||
c.full = map_px[0];
|
||||
c.full = map_px[0];
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
c.full = map_px[0] + (map_px[1] << 8);
|
||||
c.full = map_px[0] + (map_px[1] << 8);
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
c.full = *((uint32_t*)map_px);
|
||||
c.full = *((uint32_t*)map_px);
|
||||
#endif
|
||||
|
||||
if (chroma_key) {
|
||||
if(c.full == chroma_keyed_color.full) {
|
||||
if (chroma_key) {
|
||||
if(c.full == chroma_keyed_color.full) {
|
||||
mask_buf[px_i] = LV_OPA_TRANSP;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*Rotate*/
|
||||
bool ret;
|
||||
lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1;
|
||||
lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1;
|
||||
ret = lv_img_buf_get_px_rotated(&rotate_dsc, rot_x, rot_y);
|
||||
if(ret == false) {
|
||||
mask_buf[px_i] = LV_OPA_TRANSP;
|
||||
continue;
|
||||
} else {
|
||||
mask_buf[px_i] = rotate_dsc.res_opa;
|
||||
c.full = rotate_dsc.res_color.full;
|
||||
}
|
||||
}
|
||||
|
||||
@ -840,7 +446,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
blend_area.y2 = blend_area.y1;
|
||||
|
||||
px_i = 0;
|
||||
mask_res = (alpha_byte || chroma_key) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
|
||||
|
||||
/*Prepare the `mask_buf`if there are other masks*/
|
||||
if(other_mask_cnt) {
|
||||
@ -857,6 +463,4 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
lv_draw_buf_release(mask_buf);
|
||||
lv_draw_buf_release(map2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ extern "C" {
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "lv_img_decoder.h"
|
||||
#include "lv_img_buf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@ -24,26 +25,11 @@ extern "C" {
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
|
||||
|
||||
/*+ 1: to be sure no fractional row*/
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
|
||||
|
||||
/*4 * X: for palette*/
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@ -57,7 +43,7 @@ extern "C" {
|
||||
* @param opa_scale scale down all opacities by the factor
|
||||
*/
|
||||
void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style,
|
||||
lv_opa_t opa_scale);
|
||||
uint16_t angle, lv_opa_t opa_scale);
|
||||
|
||||
/**
|
||||
* Get the type of an image source
|
||||
@ -69,105 +55,26 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
*/
|
||||
lv_img_src_t lv_img_src_get_type(const void * src);
|
||||
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color);
|
||||
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
|
||||
bool lv_img_get_px_rotated(lv_img_dsc_t * img, uint16_t angle, lv_color_t color, lv_point_t * point, lv_point_t * pivot, lv_color_t * res_color, lv_opa_t * res_opa);
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Get the pixel size of a color format in bits
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return the pixel size in bits
|
||||
*/
|
||||
uint8_t lv_img_color_format_get_px_size(lv_img_cf_t cf);
|
||||
uint8_t lv_img_cf_get_px_size(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Check if a color format is chroma keyed or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: chroma keyed; false: not chroma keyed
|
||||
*/
|
||||
bool lv_img_color_format_is_chroma_keyed(lv_img_cf_t cf);
|
||||
bool lv_img_cf_is_chroma_keyed(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Check if a color format has alpha channel or not
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return true: has alpha channel; false: doesn't have alpha channel
|
||||
*/
|
||||
bool lv_img_color_format_has_alpha(lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t *dsc);
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
bool lv_img_cf_has_alpha(lv_img_cf_t cf);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
602
src/lv_draw/lv_img_buf.c
Normal file
602
src/lv_draw/lv_img_buf.c
Normal file
@ -0,0 +1,602 @@
|
||||
/**
|
||||
* @file lv_img_buf.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stddef.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color)
|
||||
{
|
||||
lv_color_t p_color = LV_COLOR_BLACK;
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is too large (out of canvas)");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is too large (out of canvas)");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED ||
|
||||
dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
memcpy(&p_color, &buf_u8[px], sizeof(lv_color_t));
|
||||
#if LV_COLOR_SIZE == 32
|
||||
p_color.ch.alpha = 0xFF; /*Only the color should be get so use a deafult alpha value*/
|
||||
#endif
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += 4 * 2;
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8, 16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
p_color.full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += 4 * 4;
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
* so the possible real width are 4, 8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
p_color.full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += 4 * 16;
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
* so the possible real width are 2, 4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
p_color.full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += 4 * 256;
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
p_color.full = buf_u8[px];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT ||
|
||||
dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
p_color = color;
|
||||
}
|
||||
return p_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
if(x >= dsc->header.w) {
|
||||
x = dsc->header.w - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is too large (out of canvas)");
|
||||
} else if(x < 0) {
|
||||
x = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: x is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
if(y >= dsc->header.h) {
|
||||
y = dsc->header.h - 1;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is too large (out of canvas)");
|
||||
} else if(y < 0) {
|
||||
y = 0;
|
||||
LV_LOG_WARN("lv_canvas_get_px: y is < 0 (out of canvas)");
|
||||
}
|
||||
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
return buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit);
|
||||
return px_opa ? LV_OPA_TRANSP : LV_OPA_COVER;
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/
|
||||
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit);
|
||||
return opa_table[px_opa];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/
|
||||
68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255};
|
||||
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
uint8_t px_opa = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit);
|
||||
return opa_table[px_opa];
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
return buf_u8[px];
|
||||
}
|
||||
|
||||
return LV_OPA_COVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
memcpy(&buf_u8[px], &c, px_size);
|
||||
} else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
memcpy(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/
|
||||
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned
|
||||
* so the possible real width are 4, 8 ,12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = c.full;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa)
|
||||
{
|
||||
uint8_t * buf_u8 = (uint8_t *)dsc->data;
|
||||
|
||||
if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3;
|
||||
uint32_t px = dsc->header.w * y * px_size + x * px_size;
|
||||
buf_u8[px + px_size - 1] = opa;
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) {
|
||||
opa = opa >> 7; /*opa -> [0,1]*/
|
||||
uint8_t bit = x & 0x7;
|
||||
x = x >> 3;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 8 ,16, 24 ...*/
|
||||
uint32_t px = ((dsc->header.w + 7) >> 3) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x1) << (7 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) {
|
||||
opa = opa >> 6; /*opa -> [0,3]*/
|
||||
uint8_t bit = (x & 0x3) * 2;
|
||||
x = x >> 2;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 4 ,8, 12 ...*/
|
||||
uint32_t px = ((dsc->header.w + 3) >> 2) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0x3) << (6 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) {
|
||||
opa = opa >> 4; /*opa -> [0,15]*/
|
||||
uint8_t bit = (x & 0x1) * 4;
|
||||
x = x >> 1;
|
||||
|
||||
/* Get the current pixel.
|
||||
* dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned
|
||||
* so the possible real width are 2 ,4, 6 ...*/
|
||||
uint32_t px = ((dsc->header.w + 1) >> 1) * y + x;
|
||||
buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit));
|
||||
buf_u8[px] = buf_u8[px] | ((opa & 0xF) << (4 - bit));
|
||||
} else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) {
|
||||
uint32_t px = dsc->header.w * y + x;
|
||||
buf_u8[px] = opa;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h,
|
||||
lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color)
|
||||
{
|
||||
memset(dsc, 0x00, sizeof(lv_img_rotate_dsc_t));
|
||||
|
||||
dsc->angle = angle;
|
||||
dsc->src = src;
|
||||
dsc->src_w = src_w;
|
||||
dsc->src_h = src_h;
|
||||
dsc->cf = cf;
|
||||
dsc->color = color;
|
||||
dsc->pivot_x = pivot_x;
|
||||
dsc->pivot_y = pivot_y;
|
||||
dsc->pivot_x_256 = pivot_x * 256;
|
||||
dsc->pivot_y_256 = pivot_y * 256;
|
||||
dsc->sinma = lv_trigo_sin(-angle);
|
||||
dsc->cosma = lv_trigo_sin(-angle + 90);
|
||||
|
||||
dsc->chroma_keyed = lv_img_cf_is_chroma_keyed(cf) ? 1 : 0;
|
||||
dsc->has_alpha = lv_img_cf_has_alpha(cf) ? 1 : 0;
|
||||
if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
|
||||
dsc->native_color = 1;
|
||||
}
|
||||
|
||||
dsc->img_dsc.data = src;
|
||||
dsc->img_dsc.header.always_zero = 0;
|
||||
dsc->img_dsc.header.cf = cf;
|
||||
dsc->img_dsc.header.w = src_w;
|
||||
dsc->img_dsc.header.h = src_h;
|
||||
|
||||
dsc->res_opa = LV_OPA_COVER;
|
||||
}
|
||||
|
||||
bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
const uint8_t * src_u8 = dsc->src;
|
||||
|
||||
/*Get the target point relative coordinates to the pivot*/
|
||||
int32_t xt = x - dsc->pivot_x;
|
||||
int32_t yt = y - dsc->pivot_y;
|
||||
|
||||
/*Get the source pixel from the upscaled image*/
|
||||
int32_t xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_x_256;
|
||||
int32_t ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_y_256;
|
||||
|
||||
/*Get the integer part of the source pixel*/
|
||||
int xs_int = xs >> 8;
|
||||
int ys_int = ys >> 8;
|
||||
|
||||
if(xs_int >= dsc->src_w) return false;
|
||||
else if(xs_int < 0) return false;
|
||||
|
||||
if(ys_int >= dsc->src_h) return false;
|
||||
else if(ys_int < 0) return false;
|
||||
|
||||
/*Get the fractional part of the source pixel*/
|
||||
int xs_fract = xs & 0xff;
|
||||
int ys_fract = ys & 0xff;
|
||||
|
||||
/* If the fractional < 0x70 mix the source pixel with the left/top pixel
|
||||
* If the fractional > 0x90 mix the source pixel with the right/bottom pixel
|
||||
* In the 0x70..0x90 range use the unchanged source pixel */
|
||||
|
||||
lv_color_t c_dest_int;
|
||||
lv_opa_t opa_dest_int;
|
||||
|
||||
uint8_t px_size;
|
||||
uint32_t px;
|
||||
if(dsc->native_color) {
|
||||
if(dsc->has_alpha == 0) {
|
||||
px_size = LV_COLOR_SIZE >> 3;
|
||||
|
||||
px = dsc->src_w * ys_int * px_size + xs_int * px_size;
|
||||
memcpy(&c_dest_int, &src_u8[px], px_size);
|
||||
} else {
|
||||
px_size = LV_IMG_PX_SIZE_ALPHA_BYTE;
|
||||
px = dsc->src_w * ys_int * px_size + xs_int * px_size;
|
||||
memcpy(&c_dest_int, &src_u8[px], px_size - 1);
|
||||
opa_dest_int = src_u8[px + px_size - 1];
|
||||
}
|
||||
} else {
|
||||
c_dest_int = lv_img_buf_get_px_color(&dsc->img_dsc, x, y, dsc->color);
|
||||
opa_dest_int = lv_img_buf_get_px_alpha(&dsc->img_dsc, x, y);
|
||||
}
|
||||
|
||||
|
||||
if(dsc->chroma_keyed) {
|
||||
lv_color_t ct = LV_COLOR_TRANSP;
|
||||
if(c_dest_int.full == ct.full) return false;
|
||||
}
|
||||
|
||||
/*Get the mixture of the original source and the neightboor pixels in both directions*/
|
||||
lv_color_t c_x_dest;
|
||||
lv_color_t c_y_dest;
|
||||
lv_opa_t opa_x_dest;
|
||||
lv_opa_t opa_y_dest;
|
||||
|
||||
int32_t xn; /*x neightboor*/
|
||||
lv_opa_t xr; /*x mix ratio*/
|
||||
lv_color_t c_dest_xn;
|
||||
lv_opa_t opa_dest_xn;
|
||||
|
||||
if(xs_fract < 0x70) {
|
||||
xn = xs_int - 1;
|
||||
if(xn < 0) return false;
|
||||
|
||||
xr = xs_fract + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_xn, &src_u8[px - px_size], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_xn = src_u8[px - 1];
|
||||
} else {
|
||||
c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, y, dsc->color);
|
||||
if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, y);
|
||||
}
|
||||
|
||||
c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr);
|
||||
if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8;
|
||||
|
||||
} else if(xs_fract > 0x90) {
|
||||
xn = xs_int + 1;
|
||||
if(xn >= dsc->src_w) return false;
|
||||
|
||||
xr = (0xFF - xs_fract) + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_xn, &src_u8[px + px_size], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_xn = src_u8[px + 2 * px_size - 1];
|
||||
} else {
|
||||
c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, y, dsc->color);
|
||||
if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, y);
|
||||
}
|
||||
|
||||
c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr);
|
||||
if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8;
|
||||
|
||||
} else {
|
||||
c_x_dest.full = c_dest_int.full;
|
||||
opa_x_dest = opa_dest_int;
|
||||
}
|
||||
|
||||
|
||||
int32_t yn; /*x neightboor*/
|
||||
lv_opa_t yr; /*x mix ratio*/
|
||||
lv_color_t c_dest_yn;
|
||||
lv_opa_t opa_dest_yn;
|
||||
|
||||
if(ys_fract < 0x70) {
|
||||
yn = ys_int - 1;
|
||||
if(yn < 0) return false;
|
||||
|
||||
lv_opa_t yr; /*y mix ratio*/
|
||||
yr = ys_fract + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_yn, &src_u8[px - px_size * dsc->src_w], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_yn = src_u8[px - px_size * dsc->src_w - 1];
|
||||
} else {
|
||||
c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, yn, y, dsc->color);
|
||||
if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, yn, y);
|
||||
}
|
||||
|
||||
c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr);
|
||||
if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8;
|
||||
|
||||
} else if(ys_fract > 0x90) {
|
||||
yn = ys_int + 1;
|
||||
if(yn >= dsc->src_h) return false;
|
||||
|
||||
yr = (0xFF - ys_fract) + 0x80;
|
||||
|
||||
if(dsc->native_color) {
|
||||
memcpy(&c_dest_yn, &src_u8[px + px_size * dsc->src_w], sizeof(lv_color_t));
|
||||
if(dsc->has_alpha) opa_dest_yn = src_u8[px + px_size * dsc->src_w + 2 * px_size - 1];
|
||||
} else {
|
||||
c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, yn, y, dsc->color);
|
||||
if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, yn, y);
|
||||
}
|
||||
|
||||
c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr);
|
||||
if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8;
|
||||
} else {
|
||||
c_y_dest.full = c_dest_int.full;
|
||||
opa_y_dest = opa_dest_int;
|
||||
}
|
||||
|
||||
dsc->res_color = lv_color_mix(c_x_dest, c_y_dest, LV_OPA_50);
|
||||
if(dsc->has_alpha) dsc->res_opa = (opa_x_dest + opa_y_dest) >> 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c)
|
||||
{
|
||||
if((dsc->header.cf == LV_IMG_CF_ALPHA_1BIT && id > 1) || (dsc->header.cf == LV_IMG_CF_ALPHA_2BIT && id > 3) ||
|
||||
(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT && id > 15) || (dsc->header.cf == LV_IMG_CF_ALPHA_8BIT)) {
|
||||
LV_LOG_WARN("lv_img_buf_set_px_alpha: invalid 'id'");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(c);
|
||||
uint8_t * buf = (uint8_t *)dsc->data;
|
||||
memcpy(&buf[id * sizeof(c32)], &c32, sizeof(c32));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate an image buffer in RAM
|
||||
* @param w width of image
|
||||
* @param h height of image
|
||||
* @param cf a color format (`LV_IMG_CF_...`)
|
||||
* @return an allocated image, or NULL on failure
|
||||
*/
|
||||
lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
/* Allocate image descriptor */
|
||||
lv_img_dsc_t *dsc = lv_mem_alloc(sizeof(lv_img_dsc_t));
|
||||
if(dsc == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(dsc, 0, sizeof(lv_img_dsc_t));
|
||||
|
||||
/* Get image data size */
|
||||
dsc->data_size = lv_img_buf_get_img_size(w, h, cf);
|
||||
if(dsc->data_size == 0) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate raw buffer */
|
||||
dsc->data = lv_mem_alloc(dsc->data_size);
|
||||
if(dsc->data == NULL) {
|
||||
lv_mem_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
memset((uint8_t *)dsc->data, 0, dsc->data_size);
|
||||
|
||||
/* Fill in header */
|
||||
dsc->header.always_zero = 0;
|
||||
dsc->header.w = w;
|
||||
dsc->header.h = h;
|
||||
dsc->header.cf = cf;
|
||||
return dsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t *dsc)
|
||||
{
|
||||
if(dsc != NULL) {
|
||||
if(dsc->data != NULL)
|
||||
lv_mem_free(dsc->data);
|
||||
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR: return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA: return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h);
|
||||
case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h);
|
||||
case LV_IMG_CF_ALPHA_1BIT: return LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_2BIT: return LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_4BIT: return LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h);
|
||||
case LV_IMG_CF_ALPHA_8BIT: return LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_1BIT: return LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_2BIT: return LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_4BIT: return LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h);
|
||||
case LV_IMG_CF_INDEXED_8BIT: return LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
241
src/lv_draw/lv_img_buf.h
Normal file
241
src/lv_draw/lv_img_buf.h
Normal file
@ -0,0 +1,241 @@
|
||||
/**
|
||||
* @file lv_img_buf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_IMG_BUF_H
|
||||
#define LV_IMG_BUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include <stdbool.h>
|
||||
#include "../lv_misc/lv_color.h"
|
||||
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*If image pixels contains alpha we need to know how much byte is a pixel*/
|
||||
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 2
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 3
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 4
|
||||
#endif
|
||||
|
||||
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
|
||||
#define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
|
||||
|
||||
/*+ 1: to be sure no fractional row*/
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
|
||||
#define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
|
||||
|
||||
/*4 * X: for palette*/
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
|
||||
#define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/*Image color format*/
|
||||
enum {
|
||||
LV_IMG_CF_UNKNOWN = 0,
|
||||
|
||||
LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/
|
||||
LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder
|
||||
function*/
|
||||
LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs
|
||||
custom decoder function*/
|
||||
|
||||
LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/
|
||||
LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/
|
||||
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels
|
||||
will be transparent*/
|
||||
|
||||
LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (always chroma keyed)*/
|
||||
|
||||
LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/
|
||||
LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/
|
||||
|
||||
LV_IMG_CF_RESERVED_15, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_16, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_17, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_18, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_19, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_20, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_21, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_22, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_23, /**< Reserved for further use. */
|
||||
|
||||
LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format. */
|
||||
};
|
||||
typedef uint8_t lv_img_cf_t;
|
||||
|
||||
|
||||
/**
|
||||
* LittlevGL image header
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
|
||||
/* The first 8 bit is very important to distinguish the different source types.
|
||||
* For more info see `lv_img_get_src_type()` in lv_img.c */
|
||||
uint32_t cf : 5; /* Color format: See `lv_img_color_format_t`*/
|
||||
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
|
||||
non-printable character*/
|
||||
|
||||
uint32_t reserved : 2; /*Reserved to be used later*/
|
||||
|
||||
uint32_t w : 11; /*Width of the image map*/
|
||||
uint32_t h : 11; /*Height of the image map*/
|
||||
} lv_img_header_t;
|
||||
|
||||
|
||||
/** Image header it is compatible with
|
||||
* the result from image converter utility*/
|
||||
typedef struct
|
||||
{
|
||||
lv_img_header_t header;
|
||||
uint32_t data_size;
|
||||
const uint8_t * data;
|
||||
} lv_img_dsc_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
lv_color_t res_color;
|
||||
lv_opa_t res_opa;
|
||||
|
||||
const void * src;
|
||||
lv_coord_t src_w;
|
||||
lv_coord_t src_h;
|
||||
lv_coord_t pivot_x;
|
||||
lv_coord_t pivot_y;
|
||||
int32_t pivot_x_256;
|
||||
int32_t pivot_y_256;
|
||||
lv_img_dsc_t img_dsc;
|
||||
int32_t sinma;
|
||||
int32_t cosma;
|
||||
int16_t angle;
|
||||
lv_color_t color;
|
||||
lv_img_cf_t cf;
|
||||
|
||||
uint8_t chroma_keyed :1;
|
||||
uint8_t has_alpha :1;
|
||||
uint8_t native_color :1;
|
||||
|
||||
}lv_img_rotate_dsc_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the color of an image's pixel
|
||||
* @param dsc an image descriptor
|
||||
* @param x x coordinate of the point to get
|
||||
* @param y x coordinate of the point to get
|
||||
* @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
|
||||
* Not used in other cases.
|
||||
* @return color of the point
|
||||
*/
|
||||
lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color);
|
||||
|
||||
|
||||
/**
|
||||
* Get the alpha value of an image's pixel
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @return alpha value of the point
|
||||
*/
|
||||
lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
|
||||
void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h,
|
||||
lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color);
|
||||
|
||||
bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
|
||||
|
||||
/**
|
||||
* Set the color of a pixel of an image. The alpha channel won't be affected.
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param c color of the point
|
||||
*/
|
||||
void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Set the alpha value of a pixel of an image. The color won't be affected
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param x x coordinate of the point to set
|
||||
* @param y x coordinate of the point to set
|
||||
* @param opa the desired opacity
|
||||
*/
|
||||
void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa);
|
||||
|
||||
/**
|
||||
* Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
|
||||
* @param dsc pointer to an image descriptor
|
||||
* @param id the palette color to set:
|
||||
* - for `LV_IMG_CF_INDEXED1`: 0..1
|
||||
* - for `LV_IMG_CF_INDEXED2`: 0..3
|
||||
* - for `LV_IMG_CF_INDEXED4`: 0..15
|
||||
* - for `LV_IMG_CF_INDEXED8`: 0..255
|
||||
* @param c the color to set
|
||||
*/
|
||||
void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c);
|
||||
|
||||
/**
|
||||
* Free an allocated image buffer
|
||||
* @param dsc image buffer to free
|
||||
*/
|
||||
void lv_img_buf_free(lv_img_dsc_t *dsc);
|
||||
|
||||
/**
|
||||
* Get the memory consumption of a raw bitmap, given color format and dimensions.
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param cf color format
|
||||
* @return size in bytes
|
||||
*/
|
||||
uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_IMG_BUF_H*/
|
@ -374,7 +374,7 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder
|
||||
cf == LV_IMG_CF_INDEXED_8BIT) {
|
||||
|
||||
#if LV_IMG_CF_INDEXED
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(cf);
|
||||
uint8_t px_size = lv_img_cf_get_px_size(cf);
|
||||
uint32_t palette_size = 1 << px_size;
|
||||
|
||||
/*Allocate the palette*/
|
||||
@ -527,7 +527,7 @@ static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * d
|
||||
#if LV_USE_FILESYSTEM
|
||||
lv_img_decoder_built_in_data_t * user_data = dsc->user_data;
|
||||
lv_fs_res_t res;
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf);
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
|
||||
uint32_t pos = ((y * dsc->header.w + x) * px_size) >> 3;
|
||||
pos += 4; /*Skip the header*/
|
||||
@ -579,7 +579,7 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l
|
||||
}
|
||||
|
||||
const lv_opa_t * opa_table = NULL;
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf);
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
@ -665,7 +665,7 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc,
|
||||
{
|
||||
|
||||
#if LV_IMG_CF_INDEXED
|
||||
uint8_t px_size = lv_img_color_format_get_px_size(dsc->header.cf);
|
||||
uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf);
|
||||
uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/
|
||||
|
||||
lv_coord_t w = 0;
|
||||
|
@ -20,6 +20,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lv_img_buf.h"
|
||||
#include "../lv_misc/lv_fs.h"
|
||||
#include "../lv_misc/lv_types.h"
|
||||
#include "../lv_misc/lv_area.h"
|
||||
@ -28,14 +29,6 @@ extern "C" {
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*If image pixels contains alpha we need to know how much byte is a pixel*/
|
||||
#if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 2
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 3
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
#define LV_IMG_PX_SIZE_ALPHA_BYTE 4
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@ -51,78 +44,6 @@ enum {
|
||||
};
|
||||
|
||||
typedef uint8_t lv_img_src_t;
|
||||
/**
|
||||
* LittlevGL image header
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
|
||||
/* The first 8 bit is very important to distinguish the different source types.
|
||||
* For more info see `lv_img_get_src_type()` in lv_img.c */
|
||||
uint32_t cf : 5; /* Color format: See `lv_img_color_format_t`*/
|
||||
uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
|
||||
non-printable character*/
|
||||
|
||||
uint32_t reserved : 2; /*Reserved to be used later*/
|
||||
|
||||
uint32_t w : 11; /*Width of the image map*/
|
||||
uint32_t h : 11; /*Height of the image map*/
|
||||
} lv_img_header_t;
|
||||
|
||||
/*Image color format*/
|
||||
enum {
|
||||
LV_IMG_CF_UNKNOWN = 0,
|
||||
|
||||
LV_IMG_CF_RAW, /**< Contains the file as it is. Needs custom decoder function*/
|
||||
LV_IMG_CF_RAW_ALPHA, /**< Contains the file as it is. The image has alpha. Needs custom decoder
|
||||
function*/
|
||||
LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs
|
||||
custom decoder function*/
|
||||
|
||||
LV_IMG_CF_TRUE_COLOR, /**< Color format and depth should match with LV_COLOR settings*/
|
||||
LV_IMG_CF_TRUE_COLOR_ALPHA, /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/
|
||||
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels
|
||||
will be transparent*/
|
||||
|
||||
LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (always chroma keyed)*/
|
||||
LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (always chroma keyed)*/
|
||||
|
||||
LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/
|
||||
LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/
|
||||
LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/
|
||||
|
||||
LV_IMG_CF_RESERVED_15, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_16, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_17, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_18, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_19, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_20, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_21, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_22, /**< Reserved for further use. */
|
||||
LV_IMG_CF_RESERVED_23, /**< Reserved for further use. */
|
||||
|
||||
LV_IMG_CF_USER_ENCODED_0, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_1, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_2, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_3, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_4, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_5, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_6, /**< User holder encoding format. */
|
||||
LV_IMG_CF_USER_ENCODED_7, /**< User holder encoding format. */
|
||||
};
|
||||
typedef uint8_t lv_img_cf_t;
|
||||
|
||||
/** Image header it is compatible with
|
||||
* the result from image converter utility*/
|
||||
typedef struct
|
||||
{
|
||||
lv_img_header_t header;
|
||||
uint32_t data_size;
|
||||
const uint8_t * data;
|
||||
} lv_img_dsc_t;
|
||||
|
||||
/* Decoder function definitions */
|
||||
|
||||
|
@ -143,7 +143,7 @@ void lv_canvas_set_buffer(lv_obj_t * canvas, void * buf, lv_coord_t w, lv_coord_
|
||||
ext->dsc.header.w = w;
|
||||
ext->dsc.header.h = h;
|
||||
ext->dsc.data = buf;
|
||||
ext->dsc.data_size = (lv_img_color_format_get_px_size(cf) * w * h) / 8;
|
||||
ext->dsc.data_size = (lv_img_cf_get_px_size(cf) * w * h) / 8;
|
||||
|
||||
lv_img_set_src(canvas, &ext->dsc);
|
||||
}
|
||||
@ -282,7 +282,7 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, l
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t px_size = lv_img_color_format_get_px_size(ext->dsc.header.cf) >> 3;
|
||||
uint32_t px_size = lv_img_cf_get_px_size(ext->dsc.header.cf) >> 3;
|
||||
uint32_t px = ext->dsc.header.w * y * px_size + x * px_size;
|
||||
uint8_t * to_copy8 = (uint8_t *)to_copy;
|
||||
lv_coord_t i;
|
||||
@ -321,36 +321,30 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
lv_point_t point_p;
|
||||
|
||||
lv_point_t pivot_p;
|
||||
pivot_p.x = pivot_x;
|
||||
pivot_p.y = pivot_y;
|
||||
|
||||
lv_color_t color_res;
|
||||
lv_opa_t opa_res;
|
||||
|
||||
bool ret;
|
||||
|
||||
lv_img_rotate_dsc_t dsc;
|
||||
lv_img_buf_rotate_init(&dsc, angle, img->data, img->header.w, img->header.h, img->header.cf, pivot_x, pivot_y, style->image.color);
|
||||
|
||||
for(x = -offset_x; x < dest_width - offset_x; x++) {
|
||||
for(y = -offset_y; y < dest_height - offset_y; y++) {
|
||||
point_p.x = x;
|
||||
point_p.y = y;
|
||||
|
||||
ret = lv_img_get_px_rotated(img, angle, style->image.color, &point_p, &pivot_p, &color_res, &opa_res);
|
||||
ret = lv_img_buf_get_px_rotated(&dsc, x, y);
|
||||
|
||||
if(ret == false) continue;
|
||||
|
||||
if(x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height) {
|
||||
/*If the image has no alpha channel just simple set the result color on the canvas*/
|
||||
if(lv_img_color_format_has_alpha(img->header.cf) == false) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, color_res);
|
||||
if(lv_img_cf_has_alpha(img->header.cf) == false) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color);
|
||||
} else {
|
||||
lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style->image.color);
|
||||
|
||||
/*If the canvas has no alpha but the image has mix the image's color with
|
||||
* canvas*/
|
||||
if(lv_img_color_format_has_alpha(ext_dst->dsc.header.cf) == false) {
|
||||
if(opa_res < LV_OPA_MAX) color_res = lv_color_mix(color_res, bg_color, opa_res);
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, color_res);
|
||||
if(lv_img_cf_has_alpha(ext_dst->dsc.header.cf) == false) {
|
||||
if(dsc.res_opa < LV_OPA_MAX) dsc.res_color = lv_color_mix(dsc.res_color, bg_color, dsc.res_opa);
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color);
|
||||
}
|
||||
/*Both the image and canvas has alpha channel. Some extra calculation is
|
||||
required*/
|
||||
@ -358,28 +352,28 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c
|
||||
lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y);
|
||||
/* Pick the foreground if it's fully opaque or the Background is fully
|
||||
* transparent*/
|
||||
if(opa_res >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, color_res);
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res);
|
||||
if(dsc.res_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color);
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_opa);
|
||||
}
|
||||
/*Opaque background: use simple mix*/
|
||||
else if(bg_opa >= LV_OPA_MAX) {
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y,
|
||||
lv_color_mix(color_res, bg_color, opa_res));
|
||||
lv_color_mix(dsc.res_color, bg_color, dsc.res_opa));
|
||||
}
|
||||
/*Both colors have alpha. Expensive calculation need to be applied*/
|
||||
else {
|
||||
|
||||
/*Info:
|
||||
* https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/
|
||||
lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - opa_res) * (255 - bg_opa)) >> 8);
|
||||
lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - dsc.res_opa) * (255 - bg_opa)) >> 8);
|
||||
if(opa_res_2 == 0) {
|
||||
opa_res_2 = 1; /*never happens, just to be sure*/
|
||||
}
|
||||
lv_opa_t ratio = (uint16_t)((uint16_t)opa_res * 255) / opa_res_2;
|
||||
lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res_opa * 255) / opa_res_2;
|
||||
|
||||
lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y,
|
||||
lv_color_mix(color_res, bg_color, ratio));
|
||||
lv_color_mix(dsc.res_color, bg_color, ratio));
|
||||
lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2);
|
||||
}
|
||||
}
|
||||
@ -592,7 +586,7 @@ void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const voi
|
||||
lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
|
||||
lv_refr_set_disp_refreshing(&disp);
|
||||
|
||||
lv_draw_img(&coords, &mask, src, style, LV_OPA_COVER);
|
||||
lv_draw_img(&coords, &mask, src, style, 0, LV_OPA_COVER);
|
||||
|
||||
lv_refr_set_disp_refreshing(refr_ori);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../lv_draw/lv_img_decoder.h"
|
||||
#include "../lv_misc/lv_fs.h"
|
||||
#include "../lv_misc/lv_txt.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_misc/lv_log.h"
|
||||
|
||||
/*********************
|
||||
@ -78,6 +79,7 @@ lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->cf = LV_IMG_CF_UNKNOWN;
|
||||
ext->w = lv_obj_get_width(new_img);
|
||||
ext->h = lv_obj_get_height(new_img);
|
||||
ext->angle = 0;
|
||||
ext->auto_size = 1;
|
||||
ext->offset.x = 0;
|
||||
ext->offset.y = 0;
|
||||
@ -199,6 +201,9 @@ void lv_img_set_src(lv_obj_t * img, const void * src_img)
|
||||
lv_obj_set_size(img, ext->w, ext->h);
|
||||
}
|
||||
|
||||
/*Provide enough room for the rotated corners*/
|
||||
if(ext->angle) lv_obj_refresh_ext_draw_pad(img);
|
||||
|
||||
lv_obj_invalidate(img);
|
||||
}
|
||||
|
||||
@ -253,6 +258,17 @@ void lv_img_set_offset_y(lv_obj_t * img, lv_coord_t y)
|
||||
}
|
||||
}
|
||||
|
||||
void lv_img_set_angle(lv_obj_t * img, int16_t angle)
|
||||
{
|
||||
if(angle < 0 || angle >= 360) angle = angle % 360;
|
||||
|
||||
lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
|
||||
ext->angle = angle;
|
||||
lv_obj_refresh_ext_draw_pad(img);
|
||||
lv_obj_invalidate(img);
|
||||
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@ -351,7 +367,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
|
||||
if(mode == LV_DESIGN_COVER_CHK) {
|
||||
lv_design_res_t cover = LV_DESIGN_RES_NOT_COVER;
|
||||
if(ext->src_type == LV_IMG_SRC_UNKNOWN || ext->src_type == LV_IMG_SRC_SYMBOL) return LV_DESIGN_RES_NOT_COVER;
|
||||
if(ext->src_type == LV_IMG_SRC_UNKNOWN || ext->src_type == LV_IMG_SRC_SYMBOL || ext->angle != 0) return LV_DESIGN_RES_NOT_COVER;
|
||||
|
||||
if(ext->cf == LV_IMG_CF_TRUE_COLOR || ext->cf == LV_IMG_CF_RAW) {
|
||||
cover = lv_area_is_in(clip_area, &img->coords) ? LV_DESIGN_RES_COVER : LV_DESIGN_RES_NOT_COVER;
|
||||
@ -378,7 +394,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
cords_tmp.x1 = coords.x1;
|
||||
cords_tmp.x2 = coords.x1 + ext->w - 1;
|
||||
for(; cords_tmp.x1 < coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
|
||||
lv_draw_img(&cords_tmp, clip_area, ext->src, style, opa_scale);
|
||||
lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, opa_scale);
|
||||
}
|
||||
}
|
||||
} else if(ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
@ -390,7 +406,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
} else {
|
||||
/*Trigger the error handler of image drawer*/
|
||||
LV_LOG_WARN("lv_img_design: image source type is unknown");
|
||||
lv_draw_img(&img->coords, clip_area, NULL, style, opa_scale);
|
||||
lv_draw_img(&img->coords, clip_area, NULL, style, 0, opa_scale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,6 +442,15 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param)
|
||||
if(ext->src_type == LV_IMG_SRC_SYMBOL) {
|
||||
lv_img_set_src(img, ext->src);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
|
||||
/*If the image has angle provide enough room for the rotated corners */
|
||||
if(ext->angle) {
|
||||
lv_sqrt_res_t ds;
|
||||
lv_sqrt(ext->w * ext->w + ext->h * ext->h, &ds);
|
||||
|
||||
lv_coord_t d = (ds.i - LV_MATH_MIN(ext->w, ext->h)) / 2;
|
||||
img->ext_draw_pad = LV_MATH_MAX(img->ext_draw_pad, d);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -42,6 +42,7 @@ typedef struct
|
||||
lv_point_t offset;
|
||||
lv_coord_t w; /*Width of the image (Handled by the library)*/
|
||||
lv_coord_t h; /*Height of the image (Handled by the library)*/
|
||||
uint16_t angle;
|
||||
uint8_t src_type : 2; /*See: lv_img_src_t*/
|
||||
uint8_t auto_size : 1; /*1: automatically set the object size to the image size*/
|
||||
uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/
|
||||
|
@ -303,7 +303,7 @@ static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * cli
|
||||
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
|
||||
lv_draw_label(&imgbtn->coords, clip_area, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
} else {
|
||||
lv_draw_img(&imgbtn->coords, clip_area, src, style, opa_scale);
|
||||
lv_draw_img(&imgbtn->coords, clip_area, src, style, 0, opa_scale);
|
||||
}
|
||||
#else
|
||||
const void * src = ext->img_src_left[state];
|
||||
|
Loading…
x
Reference in New Issue
Block a user