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:
Damjan Adamic
2014-11-16 19:56:04 +01:00
parent 3449118e07
commit ede1f7ff6f
10 changed files with 94 additions and 14 deletions
+16 -11
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+4 -1
View File
@@ -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

+71
View File
@@ -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