diff --git a/src/widgets/image/lv_image.c b/src/widgets/image/lv_image.c index 53ec9f55ce..6affb1d0c4 100644 --- a/src/widgets/image/lv_image.c +++ b/src/widgets/image/lv_image.c @@ -27,6 +27,7 @@ static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) static void lv_image_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e); static void draw_image(lv_event_t * e); +static void scale_update(lv_obj_t * obj, int32_t zoom_x, int32_t zoom_y); #if LV_USE_OBJ_PROPERTY static const lv_property_ops_t properties[] = { @@ -198,7 +199,7 @@ void lv_image_set_src(lv_obj_t * obj, const void * src) lv_obj_refresh_self_size(obj); /*Provide enough room for the rotated corners*/ - if(img->rotation || img->zoom != LV_SCALE_NONE) lv_obj_refresh_ext_draw_size(obj); + if(img->rotation || img->zoom_x != LV_SCALE_NONE || img->zoom_y != LV_SCALE_NONE) lv_obj_refresh_ext_draw_size(obj); lv_obj_invalidate(obj); } @@ -243,7 +244,7 @@ void lv_image_set_rotation(lv_obj_t * obj, int32_t angle) lv_area_t a; lv_point_t pivot_px; lv_image_get_pivot(obj, &pivot_px); - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -259,7 +260,7 @@ void lv_image_set_rotation(lv_obj_t * obj, int32_t angle) lv_obj_refresh_ext_draw_size(obj); lv_display_enable_invalidation(disp, true); - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -285,7 +286,7 @@ void lv_image_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) lv_area_t a; lv_point_t pivot_px; lv_image_get_pivot(obj, &pivot_px); - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -303,7 +304,7 @@ void lv_image_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) lv_display_enable_invalidation(disp, true); lv_image_get_pivot(obj, &pivot_px); - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; a.x2 += obj->coords.x1; @@ -314,44 +315,31 @@ void lv_image_set_pivot(lv_obj_t * obj, lv_coord_t x, lv_coord_t y) void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom) { lv_image_t * img = (lv_image_t *)obj; - if(zoom == img->zoom) return; + if(zoom == img->zoom_x && zoom == img->zoom_y) return; if(zoom == 0) zoom = 1; - if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) { - img->zoom = zoom; - lv_obj_invalidate_area(obj, &obj->coords); - return; - } + scale_update(obj, zoom, zoom); +} - lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ - lv_coord_t w = lv_obj_get_width(obj); - lv_coord_t h = lv_obj_get_height(obj); - lv_area_t a; - lv_point_t pivot_px; - lv_image_get_pivot(obj, &pivot_px); - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); - a.x1 += obj->coords.x1 - 1; - a.y1 += obj->coords.y1 - 1; - a.x2 += obj->coords.x1 + 1; - a.y2 += obj->coords.y1 + 1; - lv_obj_invalidate_area(obj, &a); +void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom) +{ + lv_image_t * img = (lv_image_t *)obj; + if(zoom == img->zoom_x) return; - img->zoom = zoom; + if(zoom == 0) zoom = 1; - /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate - * the whole ext draw area */ - lv_display_t * disp = lv_obj_get_disp(obj); - lv_display_enable_invalidation(disp, false); - lv_obj_refresh_ext_draw_size(obj); - lv_display_enable_invalidation(disp, true); + scale_update(obj, zoom, img->zoom_y); +} - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); - a.x1 += obj->coords.x1 - 1; - a.y1 += obj->coords.y1 - 1; - a.x2 += obj->coords.x1 + 1; - a.y2 += obj->coords.y1 + 1; - lv_obj_invalidate_area(obj, &a); +void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom) +{ + lv_image_t * img = (lv_image_t *)obj; + if(zoom == img->zoom_y) return; + + if(zoom == 0) zoom = 1; + + scale_update(obj, img->zoom_y, zoom); } void lv_image_set_antialias(lv_obj_t * obj, bool antialias) @@ -429,7 +417,25 @@ lv_coord_t lv_image_get_scale(lv_obj_t * obj) lv_image_t * img = (lv_image_t *)obj; - return img->zoom; + return img->zoom_x; +} + +lv_coord_t lv_image_get_scale_x(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->zoom_x; +} + +lv_coord_t lv_image_get_scale_y(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->zoom_y; } bool lv_image_get_antialias(lv_obj_t * obj) @@ -465,7 +471,8 @@ static void lv_image_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) img->w = lv_obj_get_width(obj); img->h = lv_obj_get_height(obj); img->rotation = 0; - img->zoom = LV_SCALE_NONE; + img->zoom_x = LV_SCALE_NONE; + img->zoom_y = LV_SCALE_NONE; img->antialias = LV_COLOR_DEPTH > 8 ? 1 : 0; img->offset.x = 0; img->offset.y = 0; @@ -500,7 +507,7 @@ static lv_point_t lv_image_get_transformed_size(lv_obj_t * obj) lv_point_t pivot_px; lv_image_get_pivot(obj, &pivot_px); _lv_image_buf_get_transformed_area(&area_transform, img->w, img->h, - img->rotation, img->zoom, img->zoom, &pivot_px); + img->rotation, img->zoom_x, img->zoom_y, &pivot_px); return (lv_point_t) { lv_area_get_width(&area_transform), lv_area_get_height(&area_transform) @@ -540,11 +547,11 @@ static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e) lv_coord_t * s = lv_event_get_param(e); /*If the image has angle provide enough room for the rotated corners*/ - if(img->rotation || img->zoom != LV_SCALE_NONE) { + if(img->rotation || img->zoom_x != LV_SCALE_NONE || img->zoom_y != LV_SCALE_NONE) { lv_area_t a; lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); - _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); *s = LV_MAX(*s, -a.x1); *s = LV_MAX(*s, -a.y1); *s = LV_MAX(*s, a.x2 - w); @@ -557,12 +564,13 @@ static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e) /*If the object is exactly image sized (not cropped, not mosaic) and transformed *perform hit test on its transformed area*/ if(img->w == lv_obj_get_width(obj) && img->h == lv_obj_get_height(obj) && - (img->zoom != LV_SCALE_NONE || img->rotation != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { + (img->zoom_x != LV_SCALE_NONE || img->zoom_y != LV_SCALE_NONE || + img->rotation != 0 || img->pivot.x != img->w / 2 || img->pivot.y != img->h / 2)) { lv_coord_t w = lv_obj_get_width(obj); lv_coord_t h = lv_obj_get_height(obj); lv_area_t coords; - _lv_image_buf_get_transformed_area(&coords, w, h, img->rotation, img->zoom, img->zoom, &pivot_px); + _lv_image_buf_get_transformed_area(&coords, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); coords.x1 += obj->coords.x1; coords.y1 += obj->coords.y1; coords.x2 += obj->coords.x1; @@ -622,7 +630,7 @@ static void draw_image(lv_event_t * e) } const lv_area_t * clip_area = lv_event_get_param(e); - if(img->zoom == LV_SCALE_NONE) { + if(img->zoom_x == LV_SCALE_NONE && img->zoom_y == LV_SCALE_NONE) { if(_lv_area_is_in(clip_area, &obj->coords, 0) == false) { info->res = LV_COVER_RES_NOT_COVER; return; @@ -632,7 +640,7 @@ static void draw_image(lv_event_t * e) lv_area_t a; lv_point_t pivot_px; lv_image_get_pivot(obj, &pivot_px); - _lv_image_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->zoom, img->zoom, + _lv_image_buf_get_transformed_area(&a, lv_obj_get_width(obj), lv_obj_get_height(obj), 0, img->zoom_x, img->zoom_y, &pivot_px); a.x1 += obj->coords.x1; a.y1 += obj->coords.y1; @@ -670,7 +678,7 @@ static void draw_image(lv_event_t * e) } else { _lv_image_buf_get_transformed_area(&bg_coords, obj_w, obj_h, - img->rotation, img->zoom, img->zoom, &bg_pivot); + img->rotation, img->zoom_x, img->zoom_y, &bg_pivot); /*Modify the coordinates to draw the background for the rotated and scaled coordinates*/ bg_coords.x1 += obj->coords.x1; @@ -690,7 +698,7 @@ static void draw_image(lv_event_t * e) if(code == LV_EVENT_DRAW_MAIN) { if(img->h == 0 || img->w == 0) return; - if(img->zoom == 0) return; + if(img->zoom_x == 0 || img->zoom_y == 0) return; lv_layer_t * layer = lv_event_get_layer(e); @@ -720,8 +728,8 @@ static void draw_image(lv_event_t * e) lv_draw_image_dsc_init(&img_dsc); lv_obj_init_draw_image_dsc(obj, LV_PART_MAIN, &img_dsc); - img_dsc.zoom_x = img->zoom; - img_dsc.zoom_y = img->zoom; + img_dsc.zoom_x = img->zoom_x; + img_dsc.zoom_y = img->zoom_y; img_dsc.rotation = img->rotation; img_dsc.pivot.x = pivot_px.x; img_dsc.pivot.y = pivot_px.y; @@ -775,4 +783,47 @@ static void draw_image(lv_event_t * e) } } +static void scale_update(lv_obj_t * obj, int32_t zoom_x, int32_t zoom_y) +{ + lv_image_t * img = (lv_image_t *)obj; + + if(img->obj_size_mode == LV_IMAGE_SIZE_MODE_REAL) { + img->zoom_x = zoom_x; + img->zoom_y = zoom_y; + lv_obj_invalidate_area(obj, &obj->coords); + return; + } + + lv_obj_update_layout(obj); /*Be sure the object's size is calculated*/ + lv_coord_t w = lv_obj_get_width(obj); + lv_coord_t h = lv_obj_get_height(obj); + lv_area_t a; + lv_point_t pivot_px; + lv_image_get_pivot(obj, &pivot_px); + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); + a.x1 += obj->coords.x1 - 1; + a.y1 += obj->coords.y1 - 1; + a.x2 += obj->coords.x1 + 1; + a.y2 += obj->coords.y1 + 1; + lv_obj_invalidate_area(obj, &a); + + img->zoom_x = zoom_x; + img->zoom_y = zoom_y; + + /* Disable invalidations because lv_obj_refresh_ext_draw_size would invalidate + * the whole ext draw area */ + lv_display_t * disp = lv_obj_get_disp(obj); + lv_display_enable_invalidation(disp, false); + lv_obj_refresh_ext_draw_size(obj); + lv_display_enable_invalidation(disp, true); + + _lv_image_buf_get_transformed_area(&a, w, h, img->rotation, img->zoom_x, img->zoom_y, &pivot_px); + a.x1 += obj->coords.x1 - 1; + a.y1 += obj->coords.y1 - 1; + a.x2 += obj->coords.x1 + 1; + a.y2 += obj->coords.y1 + 1; + lv_obj_invalidate_area(obj, &a); + +} + #endif diff --git a/src/widgets/image/lv_image.h b/src/widgets/image/lv_image.h index d5edb3e3ef..957d43371d 100644 --- a/src/widgets/image/lv_image.h +++ b/src/widgets/image/lv_image.h @@ -44,7 +44,8 @@ typedef struct { lv_coord_t w; /*Width of the image (Handled by the library)*/ lv_coord_t h; /*Height of the image (Handled by the library)*/ uint32_t rotation; /*rotation angle of the image*/ - uint32_t zoom; /*256 means no zoom, 512 double size, 128 half size*/ + uint32_t zoom_x; /*256 means no zoom, 512 double size, 128 half size*/ + uint32_t zoom_y; /*256 means no zoom, 512 double size, 128 half size*/ lv_point_t pivot; /*rotation center of the image*/ uint8_t src_type : 2; /*See: lv_image_src_t*/ uint8_t cf : 5; /*Color format from `lv_color_format_t`*/ @@ -170,6 +171,33 @@ static inline void _lv_image_set_pivot(lv_obj_t * obj, lv_point_t * pivot) */ void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom); +/** + * Set the horizontal zoom factor of the image. + * Note that indexed and alpha only images can't be transformed. + * @param img pointer to an image object + * @param zoom the zoom factor. + * @example 256 or LV_ZOOM_IMAGE_NONE for no zoom + * @example <256: scale down + * @example >256 scale up + * @example 128 half size + * @example 512 double size + */ +void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom); + +/** + * Set the vertical zoom factor of the image. + * Note that indexed and alpha only images can't be transformed. + * @param img pointer to an image object + * @param zoom the zoom factor. + * @example 256 or LV_ZOOM_IMAGE_NONE for no zoom + * @example <256: scale down + * @example >256 scale up + * @example 128 half size + * @example 512 double size + */ +void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom); + + /** * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not. * The quality is better with anti-aliasing looks better but slower. @@ -232,6 +260,20 @@ void lv_image_get_pivot(lv_obj_t * obj, lv_point_t * pivot); */ lv_coord_t lv_image_get_scale(lv_obj_t * obj); +/** + * Get the horizontal zoom factor of the image. + * @param obj pointer to an image object + * @return zoom factor (256: no zoom) + */ +lv_coord_t lv_image_get_scale_x(lv_obj_t * obj); + +/** + * Get the vertical zoom factor of the image. + * @param obj pointer to an image object + * @return zoom factor (256: no zoom) + */ +lv_coord_t lv_image_get_scale_y(lv_obj_t * obj); + /** * Get whether the transformations (rotate, zoom) are anti-aliased or not * @param obj pointer to an image object