#include "stdafx.h"
#include "Image.h"
#include "MyDib.h"

#define BIG 10000000

IMPLEMENT_SERIAL(CDib,CObject,0);

/*****************************/
// Two dimensional float array
float **make_2D_float_array(int row,int col)
{
	float *arr_ptr;
	float **arr;
	int i;
	if ((arr=(float **)calloc(row,sizeof(float *)))==NULL)
    {AfxMessageBox(L"Can't allocate core in make_2D_float_array",MB_OK); return(NULL);}
	if ((arr_ptr=(float *)calloc(row*col,sizeof(float)))==NULL)
    {AfxMessageBox(L"Can't allocate core in make_2D_float_array",MB_OK); return(NULL);}
	for(i=0;i<row;i++) arr[i]=&arr_ptr[i*col];
	return(arr);
} 

void free_2D_float_array(float **arr)
{
	free((char*)arr[0]);
	free((char*)arr);
}

/**************************/
// Constructor from nothing
CDib::CDib()
{
	m_data=NULL;
	m_bmih=NULL;
	m_palette=NULL;
}

/************/
// Destructor
CDib::~CDib()
{
	if (m_bmih) delete(m_bmih);
	if (m_data) delete(m_data);
	if (m_palette) delete(m_palette);
}

/******************************/
// Constructor for an empty DIB
CDib::CDib(int width,int height,int nbits)
{
	m_bmih=NULL;
	m_palette=NULL;
	if (nbits==8) m_nColors=256; else m_nColors=0;
	m_bmih=(LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors];
	m_bmih->biSize=sizeof(BITMAPINFOHEADER);
	m_bmih->biWidth=width;
	m_bmih->biHeight=height;
	m_bmih->biPlanes=1;
	m_bmih->biBitCount=nbits;
	m_bmih->biSizeImage=0;
	m_bmih->biCompression=BI_RGB;
	m_bmih->biXPelsPerMeter=0;
	m_bmih->biYPelsPerMeter=0;
	m_bmih->biClrUsed=m_nColors;
	m_bmih->biClrImportant=m_nColors;
	DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
	if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32)
		dwBytes++;
	dwBytes*=4;
	m_sizeData=dwBytes*m_bmih->biHeight;
	m_width=width;
	m_height=height;
	m_byteCount=m_bmih->biBitCount/8;
	m_virtualWidth=m_sizeData/height;
	m_data=(LPBYTE)new char[m_sizeData];
}

/***************************/
// Constructor from a CImage
CDib::CDib(CImage *image,int scale,float min,float max)
{
	int i,j;

	if (image->m_color==GRAY) m_nColors=256; else m_nColors=0;
	m_bmih=(LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors];
	m_bmih->biSize=sizeof(BITMAPINFOHEADER);
	m_bmih->biWidth=image->m_col;
	m_bmih->biHeight=image->m_row;
	m_bmih->biPlanes=1;
	if (image->m_color==GRAY) m_bmih->biBitCount=8; else m_bmih->biBitCount=24;
	m_bmih->biSizeImage=0;
	m_bmih->biCompression=BI_RGB;
	m_bmih->biXPelsPerMeter=0;
	m_bmih->biYPelsPerMeter=0;
	m_bmih->biClrUsed=m_nColors;
	m_bmih->biClrImportant=m_nColors;
	DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
	if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32)
		dwBytes++;
	dwBytes*=4;
	m_sizeData=dwBytes*m_bmih->biHeight;
	m_width=image->m_col;
	m_height=image->m_row;
	m_byteCount=m_bmih->biBitCount/8;
	m_virtualWidth=m_sizeData/image->m_row;
	m_data=(LPBYTE)new char[m_sizeData];
	if (image->m_color==GRAY)
	{
		if (scale)
		{
			if ((min==0.0f)&&(max==0.0f))
			{
				min=BIG, max=-BIG;
				for(i=0;i<image->m_row;i++) for(j=0;j<image->m_col;j++)
				{
					if (image->m_data[i][j]<min) min=image->m_data[i][j];
					if (image->m_data[i][j]>max) max=image->m_data[i][j];
				}
			}
			for(i=0;i<image->m_row;i++) for(j=0;j<image->m_col;j++)
				m_data[i*m_virtualWidth+j]=(unsigned char)((image->m_data[image->m_row-1-i][j]-min)*(float)255/(max-min));
		}
		else
		{
			for(i=0;i<image->m_row;i++) for(j=0;j<image->m_col;j++)
				m_data[i*m_virtualWidth+j]=(unsigned char)image->m_data[image->m_row-1-i][j];
		}
	}
	else
	{
		for(i=0;i<image->m_row;i++) for(j=0;j<image->m_col;j++)
		{
			m_data[i*m_virtualWidth+3*j]=(unsigned char)image->m_data[image->m_row-1-i][3*j+2];
			m_data[i*m_virtualWidth+3*j+1]=(unsigned char)image->m_data[image->m_row-1-i][3*j+1];
			m_data[i*m_virtualWidth+3*j+2]=(unsigned char)image->m_data[image->m_row-1-i][3*j];
		}
	}
	LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
	for(i=0;i<m_nColors;i++)
	{
		dibQuad->rgbRed=i;
		dibQuad->rgbGreen=i;
		dibQuad->rgbBlue=i;
		dibQuad++;
	}
	m_palette=NULL;
	MakePalette();
}

