Inaccurate bitmap zoom

Zooming in a simple bitmap image *30 times, you can clearly see that the enlarged image is distorted. LVGL version is 8.3.0.dev.

#include "../../lv_examples.h"

void lv_example_img_1(void)
{
	/* 15*10 bitmap(with alpha byte, LV_COLOR_DEPTH =8) for char 'G'
	"    . . . . . .    "
	"  . . . . . . . .  "
	". . .         . . ."
	". .             . ."
	". .                "
	". .                "
	". .                "
	". .                "
	". .         . . . ."
	". .         . . . ."
	". .             . ."
	". .             . ."
	". .           . . ."
	"  . . . . . . . .  "
	"    . . . . . .    "
	*/
	static uint8_t imgData[] = {
		0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00,
		0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0xFF,0x00,
		0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF,
		0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF,
		0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0xFF,0x00,
		0xFF,0x00, 0xFF,0x00, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0x00,0xFF, 0xFF,0x00, 0xFF,0x00,
	};

	static lv_img_dsc_t img_dsc;
	img_dsc.header.always_zero = 0;
	img_dsc.header.w = 10;
	img_dsc.header.h = 15;
	img_dsc.data_size = 10 * 15 * LV_IMG_PX_SIZE_ALPHA_BYTE;
	img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
	img_dsc.data = imgData;

	lv_obj_t *img = lv_img_create(lv_scr_act());
	lv_img_set_src (img, &img_dsc);

	lv_img_set_zoom(img, 256*30);	// zoom in X30
	lv_img_set_size_mode(img, LV_IMG_SIZE_MODE_REAL);
	lv_obj_center(img);
}

Furthermore, under my embedded platform, distortion is different from LVGL version
2

Hi,

I could reproduce the issue and pushed a fix to master. The image transformation was rewritten so it’s normal that it behaves differently than in v8.2.

I tested the fix with this chekboard pattern:

 static uint8_t imgData[] = {
          0x00, 0x76, 0x00, 0x76,
          0x76, 0x00, 0x76, 0x00,
          0x00, 0x76, 0x00, 0x76,
          0x76, 0x00, 0x76, 0x00,
};

      static lv_img_dsc_t img_dsc;
      img_dsc.header.always_zero = 0;
      img_dsc.header.w = 4;
      img_dsc.header.h = 4;
      img_dsc.data_size = 4 * 4* LV_IMG_PX_SIZE_ALPHA_BYTE;
      img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
      img_dsc.data = imgData;

I found that it works well until 20x zoom. After that due to rounding errors there will be inaccuracies.
Now the coordinates are upscaled by 256 during transformations, so we could upscale them by a larger number, but it’d limit the max image size.

I think x20 zoom is an acceptable trade off for most of the cases. Note that if you have a special use case, you can replace LVGL’s transform algorithm by using a custom draw_ctx. Learn more here: Add custom GPU — LVGL documentation

Still there is a problem with lv_img_set_size_mode(img, LV_IMG_SIZE_MODE_REAL);. Without it the result is much better.