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)