
#include	"stdafx.h"
#include	"../ExtractBase.h"
#include	"Bmp.h"

//////////////////////////////////////////////////////////////////////////////////////////
//	マウント

BOOL	CBmp::Mount(
	CArcFile*			pclArc							// アーカイブ
	)
{
	if( lstrcmpi( pclArc->GetArcExten(), _T(".bmp") ) != 0 )
	{
		return	FALSE;
	}

	return	pclArc->Mount();
}

//////////////////////////////////////////////////////////////////////////////////////////
//	初期化

BOOL	CBmp::OnInit(
	const YCString&		rfclsFileName					// ファイル名
	)
{
	// ファイルヘッダの設定

	BITMAPFILEHEADER*	pstBMPFileHeader = &m_stBMPFileHeader;

	ZeroMemory( pstBMPFileHeader, sizeof(BITMAPFILEHEADER) );

	pstBMPFileHeader->bfType = 'MB';
	pstBMPFileHeader->bfSize = (54 + m_lPitch * m_lHeight);
	pstBMPFileHeader->bfReserved1 = 0;
	pstBMPFileHeader->bfReserved2 = 0;
	pstBMPFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

	if( m_wBpp == 8 )
	{
		// 8bit

		pstBMPFileHeader->bfSize += 1024;
		pstBMPFileHeader->bfOffBits += 1024;
	}

	// インフォヘッダの設定

	BITMAPINFOHEADER*	pstBMPInfoHeader = &m_stBMPInfoHeader;

	ZeroMemory( pstBMPInfoHeader, sizeof(BITMAPINFOHEADER) );

	pstBMPInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
	pstBMPInfoHeader->biWidth = m_lWidth;
	pstBMPInfoHeader->biHeight = m_lHeight;
	pstBMPInfoHeader->biPlanes = 1;
	pstBMPInfoHeader->biBitCount = m_wBpp;
	pstBMPInfoHeader->biCompression = BI_RGB;
	pstBMPInfoHeader->biSizeImage = 0;
	pstBMPInfoHeader->biXPelsPerMeter = 0;
	pstBMPInfoHeader->biYPelsPerMeter = 0;
	pstBMPInfoHeader->biClrUsed = (m_wBpp == 8) ? 256 : 0;
	pstBMPInfoHeader->biClrImportant = 0;

	// BMPヘッダ出力

	WriteHed( rfclsFileName );

	return	TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
//	BMPヘッダの出力

void	CBmp::WriteHed(
	const YCString&		rfclsFileName					// ファイル名
	)
{
	CArcFile*			pclArc = m_pclArc;

	pclArc->OpenFile( rfclsFileName );

	// BMPヘッダの出力

	pclArc->WriteFile( &m_stBMPFileHeader, sizeof(m_stBMPFileHeader), 0 );
	pclArc->WriteFile( &m_stBMPInfoHeader, sizeof(m_stBMPInfoHeader), 0 );

	// パレットの出力

	if( m_stBMPInfoHeader.biBitCount == 8 )
	{
		// 8bit

		pclArc->WriteFile( m_astPallet, sizeof(m_astPallet), 0 );
	}
}

//////////////////////////////////////////////////////////////////////////////////////////
//	パレットの作成

BOOL	CBmp::OnCreatePallet(
	const void*			pvSrcPallet,					// 参照元パレット
	DWORD				dwSrcPalletSize					// 参照元パレットのサイズ
	)
{
	RGBQUAD*			pstPallet = m_astPallet;
	const BYTE*			pbtSrcPallet = (const BYTE*) pvSrcPallet;

	ZeroMemory( m_astPallet, sizeof(m_astPallet) );

	if( pbtSrcPallet == NULL )
	{
		// デフォルトのパレットを使用(グレースケール)

		for( int i = 0 ; i < 256 ; i++ )
		{
			pstPallet[i].rgbBlue = i;
			pstPallet[i].rgbGreen = i;
			pstPallet[i].rgbRed = i;
			pstPallet[i].rgbReserved = 0;
		}
	}
	else
	{
		// パレットを参照

		if( dwSrcPalletSize == 1024 )
		{
			// 1024バイトのパレット

			for( int i = 0 ; i < 256 ; i++ )
			{
				pstPallet[i].rgbBlue = *pbtSrcPallet++;
				pstPallet[i].rgbGreen = *pbtSrcPallet++;
				pstPallet[i].rgbRed = *pbtSrcPallet++;
				pstPallet[i].rgbReserved = *pbtSrcPallet++;
			}
		}
		else if( dwSrcPalletSize == 768 )
		{
			// 768バイトのパレット(アルファなし)

			for( int i = 0 ; i < 256 ; i++ )
			{
				pstPallet[i].rgbBlue = *pbtSrcPallet++;
				pstPallet[i].rgbGreen = *pbtSrcPallet++;
				pstPallet[i].rgbRed = *pbtSrcPallet++;
				pstPallet[i].rgbReserved = 0;
			}
		}
		else
		{
			// その他のサイズのパレット

			for( DWORD i = 0 ; i < dwSrcPalletSize / 4 ; i++ )
			{
				pstPallet[i].rgbBlue = *pbtSrcPallet++;
				pstPallet[i].rgbGreen = *pbtSrcPallet++;
				pstPallet[i].rgbRed = *pbtSrcPallet++;
				pstPallet[i].rgbReserved = *pbtSrcPallet++;
			}
		}
	}

	return	TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
//	1ライン書き込み

void	CBmp::WriteLine(
	const void*			pvBuffer						// バッファ
	)
{
	// 出力

	m_pclArc->WriteFile( pvBuffer, m_lLine, m_dwRowSize );

	// ダミーデータ出力

	if( m_bOutputDummyFromBuffer )
	{
		// バッファから出力

		const BYTE*			pbtBuffer = (const BYTE*) pvBuffer;

		m_pclArc->WriteFile( &pbtBuffer[m_lLine], (m_lPitch - m_lLine), 0 );
	}
	else
	{
		for( long i = m_lLine ; i < m_lPitch ; i++ )
		{
			m_pclArc->WriteFile( "\0", 1, 0 );
		}
	}
}

//////////////////////////////////////////////////////////////////////////////////////////
//	アルファブレンディングして1ライン書き込み

void	CBmp::WriteLineWithAlphaBlend(
	void*				pvBuffer24,						// アルファブレンディングデータ格納先
	const void*			pvBuffer32						// 32bitデータ
	)
{
	// 0で埋める(ダミーデータも出力できるように)

	ZeroMemory( pvBuffer24, m_lPitch );

	// アルファブレンディング

	AlphaBlend( pvBuffer24, pvBuffer32 );

	// 出力

	m_pclArc->WriteFile( pvBuffer24, m_lPitch, m_dwRowSize );
}