/****************************************************/
// Constructor from GrayImage (NTadt) and a gray level mapping
// Always constructs a color Dib
/*CDib::CDib(GrayImage image,int *mapping)
{
	int i,j;
	int tmp;
	int W=imGetWidth(image);
	int H=imGetHeight(image);

	//if (image->m_color==GRAY) m_nColors=256; else m_nColors=0;
	m_nColors=0;
	m_bmih=(LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors];
	m_bmih->biSize=sizeof(BITMAPINFOHEADER);
	m_bmih->biWidth =W;
	m_bmih->biHeight=H;
	m_bmih->biPlanes=1;
	//if (image->m_color==GRAY) m_bmih->biBitCount=8; else m_bmih->biBitCount=24;
	m_bmih->biBitCount=24;
	m_bmih->biSizeImage=0;
	m_bmih->biCompression=BI_RGB;
	m_bmih->biXPelsPerMeter=0;
	m_bmih->biYPelsPerMeter=0;
	m_bmih->biClrUsed=m_nColors;
	m_bmih->biClrImportant=m_nColors;
	DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
	if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32)
		dwBytes++;
	dwBytes*=4;
	m_sizeData=dwBytes*m_bmih->biHeight;
	m_width=W;
	m_height=H;
	m_byteCount=m_bmih->biBitCount/8;
	m_virtualWidth=m_sizeData/H;
	m_data=(LPBYTE)new char[m_sizeData];
	for(i=0;i<H;i++) for(j=0;j<W;j++)
	{
		tmp=mapping[(int)(imRef(image,j,H-1-i))]; //->m_data[image->m_row-1-i][j])];
		m_data[i*m_virtualWidth+3*j]=(unsigned char)tmp;
		m_data[i*m_virtualWidth+3*j+1]=(unsigned char)tmp;
		m_data[i*m_virtualWidth+3*j+2]=(unsigned char)tmp;
	}
	LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
	for(i=0;i<m_nColors;i++)
	{
		dibQuad->rgbRed=i;
		dibQuad->rgbGreen=i;
		dibQuad->rgbBlue=i;
		dibQuad++;
	}
	m_palette=NULL;
	MakePalette();
}
*/
/****************************************************/
// Constructor from GrayImage (NTadt) and a gray level mapping
// Always constructs a color Dib
/*CDib::CDib(RGBImage image,int *mapping)
{
	int i,j;
	int W=imGetWidth(image);
	int H=imGetHeight(image);

	//if (image->m_color==GRAY) m_nColors=256; else m_nColors=0;
	m_nColors=0;
	m_bmih=(LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors];
	m_bmih->biSize=sizeof(BITMAPINFOHEADER);
	m_bmih->biWidth =W;
	m_bmih->biHeight=H;
	m_bmih->biPlanes=1;
	//if (image->m_color==GRAY) m_bmih->biBitCount=8; else m_bmih->biBitCount=24;
	m_bmih->biBitCount=24;
	m_bmih->biSizeImage=0;
	m_bmih->biCompression=BI_RGB;
	m_bmih->biXPelsPerMeter=0;
	m_bmih->biYPelsPerMeter=0;
	m_bmih->biClrUsed=m_nColors;
	m_bmih->biClrImportant=m_nColors;
	DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
	if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32)
		dwBytes++;
	dwBytes*=4;
	m_sizeData=dwBytes*m_bmih->biHeight;
	m_width=W;
	m_height=H;
	m_byteCount=m_bmih->biBitCount/8;
	m_virtualWidth=m_sizeData/H;
	m_data=(LPBYTE)new char[m_sizeData];
	for(i=0;i<H;i++) for(j=0;j<W;j++)
	{
		m_data[i*m_virtualWidth+3*j]  =(unsigned char)imRef(image,H-1-i,j).r;
		m_data[i*m_virtualWidth+3*j+1]=(unsigned char)imRef(image,H-1-i,j).g;
		m_data[i*m_virtualWidth+3*j+2]=(unsigned char)imRef(image,H-1-i,j).b;
	}
	LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
	for(i=0;i<m_nColors;i++)
	{
		dibQuad->rgbRed=i;
		dibQuad->rgbGreen=i;
		dibQuad->rgbBlue=i;
		dibQuad++;
	}
	m_palette=NULL;
	MakePalette();
}
*/
/****************************************************/
// Constructor from a CImage and a gray level mapping
// Always constructs a color Dib
CDib::CDib(CImage *image,int *mapping, char ** mask)
{
	int i,j;
	int tmp;

	//if (image->m_color==GRAY) m_nColors=256; else m_nColors=0;
	m_nColors=0;
	m_bmih=(LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors];
	m_bmih->biSize=sizeof(BITMAPINFOHEADER);
	m_bmih->biWidth=image->m_col;
	m_bmih->biHeight=image->m_row;
	m_bmih->biPlanes=1;
	//if (image->m_color==GRAY) m_bmih->biBitCount=8; else m_bmih->biBitCount=24;
	m_bmih->biBitCount=24;
	m_bmih->biSizeImage=0;
	m_bmih->biCompression=BI_RGB;
	m_bmih->biXPelsPerMeter=0;
	m_bmih->biYPelsPerMeter=0;
	m_bmih->biClrUsed=m_nColors;
	m_bmih->biClrImportant=m_nColors;
	DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
	if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32)
		dwBytes++;
	dwBytes*=4;
	m_sizeData=dwBytes*m_bmih->biHeight;
	m_width=image->m_col;
	m_height=image->m_row;
	m_byteCount=m_bmih->biBitCount/8;
	m_virtualWidth=m_sizeData/image->m_row;
	m_data=(LPBYTE)new char[m_sizeData];
	char masking;
	unsigned char gray;
	if (image->m_color==GRAY)
	{
		for(i=0;i<image->m_row;i++) for(j=0;j<image->m_col;j++)
		{
			tmp = mapping[(int)(image->m_data[image->m_row-1-i][j])];
			masking=mask[j][image->m_row-1-i];
			m_data[i*m_virtualWidth+3*j]  =(unsigned char) ((masking) ? tmp/3*2 : tmp);
			m_data[i*m_virtualWidth+3*j+1]=(unsigned char) ((masking) ? tmp/3*2 : tmp);
			m_data[i*m_virtualWidth+3*j+2]=(unsigned char) ((masking) ? 200 : tmp);
		}
	}
	else
	{
		for(i=0;i<image->m_row;i++) for(j=0;j<image->m_col;j++)
		{
			if (masking=mask[j][image->m_row-1-i]) gray = (unsigned char) (image->m_data[image->m_row-1-i][3*j+2]/3 + image->m_data[image->m_row-1-i][3*j+1]/3 + image->m_data[image->m_row-1-i][3*j]/3);
			m_data[i*m_virtualWidth+3*j]  = (masking) ? gray : ((unsigned char)image->m_data[image->m_row-1-i][3*j+2]);
			m_data[i*m_virtualWidth+3*j+1]= (masking) ? gray : ((unsigned char)image->m_data[image->m_row-1-i][3*j+1]);
			m_data[i*m_virtualWidth+3*j+2]= (masking) ? gray : ((unsigned char)image->m_data[image->m_row-1-i][3*j]);
		}
	}
	LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
	for(i=0;i<m_nColors;i++)
	{
		dibQuad->rgbRed=i;
		dibQuad->rgbGreen=i;
		dibQuad->rgbBlue=i;
		dibQuad++;
	}
	m_palette=NULL;
	MakePalette();
}

