Why axis approximation for the lv canvas rotate work?

I study the code and can’t understand, but it works. Can you explain the axis approximation, where does the algorithm come from?

The following is sample in lv_canvas_rotate:

          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_width)
                continue;
            else if(xn < 0)
                continue;

I’ve figured out this algorithm on my own, but I’m sure others also use something like this.

Have a look at this:

Thank you. But why not use bilinear interpolation to the color approximation. I understand that, when the source axis is (x.a, y.b), x and y are integers, a and b are fractions. the pixels of (x, y), (x + 1, y), (x, y+1) and (x + 1, y + 1) are used to calculate the approximation with weights .Why (x - 1,y) and (x, y - 1 ) are selected as neighbor point when the axis is (x.0, y.0)?

For simplicity let’s say a pixel has 3 parts (using the notion from for your comment):

  • left (.a =0)
  • center (.a = 128)
  • right (.a = 255)

If the rotation gives "use the source pixel’s a = 128" it means the center of the pixel should be written to the destination position. It’s a clear case, no interpolation is required because if the center need to used the neighbor pixels won’t affect it.

If the rotation gives "use source the pixel’s a = 0" it means the very left point of the pixel should be written to the destination position. However, the very left is almost the other pixel on the left. So mix them with equal weight.

Thanks a lot. How does this great idea come from? which books or materials can you remind to study from?

You’re welcome!

Actually, I’ve just figured it on my own however I’m sure others also already used something like this.

I was thinking like:

  1. Some kind of interpolation is required to get smoother edges and lines
  2. If a short vertical line (1x3 px) is rotated only a little bit (1 deg) then it might be no rotation at all because always the same pixel will be sampled.
  3. But it just a rounding error. In reality e,g. the (0;1) pixel should be at (0;1,1).
  4. How to represent it? Oh, the neighbor pixel should matter.
  5. But to what extent? What if exactly the intersection of two pixels or the center of the pixel should be used.
  6. Aha! It should be related to the theoretical distance from the center of the pixel.
  7. If we used float numbers it should be easy to see how far we are from the center be seeing the fraction parts.
  8. But we don’t use floats in LittelvGL. So upscaling should be used to get more precision.

That’s it! :slight_smile:

Thanks for your detailed explanation

You’re welcome!