Added scaled Group5 compressed image drawing

This commit is contained in:
Laurence Bank
2025-02-17 13:59:54 +00:00
parent 34415ef338
commit b674746b53
4 changed files with 67 additions and 32 deletions
+24 -14
View File
@@ -5,25 +5,19 @@
#include <bb_epaper.h>
#include "bomb.h" // uncompressed 40x40 image
#include "bart.h" // compressed 128x64 image
#include "smiley.h" // 100x100 compressed image
BBEPAPER bbep(EP295_128x296);
// Mike Rankin's C3 e-ink PCB
//#define PIN_DC 3
//#define PIN_BUSY 1
//#define PIN_RST 10
//#define PIN_CS 7
//#define PIN_MOSI 6
//#define PIN_SCK 4
#define PIN_DC 16
#define PIN_BUSY 15
#define PIN_RST 14
#define PIN_CS 10
#define PIN_MOSI MOSI
#define PIN_SCK SCK
#define CS_PIN 2
#define DC_PIN 3
#define RESET_PIN 5
#define BUSY_PIN 4
#define CLK_PIN 1
#define MOSI_PIN 0
void setup()
{
bbep.initIO(PIN_DC, PIN_RST, PIN_BUSY, PIN_CS, PIN_MOSI, PIN_SCK, 8000000);
bbep.initIO(DC_PIN, RESET_PIN, BUSY_PIN, CS_PIN, MOSI_PIN, CLK_PIN, 8000000);
// Do everything with no local buffer
bbep.fillScreen(BBEP_WHITE);
bbep.setCursor(0,4); // start a few pixels away from the top edge
@@ -41,6 +35,22 @@ void setup()
}
bbep.refresh(REFRESH_FULL);
bbep.wait();
delay(3000);
// Scaled drawing requires a back buffer
bbep.allocBuffer();
bbep.setRotation(270);
bbep.fillScreen(BBEP_WHITE);
bbep.setFont(FONT_12x16);
bbep.setCursor(0,0);
bbep.print("Scaled G5 needs RAM");
float f = 0.5;
for (int i=0; i<5; i++) {
bbep.loadG5Image(smiley, (int)(i*50), 16+(int)(i*12.5*f), BBEP_TRANSPARENT, BBEP_BLACK, f);
f += 0.25;
}
bbep.writePlane();
bbep.refresh(REFRESH_FULL);
bbep.wait();
bbep.sleep(DEEP_SLEEP);
}
+40 -15
View File
@@ -505,18 +505,30 @@ void InvertBytes(uint8_t *pData, uint8_t bLen)
// draw the 1's bits as the FG color and leave
// the background (0 pixels) unchanged - aka transparent.
//
int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int iBG)
int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int iBG, float fScale)
{
uint16_t rc, tx, ty, cx, cy, size;
uint16_t rc, tx, ty, cx, cy, dx, dy, size;
int width, height;
BB_BITMAP *pbbb;
if (pBBEP == NULL || pG5 == NULL) return BBEP_ERROR_BAD_PARAMETER;
iFG = pBBEP->pColorLookup[iFG & 0xf]; // translate the color for this display type
iBG = pBBEP->pColorLookup[iBG & 0xf];
uint32_t u32Frac, u32XAcc, u32YAcc; // integer fraction vars
if (pBBEP == NULL || pG5 == NULL || fScale < 0.01) return BBEP_ERROR_BAD_PARAMETER;
if (iFG != BBEP_TRANSPARENT) {
iFG = pBBEP->pColorLookup[iFG & 0xf]; // translate the color for this display type
}
if (iBG != BBEP_TRANSPARENT) {
iBG = pBBEP->pColorLookup[iBG & 0xf];
}
pbbb = (BB_BITMAP *)pG5;
if (pgm_read_word(&pbbb->u16Marker) != BB_BITMAP_MARKER) return BBEP_ERROR_BAD_DATA;
u32Frac = (uint32_t)(65536.0f / fScale); // calculate the fraction to advance the destination x/y
cx = pgm_read_word(&pbbb->width);
cy = pgm_read_word(&pbbb->height);
width = pBBEP->width;
height = pBBEP->height;
// Calculate scaled destination size
dx = (int)(fScale * (float)cx);
dy = (int)(fScale * (float)cy);
size = pgm_read_word(&pbbb->size);
if (iFG == -1) iFG = BBEP_WHITE;
if (iBG == -1) iBG = BBEP_BLACK;
@@ -525,10 +537,16 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i
if (!pBBEP->ucScreen) { // no back buffer
bbepSetAddrWindow(pBBEP, x, y, cx+(x&7), cy);
bbepStartWrite(pBBEP, pBBEP->iPlane); // get ready to write
dy = cy; // scaling is only supported on internal framebuffers
u32Frac = 65536; // force to 1.0 scale
}
for (ty=y; ty<y+cy && ty < pBBEP->height; ty++) {
u32YAcc = 65536; // force first line to get decoded
for (ty=y; ty<y+dy && ty < height; ty++) {
uint8_t u8, *s, src_mask;
g5_decode_line(&g5dec, u8Cache);
while (u32YAcc >= 65536) { // advance to next source line
g5_decode_line(&g5dec, u8Cache);
u32YAcc -= 65536;
}
if (!pBBEP->ucScreen) {
if (x & 7) { // need to shift it over by 1-7 bits
uint8_t *d = s = u8Cache, uc1, uc0; // last shifted byte
@@ -553,13 +571,11 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i
bbepWriteData(pBBEP, u8Cache, (cx+(x&7)+7)>>3);
} else { // use the setPixel function for more features
#ifndef NO_RAM
src_mask = 0; // make it read a byte to start
s = u8Cache;
for (tx=x; tx<x+cx; tx++) {
if (src_mask == 0) { // need to load the next byte
u8 = *s++;
src_mask = 0x80; // MSB on left
}
u32XAcc = 0;
u8 = *s++; // grab first source byte (8 pixels)
src_mask = 0x80;
for (tx=x; tx<x+dx && tx < width; tx++) {
if (u8 & src_mask) {
if (iFG != BBEP_TRANSPARENT)
(*pBBEP->pfnSetPixelFast)(pBBEP, tx, ty, (uint8_t)iFG);
@@ -567,10 +583,19 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i
if (iBG != BBEP_TRANSPARENT)
(*pBBEP->pfnSetPixelFast)(pBBEP, tx, ty, (uint8_t)iBG);
}
src_mask >>= 1;
u32XAcc += u32Frac;
while (u32XAcc >= 65536) {
u32XAcc -= 65536; // whole source pixel horizontal movement
src_mask >>= 1;
if (src_mask == 0) { // need to load the next byte
u8 = *s++;
src_mask = 0x80;
}
}
} // for tx
#endif // NO_RAM
}
u32YAcc += u32Frac;
} // for y
return BBEP_SUCCESS;
} /* bbepLoadG5() */
+2 -2
View File
@@ -223,9 +223,9 @@ void BBEPAPER::setCursor(int x, int y)
_bbep.iCursorY = y;
} /* setCursor() */
int BBEPAPER::loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG)
int BBEPAPER::loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG, float fScale)
{
return bbepLoadG5(&_bbep, pG5, x, y, iFG, iBG);
return bbepLoadG5(&_bbep, pG5, x, y, iFG, iBG, fScale);
} /* loadG5Image() */
int BBEPAPER::loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG)
+1 -1
View File
@@ -447,7 +447,7 @@ class BBEPAPER
void setCursor(int x, int y);
int loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG);
int loadBMP3(const uint8_t *pBMP, int x, int y);
int loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG);
int loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG, float fScale = 1.0f);
void setFont(int iFont);
void setFont(const void *pFont);
void drawLine(int x1, int y1, int x2, int y2, int iColor);