Writing binary file to SD (creating BMP files)

Try this:

//Add the SdFat Libraries
#include <SdFat.h>
#include <SdFatUtil.h>

const uint8_t csPin = 8;

char name[] = "9px_00.bmp";
int w = 3;
int h = 2;
int px[] = {
  255, 0, 255, 0, 255, 0 };
boolean debugPrint = true;

SdFat sd;
SdFile file;


void setup() {

  // SD setup
  Serial.begin(9600);
  if (!sd.init(SPI_FULL_SPEED, csPin)) {
    sd.initErrorHalt();
  }

  // if name exists, create new filename
  for (int i=0; i<1000; i++) {
    name[4] = i/10 + '0';
    name[5] = i%10 + '0';
    if (file.open(name, O_CREAT | O_EXCL | O_WRITE)) {
      break;
    }
  }

  // create image data
  // heavily modified version via: http://stackoverflow.com/a/2654860
  unsigned char *img = NULL;          // image data
//  int filesize = 54 + 3 * w * h;      //  w is image width, h is image height
  int filesize = 54 + 4 * w * h;      //  w is image width, h is image height  
  if (img) {
    free(img);
  }
  img = (unsigned char *)malloc(3*w*h);
  //memset(img,0,sizeof(img));        // not sure if I really need this; runs fine without...

  for (int y=0; y<h; y++) {
    for (int x=0; x<w; x++) {
      int colorVal = px[y*w + x];
      img[(y*w + x)*3+2] = (unsigned char)(colorVal);
      img[(y*w + x)*3+1] = (unsigned char)(colorVal);
      img[(y*w + x)*3+0] = (unsigned char)(colorVal);
    }
  }

  // print px and img data for debugging
  if (debugPrint) {
    Serial.print("Writing \"");
    Serial.print(name);
    Serial.print("\" to file...\n");
    for (int i=0; i<w*h; i++) {
      Serial.print(px[i]);
      Serial.print("  ");
    }
  }

  // create file headers (also taken from above example)
  unsigned char bmpFileHeader[14] = {
    'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0             };
  unsigned char bmpInfoHeader[40] = {
    40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0             };
  unsigned char bmpPad[3] = {
    0,0,0             };

  bmpFileHeader[ 2] = (unsigned char)(filesize    );
  bmpFileHeader[ 3] = (unsigned char)(filesize>> 8);
  bmpFileHeader[ 4] = (unsigned char)(filesize>>16);
  bmpFileHeader[ 5] = (unsigned char)(filesize>>24);

  bmpInfoHeader[ 4] = (unsigned char)(       w    );
  bmpInfoHeader[ 5] = (unsigned char)(       w>> 8);
  bmpInfoHeader[ 6] = (unsigned char)(       w>>16);
  bmpInfoHeader[ 7] = (unsigned char)(       w>>24);
  bmpInfoHeader[ 8] = (unsigned char)(       h    );
  bmpInfoHeader[ 9] = (unsigned char)(       h>> 8);
  bmpInfoHeader[10] = (unsigned char)(       h>>16);
  bmpInfoHeader[11] = (unsigned char)(       h>>24);

  // write the file!
  // this is a combination of the bmp example above and
  // one from the SdFat library (it doesn't create a usable
  // bmp file, though)...
  file.write(bmpFileHeader, sizeof(bmpFileHeader));    // write file header
  file.write(bmpInfoHeader, sizeof(bmpInfoHeader));    // " info header
  /*
  // sizeof(img) is always 2
  for (int i=0; i<sizeof(img); i++) {                  // iterate image array
    file.write(img+(w*(h-i-1)*3), w);                  // write px data
    file.write(bmpPad, (4-(w*3)%4)%4);                 // and padding as needed
  }
  */
  int n = w*h;
  for (int i = 0; i < n; i++) {
    file.write(img + 3*i, 3);
    file.write((uint8_t)0);
  }
  file.close();
  if (debugPrint) {
    Serial.println("\n---");
  }
}

void loop() { }

This make a valid bmp but not what you intended. The write is still not correct.

Here is a sketch that will dump a small bmp file:

#include <SdFat.h>
const uint8_t csPin = 8;
SdFat sd;
SdFile file;
char* fileName = "9PX_03.BMP";

class BmpHeader {
public:
  char signature[2];
  uint32_t fileSize;
  uint32_t reserved;
  uint32_t dataOffset;
};
class BmpInfo {
public:
  uint32_t size;  // 40
  uint32_t width;
  uint32_t height;
  uint16_t planes;
  uint16_t bitsPerPixel;
  uint32_t compression;
  uint32_t imageSize;  // compressed size 
  uint32_t xPixelsPerM;
  uint32_t yPixelsPerM;
  uint32_t colorsUsed;
  uint32_t importantColors;
};
BmpHeader header;
BmpInfo info;

void printHexU8(uint8_t h) {
  if (h < 16) Serial.write('0');
  Serial.print(h, HEX);
}
void setup() {
  Serial.begin(9600);
  if (!sd.init(SPI_FULL_SPEED, csPin)) sd.initErrorHalt();
  if (!file.open(fileName, O_READ)) {
    Serial.println("openError");
    return;
  }
  if (file.read(&header, sizeof(header)) != sizeof(header) ||
    file.read(&info, sizeof(info)) != sizeof(info)) {
    Serial.println("read error");
    return;
  }
  Serial.print("header.fileSize: ");
  Serial.println(header.fileSize);
  Serial.print("header.dataOffset: ");  
  Serial.println(header.dataOffset);
  Serial.print("info.size: ");  
  Serial.println(info.size);
  Serial.print("info.width: ");   
  Serial.println(info.width);
  Serial.print("info.height: ");   
  Serial.println(info.height);
  Serial.print("info.planes: ");   
  Serial.println(info.planes);  
  Serial.print("info.bitsPerPixel: ");   
  Serial.println(info.bitsPerPixel);  
  Serial.print("info.compression: ");   
  Serial.println(info.compression);  
  Serial.print("info.imageSize: ");   
  Serial.println(info.imageSize);   
  Serial.print("info.xPixelsPerM: ");   
  Serial.println(info.xPixelsPerM);     
  Serial.print("info.yPixelsPerM: ");   
  Serial.println(info.yPixelsPerM);   
  Serial.print("info.colorsUsed: ");   
  Serial.println(info.colorsUsed);   
  Serial.print("info.importantColors: ");   
  Serial.println(info.importantColors);
  int b;
  int i = 0;
 while ((b = file.read()) >= 0) {
   printHexU8(i++);
   Serial.write(' ');
   printHexU8(b);
   Serial.println();
 }
   
}
void loop() {
}

9PX_05.BMP (78 Bytes)