//*****************************************************************************
//************** BitConv.CC: Convert BMP-Mono to X11-Bitmap file **************
//*****************************************************************************
//************************** <C> 1994 by M.Hofmann ****************************
//*****************************************************************************

//*** 18.01.1994  21:34:18

//*** How To Compile:
//***    Use C++ Compiler!
//***    IBM-PC: Compile with TINY-model
//***            Borland-C:  bcc -mt -O -G -lt -Z -d -w tfc.cc
//***    UNIX    GNU-C++:    g++ -O2 -m486 -o /usr/bin/tfc tfc.cc

#define  BitConv

#ifdef __TURBOC__
 #ifndef __TINY__
   #error compile only with tiny model !!
 #endif
#endif
#ifndef __TURBOC__
   #include <unistd.h>
#endif

// Include standard header files

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

//*****************************************************************************
//******** Messages and error messages ****************************************
//*****************************************************************************

#define  MsgTitle1    "\nBitConv: BMP-Mono -> X11 Graphics Format Conversion Utility\n"
#define  MsgTitle2    "Version 1.3 <C> Copyright " __DATE__ " by M.Hofmann\n"

#define  MsgOk        "\nProgram completed with no errors\n\n"
#define  MsgOpenF     "\n\nOpening files:\n"
#define  MsgIFile     "\n    Input file ======> (buffer length: %4XH) %s"
#define  MsgOFile     "\n    Output file  ====> (buffer length: %4XH) %s"
#define  MsgRen       "\n    Output file will be renamed to %s after completion"
#define  MsgConv      "\n\n\nConverting data:\n\n"

#define  ErrNoArg     "Wrong number of arguments"
#define  ErrNoOpt     "Unknown Option specified"
#define  ErrNoInFile  "Can't open input file"
#define  ErrNoInName  "No input file name specified"
#define  ErrNoOutFile "Can't open output file"
#define  ErrClFile    "Can't close files"
#define  ErrReadF     "Error reading file"
#define  ErrWrtF      "Error writing file"
#define  ErrNoRename  "Can't rename file"

//*****************************************************************************
//******** Some useful definitions ********************************************
//*****************************************************************************

#define true  (-1)
#define false (0)

typedef unsigned char byte;                             //  8 bits
typedef unsigned int  word;                             // 16 bits

//*****************************************************************************
//******* Variables ***********************************************************
//*****************************************************************************

// Input / Output files

char    iname[100],oname[100];
FILE    *ifile, *ofile;

//*****************************************************************************
//******* Input / Output functions ********************************************
//*****************************************************************************

void    ExitErr(char *errmsg,int ErrNum)

/*** Show an error message and quit program ***/

{
        fprintf (stderr, "\n\nError:  %s !!!\n\n",errmsg);
        fprintf (stderr, "Aborting program (ERC>0)....\n\n");
        fprintf (stderr, "Syntax: BitConv infile outfile\n\n");
        exit(ErrNum);
}

void    title()

/*** Print title ***/

{
        printf (MsgTitle1);                     // Print title
        printf (MsgTitle2);
}

//*****************************************************************************
//****** File I/O *************************************************************
//*****************************************************************************

void    fileo(char *iname, char *oname)

/*** Open files iname and oname for reading and writing. ***/

{
        printf (MsgOpenF);
        printf (MsgIFile MsgOFile,20000,iname,20000,oname);
        if ((ifile=fopen(iname,"rb"))==NULL) ExitErr(ErrReadF,1);
        if ((ofile=fopen(oname,"wb"))==NULL) ExitErr(ErrWrtF,1);
        setvbuf(ifile,NULL,_IOFBF,20000);               // Faster with buffers
        setvbuf(ofile,NULL,_IOFBF,20000);
}

void    filec()

/*** Close files ***/

{
        if (fclose(ofile)) ExitErr(ErrClFile,1);
        if (fclose(ifile)) ExitErr(ErrClFile,1);
}

//*****************************************************************************
//******* Translate Input File ************************************************
//*****************************************************************************

byte	revbits(byte a)

//*** reverse the bit order of a

{
	byte register i;
	byte register b = 0;
	
	if (a==0 || a==255)  return a;

        for (i=0; i<8 ; i++) {
                b <<= 1;
                b  |= (a & 1);
		a >>= 1;
	}         
	return b;
}

void    convtext()

{
 	byte buf[4096]; 
 	int register row, col, col1;
 	 	
 	int  xlen, ylen;
	int  filepos;
	int  minx, maxx;
	int  miny, maxy;
	int  maxcol;
	
	int  xpix, ypix;

//*** Read bitmap size

	fgets (buf, 128, ifile);
	fgets (buf, 128, ifile);
	fgets (buf, 128, ifile);
	sscanf (buf, "%d %d", &xlen, &ylen);
	filepos = ftell(ifile);
	
	maxcol = int(ceil(xlen/8.0));
	printf ("\n\nSearching for boundaries... Size: (%d x %d)\n\n", xlen, ylen);

//*** 1. Pass: Search boundaries

	maxx = maxy = 0;
	minx = miny = 30000;

	for (row=0; row<ylen; row++) {
		fread (buf, maxcol, 1, ifile);
		for (col=0; col<maxcol; col++) {
			if (buf[col] != 0) {
				if (col < minx) minx = col;
				if (col > maxx) maxx = col;
				if (row < miny) miny = row;
				maxy = row;
				col = maxx;
			}
		}	
		if (!(row % 10)) 
			printf ("[%d] ", row);
	}	
	miny-=4;					// White Border on top and bottom 
	maxy+=4;
	
//*** 2. Pass: Convert pixel to X11 BMP Format	
	
	xpix = (maxx-minx+1)*8;
	ypix = (maxy-miny+1);
	
	fprintf (ofile, "#define %s_width  %d\n", oname, xpix);
	fprintf (ofile, "#define %s_height %d\n", oname, ypix);
	fprintf (ofile, "static char %s_bits[] = {\n");	
	
	fseek (ifile, filepos, SEEK_SET);
	printf ("\n\nConverting... Size: (%d x %d)\n\n", xpix, ypix);

	for (row=0; row<ylen; row++) {
		fread (buf, maxcol, 1, ifile);
		if (row >= miny && row <= maxy) {
			for (col=minx; col<=maxx; col++) {
				fprintf (ofile, "0x%02x,",revbits(buf[col]));				
			}
			fprintf (ofile, "\n");
		}	
		if (!(row % 10)) 
			printf ("[%d] ", row);
	}
	fprintf (ofile, "};\n");	
}

//*****************************************************************************
//****** Main program *********************************************************
//*****************************************************************************

int     main (int argc, char *argv[])

{
   	if (argc!=3) ExitErr(ErrNoArg, 255);	

       	strcpy(iname,argv[1]);
       	strcpy(oname,argv[2]);

   	title();                                       	// Print Title page

   	fileo(iname,oname);                          	// Open files
   	convtext();                                     // Convert file
   	filec();                                        // Close file

      	printf (MsgOk);                                 // No error so far
   	exit(0);
	return 0;
}