/***********************/
// Constructor from data
CDib::CDib(int row,int col,int color,float **data,int scale)
{
	int i,j;

	if (color==GRAY) m_nColors=256; else m_nColors=0;
	m_bmih=(LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors];
	m_bmih->biSize=sizeof(BITMAPINFOHEADER);
	m_bmih->biWidth=col;
	m_bmih->biHeight=row;
	m_bmih->biPlanes=1;
	if (color==GRAY) m_bmih->biBitCount=8; else m_bmih->biBitCount=24;
	m_bmih->biSizeImage=0;
	m_bmih->biCompression=BI_RGB;
	m_bmih->biXPelsPerMeter=0;
	m_bmih->biYPelsPerMeter=0;
	m_bmih->biClrUsed=m_nColors;
	m_bmih->biClrImportant=m_nColors;
	DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
	if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32)
		dwBytes++;
	dwBytes*=4;
	m_sizeData=dwBytes*m_bmih->biHeight;
	m_width=col;
	m_height=row;
	m_byteCount=m_bmih->biBitCount/8;
	m_virtualWidth=m_sizeData/row;
	m_data=(LPBYTE)new char[m_sizeData];
	if (color==GRAY)
	{
		if (scale)
		{
			float min=(float)BIG, max=-(float)BIG;
			for(i=0;i<row;i++) for(j=0;j<col;j++)
			{
				if (data[i][j]<min) min=data[i][j];
				if (data[i][j]>max) max=data[i][j];
			}
			for(i=0;i<row;i++) for(j=0;j<col;j++)
				m_data[i*m_virtualWidth+j]=(unsigned char)((data[row-1-i][j]-min)*(float)255/(max-min));
		}
		else
		{
			for(i=0;i<row;i++) for(j=0;j<col;j++)
				m_data[i*m_virtualWidth+j]=(unsigned char)(data[row-1-i][j]);
		}
	}
	else
	{
		for(i=0;i<row;i++) for(j=0;j<col;j++)
		{
			m_data[i*m_virtualWidth+3*j]=(unsigned char)data[row-1-i][3*j+2];
			m_data[i*m_virtualWidth+3*j+1]=(unsigned char)data[row-1-i][3*j+1];
			m_data[i*m_virtualWidth+3*j+2]=(unsigned char)data[row-1-i][3*j];
		}
	}
	LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
	for(i=0;i<m_nColors;i++)
	{
		dibQuad->rgbRed=i;
		dibQuad->rgbGreen=i;
		dibQuad->rgbBlue=i;
		dibQuad++;
	}
	m_palette=NULL;
	MakePalette();
}

