#include"CBitmapLoader.h"

#include"../../../Graphic/CSurfaceInfo.h"
#include"../../../Graphic/Core/Driver/CPlaneTransiter.h"
#include"../../../Graphic/CSurfaceInfo.h"
#include"../../../Auxiliary/FileIO/CFileRead.h"
#include"../../../Auxiliary/FileIO/CFileReadMemory.h"
#include"../../../Auxiliary/FileIO/CFileWrite.h"
#include"../../../Auxiliary/Debug/CAssert.h"
#include"../../../Auxiliary/Debug/CException.h"
#include"../../../Auxiliary/Debug/CTrace.h"

namespace Maid
{

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ビットマップをテクスチャに読み込む
/*!
	@param	FileName	[i ]	ファイル名
	@param	dst			[i ]	転送先
 */
void   CBitmapLoader::Load( const mstring& FileName, CTextureBufferMemory& dst )
{
	CFileRead hFile;

	hFile.Open( FileName );

	BITMAPFILEHEADER	BmpFile;
	BITMAPINFOHEADER	BmpInfo;

	{
		//　ビットマップ形式のデータかチェック
		if(  hFile.Read( &BmpFile, sizeof(BITMAPFILEHEADER) )!=sizeof(BITMAPFILEHEADER) ) { MAID_THROWEXCEPTION(MAIDTEXT("!=sizeof(BITMAPFILEHEADER)")); }

		if( BmpFile.bfType!=0x4D42 ) {  { MAID_THROWEXCEPTION(MAIDTEXT("BmpFile.bfType!=BM")); } }
	}

	SIZE2DI		PlaneSize;
	PIXELFORMAT Format;
	int			Pitch;
	int			CLUTSize=0;

	{
		//　各種情報を収集する
		if( hFile.Read( &BmpInfo, sizeof(BITMAPINFOHEADER) )!=sizeof(BITMAPINFOHEADER) ) { MAID_THROWEXCEPTION(MAIDTEXT("!=sizeof(BITMAPINFOHEADER)")); }

		PlaneSize.w = BmpInfo.biWidth;
		PlaneSize.h = BmpInfo.biHeight;

		switch( BmpInfo.biBitCount )
		{
		case  8: 
			{
				Format = PIXELFORMAT_P08X08R08G08B08I;	
			}break;
		case 24: { Format = PIXELFORMAT_R08G08B08I;			}break;
		case 32: { Format = PIXELFORMAT_A08R08G08B08I;		}break;
		default: { MAID_ASSERT( true, "識別できないピクセルフォーマットです " << BmpInfo.biBitCount ); }break;
		}
		
		Pitch = BmpInfo.biWidth * BmpInfo.biBitCount/8;
		Pitch = (Pitch +3)&~3;					//	ビットマップのピッチは４の倍数である

		CLUTSize = GetCLUTBPP(Format) / 8 * GetCLUTLength(Format);
	}

	//	転送先の作成
	dst.Create( PlaneSize, Format );
	dst.SetReverseSurface( true );

	{	//	順番に転送していく。

		//	ビットマップファイルはパレット、ピクセルデータの順に並んでいるので
		//	そうやって読んでいく
		ISurfaceBuffer& dst_surf = dst.GetSurface(0);
		SPSURFACEBUFFERINFO pDstInfo;

		CSurfaceBufferLoacker Lock( dst_surf, pDstInfo );

		if( CLUTSize!=0 ) { hFile.Read( pDstInfo->GetCLUT(), CLUTSize ); }

		//	ビットマップは上下反転してるけど、 dst.SetReverseSurface( true ) のおかげで
		//	Srcの先頭ラインを Dst の一番下のラインに転送してくれる

		const int OneLineByte = PlaneSize.w * GetPixelBPP(Format) / 8;
		const int sa = Pitch - OneLineByte;

		for( int y=0; y<PlaneSize.h; ++y )
		{
			hFile.Read( pDstInfo->GetLinePtr(y), OneLineByte );
			hFile.Seek( sa, IFileRead::POSITION_CURRENT );
		}
	}
	//	最後に戻すと普通にあつかえる
	dst.SetReverseSurface( false );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 読み込んであるサーフェスをビットマップとして保存する
/*!
 */
void CBitmapLoader::Save( const mstring& FileName, const CTextureBufferMemory& src )
{
	ISurfaceBuffer& surf = const_cast<CTextureBufferMemory&>(src).GetSurface( 0 );

	Save( FileName, surf );

}

void   CBitmapLoader::Save( const mstring& FileName, ISurfaceBuffer& surf )
{
	SPSURFACEBUFFERINFO pInfo;

	surf.Lock( pInfo );

	const SIZE2DI ImageSize(pInfo->GetWidth(),pInfo->GetHeight());
	const PIXELFORMAT fmt = pInfo->GetPixelFormat();

	const int ImageWidthByte = ImageSize.w * GetPixelBPP(fmt) / 8;
	const int FilePitch = (ImageWidthByte+3)&(~3);
	const int PlaneByte   = FilePitch * ImageSize.h;
	const int PaletteByte = GetCLUTBPP(fmt) / 8 * GetCLUTLength(fmt);


	BITMAPFILEHEADER	BmpFile = {0};
	BITMAPINFOHEADER	BmpInfo = {0};

	BmpFile.bfType = 0x4D42;
	BmpFile.bfSize = sizeof(BmpFile)+sizeof(BmpInfo)+PaletteByte + PlaneByte;
	BmpFile.bfOffBits = sizeof(BmpFile)+sizeof(BmpInfo)+PaletteByte;

	BmpInfo.biSize  = sizeof(BmpInfo);
	BmpInfo.biWidth = ImageSize.w;
	BmpInfo.biHeight = ImageSize.h;
	BmpInfo.biPlanes = 1;
	BmpInfo.biBitCount = GetPixelBPP(fmt);
	BmpInfo.biCompression = BI_RGB;

	CFileWrite hFile;

	hFile.Open( FileName, CFileWrite::OPENOPTION_NEW );
	hFile.Write( &BmpFile, sizeof(BmpFile) );
	hFile.Write( &BmpInfo, sizeof(BmpInfo) );

	if( PaletteByte!=0 )
	{
		hFile.Write( pInfo->GetCLUT(), PaletteByte );
	}

	MySTL::vector<unt08> tmp( FilePitch - ImageWidthByte, 0x00 );


	//	ビットマップは上下逆
	for( int y=0; y<ImageSize.h; ++y )
	{
		hFile.Write( pInfo->GetLinePtr((ImageSize.h-1)-y), ImageWidthByte );

		if( !tmp.empty() )
		{
			hFile.Write( &(tmp[0]), (int)tmp.size() );
		}
	}

}

}