#include <windows.h>
#include <stdio.h>       // for memset

/* calculation of the dimensions of the BMP from the dimensions of the RGB */

void SizeRGBToBMPB(int width, int height, long &newsize)
{
 int padding = 0;
 int scanlinebytes = width * 3;
 while ( ( scanlinebytes + padding ) % 4 != 0 )     // DWORD = 4 bytes
		padding++;
	// get the padded scanline width
 int psw = scanlinebytes + padding;
	
	// we can already store the size of the new padded buffer
 newsize = height * psw;
}
/*******************************************************************
BYTE* ConvertRGBToBMPBuffer ( BYTE* Buffer, int width, 
		int height, long* newsize )


This function takes as input an array of RGB values, it's width
and height.
The buffer gets then transformed to an array that can be used
to write to a windows bitmap file. The size of the array
is returned in newsize, the array itself is the
return value of the function.
Both input and output buffers must be deleted by the
calling function.

The input buffer is expected to consist of width * height
RGB triplets. Thus the total size of the buffer is taken as
width * height * 3.

The function then transforms this buffer so that it can be written 
to a windows bitmap file:
First the RGB triplets are converted to BGR.
Then the buffer is swapped around since .bmps store
images uside-down.
Finally the buffer gets DWORD ( 32bit ) aligned, 
meaning that each scanline ( 3 * width bytes ) gets
padded with 0x00 bytes up to the next DWORD boundary


*******************************************************************/

bool ConvertRGBToBMPBuffer ( BYTE* newbuf, BYTE* Buffer, int width, int height)
{

	// first make sure the parameters are valid
	if ( ( Buffer == NULL ) || ( newbuf == NULL ) || ( width == 0 ) || ( height == 0 ) )
		return false;

	// now we have to find with how many bytes
	// we have to pad for the next DWORD boundary	

	int padding = 0;
	int scanlinebytes = width * 3;
	while ( ( scanlinebytes + padding ) % 4 != 0 )     // DWORD = 4 bytes
		padding++;
	// get the padded scanline width
	int psw = scanlinebytes + padding;
	
	// we can already store the size of the new padded buffer
	int newsize = height * psw;

	memset ( newbuf, 0, newsize );

	// now we loop trough all bytes of the original buffer, 
	// swap the R and B bytes and the scanlines
	long bufpos = 0;   
	long newpos = 0;
	for ( int y = 0; y < height; y++ )
		for ( int x = 0; x < 3 * width; x+=3 )
		{
			bufpos = y * 3 * width + x;     // position in original buffer
			newpos = ( height - y - 1 ) * psw + x;           // position in padded buffer

			newbuf[newpos] = Buffer[bufpos+2];       // swap r and b
			newbuf[newpos + 1] = Buffer[bufpos + 1]; // g stays
			newbuf[newpos + 2] = Buffer[bufpos];     // swap b and r
		}

	return true;
}

/***************************************************************
BYTE* ConvertBMPToRGBBuffer ( BYTE* Buffer, 
		int width, int height )

This function takes as input the data array
from a bitmap and its width and height.
It then converts the bmp data into an RGB array.
The calling function must delete both the input
and output arrays.
The size of the returned array will be 
width * height * 3
On error the returb value is NULL, else the
RGB array.


The Buffer is expected to be the exact data read out
from a .bmp file.  
The function will swap it around, since images
are stored upside-down in bmps.
The BGR triplets from the image data will
be converted to RGB.
And finally the function removes padding bytes.
The returned arraay consits then of
width * height RGB triplets.

*****************************************************************/


bool SaveBMP (FILE *PF1, BYTE* Buffer, int width, int height, long paddedsize)
{
 // declare bmp structures 
 BITMAPFILEHEADER bmfh;
 BITMAPINFOHEADER info;
	
// andinitialize them to zero
 memset ( &bmfh, 0, sizeof (BITMAPFILEHEADER ) );
 memset ( &info, 0, sizeof (BITMAPINFOHEADER ) );
	
// fill the fileheader with data
 bmfh.bfType = 0x4d42;       // 0x4d42 = 'BM'
 bmfh.bfReserved1 = 0;
 bmfh.bfReserved2 = 0;
 bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + paddedsize;
 bmfh.bfOffBits = 0x36;		// number of bytes to start of bitmap bits
	
// fill the infoheader

 info.biSize = sizeof(BITMAPINFOHEADER);
 info.biWidth = width;
 info.biHeight = height;
 info.biPlanes = 1;			// we only have one bitplane
 info.biBitCount = 24;		// RGB mode is 24 bits
 info.biCompression = BI_RGB;	
 info.biSizeImage = 0;		// can be 0 for 24 bit images
 info.biXPelsPerMeter = 0x0ec4;     // paint and PSP use this values
 info.biYPelsPerMeter = 0x0ec4;     
 info.biClrUsed = 0;			// we are in RGB mode and have no palette
 info.biClrImportant = 0;    // all colors are important

// now we open the file to write to
 if ( PF1 == NULL ) return false;
	
// write file header
 if (fwrite(&bmfh, 1, sizeof(BITMAPFILEHEADER), PF1) < sizeof(BITMAPFILEHEADER))	return false;

// write infoheader
 if (fwrite(&info, 1, sizeof (BITMAPINFOHEADER), PF1) < sizeof(BITMAPFILEHEADER)) return false;

 if (fwrite(Buffer, 1, paddedsize, PF1) < sizeof(BITMAPFILEHEADER)) return false;

// and close file
 return true;
}
