/*
 * AXMIspAdjustState.cpp
 */

#include "../AXMCommon/AXMCommonParam.hpp"
#include "../AXMCommon/AXMCommonStruct.hpp"
#include "../../project/refkit/AXMIspConfig.hpp"
#include "../AXMPixcessor/AXMPixcessor.hpp"
#include "../AXMIspAe/AXMIspAe.hpp"
#include "AXMIspAdjust.hpp"
#include "AXMIspAdjustDef.hpp"
#include <stddef.h>
#ifdef PARASOFT_CPPTEST
#include <cstring>
#endif  // PARASOFT_CPPTEST

// 3rdリリースから、「モデルイベント」と「デバイスイベント」の
// 登録が可能となる。
//
// 状態テーブルは、状態ごとに定義し、イベントIDとメンバ関数の紐付けを行う。
// ※状態テーブルの最後は、必ず{0,NULL}で終了する必要がある。

// STATE_WAITING状態の状態テーブル定義
//      {イベントID, メンバ関数ポインタ}
//      ...
//     {0,NULL}
const AXMIspAdjust::StateTable AXMIspAdjust::state_waiting[] = {
    { AXMIspAdjust::EVENT_SPEC_ADDR,                        // 設定値保存先アドレス通知
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::funcSpecAddr },
    { 0, NULL }
};

// STATE_RUNNING状態の状態テーブル定義
//      {イベントID, メンバ関数ポインタ}
//      ...
//     {0,NULL}
const AXMIspAdjust::StateTable AXMIspAdjust::state_running[] = {
    { AXMIspAdjust::EVENT_PROC_GAMMA,                       // ガンマ補正
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0000 },
    { AXMIspAdjust::EVENT_PROC_APERTURE,                    // アパーチャ補正
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0100 },
    { AXMIspAdjust::EVENT_PROC_IRIDIX_START,                // IRIDIX設定開始
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0200 },
    { AXMIspAdjust::EVENT_PROC_CHROMA,                      // クロマサプレス
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0300 },
    { AXMIspAdjust::EVENT_PROC_LENS_SHADING_START,          // レンズシェーディング補正設定開始
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0400 },
    { AXMIspAdjust::EVENT_PROC_NR_START,                    // NR設定開始
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0500 },
    { AXMIspAdjust::EVENT_PROC_SCALER_SETTINGS,             // スケーラー機能設定
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0600 },
    { AXMIspAdjust::EVENT_PROC_DEFECT_START,                // 画素欠陥補正設定開始
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0700 },
    { AXMIspAdjust::EVENT_PROC_RGB_MATRIX_START,            // RGBマトリックス設定開始
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix0800 },
    { AXMIspAdjust::EVENT_CHECK_SETTINGS,                   // 設定値変更確認
      (AXMIspAdjust::StateFuncPtr) &AXMIspAdjust::matrix1000 },
    { 0, NULL }
};

ax::actorFuncStatus AXMIspAdjust::funcSpecAddr(const void *pParam, int size) {
  if((0 < size) && (pParam != NULL)) {
    ST_MSG *msg = (ST_MSG *)pParam;
    p_adjustspec = (ST_SPEC *)msg->data;

// 今回のHardとは別物になるため今回コメントアウト
//	GammaTableInit();
//	ApertureInit();
//	ChromaInit();

//	SetLensShade(Cmd_Adjust_LensShade_Init);                //  レンズシェーディング補正設定
//	SetIridix(Cmd_Adjust_Iridix_Init);                      //  IRIDIX設定
//	SetNR(PTN_NR_ALL);                                      //  NR設定
//	SetDefect(PTN_DEFECT_ALL);                              //  画素欠陥補正設定
//	SetRGBMatrix();                                         //  RGBマトリックス設定
//#ifndef DISABLE_GAMMA_PROC
//	m_gammaCalc.NotifySettings(&m_gammaSettings);
//#endif

    state = STATE_RUNNING;
#ifndef PARASOFT_CPPTEST
    setNextState(state);
#endif  //  PARASOFT_CPPTEST
  }
  else {
    m_log.write(AXFLOG_ERR, "Adjust funcSpecAddr : Recieve data error");
  }

  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::matrix0000(const void *pParam, int size) {
	ModifyGamma();

#ifndef PARASOFT_CPPTEST
	setNextState(state);
#endif
	return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::matrix0100(const void *pParam, int size) {
	USHORT updStatusAperture  = checkApertureParam();

	bool   isUpdApertureAdapt = checkApertureAdapterParam();

#ifdef PARASOFT_CPPTEST
	BYTE paramChange = 0;
#endif
	if (0 < updStatusAperture) {
		setAperture(updStatusAperture);
#ifdef PARASOFT_CPPTEST
		paramChange |= 1;
#endif
	}

	// 輝度変調設定処理
	if (isUpdApertureAdapt) {
		setApertureAdpt();
#ifdef PARASOFT_CPPTEST
		paramChange |= 2;
#endif
	}

#ifdef PARASOFT_CPPTEST
   checkDataCPPTEST.data[0] = paramChange;
#endif

	return ax::AXFACTOR_SUCCESS;
}

USHORT AXMIspAdjust::checkApertureParam() {

	USHORT updStatus = 0u;

	// アパーチャ補正パラメータ変更チェック
	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_APERTURE] & SPEC_CHG_APER) != SPEC_CHG_APER) {
		return updStatus;
	}

	BYTE  totalGain     = p_adjustspec->Aperture.totalGain;
	SHORT limitPositive = p_adjustspec->Aperture.limitPositive;
	SHORT limitNegative = p_adjustspec->Aperture.limitNegative;
	BYTE  midRangeRatio = p_adjustspec->Aperture.midRangeRatio;
	BYTE  coringTh      = p_adjustspec->Aperture.coringTh;

	bool isChange = false;

	// トータルゲイン調整設定
	if (totalGain != m_apertureSettings.totalGain) {
		m_apertureSettings.totalGain = totalGain;
		updStatus |= PTN_AP_UPD_TOTALGAIN;
	}

	// 正側・負側リミット設定
	if (limitPositive != m_apertureSettings.limitPositive) {
		if (AP_LIMIT_NEGATIVE <= limitPositive && limitPositive <= AP_LIMIT_POSITIVE) {
			m_apertureSettings.limitPositive = limitPositive;
			isChange = true;
		}
	}
	if (limitNegative != m_apertureSettings.limitNegative) {
		if (AP_LIMIT_NEGATIVE <= limitNegative && limitNegative <= AP_LIMIT_POSITIVE) {
			m_apertureSettings.limitNegative = limitNegative;
			isChange = true;
		}
	}
	if (isChange) {
		updStatus |= PTN_AP_UPD_LIMIT;
	}

	// コアリング設定
	if (coringTh != m_apertureSettings.coringTh) {
		m_apertureSettings.coringTh = coringTh;
		updStatus |= PTN_AP_UPD_CORING;
	}

	// 高域・中域ゲイン比率設定
	if (midRangeRatio != m_apertureSettings.midRangeRatio) {
		m_apertureSettings.midRangeRatio = midRangeRatio;
		updStatus |= PTN_AP_UPD_MID_RATIO;
	}

	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_APERTURE] &= ~(SPEC_CHG_APER);

	return updStatus;
}

