/*
 * @file	AXMIspAwb2.cpp
 * @brief	AWB Package
 *
 * @par		言語
 *			C++
 */

#include "../AXMCommon/AXMCommonConfig.hpp"

#include "AXMIspAwbTypedefine.hpp"
#include "../AXMCommon/AXMCommonSetParam.hpp"
#include "AXMIspAwbCommon.hpp"								//	AXMIspCommonSetParam.hppとセットでincludeする必要がある
#include "AXMIspAwbOPDConfig.hpp"
#include "AXMIspAwbSettings.hpp"
#include "AXMIspAwbAlgorithm.hpp"
#include "AXMIspAwb2.hpp"


//
//	AWBIspAwbExec
//

#ifdef  ENABLE_COLORDATA_ATWMODE
//
//	ATWモード用色データ計算処理クラス
//		AXMIspAwbExecColorDataATWMode
//
AWB_ER	AXMIspAwbExecColorDataATWMode :: Exec(AXMIspAwbSettings AWBSettings, UCHAR *p_img, CAL_DATA& CalData, AXMIspAwbAlgorithmJudgedLightSource JudgeLightSource)
{
	AWB_ER		ret = AWB_E_OK;
	CAL_COLOR	ImageData;

	// 色データ計算処理
	ret += NormalData.Exec(AWBSettings, p_img, ImageData, CalData.ColorData);
	// OPDマスク処理
	ret += OPDMaskData.Exec(AWBSettings, CalData.ColorData);
	// 光源枠判定処理
	ret += LightSourceData.Exec(AWBSettings, CalData, JudgeLightSource);
	// 重み付け処理
	ret += WeightData.Exec(AWBSettings, CalData, JudgeLightSource);

	return ret;
}
#endif  //  ENABLE_COLORDATA_ATWMODE


#ifdef  ENABLE_COLORDATA_MANUMODE
//
//	マニュアルモード用色データ計算処理クラス
//		AXMIspAwbExecColorDataManuMode
//

//
//	色データ計算処理(マニュアルモード)
//
AWB_ER	AXMIspAwbExecColorDataManuMode :: Exec(AXMIspAwbSettings AWBSettings, UCHAR *p_img, CAL_RG_BG& ColorData)
{
	AWB_ER		ret = AWB_E_OK;
	CAL_COLOR	ImageData;

	// 色データ計算処理
	ret += NormalData.Exec(AWBSettings, p_img, ImageData, ColorData);

	return ret;
}
#endif  //  ENABLE_COLORDATA_MANUMODE


#ifdef  ENABLE_COLORDATA_ONEPUSH
//
//	one pushモード用色データ計算処理クラス
//		AXMIspAwbExecColorDataOnePushMode
//

//
//	色データ計算処理(ワンプシュモード)
//
AWB_ER	AXMIspAwbExecColorDataOnePushMode :: Exec(AXMIspAwbSettings AWBSettings, UCHAR *p_img, CAL_DATA& CalData, AXMIspAwbAlgorithmJudgedLightSource JudgeLightSource)
{
	AWB_ER		ret = AWB_E_OK;
	CAL_COLOR	ImageData;

	// 色データ計算処理
	ret += NormalData.Exec(AWBSettings, p_img, ImageData, CalData.ColorData);
	// 光源枠判定処理
	ret += LightSourceData.Exec(AWBSettings, CalData, JudgeLightSource);

	return ret;
}
#endif  //  ENABLE_COLORDATA_ONEPUSH


#ifdef  ENABLE_CALC_ATWMODE
//
//	ATWモード用演算処理クラス
//		AXMIspAwbExecCalcATWMode
//

//
//	演算処理(ATWモード用)
//
AWB_ER	AXMIspAwbExecCalcATWMode :: Exec(AXMIspAwbSettings AWBSettings, CAL_DATA& CalData, AXMIspAwbAlgorithmJudgedLightSource JudgeLightSource)
{
	AWB_ER	ret = AWB_E_OK;

	// 重心計算処理
	ret += BalanceCenter.Exec(AWBSettings, CalData, JudgeLightSource);
	// 調整/収束制御処理
	ret += AWBTarget.Exec(AWBSettings, CalData, JudgeLightSource);
	// ゲイン/マトリックス設定
	ret += ControlValue.Exec(CalData, AWBSettings);

	return	ret;
}
#endif  //  ENABLE_CALC_ATWMODE


#ifdef  ENABLE_CALC_MANUMODE
//
//	マニュアルモード用演算処理クラス
//		AXMIspAwbExecCalcManuMode
//

