/*  CONVERT A 24-BIT TRUE COLOR IMAGE TO GRAYSCALE  IMAGE USING C/C++ CODE*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<conio.h>
/*-------PROTOTYPES-------*/
long getImageInfo(FILE*, long, int);
void copyImageInfo(FILE* inputFile, FILE* outputFile);
void createColorTable(FILE* inputFile, FILE* outputFile);
/*------STRUCTURES--------*/
typedef struct
    {   int rows;
        int cols;
        unsigned char* data;
    } sImage;
int main(int argc, char* argv[])
{
 FILE            *bmpInput, *rasterOutput, *bmpOutput, *grayBmpInput;
 sImage        originalImage;
 unsigned char        someChar;
 unsigned char        *pChar;
 unsigned long        someLong;
 unsigned long        *pLong;
 long            fileSize;
 int            vectorSize, nColors;
 int            r, c, i;
 int            redValue, greenValue, blueValue, grayValue;
 /*--------INITIALIZE POINTER----------*/
 someChar = '0';
 pChar = &someChar;
 someLong = '0';
 pLong = &someLong;
 clrscr();
 if(argc < 2)
 {
   printf("Usage: %s bmpInput.bmp\n", argv[0]);
   exit(0);
 }
 printf("Reading file %s\n", argv[1]);
 /*----DECLARE INPUT FILES----*/
 bmpInput = fopen(argv[1], "rb");
 fseek(bmpInput, 0L, SEEK_END);
 grayBmpInput = fopen("p1.bmp", "rb");
 fseek(grayBmpInput, 0L, SEEK_END);
 /*----DECLARE OUTPUT FILES----*/
 rasterOutput = fopen("\\data24.txt", "w");
 bmpOutput = fopen("\\gray24.bmp", "wb");
 /*-----GET INPUT BMP DATA-----*/
 originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
 originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
 /*------------------------------------------------------
        TRIED TO COPY COLOR TABLE OF ANOTHER
        GRAYSCALE IMAGE???????
 ------------------------------------------------------*/
 copyImageInfo(bmpInput, bmpOutput);
 /*----EDIT FILE SIZE TO CONFORM TO 8 BIT BMP---*/
 fseek(bmpOutput, 2, SEEK_SET);
 *pLong = (unsigned long)(54 + 4*256 + (originalImage.cols * originalImage.rows));
 fwrite(pLong, sizeof(unsigned long), 1, bmpOutput);
 printf("File size: %ld\n", (long)getImageInfo(bmpOutput, 2, 4));
 /*----CHANGE BIT DEPTH FROM 24 TO 8----*/
 fseek(bmpOutput, 28, SEEK_SET);
 *pLong = (unsigned long)(8);
 fwrite(pLong, sizeof(unsigned long), 1, bmpOutput);
 printf("Bits/pixel: %d\n", (int)getImageInfo(bmpOutput, 28, 2));
 /*---CHANGE #COLORS FROM 16M TO 256---*/
 fseek(bmpOutput, 46, SEEK_SET);
 *pLong = (unsigned long)(256);
 fwrite(pLong, sizeof(unsigned long), 1, bmpOutput);
 printf("No. colors: %d\n", (int)getImageInfo(bmpOutput, 46, 4));
 createColorTable(grayBmpInput, bmpOutput);
 /*----FOR 24-BIT BMP, THERE IS NO COLOR TABLE-----*/
 fseek(bmpInput, 54, SEEK_SET);
 fseek(bmpOutput, (54 + 4*256), SEEK_SET);
 /*-----------READ RASTER DATA-----------*/
 for(r=0; r<=originalImage.rows-1; r++)
 {
   for(c=0; c<=originalImage.cols-1; c++)
   {
     /*-----READ FIRST BYTE TO GET BLUE VALUE-----*/
     fread(pChar, sizeof(char), 1, bmpInput);
     blueValue = *pChar;
     /*-----READ NEXT BYTE TO GET GREEN VALUE-----*/
     fread(pChar, sizeof(char), 1, bmpInput);
     greenValue = *pChar;
     /*-----READ NEXT BYTE TO GET RED VALUE-----*/
     fread(pChar, sizeof(char), 1, bmpInput);
     redValue = *pChar;
     /*-----USE FORMULA TO CONVERT RGB VALUE TO GRAYSCALE-----*/
     grayValue = (int)(0.299*redValue + 0.587*greenValue + 0.114*blueValue);
     /*-----PRINT TO TEXT FILE-----*/
     fprintf(rasterOutput, "(%d %d) = \tRed \t%d", r, c, redValue);
     fprintf(rasterOutput, "\tGreen \t%d \tBlue \t%d \tGray \t%d\n", greenValue, blueValue, grayValue);
     /*-----WRITE TO NEW BMP FILE------*/
     *pChar = grayValue;
     fwrite(pChar, sizeof(char), 1, bmpOutput);
   }
 }
 fclose(bmpInput);
 fclose(rasterOutput);
 fclose(bmpOutput);
 fclose(grayBmpInput);
 return 0;
}
/*----GET IMAGE INFO SUBPROGRAM------*/
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
 unsigned char        *ptrC;
 long            value=0L;
 int            i;
 unsigned char        dummy;
 dummy = '0';
 ptrC = &dummy;
 fseek(inputFile, offset, SEEK_SET);
 for(i=1; i<=numberOfChars; i++)
 {
   fread(ptrC, sizeof(char), 1, inputFile);
   /* calculate value based on adding bytes */
   value = (long)(value + (*ptrC)*(pow(256, (i-1))));
 }
 return(value);
}
/*--------COPIES HEADER AND INFO HEADER------*/
void copyImageInfo(FILE* inputFile, FILE* outputFile)
{
 unsigned char            *ptrC;
 unsigned char            dummy;
 int                i;
 dummy = '0';
 ptrC = &dummy;
 fseek(inputFile, 0L, SEEK_SET);
 fseek(outputFile, 0L, SEEK_SET);
 for(i=0; i<=50; i++)
 {
   fread(ptrC, sizeof(char), 1, inputFile);
   fwrite(ptrC, sizeof(char), 1, outputFile);
 }
}
/*---------COPIES COLOR TABLE--------*/
void createColorTable(FILE* inputFile, FILE* outputFile)
{
 unsigned char            *ptrC;
 unsigned char            dummy;
 int                i;
 dummy = '0';
 ptrC = &dummy;
 fseek(inputFile, 54L, SEEK_SET);
 fseek(outputFile, 54L, SEEK_SET);
 for(i=1; i<=4*256; i++)
 {
   fread(ptrC, sizeof(char), 1, inputFile);
   fwrite(ptrC, sizeof(char), 1, outputFile);
 }
}