Reading a BMP file and trigger the output LED

Hi,

I am Creating a my first project using Arduino. Reading the Image (BMP) file and trigger the output LED.

Please suggest the following,

  1. Which type of board should i buy,

  2. Two type of LED required i.e., example white for blank and red for not empty.

  3. Any example programs

With best regards,
Suresh

What size is the BMP file ?
What will you do with its contents assuming that you can read it ?
What is it about the file that triggers the LED ?

What size is the BMP file ?

Its max 200 kb.

What will you do with its contents assuming that you can read it ?
Its a kind design pattern. (attached file for more info).

What is it about the file that triggers the LED ?
See the attachment for example if its black pattern its blow some colour and white pattern its blow different LED

P.S : Unable to attach BMP files so rename it as jpg for uploading.

Example.jpg

I am still not clear what you are trying to do.

Do you want to read the file byte by byte and do something based on the byte value, for instance ?

More details please

Yes you are correct.

I want to read the file byte by byte and do something based on the byte value.

sureshdba2003:
I want to read the file byte by byte and do something based on the byte value.

Simply read the file or interpret it as an image?

To read the file byte by byte from say an SD card is probably trivial; I suppose a file is a file is a file, regardless of what its internal format is, and bytes are bytes.

But you need to clarify if you actually mean to use your leds to indicate if a spot on the page is blank or not: I suspect that is what you want to do. Then that's a whole different kettle of fish, since a .bmp file conforms to this specification and the bytes in the file are not readily "viewable" as a sort of "dot dot space dot space space space dot dot dot dot dot space dot" pattern. So you would need to decode the .bmp file bytes into the bits that you want.

I did a quick search and there seem to be some libraries around that are used to display .bmp files on Arduino graphics screens. Perhaps one of those could be used to "intercept" the bits to drive your leds.

But unless you can find a library that can do that, I doubt if this is a...

I am Creating a my first project using Arduino.

.... type of project. Even with a library off the shelf, it may not be.

I suspect you're going to need some specialist advice from an Arduino graphics guru.

Further to above, maybe it's not that difficult, if all you want to do is see if a byte represents white space or not. Looking at the hex dump below (from a small .bmp I saved from Paint) once you get past the .bmp header the image data starts with all those FF's. I suspect they are white-space, and later on in the data the bytes that are not FF's will be the not-white-space parts of the page.

So maybe you could get away with opening the file, read the value at offset 10 decimal 0a hex (it's 36 hex in this one) to the start of the image data from the header, skip to that point, and then do what you want with each of those bytes from there on?

Whatever you want to do with the image bytes, however you want to interpret them, it should actually quite straightforward to read the header to confirm where the image starts, and read every byte after that.

bmp dump1.GIF

bmp dump2.GIF

bmp dump1.GIF

bmp dump2.GIF

Thanks for your detailed reply.

I'll check and revert as suggested...

The code below reads in a .BMP from the SD card. (First checks that it starts with BM which is the signature of a .BMP.)

It reads the field in the header that defines where the data starts, and starts printing the bytes from that point on.

At least in the file I created, most of the bytes are FF which is what makes me think that’s the white spece.

SO… I decided to check each byte of image data and only print the non-FF ones. That at least shows that a byte can be interrogated, and it would be easy to perform or not-perform other actions based on each byte’s value. I also have a variable which sets how many you actually want: for testing I just printed the first 10 non-FFs.

Here’s the serial print:

Initializing SD card...card initialized.
File is open
  We seem to have a BMP....
  Reading offset to image data as 36
  *** Here comes the image data **
   (only printing the first 10 non FF's)
Got a 0 at offset E7
Got a 0 at offset E8
Got a 0 at offset E9
Got a 0 at offset 19B
Got a 0 at offset 19C
Got a 0 at offset 19D
Got a FFFFFFFC at offset 1AA
Got a FFFFFFF4 at offset 1AB
Got a FFFFFFF3 at offset 1AC
Got a FFFFFFEA at offset 1AD
             *** END of FILE ***

Here’s the sketch:

//  https://forum.arduino.cc/index.php?topic=642004
//  22 oct 2019
// bmp file reader

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile_IN = SD.open("test.bmp"); // file name goes here <<<<<<<<<<<<<<<<

  // if the file is available, write to it:
  if (dataFile_IN)
  {
    Serial.println("File is open");
    unsigned long offset = 0;
    char theChar;
    int offsetToImage = -1;
    int howManyToPrint = 10; // set this value <<<<<<<<<<<<<<<<<
    int howManyPrinted = 0;

    while (dataFile_IN.available())
    {
      if (offset != 0x0a)
      {
        theChar = dataFile_IN.read();
      }
      else
      {
        offsetToImage = dataFile_IN.read();
      }

      //check if it's a bmp file first...
      if (offset == 0 && theChar != 'B')
      {
        Serial.println("Not a BMP");
        while (1) {}
      }

      if (offset == 1 && theChar != 'M')
      {
        Serial.println("Not a BMP");
        while (1) {}
      }

      if (offset == 1) Serial.println("  We seem to have a BMP...."); //we would have stopped by now if not
      if (offset == 0x0a) //this is the field that tells us where the image begins
      {
        Serial.print("  Reading offset to image data as " );
        Serial.println(offsetToImage, HEX);
      }

      if (offset == offsetToImage)
      {
        Serial.println("  *** Here comes the image data **");
        Serial.print("   (only printing the first ");
        Serial.print(howManyToPrint);
        Serial.println(" non FF's)");
      }

      
      if (offset > offsetToImage && offsetToImage != -1)
      {
        if (theChar != 0xFFFFFFFF && howManyPrinted < howManyToPrint)
        {
          Serial.print("Got a ");
          //Serial.write(theChar);
          Serial.print(theChar, HEX);
          Serial.print(" at offset ");
          Serial.println(offset, HEX);
          howManyPrinted++;
        }
      }
      offset++;
    }
    dataFile_IN.close();
    Serial.println("             *** END of FILE ***");
  }
  // if the file isn't open, pop up an error:
  else
  {
    Serial.println("error opening file, check the name");
  }
}//setup

void loop()
{
}//loop

Below is the partial hex dump for the file in the above post.

  • The red pen shows the BM signature.
  • The blue pen shows the offset to the image data
  • The yellow highlights show the 10 non-FF bytes at the offsets shown in the serial monitor output.

Ok one last piece of info since I had a further look at how the header is defined.

The 2 bytes from offset 28 decimal, 1c hex, tell us how many bits there are per pixel. Looking at the dump in the previous post, you will see that's an 18 hex, 24 decimal in this case, or 3 bytes.

I see that the value can legally be 1, 4, 8 or 24 bits/pixel. In the case of 1 and 4, you would have to extract the 8 bits or 2 nybbles from a byte; 8 bits means you would use 1 byte; 24 means 3 bytes per pixel. (edit: I would surmise that 3 bytes is RGB.)

So now you probably have what you need to decode a bmp for whatever it is you want to do, which is still not really clear.

But the process would be:

  • Check the file is actually a BMP, by checking the BM signature.
  • Read the number of bits per pixel and figure out how many bytes (or part thereof) that is
  • Read the offset to the data
  • Read in the image data from the offset forwards, in the correct sized chunks
  • Asses each pixel according to your rule and do the LED thing.