//
//	演算処理（マニュアルモード用）
//
AWB_ER	AXMIspAwbExecCalcManuMode :: Exec(AXMIspAwbSettings& AWBSettings, CAL_DATA& CalData)
{
	AWB_ER	ret = AWB_E_OK;

	if(AWBSettings.AWB_Mode == AWBMode_TempManuMode)
	{
		//	色温度指定マニュアルモード
		if(AWBSettings.ColorTemp <= 3200)
		{
			//	黒体放射軌跡 1800-3200K間で座標計算
			CalData.WBTarget = getManuWBPoint(AWBSettings, AWBLightDefault_1800K, AWBLightDefault_3200K, 1800, 3200);
		}
		else if(AWBSettings.ColorTemp <= 4200)
		{
			//	黒体放射軌跡 3200-4200K間で座標計算
			CalData.WBTarget = getManuWBPoint(AWBSettings, AWBLightDefault_3200K, AWBLightDefault_4200K, 3200, 4200);
		}
		else if(AWBSettings.ColorTemp <= 5200)
		{
			//	黒体放射軌跡 4200-5200K間で座標計算
			CalData.WBTarget = getManuWBPoint(AWBSettings, AWBLightDefault_4200K, AWBLightDefault_5200K, 4200, 5200);
		}
		else if(AWBSettings.ColorTemp <= 5800)
		{
			//	黒体放射軌跡 5200-5800K間で座標計算
			CalData.WBTarget = getManuWBPoint(AWBSettings, AWBLightDefault_5200K, AWBLightDefault_5800K, 5200, 5800);
		}
		else if(AWBSettings.ColorTemp <= 7000)
		{
			//	黒体放射軌跡 5800-7000K間で座標計算
			CalData.WBTarget = getManuWBPoint(AWBSettings, AWBLightDefault_5800K, AWBLightDefault_7000K, 5800, 7000);
		}
		else
		{
			//	黒体放射軌跡 7000-10000K間で座標計算
			CalData.WBTarget = getManuWBPoint(AWBSettings, AWBLightDefault_7000K, AWBLightDefault_10000K, 7000, 10000);
		}
		//  Matrix係数算出
		//	マニュアルモードのため、4象限分の係数を更新する
		for(INT i = 0; i < AWB_ColorMatrixMax; i++)
		{
			CalData.MatrixTarget[i] = AWBSettings.ColorMatrix.Matrix[i];
		}
	}
	else if(AWBSettings.AWB_Mode == AWBMode_LightManuMode)
	{
		//	照明指定マニュアルモード
		AWBLightDefault	index = getLightSeletctToDefault(AWBSettings.LightSelect);
		if(index != AWBLightDefault_None)
		{
			ColPoint tgt;
			// Offsetの要素数はAWBLightSource_Maxである
			// AWBLightSelectはAWBLightSourcより少なく、*****Rollingがない以外は変わらない
			// よって、AWBLightSourceへの変換は行わない
			tgt.bg = AWBSettings.LightDefault.CPnt[index].bg + AWBSettings.Offset.Pnt[AWBSettings.LightSelect].bg;
			tgt.rg = AWBSettings.LightDefault.CPnt[index].rg + AWBSettings.Offset.Pnt[AWBSettings.LightSelect].rg;
			//	WB算出
			if((tgt.bg != 0) && (tgt.rg != 0)) {
				CalData.WBTarget.BGain = (USHORT)((0x00000001l << AWB_Rg_Bg_WB_Sft) / (LONG)tgt.bg);
				CalData.WBTarget.RGain = (USHORT)((0x00000001l << AWB_Rg_Bg_WB_Sft) / (LONG)tgt.rg);
			}
			//  Matrix係数算出
			//	マニュアルモードのため、4象限分の係数を更新する
			for(INT i = 0; i < AWB_ColorMatrixMax; i++)
			{
				CalData.MatrixTarget[i] = AWBTarget.CalcMatrix(i, (AWBLightSource)AWBSettings.LightSelect, AWBSettings);
			}
		}
	}
	else if(AWBSettings.AWB_Mode == AWBMode_GainManuMode)
	{
		//	ゲイン指定マニュアルモード
		CalData.WBTarget = AWBSettings.WB;
		//  Matrix係数算出
		//	マニュアルモードのため、4象限分の係数を更新する
		for(INT i = 0; i < AWB_ColorMatrixMax; i++)
		{
			CalData.MatrixTarget[i] = AWBSettings.ColorMatrix.Matrix[i];
		}
	}

	ret += ControlValue.Exec(CalData, AWBSettings);

	return ret;
}

//
//	色温度から黒体放射軌跡座標算出
//
WBGain	AXMIspAwbExecCalcManuMode :: getManuWBPoint(AXMIspAwbSettings& AWBSettings, AWBLightDefault p1, AWBLightDefault p2, LONG temp1, LONG temp2)
{
	LONG    x1 = (LONG)AWBSettings.LightDefault.CPnt[p1].bg;
	LONG    x2 = (LONG)AWBSettings.LightDefault.CPnt[p2].bg;
	LONG    y1 = (LONG)AWBSettings.LightDefault.CPnt[p1].rg;
	LONG    y2 = (LONG)AWBSettings.LightDefault.CPnt[p2].rg;
	WBGain   gain;
	ColPoint tgt;

	//	調整済みR/G座標算出
	if(((temp2 - temp1) == 0) || ((x2 - x1) == 0))
	{
		gain.BGain = 0;
		gain.RGain = 0;
	}
	else
	{
		//	色温度からB/G座標算出
		tgt.bg = (SHORT)(((x2 - x1) * (LONG)AWBSettings.ColorTemp + x1 * temp2 - x2 * temp1) / (temp2 -temp1));
		//	R/G座標算出
		tgt.rg = (SHORT)(((y2 - y1) * (LONG)tgt.bg + y1 * x2 - y2 * x1) / (x2 - x1));
		//	WB算出
		if((tgt.bg != 0) && (tgt.rg != 0)) {
			gain.BGain = (USHORT)((0x00000001l << AWB_Rg_Bg_WB_Sft) / (LONG)tgt.bg);
			gain.RGain = (USHORT)((0x00000001l << AWB_Rg_Bg_WB_Sft) / (LONG)tgt.rg);
		}
	}

	return	gain;
}

//
//	光源座標設定から光源デフォルト座標を選択
//
AWBLightDefault	AXMIspAwbExecCalcManuMode :: getLightSeletctToDefault(AWBLightSelect LightSelect)
{
	AWBLightDefault	index;

	switch (LightSelect)
	{
		case AWBLightSelect_A:								//	白熱灯モード
			index = AWBLightDefault_3200K;					//	黒体放射軌跡 3200Kポイント選択
			break;
		case AWBLightSelect_EBulbF:							//	電球色蛍光灯モード
			index = AWBLightDefault_EBulbF;					//	電球色蛍光灯デフォルト座標(3000K)選択
			break;
		case AWBLightSelect_CWF:								//	白色蛍光灯モード
			index = AWBLightDefault_CWF;					//	白色蛍光灯デフォルト座標(4200K)選択
			break;
		case AWBLightSelect_DayWF:							//	昼白色蛍光灯モード
			index = AWBLightDefault_DayWF;					//	昼白色蛍光灯デフォルト座標(5200K)選択
			break;
		case AWBLightSelect_DayF:							//	昼光色蛍光灯モード
			index = AWBLightDefault_DayF;					//	昼光色蛍光灯デフォルト座標(6700K)選択
			break;
		case AWBLightSelect_Day:								//	昼光モード
			index = AWBLightDefault_5800K;					//	黒体放射軌跡 5800Kポイント選択
			break;
		case AWBLightSelect_Cloudy:							//	曇天/日陰モード
			index = AWBLightDefault_7000K;					//	黒体放射軌跡	7000Kポイント選択
			break;
		case AWBLightSelect_Merculy:						//	水銀灯モード
			index = AWBLightDefault_Merculy;				//	水銀灯デフォルト座標(5700K)選択
			break;
		case AWBLightSelect_NaLamp:							//	高圧ナトリウムランプモード
			index = AWBLightDefault_NaLamp;					//	高圧ナトリウムランプデフォルト座標(2100K)選択
			break;
		case AWBLightSelect_EBulbLED:						//	電球色LEDモード
			index = AWBLightDefault_EBulbLED;				//	電球色LEDデフォルト座標(2700K)選択
			break;
		case AWBLightSelect_WhiteLED:						//	白色LEDモード
			index = AWBLightDefault_WhiteLED;				//	白色LEDデフォルト座標(5000K)選択
			break;
		case AWBLightSelect_DayLED:							//	昼光色LEDモード
			index = AWBLightDefault_DayLED;					//	昼光色デフォルト座標(6700K)選択
			break;
		default:
			index = AWBLightDefault_None;					//	デフォルト座標未選択
			//	何もしない
			break;
	}

	return index;
}
#endif  //  ENABLE_CALC_MANUMODE


#ifdef  ENABLE_CALC_ONEPUSH
//
//	one pushモード用演算処理クラス
//		AXMIspAwbExecCalcOnePushMode
//

//
//	演算処理（one pushモード用）
//
AWB_ER	AXMIspAwbExecCalcOnePushMode :: Exec(AXMIspAwbSettings AWBSettings, CAL_DATA& CalData, AXMIspAwbAlgorithmJudgedLightSource JudgeLightSource)
{
	AWB_ER ret = AWB_E_OK;

	// 重心計算処理
	ret += BalanceCenter.Exec(AWBSettings, CalData, JudgeLightSource);
	// 調整/収束制御処理
	ret += AWBTarget.Exec(AWBSettings, CalData, JudgeLightSource);
	// ゲイン/マトリックス設定
	ret += ControlValue.Exec(CalData, AWBSettings);


	return ret;
}
#endif  //  ENABLE_CALC_ONEPUSH