bool AXMIspAdjust::checkApertureAdapterParam() {

	bool isChange = false;

	// アパーチャ補正適応処理パラメータ変更チェック
	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_APERTURE] & SPEC_CHG_APER_ADP) != SPEC_CHG_APER_ADP) {
		return isChange;
	}

	BYTE  startSupresLuminance = p_adjustspec->Aperture.darkSupressStartLuminance;
	BYTE  startStrongLuminance = p_adjustspec->Aperture.highCorrectStartStrongLuminance;
	BYTE  correctSupressInc    = p_adjustspec->Aperture.darkCorrectSupressInc;
	BYTE  correctStrongInc     = p_adjustspec->Aperture.highCorrectStrongInc;
	BYTE  correctStrongLimit   = p_adjustspec->Aperture.highCorrectStrongLimit;

	// 輝度変調設定処理
	isChange = m_apertureSettings.correctStrong.Set(
		  startSupresLuminance
		, startStrongLuminance
		, correctSupressInc
		, correctStrongInc
		, correctStrongLimit
	);
	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_APERTURE] &= ~(SPEC_CHG_APER_ADP);

	return isChange;
}

void AXMIspAdjust::setAperture(USHORT updStatus) {

#ifdef PARASOFT_CPPTEST
	BYTE paramChange = 0;
#endif

	// トータルゲイン調整設定
	if ((updStatus & PTN_AP_UPD_TOTALGAIN) == PTN_AP_UPD_TOTALGAIN) {
		apertureTotalGainSet(m_apertureSettings.totalGain);
#ifdef PARASOFT_CPPTEST
		paramChange |= PTN_AP_UPD_TOTALGAIN;
#endif
	}

	// 正側・負側リミット設定
	if ((updStatus & PTN_AP_UPD_LIMIT) == PTN_AP_UPD_LIMIT) {
		apertureLimitSet(m_apertureSettings.limitPositive, m_apertureSettings.limitNegative);
#ifdef PARASOFT_CPPTEST
		paramChange |= PTN_AP_UPD_LIMIT;
#endif
	}

	// コアリング設定
	if ((updStatus & PTN_AP_UPD_CORING) == PTN_AP_UPD_CORING) {
		apertureCoringSet(m_apertureSettings.coringTh);
#ifdef PARASOFT_CPPTEST
		paramChange |= PTN_AP_UPD_CORING;
#endif
	}

	// 高域・中域ゲイン比率設定
	if ((updStatus & PTN_AP_UPD_MID_RATIO) == PTN_AP_UPD_MID_RATIO) {
		apertureOverMidRangeGainRatioSet(m_apertureSettings.midRangeRatio);
#ifdef PARASOFT_CPPTEST
		paramChange |= PTN_AP_UPD_MID_RATIO;
#endif
	}

#ifdef PARASOFT_CPPTEST
   checkDataCPPTEST.data[0] = paramChange;
#endif

}

void AXMIspAdjust::setApertureAdpt() {
	apertureLutTblSet(
			  m_apertureSettings.correctStrong.darkSupressStartLuminance
			, m_apertureSettings.correctStrong.highCorrectStartStrongLuminance
			, m_apertureSettings.correctStrong.darkCorrectSupressInc
			, m_apertureSettings.correctStrong.highCorrectStrongInc
			, m_apertureSettings.correctStrong.highCorrectStrongLimit
	);
}

void AXMIspAdjust::apertureTotalGainSet(BYTE totalGain) {
	BYTE datasize = 0;
	BYTE data     = 0;
#ifndef DISABLE_APERTURE_PROC
	data     = totalGain;
	datasize = sizeof(data);
#endif  // DISABLE_APERTURE_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_APERTURE_TOTAL_GAIN_SET), &data, datasize) < 0) {
		;
	}
#else
	checkDataCPPTEST.size = datasize;
	checkDataCPPTEST.data[0] = data;
#endif
}

