Complete newbie here.
I am following this thread: How to read bitmap image on Arduino
Specifically the third reply from : frarugi87 in my attempt to plot a monochromatic bitmap image with a plotter device. Basically: bitmap>SD card board>arduino uno> plotted image
I attempted to modify their code to work with monochromatic bitmaps and removed the print to file function:
// MODIFIED CODE FROM BELOW CONTRIBUTOR
// (c) Michael Schoeffler 2016, http://www.mschoeffler.de
#include <SD.h> //Load SD library
int chipSelect = 4; //chip select pin for the MicroSD Card Adapter
File file; // file object that is used to read and write data
int32_t readNbytesInt(File *p_file, int position, byte nBytes) // FUNCTION WHICH READS A DETERMINED AMMOUNT OF BYTES INTO A SINGLE VARIABLE
{
if (nBytes > 4)
return 0;
p_file->seek(position);
int32_t weight = 1;
int32_t result = 0;
for (; nBytes; nBytes--)
{
result += weight * p_file->read();
weight <<= 8;
}
return result;
}
void setup() {
Serial.begin(9600); // start serial connection to print out debug messages and data
pinMode(chipSelect, OUTPUT); // chip select pin must be set to OUTPUT mode
if (!SD.begin(chipSelect)) { // Initialize SD card
Serial.println("Could not initialize SD card."); // if return value is false, something went wrong.
}
if (SD.exists("bitmap.bmp")) { // if "bitmap.bmp" exists, say so
Serial.println("Found The Bitmap File.");
}
file = SD.open("bitmap.bmp", FILE_READ); // open the file to an object for reading
// DETERMINE HOW LARGE THE BITMAP FILE IS
int howmany;
howmany = file.available();
Serial.println(howmany); // print the how large the file is
// DETERMINE STARTING IMAGE ARRAY LOCATION IN THE BITMAP FILE
int32_t dataStartingOffset = readNbytesInt(&file, 0x0A, 4);
Serial.println("The starting location in the fiile is...");
Serial.println(dataStartingOffset);
// DETERMINE THE IMAGE HEIGHT AND WIDTH
int32_t imgwidth = readNbytesInt(&file, 0x12, 4);
Serial.println("The image width is the following pixels:");
Serial.println(imgwidth);
int32_t imgheight = readNbytesInt(&file, 0x16, 4);
Serial.println(imgheight);
// MODIFIED CODE. DOES THE COLOR DEPTH LOCATION WORK IN THE BITMAP AND DOES IT GIVE CORRECT INFO ABOUT THE FILE?
int16_t pixelsize = readNbytesInt(&file, 0X1C, 2);
if (pixelsize != 24)
{
Serial.println("This image is most definitely not 24 bpp");
Serial.println(" it is actually a depth of :");
Serial.println(pixelsize);
}
file.seek(dataStartingOffset); //skip bitmap header and go directly to the image data array.
/* for(int32_t i = 0; i < imgheight; i ++) {
for (int32_t j = 0; j < imgwidth; j ++) {
B = file.read();
Serial.println("height and width location from bottom");
Serial.println(i);
Serial.println(j);
Serial.println("B");
Serial.println(B);
}
Serial.println("height advance");
}
*/
int B;
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
B = file.read();
Serial.println(B, BIN);
file.close();
Serial.println("done write");
}
But when I read a 16x16 monochromatic bitmap: see below
At what I assume is the color table starting location (given by dataStartingOffset variable). I get strings two bytes of correct color information, followed by two bytes of just...zeros. Is this a bitmap formatting thing?
Serial output for 16x16 bitmap looks like this:(only up to 9 of the 16 lines starting from the bottom)
Found The Bitmap File. 126 The starting location in the file is... 62 The image width is the following pixels: 16 16 This image is most definitely not 24 bpp it is actually a depth of : 1 1111111 11111110 0 0 11111111 11111111 0 0 11111111 11111111 0 0 11111111 11111111 0 0 11111111 11111111 0 0 11111111 11111111 0 0 11111111 11111111 0 0 11111111 11111111 0 0 1111111 11111110 0 0 done write
And when I try to read a bitmap that is around 200 x 200 pixels, I get very strange height and width numbers that are negative and my above code does not work at all! Does a 16x16 bitmap have different byte structure formatting than a 200x200?
Any help is appreciated. Again, I am a complete newbie here. I am just trying to figure out how to read a bitmap.
-
did the code work before you started to modify it?jsotola– jsotola2019年02月17日 06:44:44 +00:00Commented Feb 17, 2019 at 6:44
-
check your bitmap file format here .... hexed.itjsotola– jsotola2019年02月17日 06:50:57 +00:00Commented Feb 17, 2019 at 6:50
-
That I do not know. It does give me correct values for a 16x16 monochromatic bitmap image (well...including the unwanted zeros), and the code seems straightforward, but I never tested it with a COLOR bitmap. I assume the person tested their code before posting.cheetahchips– cheetahchips2019年02月17日 06:51:21 +00:00Commented Feb 17, 2019 at 6:51
-
never assume anything, but the code in that answer is very nicely formatted, so i would tend to trust it also ....... like i implied in my first comment, run the code unmodifiedjsotola– jsotola2019年02月17日 07:03:35 +00:00Commented Feb 17, 2019 at 7:03
-
BMP file format table ..... ue.eti.pg.gda.pl/fpgalab/zadania.spartan3/…jsotola– jsotola2019年02月17日 07:10:11 +00:00Commented Feb 17, 2019 at 7:10
1 Answer 1
Bitmap files (.BMP) have to have a row size that is a multiple of 4 bytes. Any extra space in a row has to be padded with 0.
Since your rows are 16 pixels wide that equates to 2 bytes. That's not a multiple of 4, so it is padded with to bytes of 0 to make it a multiple of 4.
Your code needs to take that into account and know that if it hasn't read a multiple of 4 bytes then to read enough "dummy" bytes to get to the start of the next row.
Also, note that BMP files are the only files in the known universe where the image data is stored upside down (starting lower-left corner instead of upper-left corner).
-
ah. That makes sense. Thanks for clarification. Any idea why I would be having confusion with larger bitmaps , like 200x200? The color table "start position" ends up being a very large negative number using the code that I posted.cheetahchips– cheetahchips2019年02月17日 21:17:00 +00:00Commented Feb 17, 2019 at 21:17
-
Bitmaps come in numerous different data formats. You should inspect the header to find out what type it is. Here is a library for my chipKIT DisplayCore system (doesn't work with Arduino, only chipKIT), but feel free to take what you like from it.Majenko– Majenko2019年02月17日 21:24:57 +00:00Commented Feb 17, 2019 at 21:24
-
A side note, Postscript and PDF also has the (0,0) origin at the lower left corner of the defined page area. One could possibly argue they are not image formats, but they do describe "ink" on a "page"jose can u c– jose can u c2019年03月19日 14:41:08 +00:00Commented Mar 19, 2019 at 14:41