Sorry for that , Mea culpa , mea culpa mea maxima culpa .......
When I change the name in :
char bmp_name[FILENAME_LEN] = {"02.bmp",};
into the name of my bmp-file I get some lines and colors on the display ( 3.5" MCU on a Arduino-UNO ) insteat a readable picture .
The 02.bmp original bmp is working fine .
Than I did following test . I loaded 02.bmp in IRFAN and saved the file right again as bmp. That IRFAN-bmp don't work in the sketch . So my idea was that something in the original picture was differend from mine .
When I check out the metadata of both pictures , for me they are the same .
So therefore my question: what's wrong with my picture or what to change in the code to make accept my picture ?
I provide you with a BMP display program that will accept several different .BMP formats.
If you are only using the 24-bit colour format, I could strip out all the other code.
Or you could do it as a "user exercise".
There are many examples on the Internet that can render a BMP24 file. (only BMP24)
You appear to have made a half-hearted attempt to do your own thing.
I could debug it for you but this will defeat the "user exercise".
Please note that you do not need enormous buffers. I tend to use a Uno which has limited SRAM.
If you want readers to assist you, it is worth making your code "buildable" by forum members.
I know my knowledge of Arduino or C++ is limited but using some code ( sketch ) without understanding is something I don't like to do .
I like you bmp program but as I don't understand all of it I'm not capable to strip out all the things I don't need for my project .
I tried to do it but was blocked several times . Thanks to that I learned a lot about cases , SD-cards commands and other functions . So for me it was not a lost of time .
What I like to do :
using a MEGA
monitoring one ( 1 ) bitmap om a 3.5" tft screen .
No code in the loop
If you will strip your code monitoring one bitmap ( my rotator ) please do that.
After all I will study your code again and do some "reverce engeneering" .
Here is a minimal sketch. You would normally use the return value from showBMP24()
showBMP24_F8VOA.ino
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <SD.h>
#define SD_CS 10
#define RESTORE_SPI_GPIO() //empty for parallel TFT
void setup()
{
uint16_t ID;
Serial.begin(9600);
Serial.print("Show BMP files on TFT with ID:0x");
ID = tft.readID();
Serial.println(ID, HEX);
tft.begin(ID);
bool good = SD.begin(SD_CS);
if (!good) {
Serial.print(F("cannot start SD"));
while (1) yield();
}
}
void loop()
{
tft.setRotation(1); //LANDSCAPE
tft.fillScreen(TFT_BLUE);
uint8_t ret = showBMP24("/rotato~1.bmp", 0, 0);
delay(5000);
}
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.
uint16_t read16(File &f) {
uint16_t result;
f.read(&result, sizeof(result));
return result;
}
uint32_t read32(File &f) {
uint32_t result;
f.read(&result, sizeof(result));
return result;
}
// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates. It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel). Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster. 20 pixels seems a
// good balance.
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL 20
uint8_t showBMP24(char *nm, int x, int y)
{
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24, 16, 8, 4, 1)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[BUFFPIXEL];
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col, lcdbufsiz = BUFFPIXEL, buffidx;
uint32_t pos; // seek position
uint16_t bmpID;
uint16_t n; // blocks read
uint8_t ret;
if ((x >= tft.width()) || (y >= tft.height()))
return 1; // off screen
bmpFile = SD.open(nm); // Parse BMP header
bmpID = read16(bmpFile); // BMP signature
(void) read32(bmpFile); // Read & ignore file size
(void) read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
(void) read32(bmpFile); // Read & ignore DIB header size
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
n = read16(bmpFile); // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
pos = read32(bmpFile); // format
if (bmpID != 0x4D42) ret = 2; // bad ID
else if (bmpDepth != 24) ret = 4; // unsupported format
else {
bool first = true;
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
if (bmpHeight < 0) { // If negative, image is in top-down order.
bmpHeight = -bmpHeight;
flip = false;
}
w = bmpWidth;
h = bmpHeight;
RESTORE_SPI_GPIO();
// tft.setRotation(w > h ? 1 : 0); //PORTRAIT or LANDSCAPE
if ((x + w) >= tft.width()) // Crop area to be loaded
w = tft.width() - x;
if ((y + h) >= tft.height()) //
h = tft.height() - y;
RESTORE_SPI_GPIO();
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
uint8_t r, g, b, *sdptr;
int lcdidx, lcdleft;
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; ) { //pixels in row
lcdleft = w - col;
if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
uint16_t color;
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
color = tft.color565(r, g, b);
lcdbuffer[lcdidx] = color;
}
RESTORE_SPI_GPIO();
tft.pushColors(lcdbuffer, lcdidx, first);
first = false;
col += lcdidx;
} // end cols
} // end rows
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
ret = 0; // good render
}
bmpFile.close();
RESTORE_SPI_GPIO();
return (ret);
}
You could always pre-process the BMP24 file into a RAW file with known dimensions.
This is much simpler to display.
You can call showBMP24() as a one-off in setup()
I put it in loop() so that you could see it working.
There are lots of variables. You can declare several on the same line.
There is nothing complicated. You read width, height, ... from the BMP header.
Then read each row as RGBRGBRGB... i.e. each pixel as RGB
Rows are normally stored bottom to top in th BMP file.
Sometimes they are in top to bottom order.
Preprocessing all the RGB into a raw sequence of 16-bit pixels LHLHLHLH... is what the UTFT utility does.
I have a small problem with the bitmap and do not find the reason .
Attached you will find the whole sketch.
I use a MEGA and the 3.5 inch screen.
The sketch is not the problem , the rotator is working fine.Some small details but that's for later.
But :
When I start the sketch from the USB power or with an extern power source , the bitmat is not on the right place on the screen . The bitmap is out of the center and more to the right side . On the left side you can see than the beginning of the picture ( a small vertical white line )
When , after starting like above , I upload the sketch again , the bitmap is in the center .
Problem is :
every time I restart the Mega ( shut down the power and put it back on ) the BMP move on the screen a little bit to the right. Sometimes after restarting a few times , the screen is back to normal.
The screen and the Mega are powered by 5VDC ( stab with a 7805 - like it should be ) I checked this PS , no hum , no shut down or other issues