Commit b5826586 authored by Bodmer's avatar Bodmer

Allow 4bpp Sprites to be rotated

4bpp Sprites can now be pushed to the TFT with a rotation
parent 960ff6c7
......@@ -59,8 +59,6 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames)
_iwidth = _dwidth = _bitwidth = w;
_iheight = _dheight = h;
_colorMap = nullptr;
this->cursor_x = 0;
this->cursor_y = 0;
......@@ -94,6 +92,8 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames)
_img8_2 = _img8 + (w * h + 1);
}
if ( (_bpp == 4) && (_colorMap == nullptr)) createPalette(default_4bit_palette);
// This is to make it clear what pointer size is expected to be used
// but casting in the user sketch is needed due to the use of void*
if ( (_bpp == 1) && (frames > 1) )
......@@ -195,7 +195,7 @@ void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames)
** Description: Set a palette for a 4-bit per pixel sprite
*************************************************************************************x*/
void TFT_eSprite::createPalette(uint16_t colorMap[], int colors)
void TFT_eSprite::createPalette(uint16_t colorMap[], uint8_t colors)
{
if (_colorMap != nullptr)
{
......@@ -204,14 +204,18 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors)
if (colorMap == nullptr)
{
return; // do nothing other than clear the existing map
// Create a color map using the default FLASH map
createPalette(default_4bit_palette);
return;
}
// allocate color map
// Allocate and clear memory for 16 color map
_colorMap = (uint16_t *)calloc(16, sizeof(uint16_t));
if (colors > 16)
colors = 16;
for (auto i = 0; i < colors; i++)
if (colors > 16) colors = 16;
// Copy map colors
for (uint8_t i = 0; i < colors; i++)
{
_colorMap[i] = colorMap[i];
}
......@@ -222,7 +226,7 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors)
** Description: Set a palette for a 4-bit per pixel sprite
*************************************************************************************x*/
void TFT_eSprite::createPalette(const uint16_t colorMap[], int colors)
void TFT_eSprite::createPalette(const uint16_t colorMap[], uint8_t colors)
{
if (_colorMap != nullptr)
{
......@@ -231,14 +235,17 @@ void TFT_eSprite::createPalette(const uint16_t colorMap[], int colors)
if (colorMap == nullptr)
{
return; // do nothing other than clear the existing map
// Create a color map using the default FLASH map
colorMap = default_4bit_palette;
}
// allocate color map
// Allocate and clear memory for 16 color map
_colorMap = (uint16_t *)calloc(16, sizeof(uint16_t));
if (colors > 16)
colors = 16;
for (auto i = 0; i < colors; i++)
if (colors > 16) colors = 16;
// Copy map colors
for (uint8_t i = 0; i < colors; i++)
{
_colorMap[i] = pgm_read_word(colorMap++);
}
......@@ -306,7 +313,7 @@ int8_t TFT_eSprite::getColorDepth(void)
/***************************************************************************************
** Function name: setBitmapColor
** Description: Set the foreground foreground and background colour
** Description: Set the 1bpp foreground foreground and background colour
***************************************************************************************/
void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b)
{
......@@ -317,23 +324,22 @@ void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b)
/***************************************************************************************
** Function name: setPaletteColor
** Description: Set the palette color at the given index
** Description: Set the 4bpp palette color at the given index
***************************************************************************************/
void TFT_eSprite::setPaletteColor(uint8_t index, uint16_t color)
{
if (_colorMap == nullptr || index > 15)
return; // out of bounds
if (_colorMap == nullptr || index > 15) return; // out of bounds
_colorMap[index] = color;
}
/***************************************************************************************
** Function name: getPaletteColor
** Description: Return the palette color at index, or 0 (black) on error.
** Description: Return the palette color at 4bpp index, or 0 on error.
***************************************************************************************/
uint16_t TFT_eSprite::getPaletteColor(uint8_t index)
{
if (_colorMap == nullptr || index > 15)
return 0;
if (_colorMap == nullptr || index > 15) return 0; // out of bounds
return _colorMap[index];
}
......@@ -395,7 +401,7 @@ int16_t TFT_eSprite::getPivotY(void)
#define FP_SCALE 10
bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
{
if ( !_created || _bpp == 4) return false;
if ( !_created) return false;
// Bounding box parameters
int16_t min_x;
......@@ -413,6 +419,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
uint32_t xe = _iwidth << FP_SCALE;
uint32_t ye = _iheight << FP_SCALE;
uint32_t tpcolor = transp; // convert to unsigned
if (_bpp == 4) tpcolor = _colorMap[transp & 0x0F];
_tft->startWrite(); // Avoid transaction overhead for every tft pixel
......@@ -461,9 +468,10 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
** Function name: pushRotated - Fast fixed point integer maths version
** Description: Push a rotated copy of the Sprite to another Sprite
*************************************************************************************x*/
// Not compatible with 4bpp
bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp)
{
if ( !_created || _bpp == 4) return false; // Check this Sprite is created
if ( !_created || _bpp == 4) return false; // Check this Sprite is created
if ( !spr->_created || spr->_bpp == 4) return false; // Ckeck destination Sprite is created
// Bounding box parameters
......@@ -658,12 +666,8 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y)
}
else if (_bpp == 4)
{
if (_colorMap == nullptr) {
return;
}
_tft->pushImage(x, y, _dwidth, _dheight, _img4, false, _colorMap);
}
else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8));
}
......
......@@ -15,6 +15,7 @@ class TFT_eSprite : public TFT_eSPI {
// Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed
// RAM required is:
// - 1 bit per pixel for 1 bit colour depth
// - 1 nibble per pixel for 4 bit colour
// - 1 byte per pixel for 8 bit colour
// - 2 bytes per pixel for 16 bit color depth
~TFT_eSprite(void);
......@@ -34,8 +35,8 @@ class TFT_eSprite : public TFT_eSPI {
int8_t getColorDepth(void);
// Set the palette for a 4 bit depth sprite. Only the first 16 colours in the map are used.
void createPalette(uint16_t *palette, int colors = 16); // Palette in RAM
void createPalette(const uint16_t *palette, int colors = 16); // Palette in FLASH
void createPalette(uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in RAM
void createPalette(const uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in FLASH
// Set a single palette index to the given color
void setPaletteColor(uint8_t index, uint16_t color);
......
......@@ -10,7 +10,7 @@
// screen very simple. The rotation is clockwise with increasing angle. The angle is in
// degrees, an angle of 0 means no Sprite rotation.
// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites.
// The pushRotated() function works with 1, 4, 8 and 16 bit per pixel (bpp) Sprites.
// The original Sprite is unchanged so can be plotted again at a different angle.
......@@ -20,6 +20,10 @@
// For 1 bpp Sprites the foreground and background colours are defined with the
// function spr.setBitmapColor(foregroundColor, backgroundColor).
// For 4 bpp Sprites the colour map index is used instead of the 16 bit colour
// e.g. spr.setTextColor(5); // Green text in default colour map
// See "Transparent_Sprite_Demo_4bit" example for default colour map details
// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI
......@@ -46,7 +50,7 @@ void setup() {
void loop() {
int xw = tft.width()/2; // xw, yh is midle of screen
int xw = tft.width()/2; // xw, yh is middle of screen
int yh = tft.height()/2;
......
......@@ -88,7 +88,7 @@ void loop(void)
// Pass the palette to the Sprite class
spr.createPalette(cmap);
// Push Sprite parially off-screen to test cropping
// Push Sprite partially off-screen to test cropping
spr.pushSprite(-40, -40);
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10);
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
......
{
"name": "TFT_eSPI",
"version": "2.2.8",
"version": "2.2.9",
"keywords": "Arduino, tft, ePaper, display, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789, RM68140",
"description": "A TFT and ePaper SPI graphics library with optimisation for ESP8266, ESP32 and STM32",
"repository":
......
name=TFT_eSPI
version=2.2.8
version=2.2.9
author=Bodmer
maintainer=Bodmer
sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment