#pragma once
#include<DxLib.h>
#include<Image.h>

namespace DXFW
{
/// <summary>画像フィルタークラス</summary>
/// ImageやImagePackに対して画像編集ソフトにあるような、フィルター処理を施す。
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class Filter
{
public:
	/// <summary>モノトーンフィルタ</summary>
	/// 画像をモノトーン調に変化させる。
	/// 各ピクセルの色をRGB形式からYCbCr形式に変換して、その上ですべてのピクセルの輝度以外の成分を
	/// 引数の Cb Cr の値を置き換えた後、再びＲＧＢ形式に戻す。
	/// 値の調整が難しいが、似たような効果を得ることができる Filter::Hsb より負荷は低い。
	/// 赤色差と青色差は-255〜255で指定する。
	static bool Mono( Image* 処理イメージ , int 青色差 , int 赤色差)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_MONO ,青色差 , 赤色差);
	}
	static bool Mono( ImagePack *処理イメージ郡 , int 青色差 , int 赤色差)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			Mono( 処理イメージ郡[0][i] , 青色差 , 赤色差 );
		}
		return true;
	}

	///<summary>ガウスフィルタ</summary>
	///画像にガウス関数を使用したぼかし効果を与える。
	///使用ピクセル幅は 8 か 16 か 32で指定。
	///ぼかし強さは 1 で約1ピクセル幅ぼかす。
	///
	///ぼかしの限界は 使用ピクセル幅 で決まり、値が大きいほどぼかしの強さの限界が大きくなり、
	///それとともに処理負荷も大きくなる。
	///このフィルタは非常に負荷が大きいので、強いぼかしをかけたい場合は 使用ピクセル の値を 32 にして強いぼかしを
	///掛けるより、縮小フィルタ( DX_GRAPH_FILTER_DOWN_SCALE )で画像を縮小した後弱いぼかしを掛け、
	///その後 DrawExtend で元の大きさで描画する、という方法を採ったほうが処理負荷を小さく抑えることができます。
	static bool Gauss( Image* 処理イメージ , int 使用ピクセル幅 , double ぼかし強さ)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_GAUSS , 使用ピクセル幅 , int(ぼかし強さ*100) );
	}
	static bool Gauss( ImagePack *処理イメージ郡 , int 使用ピクセル幅 , double ぼかし強さ)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			Gauss( 処理イメージ郡[0][i]  , 使用ピクセル幅 , int(ぼかし強さ*100));
		}
		return true;
	}
			
	/// <summary>縮小フィルタ</summary>
	/// 分母は 2 か 4 か 8 を指定
	/// 画像を分母で指定した数で割って縮小する。
	/// DrawExtend でも縮小描画することができるが、それよりも綺麗に縮小した画像を得ることができる。
	/// 主にFilter::Gaussの処理負荷を下げる目的で使用されることを想定している。
	static bool DownScale( Image* 処理イメージ , int 分母)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_DOWN_SCALE , 分母 );
	}
	static bool DownScale( ImagePack *処理イメージ郡 , int 分母)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			DownScale( 処理イメージ郡[0][i] , 分母);
		}
		return true;
	}

	/// <summary>明るさクリップフィルタ</summary>
	///画像の各ピクセルを輝度に応じて引数で渡す色で塗りつぶす。
	///クリップタイプがClipType::Lessの場合、クリップパラメータより輝度が小さいピクセル、
	///クリップタイプがClipType::Graterの場合、輝度が大きいピクセルをクリップ処理する。
	///クリップ判定されたピクセルは、クリップ色で塗られ、αチャンネルがある場合α値をクリップαにする。
	static bool BrightClip( Image* 処理イメージ , ClipType cmpType,int cmpParam , int clipFillColor , int clipFillAlpha)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_BRIGHT_CLIP , cmpType, cmpParam , true , clipFillColor , clipFillAlpha);
	}
	static bool BrightClip( ImagePack *処理イメージ郡 , ClipType cmpType,int cmpParam , int clipFillColor , int clipFillAlpha)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			BrightClip( 処理イメージ郡[0][i] , cmpType , cmpParam , clipFillColor , clipFillAlpha);
		}
		return true;
	}

	/// <summary>色相・彩度・明度フィルタ</summary>
	/// 画像の各ピクセルの、色相、彩度、明度を補正する。
	/// 色相は-180〜180で指定し、相対的に変化させます
	/// 彩度 -1.0〜で指定し、相対的に変化させます、-1でグレー、0で変化。
	/// 輝度 -1.0〜1.0で指定し、負の場合暗く、正の場合は明るくなる。
	static bool Hsb( Image* 処理イメージ , int 色相 , double 彩度 , double 明度)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_HSB , TRUE , 色相 , int(彩度*255) , int(明度*255) );
	}
	static bool Hsb( ImagePack *処理イメージ郡 , int 色相 , double 彩度 , double 明度)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			Hsb( 処理イメージ郡[0][i] , 色相 , 彩度 , 明度);
		}
		return true;
	}
	
	///<summary>色相・彩度・明度フィルタ</summary>
	///画像の各ピクセルの、色相、彩度、明度を補正する。
	///色相は0〜360で指定、120が緑、240で青、360が赤になる。
	///絶対値で指定するので、モノトーン調の処理になる。
	///彩度と明度は、Filter::Hsbと同じ。
	static bool MonoHsb( Image* 処理イメージ , int 色相 , double 彩度 , double 明度)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_HSB , FALSE , 色相 , int(彩度*255) , int(明度*255) );
	}
	static bool MonoHsb( ImagePack *処理イメージ郡 , int 色相 , double 彩度 , double 明度)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			MonoHsb( 処理イメージ郡[0][i] , 色相 , 彩度 , 明度);
		}
		return true;
	}

	///<summary>階調反転フィルタ</summary>
	///各ピクセルのRGB値を反転する。
	bool Invert( Image* 処理イメージ )
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_INVERT );
	}
	bool Invert( ImagePack *処理イメージ郡 )
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			Invert( 処理イメージ郡[0][i] );
		}
		return true;
	}

	///<summary>レベル補正フィルタ</summary>
	///画像にレベル補正を行い、コントラストを調整する。
	///処理前下限、0以上にすると暗くなります。
	///処理前上限、255以下にすると、明るくなります。
	///処理後下限、0以上にすると白っぽくなります。
	///処理後上限、255以下にすると黒に近くなります
	///ガンマ値は1以上にすると、明るくなり、1以下にすると暗くなります。
	bool Level( Image* 処理イメージ , int 処理前下限 , int 処理前上限 , int 処理後下限 , int 処理後上限, double ガンマ値 )
	{
		if( ガンマ値 < 0.01 ) ガンマ値 = 0.01;
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_LEVEL , 処理前下限 , 処理前上限 , int(ガンマ値*100) , 処理後下限 , 処理後上限);
	}
	bool Level( ImagePack *処理イメージ郡 , int 処理前下限 , int 処理前上限 , int 処理後下限 , int 処理後上限, double ガンマ値 )
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
				Level( 処理イメージ郡[0][i] , 処理前下限 , 処理前上限 , 処理後下限 , 処理後上限, ガンマ値);
		}
		return true;
	}

	///<summary>２階調フィルタ</summary>
	///各ピクセルの輝度が閾値より暗いか明るいかで各ピクセルを変換する
	bool TwoColor( Image* 処理イメージ , int 閾値 , int 暗色 , int 暗色α値 , int 明色 , int 明色α値 )
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_TWO_COLOR , 閾値 , 暗色 , 暗色α値 , 明色 , 明色α値 );
	}
	bool TwoColor( ImagePack *処理イメージ郡 , int 閾値 , int 暗色 , int 暗色α値 , int 明色 , int 明色α値 )
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			TwoColor( 処理イメージ郡[0][i] , 閾値 , 暗色 , 暗色α値 , 明色 , 明色α値 );
		}
		return true;
	}
			
	///<summary>グラデーションマップフィルタ</summary>
	///各ピクセルの輝度からグラデーションマップのＸ座標を算出し変換する。
	///輝度が0の場合はグラデーションマップの一番左上のピクセルの色が( x:0 y:0 座標のピクセル )、
	///輝度が255( 最大 )の場合、グラデーションマップの一番右上のピクセルの色が( x:255 y:0 座標のピクセル )
	///出力結果の色になる。
	bool GradientMap( Image* 処理イメージ , const Image *入力イメージ , bool 反転フラグ)
	{
		return !DxLib::GraphFilter( 処理イメージ->GetHandle() , DX_GRAPH_FILTER_GRADIENT_MAP , 入力イメージ->GetHandle(), 反転フラグ );
	}
	bool GradientMap( ImagePack *処理イメージ郡 , const Image *入力イメージ , bool 反転フラグ)
	{
		for( int i=0 ; i<処理イメージ郡->GetSize() ;i++ )
		{
			GradientMap( 処理イメージ郡[0][i] , 入力イメージ , 反転フラグ);
		}
		return true;
	}
};
	
