Fixed bmpLoad():
* added gtests * fixed various memory leaks * fixed wrong display of images with width < 8 * fixed wrong display of images with odd width and/or height
This commit is contained in:
+16
-11
@@ -44,7 +44,9 @@ const pm_char * bmpLoad(uint8_t *bmp, const char *filename, const unsigned int w
|
||||
uint8_t bmpBuf[LCD_W]; /* maximum with LCD_W */
|
||||
uint8_t *buf = &bmpBuf[0];
|
||||
|
||||
assert(width <= LCD_W);
|
||||
if (width > LCD_W) {
|
||||
return STR_INCOMPATIBLE;
|
||||
}
|
||||
|
||||
FRESULT result = f_open(&bmpFile, filename, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
@@ -70,7 +72,7 @@ const pm_char * bmpLoad(uint8_t *bmp, const char *filename, const unsigned int w
|
||||
uint32_t fsize = *((uint32_t *)&buf[2]);
|
||||
uint32_t hsize = *((uint32_t *)&buf[10]); /* header size */
|
||||
|
||||
uint32_t len = limit((uint32_t)0, (uint32_t)(hsize-14), (uint32_t)32);
|
||||
uint32_t len = limit((uint32_t)4, (uint32_t)(hsize-14), (uint32_t)32);
|
||||
result = f_read(&bmpFile, buf, len, &read);
|
||||
if (result != FR_OK || read != len) {
|
||||
f_close(&bmpFile);
|
||||
@@ -152,16 +154,16 @@ const pm_char * bmpLoad(uint8_t *bmp, const char *filename, const unsigned int w
|
||||
*dest++ = w;
|
||||
*dest++ = h;
|
||||
|
||||
memset(dest, 0, w*((h+7)/8)*4);
|
||||
memset(dest, 0, BITMAP_BUFFER_SIZE(w, h) - 2);
|
||||
|
||||
uint32_t n;
|
||||
uint32_t rowSize;
|
||||
|
||||
switch (depth) {
|
||||
case 1:
|
||||
n = w/8;
|
||||
rowSize = ((w+31)/32)*4;
|
||||
for (uint32_t i=0; i<h; i+=2) {
|
||||
result = f_read(&bmpFile, buf, n*2, &read);
|
||||
if (result != FR_OK || read != n*2) {
|
||||
result = f_read(&bmpFile, buf, rowSize*2, &read);
|
||||
if (result != FR_OK || read != rowSize*2) {
|
||||
f_close(&bmpFile);
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
@@ -170,30 +172,33 @@ const pm_char * bmpLoad(uint8_t *bmp, const char *filename, const unsigned int w
|
||||
uint8_t * dst = dest + (h-i-2)/2 * w + j;
|
||||
if (!(buf[j/8] & (1<<(7-(j%8)))))
|
||||
*dst |= 0xF0;
|
||||
if (!(buf[n+j/8] & (1<<(7-(j%8)))))
|
||||
if (!(buf[rowSize+j/8] & (1<<(7-(j%8)))))
|
||||
*dst |= 0x0F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rowSize = ((4*w+31)/32)*4;
|
||||
for (int32_t i=h-1; i>=0; i--) {
|
||||
result = f_read(&bmpFile, buf, ((w+7)/8)*4, &read);
|
||||
if (result != FR_OK || read != ((w+7)/8)*4) {
|
||||
result = f_read(&bmpFile, buf, rowSize, &read);
|
||||
if (result != FR_OK || read != rowSize) {
|
||||
f_close(&bmpFile);
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
for (uint32_t j=0; j<(w+1)/2; j++) {
|
||||
for (uint32_t j=0; j<rowSize; j++) {
|
||||
uint8_t * dst = dest + (i/2)*w + j*2;
|
||||
if (i & 1) {
|
||||
uint8_t val = palette[(buf[j] >> 4) & 0x0F] << 4;
|
||||
*dst |= val ^ 0xF0;
|
||||
if ((j+1)*2 >= w) break;
|
||||
val = palette[buf[j] & 0x0F] << 4;
|
||||
*(dst+1) |= val ^ 0xF0;
|
||||
}
|
||||
else {
|
||||
uint8_t val = palette[(buf[j] >> 4) & 0x0F];
|
||||
*dst |= val ^ 0x0F;
|
||||
if ((j+1)*2 >= w) break;
|
||||
val = palette[buf[j] & 0x0F];
|
||||
*(dst+1) |= val ^ 0x0F;
|
||||
}
|
||||
|
||||
+1
-1
@@ -450,7 +450,7 @@ static int luaLcdDrawPixmap(lua_State *L)
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
const char * filename = luaL_checkstring(L, 3);
|
||||
uint8_t bitmap[2+LCD_W/2*LCD_H/2]; // width max is LCD_W/2 pixels for saving stack and avoid a malloc here
|
||||
uint8_t bitmap[BITMAP_BUFFER_SIZE(LCD_W/2, LCD_H)]; // width max is LCD_W/2 pixels for saving stack and avoid a malloc here
|
||||
const pm_char * error = bmpLoad(bitmap, filename, LCD_W/2, LCD_H);
|
||||
if (!error) {
|
||||
lcd_bmp(x, y, bitmap);
|
||||
|
||||
+2
-1
@@ -439,9 +439,10 @@ enum PotType {
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#define BITMAP_BUFFER_SIZE(width, height) (2 + width * ((height+7)/8)*4)
|
||||
#define MODEL_BITMAP_WIDTH 64
|
||||
#define MODEL_BITMAP_HEIGHT 32
|
||||
#define MODEL_BITMAP_SIZE (2+4*(MODEL_BITMAP_WIDTH*MODEL_BITMAP_HEIGHT/8))
|
||||
#define MODEL_BITMAP_SIZE BITMAP_BUFFER_SIZE(MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)
|
||||
extern uint8_t modelBitmap[MODEL_BITMAP_SIZE];
|
||||
void loadModelBitmap(char *name, uint8_t *bitmap);
|
||||
#define LOAD_MODEL_BITMAP() loadModelBitmap(g_model.header.bitmap, modelBitmap)
|
||||
|
||||
@@ -520,7 +520,10 @@ FRESULT f_open (FIL * fil, const TCHAR *name, BYTE flag)
|
||||
|
||||
FRESULT f_read (FIL* fil, void* data, UINT size, UINT* read)
|
||||
{
|
||||
if (fil && fil->fs) *read = fread(data, 1, size, (FILE*)fil->fs);
|
||||
if (fil && fil->fs) {
|
||||
*read = fread(data, 1, size, (FILE*)fil->fs);
|
||||
// TRACE("fread(%p) %u, %u", fil->fs, size, *read);
|
||||
}
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
Binary file not shown.
|
After Width: | Height: | Size: 190 B |
Binary file not shown.
|
After Width: | Height: | Size: 614 B |
Binary file not shown.
|
After Width: | Height: | Size: 242 B |
@@ -296,3 +296,74 @@ TEST(Lcd, lcd_vlineStip)
|
||||
}
|
||||
#endif
|
||||
|
||||
template <int padding> class TestBuffer
|
||||
{
|
||||
private:
|
||||
uint8_t * buf;
|
||||
uint32_t size;
|
||||
public:
|
||||
TestBuffer(uint32_t size) : buf(0), size(size) {
|
||||
buf = new uint8_t[size + padding * 2];
|
||||
memset(buf, 0xA5, padding);
|
||||
memset(buf+padding, 0x00, size);
|
||||
memset(buf+padding+size, 0x5A, padding);
|
||||
};
|
||||
~TestBuffer() { if (buf) delete[] buf; };
|
||||
uint8_t * buffer() { return buf + padding; };
|
||||
void leakCheck() const {
|
||||
uint8_t paddingCompareBuf[padding];
|
||||
memset(paddingCompareBuf, 0xA5, padding);
|
||||
if (memcmp(buf, paddingCompareBuf, padding) != 0) {
|
||||
ADD_FAILURE() << "buffer leaked low";
|
||||
};
|
||||
memset(paddingCompareBuf, 0x5A, padding);
|
||||
if (memcmp(buf+padding+size, paddingCompareBuf, padding) != 0) {
|
||||
ADD_FAILURE() << "buffer leaked high";
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
TEST(Lcd, lcd_bmpLoadAndDisplay)
|
||||
{
|
||||
lcd_clear();
|
||||
// Test proper BMP files, they should display correctly
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(7, 32));
|
||||
EXPECT_EQ(bmpLoad(bitmap.buffer(), "./tests/4b_7x32.bmp", 7, 32), (char *)0);
|
||||
bitmap.leakCheck();
|
||||
lcd_bmp(10, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(6, 32));
|
||||
EXPECT_EQ(bmpLoad(bitmap.buffer(), "./tests/1b_6x32.bmp", 6, 32), (char *)0);
|
||||
bitmap.leakCheck();
|
||||
lcd_bmp(20, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(31, 31));
|
||||
EXPECT_EQ(bmpLoad(bitmap.buffer(), "./tests/4b_31x31.bmp", 31, 31), (char *)0);
|
||||
bitmap.leakCheck();
|
||||
lcd_bmp(30, 2, bitmap.buffer());
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(39, 32));
|
||||
EXPECT_EQ(bmpLoad(bitmap.buffer(), "./tests/1b_39x32.bmp", 39, 32), (char *)0);
|
||||
bitmap.leakCheck();
|
||||
lcd_bmp(70, 2, bitmap.buffer());
|
||||
}
|
||||
EXPECT_TRUE(checkScreenshot("lcd_bmpLoadAndDisplay"));
|
||||
|
||||
// Test various bad BMP files, they should not display
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(LCD_W+1, 32));
|
||||
EXPECT_EQ(bmpLoad(bitmap.buffer(), "", LCD_W+1, 32), STR_INCOMPATIBLE) << "to wide";
|
||||
bitmap.leakCheck();
|
||||
}
|
||||
{
|
||||
TestBuffer<1000> bitmap(BITMAP_BUFFER_SIZE(10, 10));
|
||||
EXPECT_EQ(bmpLoad(bitmap.buffer(), "./tests/1b_39x32.bmp", 10, 10), STR_INCOMPATIBLE) << "to small buffer";
|
||||
bitmap.leakCheck();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user