#if defined(WIN32)
#include <direct.h>
#include <io.h>
#endif /* WIN32 */
 
#include "FIL_CPA.h"
 
#define D_FIL_StructureDefine
 
#include "ErmFil.h"
 
#include "FIL_Pub.h"
#include "FIL_Priv.h"
 
#include "FIL_Bmp.h"
 
#include "MMG.h"
/**************************************************************************/
void FIL_fn_vSaveBMPInFile(char *p_szFileName,unsigned char *p_ucSource,unsigned long ulWidth,unsigned long ulHeight,unsigned char ucNumberOfBytesInFile,unsigned char ucNumberOfBytesInSource)
{
 struct FIL_tdstBmp_ stBmp;
 
 FILE *p_stFile;
 long x,y;
 
 /**** Bmp File Header ****/
 stBmp.stFileHeader.uwType       = 0x4D42; /**** BM ****/
 stBmp.stFileHeader.ulSize       = sizeof(struct FIL_tdstBmpFileHeader_)+sizeof(struct FIL_tdstBmpInfoHeader_)+ucNumberOfBytesInFile*ulHeight*ulWidth;
 stBmp.stFileHeader.ulReserved   = 0x00000000;
 stBmp.stFileHeader.ulOffsetBits = sizeof(struct FIL_tdstBmpFileHeader_)+sizeof(struct FIL_tdstBmpInfoHeader_);
 
 /**** Bmp Info Header ****/
 stBmp.stInfoHeader.ulSize            = sizeof(struct FIL_tdstBmpInfoHeader_);
 stBmp.stInfoHeader.ulWidth           = ulWidth;
 stBmp.stInfoHeader.ulHeight          = ulHeight;
 stBmp.stInfoHeader.uwPlanes          = 1;
 stBmp.stInfoHeader.uwBitCount        = (unsigned short)(8*ucNumberOfBytesInFile);
 stBmp.stInfoHeader.ulCompression     = 0;
 stBmp.stInfoHeader.ulSizeImage       = ucNumberOfBytesInFile*ulHeight*ulWidth;
 stBmp.stInfoHeader.ulXPelsPerMeter   = 0;
 stBmp.stInfoHeader.ulYPelsPerMeter   = 0;
 stBmp.stInfoHeader.ulColorsUsed      = 0;
 stBmp.stInfoHeader.ulColorsImportant = 0;
 
 stBmp.p_ucBitMap = p_ucSource;
 
 FIL_fn_bValidatePath("",p_szFileName);
 if ((p_stFile = fopen(p_szFileName,"wb"))!=NULL)
 {
  fwrite(&stBmp.stFileHeader,sizeof(struct FIL_tdstBmpFileHeader_),1,p_stFile);
  fwrite(&stBmp.stInfoHeader,sizeof(struct FIL_tdstBmpInfoHeader_),1,p_stFile);
  for (y=ulHeight-1;y>=0;y--)
  {
   for (x=0;x<(long)ulWidth;x++)
   {
    fwrite(stBmp.p_ucBitMap+(y*ulWidth+x)*ucNumberOfBytesInSource,sizeof(unsigned char),ucNumberOfBytesInFile,p_stFile);
   }
  }
  fclose(p_stFile);
 }
}
/**************************************************************************/
void FIL_fn_vLoadBMPInformationFromFile(char *p_szPath,char *p_szFileName,unsigned char *p_ucNumberOfBytesInDest,unsigned long *p_ulWidth,unsigned long *p_ulHeight)
{
 FILE *p_stFile;
 struct FIL_tdstBmp_ stBmp;
 char szCompleteName[_MAX_PATH];
 
 sprintf(szCompleteName,"%s\\%s",p_szPath,p_szFileName);
 
 *p_ucNumberOfBytesInDest = 0;
 *p_ulWidth = 0;
 *p_ulHeight = 0;
 
 if ((p_stFile = fopen(szCompleteName,"rb"))!=NULL)
 {
  fread(&stBmp.stFileHeader,sizeof(struct FIL_tdstBmpFileHeader_),1,p_stFile);
  fread(&stBmp.stInfoHeader,sizeof(struct FIL_tdstBmpInfoHeader_),1,p_stFile);
  if (  stBmp.stFileHeader.uwType!=0x4D42 /**** BM ****/
      ||stBmp.stInfoHeader.uwPlanes!=1
/* CGHT Palette*/
      ||((stBmp.stInfoHeader.uwBitCount!=24)&&(stBmp.stInfoHeader.uwBitCount!=8))
      ||stBmp.stInfoHeader.ulCompression!=0
     )
  {
   M_FILInformationErrorWithMessage(E_uwFILBadBmpFormat,szCompleteName);
  }
  else
  {
   *p_ucNumberOfBytesInDest = (unsigned char)(stBmp.stInfoHeader.uwBitCount/8);
   *p_ulWidth  = stBmp.stInfoHeader.ulWidth;
   *p_ulHeight = stBmp.stInfoHeader.ulHeight;
  }
  fclose(p_stFile);
 }
}
/**************************************************************************/
#if !defined(RETAIL) /* Use only in ConvImg*/
void FIL_fn_vLoadBMPFromFileWithInvertPicture(char *p_szPath, char *p_szFileName, FIL_tdstGF *_p_stHeader)
{
 FIL_fn_vLoadBMPFromFileWithoutInvertPicture(p_szPath,p_szFileName,
											&_p_stHeader->p_ucBitMap,
											&_p_stHeader->stFileHeader.ucBpp,
											&_p_stHeader->stFileHeader.ulWidth,
											&_p_stHeader->stFileHeader.ulHeight);
  if (_p_stHeader ->p_ucBitMap != NULL)
	FIL_fn_vInvertBMP(	_p_stHeader ->p_ucBitMap,
						_p_stHeader->stFileHeader.ucBpp,
						_p_stHeader->stFileHeader.ulWidth,
						_p_stHeader->stFileHeader.ulHeight);
}
#endif /*RETAIL*/
/**************************************************************************/
void FIL_fn_vLoadBMPFromFileWithoutInvertPicture(char *p_szPath,char *p_szFileName,unsigned char **pp_ucDest,unsigned char *p_ucNumberOfBytesInDest,unsigned long *p_ulWidth,unsigned long *p_ulHeight)
{
 FILE *p_stFile;
 struct FIL_tdstBmp_ stBmp;
 char szCompleteName[_MAX_PATH];
 
 if (p_szPath[0]!=0)
	 sprintf(szCompleteName,"%s\\%s",p_szPath,p_szFileName);
 else
	 sprintf(szCompleteName,"%s",p_szFileName);
 
 *pp_ucDest = NULL;
 *p_ucNumberOfBytesInDest = 0;
 *p_ulWidth = 0;
 *p_ulHeight = 0;
 
 if ((p_stFile = fopen(szCompleteName,"rb"))!=NULL)
 {
  fread(&stBmp.stFileHeader,sizeof(struct FIL_tdstBmpFileHeader_),1,p_stFile);
  fread(&stBmp.stInfoHeader,sizeof(struct FIL_tdstBmpInfoHeader_),1,p_stFile);
  if (  stBmp.stFileHeader.uwType!=0x4D42 /**** BM ****/
      ||stBmp.stInfoHeader.uwPlanes!=1
/* CGHT Palette*/
      ||((stBmp.stInfoHeader.uwBitCount!=24)&&(stBmp.stInfoHeader.uwBitCount!=8))
      ||stBmp.stInfoHeader.ulCompression!=0
     )
  {
   M_FILInformationErrorWithMessage(E_uwFILBadBmpFormat,szCompleteName);
  }
  else
  {
   unsigned long ulSizeOfPalette;
	 
   *p_ucNumberOfBytesInDest = (unsigned char)(stBmp.stInfoHeader.uwBitCount/8);
   *p_ulWidth  = stBmp.stInfoHeader.ulWidth;
   *p_ulHeight = stBmp.stInfoHeader.ulHeight;
 
   /* CGHT Palette*/
   if(stBmp.stInfoHeader.uwBitCount==8)
   {
	   /* Palette is on the start of the block*/
		ulSizeOfPalette=256*sizeof(RGBQUAD);
   }
   else
   {
	   ulSizeOfPalette=0;
   }
   MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeBmpFile , NULL);
   stBmp.p_ucBitMap = (unsigned char *)TMP_M_p_Malloc(*p_ulWidth**p_ulHeight**p_ucNumberOfBytesInDest+ulSizeOfPalette);
   *pp_ucDest = stBmp.p_ucBitMap;
   /* CGHT Palette*/
   fread(stBmp.p_ucBitMap,1,*p_ucNumberOfBytesInDest**p_ulWidth**p_ulHeight+ulSizeOfPalette,p_stFile);
  }
  fclose(p_stFile);
 }
}
/**************************************************************************/
void FIL_fn_vLoadBMPInformationFromConcatFile(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFileName,unsigned char *p_ucNumberOfBytesInDest,unsigned long *p_ulWidth,unsigned long *p_ulHeight)
{
 FIL_tdxHandleToFileInConcatFile hHandleToFile;
 struct FIL_tdstBmp_ stBmp;
 
 *p_ucNumberOfBytesInDest = 0;
 *p_ulWidth = 0;
 *p_ulHeight = 0;
 
 if ((hHandleToFile = FIL_fn_hOpenFileInConcatFile(hConcatFile,p_szPath,p_szFileName))!=NULL)
 {
  FIL_fn_lReadFileInConcatFile(&stBmp.stFileHeader,sizeof(struct FIL_tdstBmpFileHeader_),1,hHandleToFile);
  FIL_fn_lReadFileInConcatFile(&stBmp.stInfoHeader,sizeof(struct FIL_tdstBmpInfoHeader_),1,hHandleToFile);
  if (  stBmp.stFileHeader.uwType!=0x4D42 /**** BM ****/
      ||stBmp.stInfoHeader.uwPlanes!=1
      ||stBmp.stInfoHeader.uwBitCount!=24
      ||stBmp.stInfoHeader.ulCompression!=0
     )
  {
   M_FILInformationErrorWithMessage(E_uwFILBadBmpFormat,p_szFileName);
  }
  else
  {
   *p_ucNumberOfBytesInDest = (unsigned char)(stBmp.stInfoHeader.uwBitCount/8);
   *p_ulWidth  = stBmp.stInfoHeader.ulWidth;
   *p_ulHeight = stBmp.stInfoHeader.ulHeight;
  }
  FIL_fn_vCloseFileInConcatFile(&hHandleToFile);
 }
}
/**************************************************************************/
void FIL_fn_vLoadBMPFromConcatFileWithInvertPicture(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFileName,unsigned char **pp_ucDest,unsigned char *p_ucNumberOfBytesInDest,unsigned long *p_ulWidth,unsigned long *p_ulHeight)
{
 FIL_fn_vLoadBMPFromConcatFileWithoutInvertPicture(hConcatFile,p_szPath,p_szFileName,pp_ucDest,p_ucNumberOfBytesInDest,p_ulWidth,p_ulHeight);
 if (*pp_ucDest!=NULL)
  FIL_fn_vInvertBMP(*pp_ucDest,*p_ucNumberOfBytesInDest,*p_ulWidth,*p_ulHeight);
}
/**************************************************************************/
void FIL_fn_vLoadBMPFromConcatFileWithoutInvertPicture(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFileName,unsigned char **pp_ucDest,unsigned char *p_ucNumberOfBytesInDest,unsigned long *p_ulWidth,unsigned long *p_ulHeight)
{
 FIL_tdxHandleToFileInConcatFile hHandleToFile;
 struct FIL_tdstBmp_ stBmp;
 
 *pp_ucDest = NULL;
 *p_ucNumberOfBytesInDest = 0;
 *p_ulWidth = 0;
 *p_ulHeight = 0;
 
 if ((hHandleToFile = FIL_fn_hOpenFileInConcatFile(hConcatFile,p_szPath,p_szFileName))!=NULL)
 {
  FIL_fn_lReadFileInConcatFile(&stBmp.stFileHeader,sizeof(struct FIL_tdstBmpFileHeader_),1,hHandleToFile);
  FIL_fn_lReadFileInConcatFile(&stBmp.stInfoHeader,sizeof(struct FIL_tdstBmpInfoHeader_),1,hHandleToFile);
  if (  stBmp.stFileHeader.uwType!=0x4D42 /**** BM ****/
      ||stBmp.stInfoHeader.uwPlanes!=1
/* CGHT Palette*/
      ||((stBmp.stInfoHeader.uwBitCount!=24)&&(stBmp.stInfoHeader.uwBitCount!=8))
      ||stBmp.stInfoHeader.ulCompression!=0
     )
  {
   M_FILInformationErrorWithMessage(E_uwFILBadBmpFormat,p_szFileName);
  }
  else
  {
   *p_ucNumberOfBytesInDest = (unsigned char)(stBmp.stInfoHeader.uwBitCount/8);
   *p_ulWidth  = stBmp.stInfoHeader.ulWidth;
   *p_ulHeight = stBmp.stInfoHeader.ulHeight;
 
	MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeBmpFile , NULL);   
	stBmp.p_ucBitMap = (unsigned char *)TMP_M_p_Malloc(*p_ulWidth**p_ulHeight**p_ucNumberOfBytesInDest);
   *pp_ucDest = stBmp.p_ucBitMap;
   FIL_fn_lReadFileInConcatFile(stBmp.p_ucBitMap,*p_ucNumberOfBytesInDest,*p_ulWidth**p_ulHeight,hHandleToFile);
  }
  FIL_fn_vCloseFileInConcatFile(&hHandleToFile);
 }
}
/**************************************************************************/
void FIL_fn_vFreeBMP(unsigned char **pp_ucMemory)
{
 if (*pp_ucMemory!=NULL)
  TMP_M_Free(*pp_ucMemory);
 *pp_ucMemory = NULL;
}
/**************************************************************************/
void FIL_fn_vInvertBMP(unsigned char *p_ucDest,unsigned char ucNumberOfBytesInDest,unsigned long ulWidth,unsigned long ulHeight)
{
 unsigned char *p_ucOneLine,*p_ucBlockStart;
 unsigned long y;
 
  MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeBmpFile , NULL);
  p_ucOneLine = (unsigned char *)TMP_M_p_Malloc(ulWidth*ucNumberOfBytesInDest);
 
 /* CGHT Palette*/
 
 p_ucBlockStart=p_ucDest;
 
 if(ucNumberOfBytesInDest==1)
 {
	 p_ucBlockStart+=256*sizeof(RGBQUAD);
 }
 
 
 for (y=0;y<ulHeight/2;y++)
 {
  memcpy(p_ucOneLine,p_ucBlockStart+y*ulWidth*ucNumberOfBytesInDest,ulWidth*ucNumberOfBytesInDest);
  memcpy(p_ucBlockStart+y*ulWidth*ucNumberOfBytesInDest,p_ucBlockStart+(ulHeight-1-y)*ulWidth*ucNumberOfBytesInDest,ulWidth*ucNumberOfBytesInDest);
  memcpy(p_ucBlockStart+(ulHeight-1-y)*ulWidth*ucNumberOfBytesInDest,p_ucOneLine,ulWidth*ucNumberOfBytesInDest);
 }
 
 TMP_M_Free(p_ucOneLine);
}
/**************************************************************************/