void AXMIspAdjust::apertureLimitSet(SHORT limitPositive, SHORT limitNegative) {
	BYTE  datasize = 0;
	SHORT data[2]  = {};
#ifndef DISABLE_APERTURE_PROC
	data[0] = limitPositive;
	data[1] = limitNegative;
	datasize = sizeof(data);
#endif  // DISABLE_APERTURE_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_APERTURE_LIMIT_SET), &data, datasize) < 0) {
		;
	}
#else
	checkDataCPPTEST.size = datasize;
	checkDataCPPTEST.data[0] = data[0];
	checkDataCPPTEST.data[1] = data[1];
#endif
}

void AXMIspAdjust::apertureOverMidRangeGainRatioSet(BYTE midRangeRatio) {
	BYTE datasize = 0;
	BYTE data[2]  = {};
#ifndef DISABLE_APERTURE_PROC
	m_apertureCalc.CalcOverMidRangeGainRatio(midRangeRatio, &data[0], &data[1]);
	datasize = sizeof(data);
#endif  // DISABLE_APERTURE_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_APERTURE_OVERMIDRANGE_GAINRATIO_SET), &data[0], datasize) < 0) {
		;
	}
#else
	checkDataCPPTEST.size = datasize;
	checkDataCPPTEST.data[0] = data[0];
	checkDataCPPTEST.data[1] = data[1];
#endif
}

void AXMIspAdjust::apertureLutTblSet(BYTE startSupresLuminance, BYTE startStrongLuminance, BYTE correctSupressInc, BYTE correctStrongInc, BYTE correctStrongLimit) {
	BYTE datasize = 0;
	ST_MSG msg;

#ifndef DISABLE_APERTURE_PROC
	m_apertureCalc.CalcLuminanceModulationLUT(
		  startSupresLuminance
		, startStrongLuminance
		, correctSupressInc
		, correctStrongInc
		, correctStrongLimit
		, &m_apertureSettings.lut[0]
	);
	msg.data = &m_apertureSettings.lut[0];
	datasize = sizeof(msg);
#endif  // DISABLE_APERTURE_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_APERTURE_LUT_TABLE_SET), &msg, datasize) < 0) {
		;
	}
#else
	memcpy(&checkDataCPPTEST.data[0], (BYTE*)msg.data, AP_LUT_DATA_CNT);
#endif
}

void AXMIspAdjust::apertureDefaultLutTblSet() {
	ST_MSG msg;
#ifndef DISABLE_APERTURE_PROC
	// アパーチャ補正後変調ゲインLUT初期値
	for (int i = 0; i < AP_LUT_DATA_CNT; i++) {
		m_apertureSettings.lut[i] = (BYTE)AP_MODULATION_GAIN_BASE;
	}
	msg.data = &m_apertureSettings.lut[0];
#endif  // DISABLE_APERTURE_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_APERTURE_LUT_TABLE_SET), &msg, sizeof(ST_MSG)) < 0) {
		;
	}
#else
	memcpy(&checkDataCPPTEST.data[0], (BYTE*)msg.data, AP_LUT_DATA_CNT);
#endif
}

void AXMIspAdjust::apertureCoringSet(BYTE coringTh) {
	BYTE datasize = 0;
	BYTE data;
#ifndef DISABLE_APERTURE_PROC
	data     = coringTh;
	datasize = sizeof(data);
#endif  // DISABLE_APERTURE_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_APERTURE_CORING_SET), &data, datasize) < 0) {
		;
	}
#else
	checkDataCPPTEST.data[0] = data;
	checkDataCPPTEST.size    = datasize;
#endif
}

ax::actorFuncStatus AXMIspAdjust::matrix0200(const void *pParam, int size) {
  bool ret = CheckIridixParam();
  if(ret == true) {
    SetIridix(Cmd_Adjust_Iridix_Run);
  }
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::matrix0300(const void *pParam, int size) {
#ifdef PARASOFT_CPPTEST
	BYTE procExeChk1 = 0;
	BYTE procExeChk2 = 0;
#endif  //  PARASOFT_CPPTEST
	bool isChange     = checkChromaParam();
	bool isChangeEdge = checkChromaEdgeParam();

	if (isChange) {
		chromaLutTblSet();
#ifdef PARASOFT_CPPTEST
		procExeChk1 = 1;
#endif
	}

	if (isChangeEdge) {
		chromaEdgeLutTblSet();
#ifdef PARASOFT_CPPTEST
		procExeChk2 = 1;
#endif
	}

#ifdef PARASOFT_CPPTEST
	checkDataCPPTEST.data[0] = procExeChk1;
	checkDataCPPTEST.data[1] = procExeChk2;
#endif
	return ax::AXFACTOR_SUCCESS;
}

bool AXMIspAdjust::checkChromaParam() {
	bool  isChange = false;

	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_CHROMA] & SPEC_CHG_CHRO) != SPEC_CHG_CHRO) {
		return isChange;
	}

	BYTE darkStartLuminance       = p_adjustspec->CHROMA.darkStartLuminance;
	BYTE darkInc                  = p_adjustspec->CHROMA.darkInc;
	BYTE highColorStartLuminance  = p_adjustspec->CHROMA.highColorStartLuminance;
	BYTE highColorInc             = p_adjustspec->CHROMA.highColorInc;
	BYTE highColorLimit           = p_adjustspec->CHROMA.highColorLimit;
	BYTE highLightStartLuminance  = p_adjustspec->CHROMA.highLightStartLuminance;
	BYTE highLightInc             = p_adjustspec->CHROMA.highLightInc;

	// 色ゲイン変調設定処理
	isChange = m_chromaLutSettings.modSettings.Set(
		  darkStartLuminance
		, darkInc
		, highColorStartLuminance
		, highColorInc
		, highColorLimit
		, highLightStartLuminance
		, highLightInc
	);

	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_CHROMA] &= ~SPEC_CHG_CHRO;

	return isChange;
}

