Cannot draw BMP picture on tft screen shield

Hi,

I've recently bought an Adafruit TFT Arduino Uno Screen Shield with micro sd card included. I want to draw a picture on it using the bmp draw script:

#define BUFFPIXEL 20

void bmpDraw(char *filename, uint8_t x, uint16_t y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();

  if((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print(F("Loading image '"));
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    Serial.print(F("File not found"));
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print(F("Image size: "));
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // 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).
          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; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            tft.pushColor(tft.color565(r,g,b));
          } // end pixel
        } // end scanline
        Serial.print(F("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println(F("BMP format not recognized."));
}

// 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;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File &f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

I've made a bunch of 32x32 PNG icons and I've converted them all into 24 bit BMP pictures. What I load to script to draw the picture I get this error message BMP format not recognized. I don't know why it's not working...

To make new bitmaps, make sure they are less than 240 by 320 pixels and save them in 24-bit BMP format! They must be in 24-bit format, even if they are not 24-bit color as that is the easiest format for the Arduino. You can rotate images using the setRotation() procedure

You can draw as many images as you want - dont forget the names must be less than 8 characters long. Just copy the BMP drawing routines below loop() and call
bmpDraw(bmpfilename, x, y);
For each bitmap. They can be smaller than 320x240 and placed in any location on the screen.

That's wierd because my picture is smaller than 320x240. By the way, what's a 24bit format?

  • Thanks for helping me and don't forget that I speak french... And google translate is not perfect...

What you have shown is a function, not a script. Arduino code is usually C or C++, not a script.

24 bits refers to using 8 bits for red, 8 bits for blue and 8 bits for green. 8+8+8=24

My crystal ball is not working well but it says that the problem is on line 42 of the code that you did not show.

What do the serial prints show you? Please show us as well.

To post code and/or error messages:

  1. Use CTRL-T in the Arduino IDE to autoformat your complete code.
  2. Paste the complete autoformatted code between code tags (the </> button)
    so that we can easily see and deal with your code.
  3. Paste the complete error message between code tags (the </> button)
    so that we can easily see and deal with your messages.
  4. If you already posted without code tags, you may add the code tags by
    editing your post. Do not change your existing posts in any other way.
    You may make additional posts as needed.

Before posting again, you should read the three locked topics at the top of the Programming Questions forum, and any links to which these posts point.

If your project involves wiring, please provide a schematic and/or a wiring diagram and/or a clear photograph of the wiring.

Good Luck!

I've made a bunch of 32x32 PNG icons and I've converted them all into 24 bit BMP pictures. What I load to script to draw the picture I get this error message BMP format not recognized. I don't know why it's not working...

Look at the example bitmap file that the library CAN read. It is NOT a 24 bit file. A 24 bit file has 8 bits for each of red, green, and blue, whereas the library (I think) expects a 16 bit value for r, g, and b (5, 6, 5).

My crystal ball is not working well

Well, you probably shouldn't be using it to read the forum, then. OP asked distinct questions that could be answered.

I've converted them all into 24 bit BMP pictures

How? Whatever method/program you are you using to do the conversion is not creating a correctly formatted 24-bit BMP.
The bmpDraw function will reject the BMP file if:

  • it doesn't begin with the letters 'BM'
  • or the number of colour planes is not 1
  • or it isn't a 24-bits per pixel file
  • or it isn't an uncompressed file.

Pete
P.S. There is a French Section here.

el_supremo:
How? Whatever method/program you are you using to do the conversion is not creating a correctly formatted 24-bit BMP.
The bmpDraw function will reject the BMP file if:

  • it doesn't begin with the letters 'BM'
  • or the number of colour planes is not 1
  • or it isn't a 24-bits per pixel file
  • or it isn't an uncompressed file.

Pete
P.S. There is a French Section here.

I have few questions:

What's a colour plane? (Is it some sort of 3d stuff or layering things?)
How can i verify if the picture is a 24-bit and uncompressed?

And the program i use to convert png to 24bit BMP is https://convertio.co/

Also, there're fewer people in the french forum so i have more chance to get an answer.

It's not a big problem if you don't answer all my question, i may find the answer on the internet.

vaj4088:
What you have shown is a function, not a script. Arduino code is usually C or C++, not a script.

24 bits refers to using 8 bits for red, 8 bits for blue and 8 bits for green. 8+8+8=24

My crystal ball is not working well but it says that the problem is on line 42 of the code that you did not show.

What do the serial prints show you? Please show us as well.

To post code and/or error messages:

  1. Use CTRL-T in the Arduino IDE to autoformat your complete code.
  2. Paste the complete autoformatted code between code tags (the </> button)
    so that we can easily see and deal with your code.
  3. Paste the complete error message between code tags (the </> button)
    so that we can easily see and deal with your messages.
  4. If you already posted without code tags, you may add the code tags by
    editing your post. Do not change your existing posts in any other way.
    You may make additional posts as needed.

Before posting again, you should read the three locked topics at the top of the Programming Questions forum, and any links to which these posts point.

If your project involves wiring, please provide a schematic and/or a wiring diagram and/or a clear photograph of the wiring.

Good Luck!

Ok.

I didn't show all how the script because the rest is useless. It's not only one function, there's two other at the end. There's no wiring, it's simply a screen shield that you plug on the arduino uno (2.8 TFT Touch Shield for Arduino with Resistive Touch Screen v2 [STEMMA QT / Qwiic] : ID 1651 : $24.95 : Adafruit Industries, Unique & fun DIY electronics and kits). The serial return me BMP format not recognized.

Post one of the PNG icons and the BMP file that convertio.co produced from it.

I have the feeling that the problem might be the fact that you are converting icon files. They can have multiple layers and multiple images in them which would produce a BMP file that the bmpDraw function won't like.

Pete

PaulS:
Look at the example bitmap file that the library CAN read. It is NOT a 24 bit file. A 24 bit file has 8 bits for each of red, green, and blue, whereas the library (I think) expects a 16 bit value for r, g, and b (5, 6, 5).

Look at this: Drawing Bitmaps | Adafruit 2.8" TFT Touch Shield v2 - Capacitive or Resistive | Adafruit Learning System
This said that the pic need to be 24bit not 16...

el_supremo:
Post one of the PNG icons and the BMP file that convertio.co produced from it.

I have the feeling that the problem might be the fact that you are converting icon files. They can have multiple layers and multiple images in them which would produce a BMP file that the bmpDraw function won't like.

Pete

Here's the file

el_supremo:
Post one of the PNG icons and the BMP file that convertio.co produced from it.

I have the feeling that the problem might be the fact that you are converting icon files. They can have multiple layers and multiple images in them which would produce a BMP file that the bmpDraw function won't like.

Pete

I cannot attach bmp files... Here's the link File sharing and storage made simple

That code does require a 24-bit BMP which it then converts to a 565 format.

BTW. There is a bug in that code. It looks essentially the same as the code I'm using with an ST7735 display and it doesn't display the colours correctly. Near the end of bmpDraw it has these three lines:

          b = sdbuffer[buffidx++];
          g = sdbuffer[buffidx++];
          r = sdbuffer[buffidx++];

BMP files store the three colours in RGB order but this is reading them in BGR. They should be:

          r = sdbuffer[buffidx++];
          g = sdbuffer[buffidx++];
          b = sdbuffer[buffidx++];

Pete

Your file isn't there.
This sticky thread (Out of Date) Guide: How to Insert Uploaded Images in a Post - Website and Forum - Arduino Forum explains how to post an image in a message.

Pete

el_supremo:
Your file isn't there.
This sticky thread (Out of Date) Guide: How to Insert Uploaded Images in a Post - Website and Forum - Arduino Forum explains how to post an image in a message.

Pete

A glitch on the website happen... My Reply is wierd...
I write a link because i cannot attach BMP picture, only PNG, JPEG, JPG, GIF

The problem with icons is that they almost always have an alpha (transparent) channel. When a program converts the icon to a BMP, it has to make the BMP 32-bits instead of 24-bits to allow for the extra one (or more) bits of alpha information per pixel.
Even if you could convert the PNG to BMP correctly, you would still have a problem with the part of the image which is supposed to be transparent because the bmpDraw function doesn't handle transparency at all. I don't think your display does either.

Pete

I need to remove the transparency channel of the PNG file before converting it to 24bit BMP? If it's that what i need to do... I don't know how to do it...

Post a PNG file - IconAction.png.

Pete

Emmm... I know how to do it but i need Photoshop or Gimp... Gimp glitch out on my computer and PS is realy expensive.

There is an image converter which is free for personal use: Download Image File Converter Software Free for PC or Mac. Under the red "Download Now" button there is some smaller red text "Get it free" which has the link to the free Windows version.
I found an example of a transparent PNG online and converted it with that program. It gives you a few options of the BMP's format (See the Encoder Options button) and there is also an Options menu where you can specify which colour is to be used to replace the transparent parts of the image.

Pete

I've converted my 32 bit bmp to a 24 bit bmp picture but my picture editor still allow me to use the transparent chanel

STUDIOCRAFTapps:
I've converted my 32 bit bmp to a 24 bit bmp picture but my picture editor still allow me to use the transparent chanel

WTF i have 32 planes things on my picture... What's a plane?

Sometimes it gives me 1 planes and it's compressed and sometimes it gives me 32 planes and it's uncompressed