Color Garbage

Hello. I have recently purchased an Arduino compatible 2.8" TFT Touch Shield by Seedstudio (http://seeedstudio.com/wiki/2.8’’_TFT_Touch_Shield). I started to run some demo sketches using a SD card reader also by Seedstudio (http://www.seeedstudio.com/depot/sd-card-shield-p-492.html) and my Arduino uno. One of these sketches is called tftbmp (http://seeedstudio.com/wiki/images/1/11/Tftbmp_demo.zip). After downloading the sketch to my Arduino uno, have copied two 24-bit bmp pictures in a SD card and set pin 10 of Arduino, I am getting a kind of color garbage as shown. I understand I have fall between two stools testing products from different manufacturers together (this is usual in integration). So, if someone else has been working in tests similar to this, any help is welcome.

Here the picture of the color garbage, the code and serial outputs.

//  This sketch is adapted to Seeed's TFT library from 
//  https://github.com/adafruit/TFTLCD-Library/blob/master/examples/tftbmp/tftbmp.pde
//  by ladyada/adafruit under MIT license

#include <SD.h>
#include <TFT.h>

// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
// the file itself
File bmpFile;

// information we extract about the bitmap file
int bmpWidth, bmpHeight;
uint8_t bmpDepth, bmpImageoffset;

void setup()
{
  Serial.begin(9600);
 
  Tft.init();
 
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT); //53 is used as chip select pin

  if (!SD.begin(10)) { //53 is used as chip select pin
    Serial.println("failed!");
    return;
  }
  Serial.println("SD OK!");
    
}

void loop()
{
  Tft.setOrientation(0);
  
  //Image 1
  bmpFile = SD.open("flower.bmp");
  if (! bmpFile) {
    Serial.println("didnt find image");
    while (1);
  }
  
  if (! bmpReadHeader(bmpFile)) { 
     Serial.println("bad bmp");
     return;
  }
  
  Serial.print("image size "); 
  Serial.print(bmpWidth, DEC);
  Serial.print(", ");
  Serial.println(bmpHeight, DEC);
  bmpdraw(bmpFile, 0, 0);
  delay(3000);
  bmpFile.close();
  
  //Image 2
  bmpFile = SD.open("hibiscus.bmp");
  if (! bmpFile) {
    Serial.println("didnt find image");
    while (1);
  }
  
  if (! bmpReadHeader(bmpFile)) { 
     Serial.println("bad bmp");
     return;
  }
  
  Serial.print("image size "); 
  Serial.print(bmpWidth, DEC);
  Serial.print(", ");
  Serial.println(bmpHeight, DEC);
  bmpdraw(bmpFile, 0, 0);
  delay(3000);
}


/*********************************************/
// This procedure reads a bitmap and draws it to the screen
// its sped up by reading many pixels worth of data at a time
// instead of just one pixel at a time. increading the buffer takes
// more RAM but makes the drawing a little faster. 20 pixels' worth
// is probably a good place

#define BUFFPIXEL 20

void bmpdraw(File f, int x, int y) {
  bmpFile.seek(bmpImageoffset);
  
  uint32_t time = millis();
  uint16_t p;
  uint8_t g, b;
  int i, j;
  
  uint8_t sdbuffer[3 * BUFFPIXEL];  // 3 * pixels to buffer
  uint8_t buffidx = 3*BUFFPIXEL;
  

  for (i=0; i< bmpHeight; i++) {
    
      Tft.setXY(x, y+bmpHeight-i); 
    
    
    for (j=0; j<bmpWidth; j++) {
      // read more pixels
      if (buffidx >= 3*BUFFPIXEL) {
        bmpFile.read(sdbuffer, 3*BUFFPIXEL);
        buffidx = 0;
      }
      
      // convert pixel from 888 to 565
      b = sdbuffer[buffidx++];     // blue
      g = sdbuffer[buffidx++];     // green
      p = sdbuffer[buffidx++];     // red
      
      p >>= 3;
      p <<= 6;
      
      g >>= 2;
      p |= g;
      p <<= 5;
      
      b >>= 3;
      p |= b;
     
       // write out the 16 bits of color
      Tft.sendData(p);
    }
  }
  Serial.print(millis() - time, DEC);
  Serial.println(" ms");
}