bool AXMIspAdjust::checkChromaEdgeParam() {

	bool  isChange = false;

	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_CHROMA] & SPEC_CHG_EDGE_CHRO) != SPEC_CHG_EDGE_CHRO) {
		return isChange;
	}
	BYTE startTh  = p_adjustspec->CHROMA.edgeTh;
	BYTE supprStr = p_adjustspec->CHROMA.edgeSuppressStrong;

	if (m_chromaLutSettings.edgeTh != startTh) {
		m_chromaLutSettings.edgeTh = startTh;
		isChange = true;
	}

	if (m_chromaLutSettings.edgeSuppressStrong != supprStr) {
		m_chromaLutSettings.edgeSuppressStrong = supprStr;
		isChange = true;
	}

	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_CHROMA] &= ~SPEC_CHG_EDGE_CHRO;

	return isChange;
}

ax::actorFuncStatus AXMIspAdjust::matrix0400(const void *pParam, int size) {
  int ret = CheckLensShadeParam();
  if(ret != 0) {
    SetLensShade(ret);
  }
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::matrix0500(const void *pParam, int size) {
  USHORT ret = CheckNRParam();
  if(ret != PTN_NR_ALL) {
    SetNR(ret);
  }
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::matrix0600(const void *pParam, int size) {
#ifdef PARASOFT_CPPTEST
	checkDataCPPTEST.data[0] = 0;
	checkDataCPPTEST.data[1] = 0;
	checkDataCPPTEST.data[2] = 0;
#endif  //  PARASOFT_CPPTEST
	// スケーラ機能パラメータ更新チェック
	USHORT updateStatus = checkScalerParam();
	if (0 != updateStatus) {
		setScalerParam(updateStatus);
	}

	return ax::AXFACTOR_SUCCESS;
}

USHORT AXMIspAdjust::checkScalerParam() {

	USHORT updStatus = 0u;

	if (p_adjustspec == NULL) {
#ifdef PARASOFT_CPPTEST
		checkDataCPPTEST.data[2] = 1;
#endif  //  PARASOFT_CPPTEST
		return updStatus;
	}

	ST_SCALER scaler = p_adjustspec->Scaler;

	// スケーラ機能拡大縮小設定パラメータ変更チェック
	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_SCALER] & SPEC_CHG_SCAL_ZOOM) == SPEC_CHG_SCAL_ZOOM) {
		if (scaler.scaling.InImgSize.Width  != m_scalerSettings.scaling.InImgSize.Width
		||  scaler.scaling.InImgSize.Height != m_scalerSettings.scaling.InImgSize.Height) {
			m_scalerSettings.scaling.InImgSize.Width  = scaler.scaling.InImgSize.Width;
			m_scalerSettings.scaling.InImgSize.Height = scaler.scaling.InImgSize.Height;
			updStatus |= PTN_SCL_UPD_ZOOM;
		}
		for (int ch = 0; ch < SCL_SCALING_CH_CNT; ch++) {

			bool checkOutImgSize = false;
			if (scaler.scaling.OutImgSize[ch].Width  != m_scalerSettings.scaling.OutImgSize[ch].Width
			||  scaler.scaling.OutImgSize[ch].Height != m_scalerSettings.scaling.OutImgSize[ch].Height) {

				checkOutImgSize = checkScalerOutImageSize(
						  ch
						, m_scalerSettings.scaling.InImgSize.Width
						, m_scalerSettings.scaling.InImgSize.Height
						, scaler.scaling.OutImgSize[ch].Width
						, scaler.scaling.OutImgSize[ch].Height
				);
			}

			if (checkOutImgSize == true) {
				m_scalerSettings.scaling.OutImgSize[ch].Width  = scaler.scaling.OutImgSize[ch].Width;
				m_scalerSettings.scaling.OutImgSize[ch].Height = scaler.scaling.OutImgSize[ch].Height;
				updStatus |= PTN_SCL_UPD_ZOOM;
			}
		}
	}

	// スケーラ機能上下反転/ネガポジ反転設定パラメータ変更チェック
	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_SCALER] & SPEC_CHG_SCAL_REVERSE) == SPEC_CHG_SCAL_REVERSE) {
		// ネガポジ/上下左右反転設定
		for (int ch = 0; ch < SCL_NEG_FLIP_CH_CNT; ch++) {
			if (scaler.flip[ch].vFlip != m_scalerSettings.flip[ch].vFlip
			||  scaler.flip[ch].hFlip != m_scalerSettings.flip[ch].hFlip
			||  scaler.neg[ch]        != m_scalerSettings.neg [ch]) {
				m_scalerSettings.flip[ch].vFlip = scaler.flip[ch].vFlip;
				m_scalerSettings.flip[ch].hFlip = scaler.flip[ch].hFlip;
				m_scalerSettings.neg [ch]       = scaler.neg [ch];
				updStatus |= PTN_SCL_UPD_REVERSE;
			}
		}
	}

	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_SCALER] &= ~(SPEC_CHG_SCAL_ZOOM | SPEC_CHG_SCAL_REVERSE);
	return updStatus;
}

void AXMIspAdjust::setScalerParam(USHORT updateStatus) {
	ST_MSG msg;
	int datasize = sizeof(ST_MSG);

	msg.data = &m_scalerSettings;

	if ((updateStatus & PTN_SCL_UPD_ZOOM) == PTN_SCL_UPD_ZOOM) {
#ifndef PARASOFT_CPPTEST
		if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_SCALER_IMAGE_SIZE_SET), &msg, datasize) < 0) {
			;
		}
