0

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

enter image description here

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.

6
  • did the code work before you started to modify it?
    – jsotola
    Feb 17, 2019 at 6:44
  • check your bitmap file format here .... hexed.it
    – jsotola
    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. 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 unmodified
    – jsotola
    Feb 17, 2019 at 7:03
  • BMP file format table ..... ue.eti.pg.gda.pl/fpgalab/zadania.spartan3/…
    – jsotola
    Feb 17, 2019 at 7:10

1 Answer 1

0

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).

3
  • 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. 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
    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" Mar 19, 2019 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.