boolean bmpReadHeader(File f) {
   // read header
  uint32_t tmp;
  
  if (read16(f) != 0x4D42) {
    // magic bytes missing
    return false;
  }
 
  // read file size
  tmp = read32(f);  
  Serial.print("size 0x"); Serial.println(tmp, HEX);
  
  // read and ignore creator bytes
  read32(f);
  
  bmpImageoffset = read32(f);  
  Serial.print("offset "); Serial.println(bmpImageoffset, DEC);
  
  // read DIB header
  tmp = read32(f);
  Serial.print("header size "); Serial.println(tmp, DEC);
  bmpWidth = read32(f);
  bmpHeight = read32(f);

  
  if (read16(f) != 1)
    return false;
    
  bmpDepth = read16(f);
  Serial.print("bitdepth "); Serial.println(bmpDepth, DEC);

  if (read32(f) != 0) {
    // compression not supported!
    return false;
  }
  
  Serial.print("compression "); Serial.println(tmp, DEC);

  return true;
}

/*********************************************/
// These read data from the SD card file and convert them to big endian 
// (the data is stored in little endian format!)

// LITTLE ENDIAN!
uint16_t read16(File f) {
  uint16_t d;
  uint8_t b;
  b = f.read();
  d = f.read();
  d <<= 8;
  d |= b;
  return d;
}

// LITTLE ENDIAN!
uint32_t read32(File f) {
  uint32_t d;
  uint16_t b;
 
  b = read16(f);
  d = read16(f);
  d <<= 16;
  d |= b;
  return d;
}

Initializing SD card…SD OK!
size 0x38436
offset 54
header size 40
bitdepth 24
compression 40
image size 240, 320
2169 ms
size 0x38436
offset 54
header size 40
bitdepth 24
compression 40
image size 240, 320
2171 ms
size 0x38436
offset 54
header size 40
bitdepth 24
compression 40
image size 240, 320
2170 ms
size 0x38436
offset 54
header size 40
bitdepth 24
compression 40
image size 240, 320
2171 ms
size 0x38436
offset 54
header size 40
bitdepth 24
compression 40
image size 240, 320
2170 ms

have copied two 24-bit bmp pictures in a SD card and set pin 10 of Arduino, I am getting a kind of color garbage as shown.

I don't think that display can handle 24 bit bmp pictures so it is bound to fail.

According to the manufacturer, this specific display model can handle 24-bmp. I already posted the problem at their forum (http://www.seeedstudio.com/forum/) but not answer yet. After checking similar posts in the mentioned forum, not few user have been having similar issues same as mine. Indeed, I couldn't find anybody with this bitmap demo running accordingly for Arduino uno/Mega. Let's wait and see.

Palliser: According to the manufacturer, this specific display model can handle 24-bmp.

From the Wiki link you supplied above

setPixel(unsigned int poX, unsigned int poY,unsigned int color) Sets the (poX,poY) pixel to color color. This function is internally used by other graphics APIs.

The display is only 16 bit colour.

There is a small (non relevant) error in your code here

  if (read32(f) != 0) {
    // compression not supported!
    return false;
  }
  
  Serial.print("compression "); Serial.println(tmp, DEC);

It won't handle any form of compression (value > 0) but reports header size as compression mode.

Have you tried using older version of Arduino IDE and the older TFT library or altering the older library work on 1.0+ and maybe some simple line/circle commands to confirm library is working okay.

Palliser: According to the manufacturer, this specific display model can handle 24-bmp.

No, it can't. From the link you gave (!):

Resolution 320x240 LCD color 65k

So it is 16bit per pixel, not 24. This will probably be 5 bits red, 6 bits green, b bits blue. But instead of guessing, lets look at the datasheet (linked from the link you gave)

Display Colors (Color Mode) - Full Color: 262K, RGB=(666) max., Idle Mode Off - Color Reduce: 8-color, RGB=(111), Idle Mode On  Programmable Pixel Color Format (Color Depth) for Various Display Data input Format - 12-bit/pixel: RGB=(444) using the 1.38M -bit frame memory - 16-bit/pixel: RGB=(565) using the 1.38M -bit frame memory - 18-bit/pixel: RGB=(666) using the 1.38M-bit frame memory

Actually that is a little bit better - it can do 18-bit truecolor. This avoids the problems of greyscale color casts when the number of bits per component is not identical between the three channels. So, starting from a 24bit (8 bits per component) truecolor image, for each pixel, take each component from 8 bits to 6 bits to construct an 18-bit value and write that pixel value to the screen.

If the image is larger than the screen dimensions you will need to downsample it, as well.

You should also check out what the datasheet says about gamma correction.

take a look at UTFT library Electronics - Henning Karlsen it’s tried and tested.

I find when a vendor puts their own badge on something and supplies their own library there’s always trouble, which is why i like utft, it’s bulletproof