/*************/
// Read a CDib
BOOL CDib::Read(CFile *pFile)
{
	int nCount,nSize;
	BITMAPFILEHEADER bmfh;

	nCount=pFile->Read((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
	if (nCount!=sizeof(BITMAPFILEHEADER))
	{
		AfxMessageBox(L"Read error 1");
		return FALSE;
	}
	if (bmfh.bfType!=0x4d42)
	{
		AfxMessageBox(L"Invalid bitmap file");
		return FALSE;
	}
	// Read the header
	nSize=bmfh.bfOffBits-sizeof(BITMAPFILEHEADER);
	m_bmih=(LPBITMAPINFOHEADER)new char[nSize];
	nCount=pFile->Read(m_bmih, nSize); 
	// Compute the number of colors 
	if (m_bmih->biClrUsed)
		m_nColors=m_bmih->biClrUsed;
	else
		m_nColors=1<<m_bmih->biBitCount;
	// Read the data
	m_sizeData=m_bmih->biSizeImage;
	m_width=m_bmih->biWidth;
	m_height=m_bmih->biHeight;
	m_byteCount=m_bmih->biBitCount/8;
	// This has to be done because the data is padded to a 4 byte boundary
	if (!m_sizeData) 
	{
		DWORD dwBytes=((DWORD)m_bmih->biWidth*m_bmih->biBitCount)/32;
		if (((DWORD)m_bmih->biWidth*m_bmih->biBitCount)%32) 
			dwBytes++;
		dwBytes*=4;
		m_sizeData=dwBytes*m_bmih->biHeight;
	}
	m_virtualWidth=m_sizeData/m_height;
	m_data = (LPBYTE) new char[m_sizeData];
	nCount = pFile->Read(m_data, m_sizeData);
	return TRUE;
}

/**************/
// Write a CDib
BOOL CDib::Write(CFile *pFile)
{
	BITMAPFILEHEADER bmfh;
	int nSize;
	
	bmfh.bfType=0x4d42;
	nSize=sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors;
	bmfh.bfSize=m_sizeData+nSize+sizeof(BITMAPFILEHEADER);
	bmfh.bfReserved1=bmfh.bfReserved2=0;
	bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColors;
	pFile->Write((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
	pFile->Write((LPVOID)m_bmih,nSize);
	pFile->Write((LPVOID)m_data,m_sizeData);
	pFile->Close();
	return(TRUE);
}

/**************************************/
// Create a palette do display the CDib
BOOL CDib::MakePalette()
{
	if (m_bmih==NULL) return FALSE;
	if(m_palette != NULL) 
	{
		delete m_palette;
		m_palette=NULL;
	}
	if (m_nColors==0) return FALSE;
	if (m_nColors>256) return FALSE;
	LPLOGPALETTE pLogPal=(LPLOGPALETTE)new char[2*sizeof(WORD)+m_nColors*sizeof(PALETTEENTRY)];
	pLogPal->palVersion=0x300;
	pLogPal->palNumEntries=m_nColors;
	LPRGBQUAD pDibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
	for(int i=0;i<m_nColors;i++) 
	{
		pLogPal->palPalEntry[i].peRed=pDibQuad->rgbRed;
		pLogPal->palPalEntry[i].peGreen=pDibQuad->rgbGreen;
		pLogPal->palPalEntry[i].peBlue=pDibQuad->rgbBlue;
		pLogPal->palPalEntry[i].peFlags=0;
		pDibQuad++;
	}
	m_palette=new CPalette();
	m_palette->CreatePalette(pLogPal);
	delete pLogPal;
	return TRUE;
}

/******************************************************/
// Use the system palette if no better one is available
BOOL CDib::SetSystemPalette(CDC* pDC)
{
	HDC hDC=pDC->GetSafeHdc();
	if (GetDeviceCaps(hDC,RASTERCAPS)&RC_PALETTE==0) return FALSE;
	int nSysColors=GetDeviceCaps(hDC,NUMCOLORS);
	int nPalEntries=GetDeviceCaps(hDC,SIZEPALETTE);
	int nEntries=(nPalEntries==0)?nSysColors:nPalEntries;
	LPLOGPALETTE pLogPal=(LPLOGPALETTE)new char[2*sizeof(WORD)+nEntries*sizeof(PALETTEENTRY)];
	pLogPal->palVersion=0x300;
	pLogPal->palNumEntries=nEntries;
	GetSystemPaletteEntries(hDC,0,nEntries,(LPPALETTEENTRY)((LPBYTE)pLogPal+2*sizeof(WORD)));
	m_palette=(CPalette *)new CPalette();
	m_palette->CreatePalette(pLogPal);
	//delete pLogPal;
	return TRUE;
}

/**********************/
// Display a CDib image
BOOL CDib::Draw(CDC *pDC,int x,int y,int width,int height)
{
	if ((m_bmih==NULL)||(m_data==NULL)) return FALSE;
	if (m_palette==NULL) SetSystemPalette(pDC);
	CPalette* oldCPal=pDC->SelectPalette(m_palette,FALSE);
	pDC->RealizePalette();
	StretchDIBits(pDC->GetSafeHdc(),x,y,width,height,
		0,0,m_width,m_height,m_data,
		(LPBITMAPINFO)m_bmih,DIB_RGB_COLORS,SRCCOPY);
	pDC->SelectPalette(oldCPal,FALSE);
	return TRUE;
}

/**********************************/
// Create a float image from a CDib
float **CDib::MakeFloatImage(int *row,int *col,int *color)
{
	float **image,**image2;
	int i,j,check;
	BYTE value;

	*row=m_height;
	*col=m_width;
	image=make_2D_float_array(m_height,3*m_width);
	if (m_bmih->biBitCount==8)
	{
		LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
		check=1;
		for(i=0;i<m_height;i++)
			for(j=0;j<m_width;j++)
		{
			value=m_data[(m_height-1-i)*m_virtualWidth+j];
			image[i][3*j]=(float)(dibQuad[value].rgbRed);
			image[i][3*j+1]=(float)(dibQuad[value].rgbGreen);
			image[i][3*j+2]=(float)(dibQuad[value].rgbBlue);
			if ((image[i][3*j]!=image[i][3*j+1])||
				(image[i][3*j]!=image[i][3*j+2])||
				(image[i][3*j+1]!=image[i][3*j+2]))
				check=0;
		}
		// There is no need to store 3 values per pixel if the image is gray
		if (check)
		{
			image2=make_2D_float_array(m_height,m_width);
			for(i=0;i<m_height;i++)
				for(j=0;j<m_width;j++)
					image2[i][j]=image[i][3*j];
			*color=GRAY;
			free_2D_float_array(image);
			return(image2);
		}
		else
		{
			*color=COLOR;
			return(image);
		}
	}
	else if (m_bmih->biBitCount==24)
	{
		check=1;
		for(i=0;i<m_height;i++)
			for(j=0;j<m_width;j++)
		{
			image[i][3*j]=(float)m_data[(m_height-1-i)*m_virtualWidth+3*j+2];
			image[i][3*j+1]=(float)m_data[(m_height-1-i)*m_virtualWidth+3*j+1];
			image[i][3*j+2]=(float)m_data[(m_height-1-i)*m_virtualWidth+3*j];
			if ((image[i][3*j]!=image[i][3*j+1])||
				(image[i][3*j]!=image[i][3*j+2])||
				(image[i][3*j+1]!=image[i][3*j+2]))
				check=0;
		}
		// There is no need to store 3 values per pixel if the image is gray
		if (check)
		{
			image2=make_2D_float_array(m_height,m_width);
			for(i=0;i<m_height;i++)
				for(j=0;j<m_width;j++)
					image2[i][j]=image[i][3*j];
			*color=GRAY;
			free_2D_float_array(image);
			return(image2);
		}
		else
		{
			*color=COLOR;
			return(image);
		}
	}
	return(NULL);
}

/*********************************************************/
// Create a float image of known size and color from a DIB
int CDib::MakeKnownFloatImage(float **image,int color)
{
	int i,j;
	BYTE value;

	if (color==GRAY)
	{
		if (m_bmih->biBitCount==8)
		{
			LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
			for(i=0;i<m_height;i++)
				for(j=0;j<m_width;j++)
			{
				value=m_data[(m_height-1-i)*m_virtualWidth+j];
				image[i][j]=(float)(dibQuad[value].rgbRed+dibQuad[value].rgbGreen+dibQuad[value].rgbBlue)/(float)(3.);
			}
		}
		else if (m_bmih->biBitCount==24)
		{
			for(i=0;i<m_height;i++)
				for(j=0;j<m_width;j++)
			{
				image[i][j]=(float)(m_data[(m_height-1-i)*m_virtualWidth+3*j+2]
								   +m_data[(m_height-1-i)*m_virtualWidth+3*j+1]
								   +m_data[(m_height-1-i)*m_virtualWidth+3*j])/(float)(3.);
			}
		}
	}
	else if (color==COLOR)
	{
		if (m_bmih->biBitCount==8)
		{
			LPRGBQUAD dibQuad=(LPRGBQUAD)((char *)m_bmih+sizeof(BITMAPINFOHEADER));
			for(i=0;i<m_height;i++)
				for(j=0;j<m_width;j++)
			{
				value=m_data[(m_height-1-i)*m_virtualWidth+j];
				image[i][3*j]=(float)(dibQuad[value].rgbRed);
				image[i][3*j+1]=(float)(dibQuad[value].rgbGreen);
				image[i][3*j+2]=(float)(dibQuad[value].rgbBlue);
			}
		}
		else if (m_bmih->biBitCount==24)
		{
			for(i=0;i<m_height;i++)
				for(j=0;j<m_width;j++)
			{
				image[i][3*j]=(float)m_data[(m_height-1-i)*m_virtualWidth+3*j+2];
				image[i][3*j+1]=(float)m_data[(m_height-1-i)*m_virtualWidth+3*j+1];
				image[i][3*j+2]=(float)m_data[(m_height-1-i)*m_virtualWidth+3*j];
			}
		
		}
	}
	return(1);
}