//	bmpreader.cpp
//

#include "stdafx.h"
#include "dibsect.h"

/*
 * Dib Header Marker - used in writing DIBs to files
 */
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
int ReadDIBFile(const char * filename, DIBSection& dib);

int ReadBMPFile(const char * filename, DIBSection& dib)
{
	int result = ReadDIBFile(filename,dib);
	return result;
}

int ReadDIBFile(const char * filename, DIBSection& dib)
{
	int result = 0;

	BITMAPFILEHEADER bmfHeader;
	BITMAPINFO bmInfo;
	DWORD dwBitsSize;

	/*
	** get length of DIB in bytes for use when reading
	*/

	FILE * fp = fopen(filename,"rb");
	if (fp)
	{
		fseek(fp,0l,SEEK_END);
		dwBitsSize = ftell(fp);
		fseek(fp,0l,SEEK_SET);

		unsigned long bmfHeaderSize = sizeof(bmfHeader);

		if (fread(&bmfHeader,sizeof(unsigned char),bmfHeaderSize,fp) == bmfHeaderSize)
		{
			//if (bmfHeader.bfType != DIB_HEADER_MARKER)
			//	return result;
		}

		unsigned long bmInfoSize = sizeof(BITMAPINFOHEADER);

		if (fread(&bmInfo,sizeof(unsigned char),bmInfoSize,fp) == bmInfoSize)
		{
		}
		else
		{
			return result;
		}

		if (bmInfo.bmiHeader.biBitCount != 24)
		{
			return result;
		}

		int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed : 
						1 << bmInfo.bmiHeader.biBitCount;

		int w = bmInfo.bmiHeader.biWidth;
		int h = bmInfo.bmiHeader.biHeight;
		int bitcount = bmInfo.bmiHeader.biBitCount;

		dib.Create(w,h,bitcount);

		if (dib.IsCreated())
		{
			unsigned long total_width = dib.GetTotalWidth();

			DWORD remainder = dwBitsSize - bmfHeaderSize - bmInfo.bmiHeader.biSize;

			unsigned char * bits = new unsigned char[remainder];
			if (!bits)
			{
				  // outta memory
				return result;
			}

			memset(bits,0,(size_t)remainder);
			unsigned long bytes_read = fread(bits,sizeof(unsigned char),remainder,fp);

			if (bytes_read == remainder)
			{
				result++;

				if (nColors <= 256)
				{
				}

				unsigned char * dst = (unsigned char *)dib.GetBits();
				unsigned long dst_offset;
				unsigned long src_offset;

				for (int row=0;row<h;row++){
					dst_offset = row*total_width*3;
					src_offset = row*w*bitcount/8;
					memcpy(&dst[dst_offset],&bits[src_offset],w*bitcount/8);
				}
			}

			delete [] bits;
		}

		fclose(fp);
	}

	return result;
}
