feat(image): add LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE (#10063)

Co-authored-by: Simon Stumm <simon.stumm@sartorius.com>
This commit is contained in:
Niklas Fiekas
2026-05-07 09:31:07 +02:00
committed by GitHub
parent 9a92075952
commit c41e958cf7
5 changed files with 38 additions and 4 deletions
+1
View File
@@ -55,6 +55,7 @@ typedef enum {
LV_IMAGE_ALIGN_STRETCH, /**< Set X and Y scale to fill the Widget's area. */
LV_IMAGE_ALIGN_TILE, /**< Tile image to fill Widget's area. Offset is applied to shift the tiling. */
LV_IMAGE_ALIGN_CONTAIN, /**< The image keeps its aspect ratio, but is resized to the maximum size that fits within the Widget's area. */
LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE, /**< The image keeps its aspect ratio, but is resized to the maximum size that fits within the Widget's area if the image is bigger. */
LV_IMAGE_ALIGN_COVER, /**< The image keeps its aspect ratio and fills the Widget's area. */
} lv_image_align_t;
+8 -4
View File
@@ -464,7 +464,7 @@ void lv_image_set_inner_align(lv_obj_t * obj, lv_image_align_t align)
/*If we're removing STRETCH, reset the scale*/
if(img->align == LV_IMAGE_ALIGN_STRETCH || img->align == LV_IMAGE_ALIGN_CONTAIN ||
img->align == LV_IMAGE_ALIGN_COVER) {
img->align == LV_IMAGE_ALIGN_COVER || img->align == LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE) {
lv_image_set_scale(obj, LV_SCALE_NONE);
}
@@ -749,7 +749,7 @@ static void lv_image_event(const lv_obj_class_t * class_p, lv_event_t * e)
}
else if(code == LV_EVENT_SIZE_CHANGED) {
if(img->align == LV_IMAGE_ALIGN_STRETCH || img->align == LV_IMAGE_ALIGN_CONTAIN ||
img->align == LV_IMAGE_ALIGN_COVER) {
img->align == LV_IMAGE_ALIGN_COVER || img->align == LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE) {
update_align(obj);
if(img->rotation || img->scale_x != LV_SCALE_NONE || img->scale_y != LV_SCALE_NONE) {
lv_obj_refresh_ext_draw_size(obj);
@@ -890,7 +890,8 @@ static void draw_image(lv_event_t * e)
lv_area_align(&obj->coords, &draw_dsc.image_area, img->align, img->offset.x, img->offset.y);
coords = draw_dsc.image_area;
}
else if(img->align == LV_IMAGE_ALIGN_CONTAIN || img->align == LV_IMAGE_ALIGN_COVER) {
else if(img->align == LV_IMAGE_ALIGN_CONTAIN || img->align == LV_IMAGE_ALIGN_COVER ||
img->align == LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE) {
int32_t scale = lv_image_get_scale(obj);
lv_point_t offset;
offset.x = (lv_obj_get_width(obj) - img->w * scale / LV_SCALE_NONE) / 2;
@@ -1004,7 +1005,7 @@ static void update_align(lv_obj_t * obj)
scale_update(obj, scale_x, scale_y);
}
}
else if(img->align == LV_IMAGE_ALIGN_CONTAIN) {
else if(img->align == LV_IMAGE_ALIGN_CONTAIN || img->align == LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE) {
lv_image_set_rotation(obj, 0);
lv_image_set_pivot(obj, 0, 0);
if(img->w != 0 && img->h != 0) {
@@ -1012,6 +1013,9 @@ static void update_align(lv_obj_t * obj)
int32_t scale_x = lv_obj_get_width(obj) * LV_SCALE_NONE / img->w;
int32_t scale_y = lv_obj_get_height(obj) * LV_SCALE_NONE / img->h;
int32_t scale = LV_MIN(scale_x, scale_y);
if(img->align == LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE) {
scale = LV_MIN(scale, LV_SCALE_NONE);
}
scale_update(obj, scale, scale);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

+29
View File
@@ -320,6 +320,35 @@ void test_image_contain(void)
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_contain.png");
}
void test_image_contain_downscale(void)
{
lv_obj_t * img;
uint32_t i;
int32_t img_w = test_img_lvgl_logo_png.header.w;
int32_t img_h = test_img_lvgl_logo_png.header.h;
int32_t aspect_ratio = img_w / img_h;
int32_t w_array[] = {img_w / 2, img_w, img_w * 2};
int32_t h_array[] = {img_h / 2, img_h, img_h * 2};
for(i = 0; i < 9; i++) {
img = img_create();
const int32_t w = w_array[i / 3];
const int32_t h = h_array[i % 3];
lv_obj_set_size(img, w, h);
lv_obj_set_pos(img, 30 + (i % 3) * 260, 40 + (i / 3) * 150);
lv_image_set_inner_align(img, LV_IMAGE_ALIGN_CONTAIN_DOWNSCALE);
const int32_t scale = lv_image_get_scale(img);
TEST_ASSERT_EQUAL_INT(aspect_ratio, lv_image_get_transformed_width(img) / lv_image_get_transformed_height(img));
TEST_ASSERT_EQUAL_INT((img_w * scale) >> 8, lv_image_get_transformed_width(img));
TEST_ASSERT_EQUAL_INT((img_h * scale) >> 8, lv_image_get_transformed_height(img));
}
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/image_contain_downscale.png");
}
void test_image_cover(void)
{
lv_obj_t * img;