diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index f3d7e3e..c82024c 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -868,12 +868,46 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_ } else if (_bpp == 4) { - // not supported. The image is unlikely to have the correct colors for the color map. - // we could implement a way to push a 4-bit image using the color map? - #ifdef TFT_eSPI_DEBUG - Serial.println("pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) not implemented"); - #endif - return; + // the image is assumed to be 4 bit, where each byte corresponds to two pixels. + // much faster when aligned to a byte boundary, because the alternative is slower, requiring + // tedious bit operations. + + const uint8_t *dataBuf = (uint8_t *)data; + int sWidth = (_iwidth >> 1); + + if ((xs & 0x01) == 0 && (xo & 0x01) == 0 && (ws & 0x01) == 0) + { + if ((ws & 0x01) == 0) // use memcpy for better perf. + { + xs = (xs >> 1) + ys * sWidth; + ws = (ws >> 1); + xo = (xo >> 1) + yo * (w>>1); + while (hs--) + { + memcpy(_img4 + xs, dataBuf + xo, ws); + xo += (w >> 1); + xs += sWidth; + } + } + } + else // not optimized + { + for (int32_t yp = yo; yp < yo + hs; yp++) + { + x = xs; + for (int32_t xp = xo; xp < xo + ws; xp++) + { + uint32_t color; + if ((xp & 0x01) == 0) + color = (dataBuf[((xp+yp*w)>>1)] & 0xF0) >> 4; // even index = bits 7 .. 4 + else + color = dataBuf[((xp-1+yp*w)>>1)] & 0x0F; // odd index = bits 3 .. 0. + drawPixel(x, ys, color); + x++; + } + ys++; + } + } } else // 1bpp diff --git a/Extensions/Sprite.h b/Extensions/Sprite.h index 74ba6b2..b1307b6 100644 --- a/Extensions/Sprite.h +++ b/Extensions/Sprite.h @@ -114,7 +114,7 @@ class TFT_eSprite : public TFT_eSPI { // 16bpp = colour, 8bpp = byte, 4bpp = colour index, 1bpp = 1 or 0 uint16_t readPixelValue(int32_t x, int32_t y); - // Write an image (colour bitmap) to the sprite. Not implemented for _bpp == 4. + // Write an image (colour bitmap) to the sprite. void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); diff --git a/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino b/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino index e004df4..bdf5390 100644 --- a/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino +++ b/examples/Sprite/Sprite_image_4bit/Sprite_image_4bit.ino @@ -39,10 +39,6 @@ TFT_eSPI tft = TFT_eSPI(); // Declare object "tft" TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object -const int freq = 5000; -int screenBrightnessChannel = 0; -int resolution = 8; - byte red = 31; // Red is the top 5 bits of a 16 bit colour value byte green = 0;// Green is the middle 6 bits byte blue = 0; // Blue is the bottom 5 bits @@ -55,11 +51,6 @@ uint16_t cmap[16]; void setup() { - pinMode(21, OUTPUT); - ledcSetup(screenBrightnessChannel, freq, resolution); - ledcAttachPin(21, screenBrightnessChannel); - ledcWrite(screenBrightnessChannel, 127); - Serial.begin(9600); Serial.println(); @@ -94,13 +85,12 @@ void loop(void) cmap[i] = cmap[i + 1]; } if (incr == 2) { - (void)rainbow(); // skip alternate steps + (void)rainbow(); // skip alternate steps to go faster } cmap[15] = rainbow(); rloop += incr; if (rloop > 0xc0) { incr = incr == 2 ? 1 : 2; - Serial.printf("incr %d, rloop %d\r\n", incr, rloop); rloop = 0; }