#else
		checkDataCPPTEST.data[0] = 1;
#endif
	}

	if ((updateStatus & PTN_SCL_UPD_REVERSE) == PTN_SCL_UPD_REVERSE) {
#ifndef PARASOFT_CPPTEST
		if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_SCALER_NEG_FLIP_SET), &msg, datasize) < 0) {
			;
		}
#else
		checkDataCPPTEST.data[1] = 1;
#endif
	}
}

ax::actorFuncStatus AXMIspAdjust::matrix0700(const void *pParam, int size) {
  USHORT ret = CheckDefectParam();
  if(ret != PTN_NR_ALL) {
    SetDefect(ret);
  }
  return ax::AXFACTOR_SUCCESS;
}

ax::actorFuncStatus AXMIspAdjust::matrix0800(const void *pParam, int size) {
  bool ret = CheckRGBMatrixParam();
  if(ret == true) {
    SetRGBMatrix();
  }
  return ax::AXFACTOR_SUCCESS;
}
//
//void AXMIspAdjust::chromaDefaultLutTblSet() {
//	ST_MSG msg;
//	int datasize = 0;
//#ifndef DISABLE_CHROMA_PROC
//	AXMIspChromaSettings chSettings;
//	// クロマサプレス色ゲイン変調LUT初期設定
//	m_chromaLutCalc.CalcLuminanceModulationLUT(
//		  0
//		, 0
//		, 0
//		, 0
//		, CH_MODULATION_GAIN_BASE
//		, CH_DEF_HIGH_LIGHT_START_LUMINANCE
//		, CH_DEF_HIGH_LIGHT_INC
//		, &m_chromaLutSettings.lut[0]
//	);
//	msg.data = &m_chromaLutSettings.lut[0];
//	datasize = sizeof(ST_MSG);
//#endif  // DISABLE_CHROMA_PROC
//
//#ifndef PARASOFT_CPPTEST
//	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_CHROMA_LUT_TABLE_SET), &msg, datasize) < 0) {
			;
//	}
//#else
//	memcpy(&checkDataCPPTEST.data[0], (BYTE*)msg.data, CH_MAX_LUT_SIZE);
//#endif
//}

void AXMIspAdjust::chromaLutTblSet() {
	BYTE datasize = 0;
	ST_MSG msg;

#ifndef DISABLE_CHROMA_PROC
	ChromaModSettings* setting = &m_chromaLutSettings.modSettings;
	m_chromaLutCalc.CalcLuminanceModulationLUT(
		  setting->darkStartLuminance
		, setting->darkInc
		, setting->highColorStartLuminance
		, setting->highColorInc
		, setting->highColorLimit
		, setting->highLightStartLuminance
		, setting->highLightInc
		, &m_chromaLutSettings.lut[0]
	);
	msg.data = &m_chromaLutSettings.lut[0];
	datasize = sizeof(msg);
#endif  // DISABLE_CHROMA_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_CHROMA_LUT_TABLE_SET), &msg, datasize) < 0) {
		;
	}
#else
	checkDataCPPTEST.param[0] = setting->darkStartLuminance;
	checkDataCPPTEST.param[1] = setting->darkInc;
	checkDataCPPTEST.param[2] = setting->highColorStartLuminance;
	checkDataCPPTEST.param[3] = setting->highColorInc;
	checkDataCPPTEST.param[4] = setting->highColorLimit;
	checkDataCPPTEST.param[5] = setting->highLightStartLuminance;
	checkDataCPPTEST.param[6] = setting->highLightInc;
	memcpy(&checkDataCPPTEST.data[0], (BYTE*)msg.data, CH_MAX_LUT_SIZE);
#endif
}

void AXMIspAdjust::chromaEdgeLutTblSet() {
	ST_MSG msg;
	int datasize = 0;
#ifndef DISABLE_CHROMA_PROC
	// エッジクロマサプレス色ゲイン変調LUT設定
	m_chromaLutCalc.CalcEdgeLuminanceModulationLUT(
		  m_chromaLutSettings.edgeTh
		, m_chromaLutSettings.edgeSuppressStrong
		, &m_chromaLutSettings.edgeLut[0]
	);
	msg.data = &m_chromaLutSettings.edgeLut[0];
	datasize = sizeof(ST_MSG);
#endif  // DISABLE_CHROMA_PROC

#ifndef PARASOFT_CPPTEST
	if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_CHROMA_EDGE_LUT_TABLE_SET), &msg, datasize) < 0) {
		;
	}
#else
	memcpy(&checkDataCPPTEST.data[0], (BYTE*)msg.data, CH_MAX_EDGE_LUT_SIZE);
#endif
}

bool AXMIspAdjust::checkScalerOutImageSize(int ch, USHORT in_width, USHORT in_height, USHORT out_width, USHORT out_height) {
	const int WIDTH_ALIGNMENT_SHIFT   = 4;
	const int HEIGHT_ALIGNMENT_SHIFT  = 3;
	const int OVER_HALF_SIZE_IMAGE_CH = 2;
	const int MAX_CH = 2;
	bool checkOK = true;
	if (MAX_CH < ch || ch < 0) {
		checkOK = false;
	}
	// スケーラー後の画像幅は16の倍数でない場合はエラー
	USHORT checkVal = out_width - ((USHORT)(out_width >> WIDTH_ALIGNMENT_SHIFT) << WIDTH_ALIGNMENT_SHIFT);
	if (0 != checkVal) {
		checkOK = false;
	}
	// 高さは8の倍数でない場合はエラー
	checkVal = out_height - ((USHORT)(out_height >> HEIGHT_ALIGNMENT_SHIFT) << HEIGHT_ALIGNMENT_SHIFT);
	if (0 != checkVal) {
		checkOK = false;
	}

	// 2ch以外で、出力画像のサイズに、入力画像の半分以上のサイズを指定した場合はエラー
	if (ch != OVER_HALF_SIZE_IMAGE_CH) {
		if ((in_width >> 1) < out_width) {
			checkOK = false;
		}
		if ((in_height >> 1) < out_height) {
			checkOK = false;
		}
	}
	return checkOK;
}

