M5Paper Canvas Rendering Artifacts



  • Hey folks!

    While playing with the M5Paper, I came across the following issues. When drawing mutliple canvas on the screen sometimes the different canvases seem to be misaligned by few pixels even though the coordinates are all matching.

    Here is a very simple example:

    #include <Arduino.h>
    #include <M5EPD.h>
    
    
    // Prepare some stuff.
    void initializeSystem() {
      log_d("Prepare SysInit");
      M5.begin();
      M5.EPD.SetRotation(90);
      M5.TP.SetRotation(90);
      M5.EPD.Clear(true);
      M5.RTC.begin();
      log_d("Done SysInit");
    }
    
    void setup() {
      initializeSystem();
      M5EPD_Canvas c1(&M5.EPD);
      M5EPD_Canvas c2(&M5.EPD);
    
      log_d("Drawing first canvas");
      c1.createCanvas(200, 200);
      c1.fillRect(0,0, 200, 200, G5);
      // physical position is 300, 300
      c1.drawRect(100,100, 50, 50, G15);
      c1.pushCanvas(200, 200, UPDATE_MODE_NONE);
    
      M5.EPD.UpdateFull(UPDATE_MODE_GC16);
    
      delay(2000);
    
      log_d("Drawing second canvas");
      c2.createCanvas(50, 50);
      c2.drawRect(0,0,50,50, G15);
      c2.pushCanvas(300, 300, UPDATE_MODE_GC16);
    }
    
    void loop() {
    }
    

    In theory the two rectangles should perfectly overlap, but they do not. Please see the following picture:

    alt text

    When trying to build a nice UI this can be quite annoying. I was trying to understand where this comes from and while going through the source of the M5EPD library I found the following comment in callocSprite():

    w = (w + 3) & 0xFFFC; // width should be the multiple of 4 bits to be compatible with epdpaint
    

    Now, this made me suspicious, in the above example, the width of 50px is rounded up to 52px and this values is then used for the framebuffer. If I adjust the code above to be 52px for the rectangle and the partial canvas all the misalignment goes away. In this example the artifact just appears on the horizontal axis, but I've seen misalignment as well on the vertical axis.

    My question is, if the behavior is required or an artifact of the integration with the driver? Shouldn't the library simply forbid creating a canvas that is not a multiple of 4?

    Probably, I can just make sure that all my elements have widths that are multiples of 4 but this seems a bit weird. Any suggestions?



  • My question is, if the behavior is required or an artifact of the integration with the driver?

    I think this is required.
    When actually transferring data to the screen, this is done 4 pixels at a time.

    Shouldn't the library simply forbid creating a canvas that is not a multiple of 4?

    Probably, yes.