/// <summary>フィルター処理したイメージを生成[修正中]</summary>
/// 修正中です。
///	<example>
///	[サンプルコード:未完成]<BR>
/// サンプル説明<BR>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<BR>
///	{<BR>
///		if( !Dx::Initialise() ) return -1;<BR>
///		Dx::End();<BR>
///		return 0;<BR>
/// }<BR>
/// </code>	
/// </example>
class FilterBlt
{
public:
	/// <summary>説明</summary>
	static bool Mono(Image *image , const Image *origin , int 青色差 , int 赤色差)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_MONO ,青色差 , 赤色差);
	}
	static bool Mono(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , int 青色差 , int 赤色差)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_MONO ,青色差 , 赤色差);
	}
	
	/// <summary>説明</summary>
	static bool Gauss(Image *image , const Image *origin , int 使用ピクセル幅 , int ぼかし強さ)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_GAUSS , 使用ピクセル幅 , ぼかし強さ);
	}
	static bool Gauss(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , int 使用ピクセル幅 , int ぼかし強さ)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_GAUSS , 使用ピクセル幅 , ぼかし強さ);
	}
	/*
	/// <summary>説明</summary>
	static bool DownScale(Image *image , const Image *origin , DivNumber num)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_DOWN_SCALE , num );
	}
	static bool DownScale(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , DivNumber num)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_DOWN_SCALE , num );
	}
	
	/// <summary>説明</summary>
	static bool BrightClip(Image *image , const Image *origin , CmpType cmpType,int cmpParam , bool isClipFill , int clipFillColor , int clipFillAlpha)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_BRIGHT_CLIP , cmpType, cmpParam , isClipFill , clipFillColor , clipFillAlpha);
	}
	static bool BrightClip(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , CmpType cmpType,int cmpParam , bool isClipFill , int clipFillColor , int clipFillAlpha)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_BRIGHT_CLIP , cmpType, cmpParam , isClipFill , clipFillColor , clipFillAlpha);
	}
	
	/// <summary>説明</summary>
	static bool Hsb(Image *image , const Image *origin , HueType hueType , int hue , int saturation , int bright)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_HSB , hueType , hue , saturation , bright );
	}
	static bool Hsb(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , HueType hueType , int hue , int saturation , int bright)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_HSB , hueType , hue , saturation , bright );
	}
	*/
	
	/// <summary>説明</summary>
	static bool Invert(Image *image , const Image *origin )
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_INVERT );
	}
	static bool Invert(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_INVERT );
	}
	
	/// <summary>説明</summary>
	static bool Level(Image *image , const Image *origin ,int min , int max , int gammma , int affterMin , int affterMax)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_LEVEL , min , max , gammma , affterMin , affterMax);
	}
	static bool Level(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY, int min , int max , int gammma , int affterMin , int affterMax)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_LEVEL , min , max , gammma , affterMin , affterMax);
	}
	
	/// <summary>説明</summary>
	static bool TwoColor(Image *image , const Image *origin , int threshold , int lowColor , int lowAlpha , int highColor , int highAlpha )
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_TWO_COLOR , threshold , lowColor , lowAlpha , highColor , highAlpha );
	}
	static bool TwoColor(Image *image , const Image *origin , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , int threshold , int lowColor , int lowAlpha , int highColor , int highAlpha )
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_TWO_COLOR , threshold , lowColor , lowAlpha , highColor , highAlpha );
	}
	
	/// <summary>説明</summary>
	static bool GradientMap(Image *image , const Image *origin , const Image *mapGraph , bool isReverse)
	{
		return !DxLib::GraphFilterBlt( origin->GetHandle() ,image->GetHandle() , DX_GRAPH_FILTER_GRADIENT_MAP , mapGraph->GetHandle() , isReverse );
	}
	static bool GradientMap(Image *image , const Image *origin  , int srcX1, int srcY1, int srcX2, int srcY2, int destX, int destY , const Image *mapGraph , bool isReverse)
	{
		return !DxLib::GraphFilterRectBlt( origin->GetHandle() ,image->GetHandle() , srcX1, srcY1, srcX2, srcY2, destX, destY , DX_GRAPH_FILTER_GRADIENT_MAP , mapGraph->GetHandle() , isReverse );
	}
};	
}