I'm currently trying to create a ray tracer in C++ but I'm having difficulty writing the .bmp produced at the end. I'm determined to do it manually, so I can learn more about image files and writing them etc. But I'm having some difficulty. I'm fairly new to C++ but have been using Python for a while.
I'm almost there now, I just have one strange problem. Everything is correct up to mid way trough the important colours (which I set to 0), where all sorts of random characters spring up and this continues for the next few bytes, a couple of bytes in to the pixel data. Before and after that everything is fine, but I just can't explain it. My current code is in the edit:
Here is the hex:

the problem area is highlighted
 #include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
//-------------------------Object list
const int renderSize[2] = {254,254};
float sphere1Pos[3] = {0.0,0.0,0.0}; //first sphere at origin to make calculations easier
float sphere1Radius = 10.0;
float sphere1Colour= (255.0,0.0,0.0); 
float light1Pos = (0.0,20.0,0.0); //Above sphere
float light1Intensity = 0.5;
// ------------------------
float dot(float* a,float* b); //Calculates the dot product
struct pixel {
    unsigned char R;
    unsigned char G;
    unsigned char B;
    };
//bmp--------------
struct bitmapMagicNumber {
    unsigned char magicNumber[2];
    };
struct bitmapFileHeader {
    unsigned char fileSize;
    short reserved1;
    long reserved2;
    short offset;
    };
struct bitmapInformationHeader {
    short headerSize;
    short padding;
    short width;
    short height; 
    short planes;
    short bitDepth;
    short compression;
    short imageSize;
    short xPixelsPerMetre;
    short yPixelsPerMetre;
    short colours;
    short importantColours;
    };
void setBitmapMagicNumber(bitmapMagicNumber& magicNum){
    magicNum.magicNumber[0] = 0x42;
    magicNum.magicNumber[1] = 0x4D;
    };
void setBitmapFileHeader(bitmapFileHeader& fileHeader,bitmapInformationHeader& informationHeader,pixel pixelArray) {
    fileHeader.fileSize = 54 + sizeof(pixelArray);
    fileHeader.reserved1 = 0;
    fileHeader.reserved2 = 0;
    fileHeader.offset = 54;
    };
void setBitmapInformationHeader(bitmapInformationHeader& informationHeader){
    informationHeader.headerSize = 40;
    informationHeader.padding=0;
    informationHeader.width = renderSize[0];
    informationHeader.height = renderSize[1];
    informationHeader.planes = 1;
    informationHeader.bitDepth = 24;
    informationHeader.compression = 0;
    informationHeader.imageSize = 0;
    informationHeader.xPixelsPerMetre = 0;
    informationHeader.yPixelsPerMetre = 0 ;
    informationHeader.colours = 0;
    informationHeader.importantColours = 0;
    };
void writeBitmap(bitmapMagicNumber& magicNum, bitmapFileHeader& fileHeader,bitmapInformationHeader& informationHeader,pixel pixelArray){
    ofstream out("test.bmp",ios::out|ios::binary);
    //file header
    out.write((char*) &magicNum,2);
    out.write((char*) &fileHeader.fileSize,sizeof(fileHeader.fileSize));
    if (sizeof(fileHeader.fileSize)<3){
        out.write((char*) &informationHeader.padding,1);
        }
    out.write((char*) &informationHeader.padding,1);
    out.write((char*) &fileHeader.reserved1,2);
    out.write((char*) &fileHeader.reserved2,2);
    out.write((char*) &fileHeader.offset,sizeof(fileHeader.offset));
    out.write((char*) &informationHeader.padding,1);
    out.write((char*) &informationHeader.padding,1);
    //information header
    out.write((char*) &informationHeader.headerSize,sizeof(informationHeader.headerSize));
    out.write((char*) &informationHeader.padding,1);
    out.write((char*) &informationHeader.padding,1);
    out.write((char*) &informationHeader.width,sizeof(informationHeader.width));
    if (sizeof(informationHeader.width)<4){
        out.write((char*) &informationHeader.padding,1);
        }
    if (sizeof(informationHeader.width)<3){
        out.write((char*) &informationHeader.padding,1);
        }
    if (sizeof(informationHeader.width)<2){
        out.write((char*) &informationHeader.padding,1);
        }
    out.write((char*) &informationHeader.height,sizeof(informationHeader.height));
    if (sizeof(informationHeader.height)<4){
        out.write((char*) &informationHeader.padding,1);
        }
    if (sizeof(informationHeader.height)<3){
        out.write((char*) &informationHeader.padding,1);
        }
    if (sizeof(informationHeader.height)<2){
        out.write((char*) &informationHeader.padding,1);
        }   
    out.write((char*) &informationHeader.planes,sizeof(informationHeader.planes));
    out.write((char*) &informationHeader.bitDepth,sizeof(informationHeader.bitDepth));
    out.write((char*) &informationHeader.compression,4);
    out.write((char*) &informationHeader.imageSize,4);
    out.write((char*) &informationHeader.xPixelsPerMetre,4);
    out.write((char*) &informationHeader.yPixelsPerMetre,4);
    out.write((char*) &informationHeader.colours,4);
    out.write((char*) &informationHeader.importantColours,4);
    //pixel data
    for (int y=0; y < renderSize[1]; y++) {
        for (int x=0; x< renderSize[0]; x++) {
            out.write((char*) &pixelArray[x][y],sizeof(pixel));
        }
    }
    out.close();
}
// end bmp-----------
int main() {
pixel pixelArray[renderSize[0]][renderSize[1]];
    for (int y=0; y < renderSize[1]; y++) {
        for (int x=0; x< renderSize[0]; x++) {
            float rayPos[3] = {x,y, -1000.0};
            float rayDir[3] = {0.0,0.0,-1.0};   
            bool intersect;
            //for each object in scene, see if intersects. (for now there is only one object to make things easier)
            //-------sphere ray intersection....
            float distance[3];
            distance[0]= rayPos[0]-sphere1Pos[0];
            distance[1]= rayPos[1]-sphere1Pos[1];
            distance[2]= rayPos[2]-sphere1Pos[2];
            float a = dot(rayDir, rayDir);
            float b = 2 * dot(rayDir, distance);
            float c = dot(distance, distance) - (sphere1Radius * sphere1Radius);
            float disc = b * b - 4 * a * c;
            if (disc < 0)
                intersect=false;
            else
                intersect=true;
            //--------------------
            if (intersect==true){
                pixelArray[x][y].R = 0;
                pixelArray[x][y].G = 0;
                pixelArray[x][y].B = 0;
                }
            else {
                pixelArray[x][y].R = 0;
                pixelArray[x][y].G = 0;
                pixelArray[x][y].B = 0;
                }
            // trace to lights (as long as another object is not in the way) 
        }
    }
    //write .bmp
    bitmapMagicNumber magicNum;
    bitmapFileHeader fileHeader;
    bitmapInformationHeader informationHeader;
    setBitmapMagicNumber(magicNum);
    setBitmapFileHeader(fileHeader,informationHeader, pixelArray[renderSize[0]][renderSize[1]]);
    setBitmapInformationHeader(informationHeader);
    writeBitmap(magicNum,fileHeader,informationHeader, pixelArray[renderSize[0]][renderSize[1]]);
}
//calculate dot product
float dot(float* a,float* b)
{
float dp = 0.0;
for (int i=0;i<3;i++)
    dp += a[i] * b[i];
return dp;
}
 
     
     
     
    