Bitmap tft 1.8 128*160

hello, could anyone help me with a code to show images in bitmap ?, I’m working with a Chinese tft lcd 1.8 128x160 v1.1 , due to it has the ST7735 driver and it works very well for me when I use the Adafruit libraries in arduino

but when i was compiling the program I got the following error:

the code is:

// This #include statement was automatically added by the Particle IDE.
#include <sd-card-library.h>

// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_ST7735.h>
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_GFX.h>

// TFT display and SD card will share the hardware SPI interface.
// Hardware SPI pins are specific to the Arduino board type and
// cannot be remapped to alternate pins.  For Arduino Uno,
// Duemilanove, etc., pin 11 = MOSI, pin 12 = MISO, pin 13 = SCK.
#define cs   A2
#define dc   A1
#define rst  A0 

#define sdcs   D4  // Chip select line for SD card

//Use this reset pin for the shield!
//#define TFT_RST  0  // you can also connect this to the Arduino reset!

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); // hardware spi

void setup(void) {

  // Use this initializer if you're using a 1.8" TFT

  // Use this initializer (uncomment) if you're using a 1.44" TFT

  Serial.print("Initializing SD card...");
  if (!SD.begin(sdcs)) {

  // change the name here!
  bmpDraw("Particle.bmp", 0, 0);
  // wait 5 seconds

void loop() {
// uncomment these lines to draw bitmaps in different locations/rotations!
  tft.fillScreen(ST7735_BLACK); // Clear display
  for(uint8_t i=0; i<4; i++)    // Draw 4 parrots
    bmpDraw("parrot.bmp", tft.width() / 4 * i, tft.height() / 4 * i);
  tft.setRotation(tft.getRotation() + 1); // Inc rotation 90 degrees
// change the name here!
  bmpDraw("Photon.bmp", 0, 0);
  // wait 5 seconds
// change the name here!
  bmpDraw("ruina.bmp", 0, 0);
  // wait 5 seconds
// change the name here!
  bmpDraw("yo.bmp", 0, 0);
  // wait 5 seconds
  // change the name here!
  bmpDraw("calendar.bmp", 0, 0);
  // wait 5 seconds

// 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 BUFFPIXEL 20

void bmpDraw(char *filename, uint8_t x, uint8_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.print("Loading image '");

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

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: "); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("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("Bit Depth: "); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print("Image size: ");

        // 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?
            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
    , 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++];
          } // end pixel
        } // end scanline
        Serial.print("Loaded in ");
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp

  if(!goodBmp) Serial.println("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] =; // LSB
  ((uint8_t *)&result)[1] =; // MSB
  return result;

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

I tried to modify the code in the link, however i have been the same error

The compile issue is the first to fix. You are missing a few things to make the SD card reading work.

Instead of sd-card-library I would use this library
#include <SdFat.h> v1.0.16

You need to create the SdFat object
SdFat sd;

Although you have a SD.begin() you have not specified the SPI bus speed. In my experience the SD.begin() is time critical after startup and needs to be put at the very start of setup(). The SPI_HALF_SPEED runs the SPI bus at half of 60MHz which is plenty for the small screen. You also need to ensure the TFT controller which is using the same SPI bus is set to run at SPI_HALF_SPEED. I use my own version of the Adafruit_ST7735 library - you will need to check in the library code for the SPI.begin();

sd.begin(sdcs, SPI_HALF_SPEED)

I could suggest another couple of changes.

void bmpDraw(const char * filename, uint16_t x, uint16_t y)

And the test for file existing
if (, O_READ))

I haven’t had any display issues for the last couple of years. Good luck.

1 Like

thank you I will try to make the suggested changes and then I will tell you