/* Image Converter */

//Converts a monochrome, 256*256 BMP file into DRTV data suitable
//for display on an EL panel running the DRTV display engine
//(for Microchip dsPIC processors)

//Professor Mark Csele, Niagara College, 2006/12

#include <windows.h>
#include <stdio.h>

/* Global variables */

char	FileName[80];
char	OutFileName[80];
char	InString[10001];		//Incoming raw BMP data
char	PixelData;				//Eight Pixels, MSB first
char	PixelArray[65536];		//One byte per pixel, sequential
int		ArrayValue;
int		XSize,YSize;			//BMP size (in pixels)
int     Index,SourceIndex;
int		TargetIndex;
int		LineCounter;			//Counter for 32 lines of 32 bytes
int		StartLine,LineByte;
int		BitMask,BitCounter;
int		TargetPixelNumber;		//Array index from 0 to 64K
FILE	*fp;					//Source file
FILE	*fp2;					//Output file

char	VideoState;
char	VideoOutput;
char	VideoData[65536];
int		LinePixelCounter;		
int		PixelCount;
int		VideoCounter;
int		ImageLine;
int		ArrayIndex;
int		DataSize;				//Number of bytes of output data 
int		BytePerLineCtr;

INT main( int argc, char * argv[])
{

	printf("\n\nImage File Converter - Version 1.00, M. Csele, Niagara College\n\n");

	sprintf(FileName,"panel.bmp");
	sprintf(OutFileName,"code.txt");

	//Open the file
	fp=fopen(FileName,"rb");
	if (!fp)			
	{
		printf("\n\nFile OPEN Failed\n");
		return(1);
	}

	//Read the entire file into an array
	fread(InString,10000,1,fp);	
	
	//Ensure it is a BMP file format
	if (!(InString[0] = 0x42))
	{
		printf("\n\nFile is not in BMP format\n");
		return(1);
	}

	//Ensure it is a 256*256 Image Size
	XSize=InString[18]+InString[19]*256;
	YSize=InString[22]+InString[23]*256;
	if (!(XSize==0x100) || !(YSize==0x100))
	{
		printf("\n\nFile is %d by %d in size - must by 256 by 256\n",XSize,YSize);
		return(1);
	}

	//Ensure it is monochrome
	if (!(InString[28] = 0x01))
	{
		printf("\n\nBMP File is not monochrome\n");
		return(1);
	}

	//Reverse the entire image
	//BMP format represents the bottom line first, top line last
	//The target array has MSB (D7) as first bit
	SourceIndex=62;			//Start of last line of bmp
	TargetIndex=8160;		//Target last line of bmp
	LineCounter=0;
	TargetPixelNumber=65536;
	while (LineCounter < 256) //256
	{
		StartLine=TargetIndex;
		//Start at the beginning of the line moving forward
		TargetPixelNumber=TargetPixelNumber-256; 
		for(LineByte=0;LineByte<32;LineByte++)	//32
		{
			PixelData=InString[SourceIndex];

			//Break into individual bytes (one byte per pixel)
			BitMask=0x80;
			BitCounter=0;
			while(BitCounter < 8)
			{
			//	printf("Testing Ctr %d BitMask %d\n",BitCounter,BitMask);
				PixelArray[TargetPixelNumber]=0;
				if(PixelData&BitMask)
				{	
					PixelArray[TargetPixelNumber]=1;
				}
				TargetPixelNumber++;
				BitCounter++;
				BitMask=BitMask>>1;
			}
			SourceIndex++;
			TargetIndex++;
		}
		LineCounter++;
		TargetIndex=StartLine-32;
		//Original starting position of first pixel on line
		TargetPixelNumber=TargetPixelNumber-256;
	}

	//At this point we have a nice array representing the entire
	//image with PixelArray[0] the upper-left corner and [65535]
	//the lower-right.  Now, compress the data into the DRTV
	//format (RLL encoded), 256 pixel line limited
	//	Bit7=Video Data (1 on/0 off)
	//  Bit6-Bit0=Pixel count (1-129), add one
	//  Always terminates on a line HSYNC (256 pixels per line)

	//Compression Algorithm
	//ImageLine is the pixel number which starts a particular line
	DataSize=0;
	for(ImageLine=0;ImageLine<65536;ImageLine+=256)
	{
		VideoState=PixelArray[(ImageLine)];		//Starting video state
		VideoOutput=PixelArray[(ImageLine)]*128;	//Bit 7 state for first data byte

		PixelCount=1;					//Number of pixels the same
		for(LinePixelCounter=1;LinePixelCounter<256;LinePixelCounter++)
			{
			//Check for a change in video state 
			//Also check for >128 same pixels in a row
			ArrayIndex = LinePixelCounter+ImageLine;

			if((PixelArray[ArrayIndex]==VideoState)&&!(PixelCount==128))
				{
				//Same state as last, add one to count
				PixelCount=PixelCount+1;
				}
			else
				{
				//State change, save data (pixel count 0 = 1 pixel)
				VideoOutput=VideoOutput+PixelCount-1;
				VideoData[VideoCounter]=VideoOutput;
				DataSize++;
//				printf("Video = %X, ",VideoData[VideoCounter]&0xFF);
				VideoCounter=VideoCounter+1;
				//Start Again
				PixelCount=1;
				VideoState=PixelArray[ArrayIndex];
				VideoOutput=PixelArray[ArrayIndex]*128;
				}
			}//End FOR loop

		//End the line regardless for HSYNC then start again on the next line
		VideoOutput=VideoOutput+PixelCount-1;
		VideoData[VideoCounter]=VideoOutput;
		DataSize++;
//		printf("EOL = %X\n",VideoData[VideoCounter]&0xFF);
		VideoCounter=VideoCounter+1;
	}//End FOR ImageLine loop

	//Finally, Output the Data in the form of DATA for a dsPIC compiler
	fp2=fopen(OutFileName,"wb");
	if (!fp2)			
	{
		printf("\n\nOutput File OPEN Failed\n");
		return(1);
	}

	printf("; Compressed Video Data for %s, %d bytes\n",FileName,DataSize);
	fprintf(fp2,"; Compressed Video Data for %s, %d bytes\n",FileName,DataSize);
	BytePerLineCtr=0;
	for(ArrayIndex=0;ArrayIndex<DataSize;ArrayIndex++)
	{
		if(BytePerLineCtr==8) //If last one per line, end line
		{
			BytePerLineCtr=0;
			printf("\n");
			fprintf(fp2,"\n");
		}
		if(BytePerLineCtr>0)
		{
			printf(",");
			fprintf(fp2,",");
		}
		if(BytePerLineCtr==0)
		{
			printf("     .BYTE ");
			fprintf(fp2,"     .BYTE ");
		}
		
		BytePerLineCtr++;
		printf("0x%02.2X",VideoData[ArrayIndex]&0xFF);
		fprintf(fp2,"0x%02.2X",VideoData[ArrayIndex]&0xFF);
	}
	printf("\n\n");
	fprintf(fp2,"\n");

	printf("\n Output code written to file %s\n\n",OutFileName);

	
	//getc(stdin);
	
	return (LRESULT) 0;
}