//  (デバッグ用)
//  設定値が変更されていれば、AXMPixcessorへイベント送信を行う
ax::actorFuncStatus AXMIspAdjust::matrix1000(const void *pParam, int size) {
	// 今回シェーディング補正なしのため不要
	/*
  //  シェーディング補正 設定値変更確認および設定値変更
  //  ※設定値の変更確認方法については、仕様確定後に修正のこと
  {
    int ret = CheckLensShadeParam();
    if(ret != 0) {
      SetLensShade(ret);
#ifdef  PARASOFT_CPPTEST
      //  テストの都合により、ここで変更があったときはreturnにて終了する
      return ax::AXFACTOR_SUCCESS;
#endif  //  PARASOFT_CPPTEST
    }
  }
	
  //  ガンマ補正 設定値変更確認および設定値変更
#ifndef PARASOFT_CPPTEST
  //  テスト都合にて、ガンマ補正の設定値の確認は行わない
  ModifyGamma();
#endif  //  PARASOFT_CPPTEST

  //  アパーチャ補正 設定値確認および設定値変更
  //  ここに、アパーチャ補正関連設定値の変更確認と変更処理を追加すること

  //  IRIDIX 設定値変更確認および設定値変更
  {
    bool ret = CheckIridixParam();
    if(ret == true) {
      SetIridix(Cmd_Adjust_Iridix_Run);
#ifdef  PARASOFT_CPPTEST
      //  テストの都合により、ここで変更があったときはreturnにて終了する
      return ax::AXFACTOR_SUCCESS;
#endif  //  PARASOFT_CPPTEST
    }
  }
	
  //  NR 設定値変更確認および設定値変更
  {
    USHORT ret = CheckNRParam();
    if(ret != PTN_NR_ALL) {
      SetNR(ret);
#ifdef  PARASOFT_CPPTEST
      //  テストの都合により、ここで変更があったときはreturnにて終了する
      return ax::AXFACTOR_SUCCESS;
#endif  //  PARASOFT_CPPTEST
    }
  }
	
  //  画素欠陥補正 設定値変更確認および設定値変更
  {
    USHORT ret = CheckDefectParam();
    if(ret != PTN_DEFECT_ALL) {
      SetDefect(ret);
#ifdef  PARASOFT_CPPTEST
      //  テストの都合により、ここで変更があったときはreturnにて終了する
      return ax::AXFACTOR_SUCCESS;
#endif  //  PARASOFT_CPPTEST
    }
  }

  //  RGBマトリックス 設定値変更確認および設定値変更
  {
    bool ret = CheckRGBMatrixParam();
    if(ret == true) {
      SetRGBMatrix();
    
	*/

  return ax::AXFACTOR_SUCCESS;
}

bool AXMIspAdjust::CheckIridixParam()
{
  bool result = false;

  if((p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_IRIDIX] & SPEC_CHG_IRIDIX) == SPEC_CHG_IRIDIX) {
    if((p_adjustspec->Iridix.Strength != IridixSettings.Strength) ||
       (p_adjustspec->Iridix.MinSlope != IridixSettings.MinSlope) ||
       (p_adjustspec->Iridix.MaxSlope != IridixSettings.MaxSlope)) {
      result = true;
      //  設定値更新
      IridixSettings = p_adjustspec->Iridix;
    }
    //  設定値更新フラグクリア
    p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_IRIDIX] &= ~SPEC_CHG_IRIDIX;
  }
  return result;
}

USHORT AXMIspAdjust::CheckLensShadeParam()
{
  USHORT result = 0x0000u;

  //  レンズシェーディング補正設定値更新フラグ確認
  if((p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_SHADE] & SPEC_CHG_SHADE) == SPEC_CHG_SHADE) {
    //  更新要求フラグON:設定値更新処理
    //  モード設定値確認
    if(p_adjustspec->LensShade.Enabled != LensShadeSettings.Enabled) {
      result |= Cmd_Adjust_LensShade_Enabled;
      //  設定値更新
      LensShadeSettings.Enabled = p_adjustspec->LensShade.Enabled;
    }
    //  ピッチ設定値確認
    if(p_adjustspec->LensShade.Pitch != LensShadeSettings.Pitch) {
      result |= Cmd_Adjust_LensShade_Pitch;
      //  設定値更新
      LensShadeSettings.Pitch = p_adjustspec->LensShade.Pitch;
    }
    if(p_adjustspec->LensShade.Shift != LensShadeSettings.Shift) {
      result |= Cmd_Adjust_LensShade_Shift;
      //  設定値更新
      LensShadeSettings.Shift = p_adjustspec->LensShade.Shift;
    }
    //  更新フラグクリア
    p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_SHADE] &= ~SPEC_CHG_SHADE;
  }
  return result;
}

