/*
Combines Two 8-bit Images, writes the raster data to a text file for reference.
First it copies the first BMP's header, color table to the output BMP file, which is going to be the combination of the two images. Then whenever there is a color information other than white (255) in the second file that information is copied to t
he output file. Therefore it is supposed that white is the unnecessary information in the second file. Furthermore this code needs to have same sized bmp files to accomplish the addition.
Because every bmp that has a color table would have different color tables, only grayscale addition is possible with bmp files having color tables (bmp files that are 8-bit and lower). Grayscale 8-bit images has the same color table, 256 shades of
gray.
*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>


/* Functions */
long getImageInfo(FILE*, long, int);
void copyImageInfo(FILE*, FILE*);
void copyColorTable(FILE*, FILE*, int);

void main(void)
{

FILE                 *bmpfile1, *bmpfile2, *bmpOutput, *rawdata;            /* Files that are used with this code */
unsigned char        *pChar1, *pChar2, *pCharO, dummy1, dummy2, dummyO;     /* The pointers here are used to read and write raster data and the rest are used to safely initialize the pointers */
int                  r, r1, r2, c, c1, c2;                                  /* Variables that are assigned to width and height of the bmp files 1 and 2  */
int                  nColors = 256;                                         /* Number of colors = 256 */
long                 fileSize1, fileSize2;
long                 nbits1, nbits2;


/* Initialization */
dummy1 = '0'; pChar1 = &dummy1;
dummy2 = '0'; pChar2 = &dummy2;
dummyO = '0'; pCharO = &dummyO;


printf("ONLY 8 BIT BMPs CAN BE PROCESSED.!!!\n");
printf("IMAGE SIZES AND FORMATS MUST BE SAME.!!!\n");
printf("Reading bmpin1.bmp & bmpin2.bmp\n bmpin1.bmp is the main BMP.\n");

if ((bmpfile1 = fopen("bmpin1.bmp", "rb")) == NULL)
{
     printf("Can not open bmpin1.bmp\n");
     exit(0);
}

if ((bmpfile2 = fopen("bmpin2.bmp", "rb")) == NULL)
{
     printf("Can not open bmpin2.bmp\n");
     exit(0);
}

if ((bmpOutput = fopen("bmpOutx.bmp", "wb")) == NULL)
{
     printf("Can not open bmpoutx.bmp\n");
     exit(0);
}

if ((rawdata = fopen("rawdata.txt", "w")) == NULL)
{
     printf("Can not open rawdata.txt");
     exit(0);
}

/* Get Info of the Files and Compare */
c1 = (int)getImageInfo(bmpfile1, 18, 4);
c2 = (int)getImageInfo(bmpfile2, 18, 4);
printf("Width of File 1: \t\t%d\n", c1);
printf("Width of File 2: \t\t%d\n", c2);

r1 = (int)getImageInfo(bmpfile1, 22, 4);
r2 = (int)getImageInfo(bmpfile2, 22, 4);
printf("Height of File 1: \t%d\n", r1);
printf("Height of File 2: \t%d\n", r2);
if ( (r1 != r2) || (c1 != c2) )
{
     printf("Rows or cloumns don't match. Must enter same size BMPs.");
     exit(0);
}


nbits1 = getImageInfo(bmpfile1, 28, 2);
nbits2 = getImageInfo(bmpfile2, 28, 2);
printf("Bits/pixel of File 1: \t%ld\n", nbits1);
printf("Bits/pixel of File 2: \t%ld\n", nbits2);
if (nbits1 != nbits2)
{
     printf("File formats don't match. Must have same formatted BMPs");
     exit(0);
}

copyImageInfo(bmpfile1, bmpOutput);

copyColorTable(bmpfile1, bmpOutput, nColors);

/* Beginning of the Raster Data is set*/
fseek(bmpfile1, (int)(54+4*nColors), SEEK_SET);
fseek(bmpfile2, (int)(54+4*nColors), SEEK_SET);
fseek(bmpOutput, (int)(54+4*nColors), SEEK_SET);

/* BMP PROCESSING */

for(r=0; r<r1; r++)
{
     for(c=0; c<c1; c++)
     {
          fread(pChar1, sizeof(char), 1, bmpfile1);
          fread(pChar2, sizeof(char), 1, bmpfile2);

          /*////////////////////*/

          /* Copy main image to output */
          *pCharO = *pChar1;

          /* Copy the non-white of image 2 to output */
          if(*pChar2 != 255) *pCharO = *pChar2;

          /*////////////////////*/

          /* Raster Data is written to rawdata.txt for reference */
          fprintf(rawdata, "%d %d %d\n", *pChar1, *pChar2, *pCharO);

          fwrite(pCharO, sizeof(char), 1, bmpOutput);

     }
}

fclose(bmpOutput);
fclose(bmpfile1);
fclose(bmpfile2);

} /* end of main */

long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{

unsigned char    *ptrC, dummy = '0';
long             value = 0L;
int              i;

ptrC = &dummy;

fseek(inputFile, offset, SEEK_SET);

for(i=1; i<=numberOfChars; i++)
{
     fread(ptrC, sizeof(char), 1, inputFile);
     /* Byte by byte reading */
     value = (long)(value + (*ptrC)*(pow(256, (i-1))));
}
return(value);

} /* end of getImageInfo */

void copyImageInfo(FILE* inputFile, FILE* outputFile)
{

/* copies inputFile's header data to outputFile */

unsigned char    *ptrC, dummy = '0';
int              i;

ptrC = &dummy;

fseek(inputFile, 0L, SEEK_SET);
fseek(outputFile, 0L, SEEK_SET);

for(i=1; i<=54; i++)
{
     fread(ptrC, sizeof(char), 1, inputFile);
     fwrite(ptrC, sizeof(char), 1, outputFile);
}

} /* end of copyImageInfo */

void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors) {

/* copies inputFile's color table to outputFile */

unsigned char    *ptrC, dummy = '0';
int              i;

ptrC = &dummy;

fseek(inputFile, 54L, SEEK_SET);
fseek(outputFile, 54L, SEEK_SET);

for(i=1; i<=4*nColors; i++)
{
     fread(ptrC, sizeof(char), 1, inputFile);
     fwrite(ptrC, sizeof(char), 1, outputFile);
}

} /* end of copyColorTable */

