lovyan03 / LovyanGFX

SPI LCD graphics library for ESP32 (ESP-IDF/ArduinoESP32) / ESP8266 (ArduinoESP8266) / SAMD51(Seeed ArduinoSAMD51)
Other
1.02k stars 187 forks source link

Allocate a static buffer for 1bpp/2bpp/4bpp greyscale sprites and draw bitmaps on it #541

Closed fsender closed 1 month ago

fsender commented 2 months ago

I'm developing a library for E-paper displays. It supports 16-level grey display for most common E-paper displays. I hope you can pay more attention to greyscale bitmaps and sprites.

Firstly. Setting buffer for static greyscale bitmaps.

I tried using setBuffer function for my static 8-bpp greyscale bitmap array. Bit it was always converted to RGB332 colour format. Now I have to edit your library to show a static greyscale bitmap.

Now there is an available function prototype for setBuffer at file LGFX_Sprite.hpp line 155.

    void setBuffer(void* buffer, int32_t w, int32_t h, uint8_t bpp = 0);

Could you add a function like this?

    void setBuffer(void* buffer, int32_t w, int32_t h, color_depth_t bpp = rgb565_2Byte)
    {
      deleteSprite();
      if (bpp != 0) {
        _write_conv.setColorDepth(bpp);
        _read_conv = _write_conv;
        _panel_sprite.setColorDepth(bpp);
      }

      _panel_sprite.setBuffer(buffer, w, h, &_write_conv);
      _img = _panel_sprite.getBuffer();

      _sw = w;
      _clip_r = w - 1;
      _xpivot = w >> 1;

      _sh = h;
      _clip_b = h - 1;
      _ypivot = h >> 1;
    }

Next. My ESP32 Halted when copying from an RGB sprite to a 4bpp greyscale sprite.

When copying from an RGB565 or RGB888 sprite to a grey bitmap (1bpp, 2bpp and 4bpp) the library halted at file LGFX_Sprite.cpp line 481: in void Panel_Sprite::writeImage(uint_fast16_t x, uint_fast16_t y, uint_fast16_t w, uint_fast16_t h, pixelcopy_t* param, bool) fp_copy is nullptr.

my destination sprite is greyscale 4bit color type. Source sprite is RGB565 color type.

I have tried these: source destination result
RGB565 RGB332 OK
RGB565 8bit Greyscale OK
RGB888 8bit Greyscale OK
RGB332 8bit Greyscale OK
8bit Greyscale 8bit Greyscale OK
4bit Greyscale 8bit Greyscale OK
2bit Greyscale 8bit Greyscale OK
1bit Greyscale 8bit Greyscale OK
2bit palette 8bit Greyscale OK
RGB565 4bit Greyscale NG
RGB888 4bit Greyscale NG
RGB332 4bit Greyscale NG
8bit Greyscale 4bit Greyscale NG
4bit Greyscale 4bit Greyscale NG
1bit Greyscale 4bit Greyscale NG
2bit palette 4bit Greyscale NG
RGB565 2bit Greyscale NG
RGB565 1bit Greyscale NG
RGB565 2bit palette NG
RGB565 1bit palette NG

At file pixelcopy.hpp line 115.

    template<typename TSrc>
    static auto get_fp_copy_rgb_affine(color_depth_t dst_depth) -> uint32_t(*)(void*, uint32_t, uint32_t, pixelcopy_t*)
    {
      return (dst_depth == rgb565_2Byte) ? copy_rgb_affine<swap565_t, TSrc>
           : (dst_depth == rgb332_1Byte) ? copy_rgb_affine<rgb332_t , TSrc>
           : (dst_depth == rgb888_3Byte) ? copy_rgb_affine<bgr888_t, TSrc>
           : (dst_depth == rgb666_3Byte) ? (std::is_same<bgr666_t, TSrc>::value
                                           ? copy_rgb_affine<bgr888_t, bgr888_t>
                                           : copy_rgb_affine<bgr666_t, TSrc>)
           : (dst_depth == grayscale_8bit) ? copy_rgb_affine<grayscale_t, TSrc>
           : nullptr;
    }

I think this nullptr is the reason. Please add pixel copying support for 1bpp,2bpp and 4bpp bitmaps and sprites. Thanks.

lovyan03 commented 2 months ago

I understand exactly what you mean, and I was originally going to implement it as well. However, if you implement it, the template will become larger and the binary size will become huge. I believe this implementation was a failure.

lovyan03 commented 2 months ago

I actually have quite a few problems with the current LovyanGFX V1 implementation, and am considering creating a new V2 design from HAL. So we don't want to spend time supporting V1.

fsender commented 1 month ago

Just add a function prototype like this. I think it takes just a few bytes. However, most of projects do not use this prototype.

lovyan03 commented 1 month ago

By the way, if you copy an RGB565 image to a palette image, what kind of result do you expect to get? If I were to implement this, I would simply allocate the low byte of the bit string. If you want to automatically select a palette that reproduces the colors of the original image, that would require a fairly tedious implementation.

fsender commented 1 month ago

It is not easy to copy a normal image like RGB565, RGB888 etc to a palette image. But it is easier to copy to a 1bpp/2bpp/4bpp greyscale image.

I will create my own transform function if I must copy from an normal image to a palette image.

So, I just hope to add a prototype for creating a static sprite. You do not need to do anything else for V1.

    void setBuffer(void* buffer, int32_t w, int32_t h, color_depth_t bpp = rgb565_2Byte);

Source code reference previous text.

fsender commented 1 month ago

Use this setBuffer function, I'll create a static sprite with any color_depth_t.