USHORT AXMIspAdjust::CheckNRParam()
{
  USHORT result = 0x0000u;

  //  NR設定値更新フラグ確認
  if((p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_NR] & SPEC_CHG_NR) == SPEC_CHG_NR) {
    //  更新要求フラグON:設定値更新処理
    //  モード設定値確認
    if(p_adjustspec->NR.Mode != NRSettings.Mode) {
      result |= PTN_NR_MODE;
      //  モード設定値更新
      NRSettings.Mode = p_adjustspec->NR.Mode;
    }
    //  MainY信号設定値確認
    for(UINT i = 0; i < AXH_NR_Main_Max; i++) {
      if((p_adjustspec->NR.Main.YTH[i] != NRSettings.Main.YTH[i]) ||
         (p_adjustspec->NR.Main.YIN[i] != NRSettings.Main.YIN[i]) ||
         (p_adjustspec->NR.Main.YLV[i] != NRSettings.Main.YLV[i])) {
        result |= PTN_NR_MainY;
        break;
      }
    }
    //  MainC信号設定値確認
    for(UINT i = 0; i < AXH_NR_Main_Max; i++) {
      if((p_adjustspec->NR.Main.CTH[i] != NRSettings.Main.CTH[i]) ||
         (p_adjustspec->NR.Main.CIN[i] != NRSettings.Main.CIN[i]) ||
         (p_adjustspec->NR.Main.CLV[i] != NRSettings.Main.CLV[i])) {
        result |= PTN_NR_MainC;
        break;
      }
    }
    //  Main設定値更新
    NRSettings.Main = p_adjustspec->NR.Main;

    //  SubY信号設定値確認
    for(UINT i = 0; i < AXH_NR_Sub_Max; i++) {
      if((p_adjustspec->NR.Sub.YTH[i] != NRSettings.Sub.YTH[i]) ||
         (p_adjustspec->NR.Sub.YIN[i] != NRSettings.Sub.YIN[i]) ||
         (p_adjustspec->NR.Sub.YLV[i] != NRSettings.Sub.YLV[i])) {
        result |= PTN_NR_SubY;
        break;
      }
    }
    //  SubC信号設定値確認
    for(UINT i = 0; i < AXH_NR_Sub_Max; i++) {
      if((p_adjustspec->NR.Sub.CTH[i] != NRSettings.Sub.CTH[i]) ||
         (p_adjustspec->NR.Sub.CIN[i] != NRSettings.Sub.CIN[i]) ||
         (p_adjustspec->NR.Sub.CLV[i] != NRSettings.Sub.CLV[i])) {
        result |= PTN_NR_SubC;
        break;
      }
    }
    //  Sub設定値更新
    NRSettings.Sub = p_adjustspec->NR.Sub;
    //  設定値更新フラグクリア
    p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_NR] &=  ~SPEC_CHG_NR;
  }
  return result;
}

USHORT AXMIspAdjust::CheckDefectParam()
{
  USHORT result = 0x0000u;

  //  画素欠陥補正 設定値更新フラグ確認
  if((p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_KIZU_Dynamic] & SPEC_CHG_KIZU_Dynamic) == SPEC_CHG_KIZU_Dynamic) {
    //  更新要求フラグON:設定値更新処理
    //  モード設定 設定値確認
    if((p_adjustspec->Defect.Mode.External    != DefectSettings.Mode.External   ) ||
       (p_adjustspec->Defect.Mode.AutoCorrect != DefectSettings.Mode.AutoCorrect)) {
      result |= PTN_DEFECT_Mode;
    }
    //  欠陥画素アドレス 設定値確認
    for(unsigned int i = 0; i < AXH_Defect_IntAddr_Max; i++) {
      if((p_adjustspec->Defect.Address[i].H   != DefectSettings.Address[i].H  ) ||
         (p_adjustspec->Defect.Address[i].V   != DefectSettings.Address[i].V  ) ||
         (p_adjustspec->Defect.Address[i].CLS != DefectSettings.Address[i].CLS)) {
        result |= PTN_DEFECT_Address;
        break;
      }
    }
    //  自動補正機能 設定値確認
    if((p_adjustspec->Defect.AutoCorrect.CLS  != DefectSettings.AutoCorrect.CLS ) ||
       (p_adjustspec->Defect.AutoCorrect.Ave  != DefectSettings.AutoCorrect.Ave ) ||
       (p_adjustspec->Defect.AutoCorrect.TH_H != DefectSettings.AutoCorrect.TH_H) ||
       (p_adjustspec->Defect.AutoCorrect.TH_L != DefectSettings.AutoCorrect.TH_L)) {
      result |= PTN_DEFECT_AutoSettings;
    }
    //  輝度信号レベル変調設定 設定値確認
    for(unsigned int i = 0; i < AXH_Defect_IntAddr_Max; i++) {
      if(p_adjustspec->Defect.AutoCorrect.OFST[i] != DefectSettings.AutoCorrect.OFST[i]) {
        result |= PTN_DEFECT_AutoLevel;
        break;
      }
    }
    //  設定値更新
    DefectSettings = p_adjustspec->Defect;
    //  設定値更新フラグクリア
    p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_KIZU_Dynamic] &=  ~SPEC_CHG_KIZU_Dynamic;
  }

  return result;
}

bool AXMIspAdjust::CheckRGBMatrixParam()
{
  if((p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_RGB_Matrix] & SPEC_CHG_RGB_Matrix) == SPEC_CHG_RGB_Matrix) {
    for(unsigned int i = 0; i < AXH_RGBMatrixSetOut_Max; i++) {
      for(unsigned int j = 0; j < AXH_RGBMatrixSetIn_Max; j++) {
        if(p_adjustspec->RGBMatrix.Coef[i][j] != RGBMatrixSettings.Coef[i][j]) {
          //  設定値更新
          RGBMatrixSettings = p_adjustspec->RGBMatrix;
          //  設定値更新フラグクリア
          p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_RGB_Matrix] &= ~SPEC_CHG_RGB_Matrix;
          return true;
        }
      }
      if(p_adjustspec->RGBMatrix.Offset[i] != RGBMatrixSettings.Offset[i]) {
        //  設定値更新
        RGBMatrixSettings = p_adjustspec->RGBMatrix;
        //  設定値更新フラグクリア
        p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_RGB_Matrix] &= ~SPEC_CHG_RGB_Matrix;
        return true;
      }
    }
    //  設定値更新フラグクリア
    p_adjustspec->changeStatus[AXH_Index_SPEC_CHG_RGB_Matrix] &= ~SPEC_CHG_RGB_Matrix;
  }
  return false;
}

void AXMIspAdjust::ModifyGamma() {
	USHORT* sendCurvePoint = NULL;

#ifdef PARASOFT_CPPTEST
	checkDataCPPTEST.size = GMTest_noProc;
#endif
#ifndef DISABLE_GAMMA_PROC
	USHORT updStatus = checkGammaParam();
	bool   updateTbl = checkGammaMode();
	bool   isUpdUser = checkGammaUserSetParam();
	switch (m_gammaSettings.gammaMode) {
	default:
	case GammaPreset:
		// ガンマ補正カーブ選択変更チェック
		if ((updStatus & PTN_GM_UPD_CURVE) == PTN_GM_UPD_CURVE) {
			// デフォルトガンマ補正カーブ生成
			m_gammaCalc.CreateDefGammaCurve();
			updateTbl = true;
#ifdef PARASOFT_CPPTEST
			checkDataCPPTEST.size += GMTest_curvChange;
#endif

		}
		// Knee設定変更チェック
		if ((updStatus & PTN_GM_UPD_KNEE) == PTN_GM_UPD_KNEE) {
			// ガンマ補正カーブ変換
			m_gammaCalc.ConvertGammaCurve();
			updateTbl = true;
#ifdef PARASOFT_CPPTEST
			checkDataCPPTEST.size += GMTest_kneeChange;
#endif
		}

		sendCurvePoint = &m_gammaSettings.setGammaCurvePoint[0];
		break;
	case GammaUserset:
		if (isUpdUser) {
			updateTbl = true;
#ifdef PARASOFT_CPPTEST
			checkDataCPPTEST.size += GMTest_userChange;
#endif
		}
		sendCurvePoint = &m_gammaSettings.usrGammaCurvePoint[0];
		break;
	}
#endif  // DISABLE_GAMMA_PROC

	if (updateTbl) {
#ifdef PARASOFT_CPPTEST
		checkDataCPPTEST.size += GMTest_dataSend;
#endif
		ST_MSG msg;
		msg.data = &sendCurvePoint[0];

#ifndef PARASOFT_CPPTEST
		// ガンマ補正カーブ設定
		if (send(namePixessor, AXFEVENT_MODEL(AXMPixcessor::ISP_EVENT_GAMMA_TABLE_SET), &msg, sizeof(ST_MSG)) < 0) {
			;
		}
#endif
	}
}

bool AXMIspAdjust::checkGammaMode() {
	bool isUpdate = false;

	BYTE mode = p_adjustspec->Gamma.mode;

	if (mode != m_gammaSettings.gammaMode) {
		if (mode < GAMMA_MODE_MAX) {
			m_gammaSettings.gammaMode = static_cast<GammaMode>(mode);
#ifdef PARASOFT_CPPTEST
			checkDataCPPTEST.size += GMTest_modeChange;
#endif
			isUpdate = true;
		}
	}
	return isUpdate;
}

bool AXMIspAdjust::checkGammaUserSetParam() {
	bool isUpdate = false;
	// ガンマ補正ユーザー設定
	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_GAMMA] & SPEC_CHG_GAM_USR) != SPEC_CHG_GAM_USR) {
		return isUpdate;
	}

	isUpdate = m_gammaCalc.SetUserGammaCurve(&p_adjustspec->Gamma.usrCurvePoint[0]);

	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_GAMMA] &= ~(SPEC_CHG_GAM_USR);

	return isUpdate;
}

USHORT AXMIspAdjust::checkGammaParam() {

	USHORT updStatus = 0u;

	// ガンマ補正モード/プリセットモードパラメータ変更チェック
	if ((p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_GAMMA] & SPEC_CHG_GAM_PRE) != SPEC_CHG_GAM_PRE) {
		return updStatus;
	}

	BYTE	curve  = p_adjustspec->Gamma.curveSelect;
	USHORT	dRange = p_adjustspec->Gamma.dRange;
	USHORT	hRange = p_adjustspec->Gamma.hRange;

	if (curve != m_gammaSettings.gammaCurveSelect) {
		if (curve < GAMMA_CURVE_MAX) {
			m_gammaSettings.gammaCurveSelect = static_cast<GammaCurve>(curve);;
			m_gammaSettings.kneeSettings.dRange = DEF_KNEE_X;
			m_gammaSettings.kneeSettings.hRange = DEF_KNEE_Y;
			updStatus |= PTN_GM_UPD_CURVE;
		}
	}

	if (dRange != m_gammaSettings.kneeSettings.dRange
	||  hRange != m_gammaSettings.kneeSettings.hRange) {
		if (dRange <= DEF_KNEE_MAX && hRange <= DEF_KNEE_MAX) {
			m_gammaSettings.kneeSettings.dRange = dRange;
			m_gammaSettings.kneeSettings.hRange = hRange;
			updStatus |= PTN_GM_UPD_KNEE;
		}
	}

	p_adjustspec->changeStatus[AXH_Index_SPEC_CHK_GAMMA] &= ~(SPEC_CHG_GAM_PRE);

	return updStatus;
}
