#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	channel_rgb,
	channel_red,
	channel_green,
	channel_blue,
};
enum{
	flt_min,
	flt_max,
	flt_clamp,
};


#include <GetNBox.h>
#include <image_utils.h>

static void _set_threshold_array(int* arrLow, int* arrHigh, int nChannel, int low, int high)
{
	int ii;
	
	if(nChannel==0)
	{
		for(ii=0;ii<3;ii++)
		{
			arrLow[ii]=low;
			arrHigh[ii]=high;
		}
	}	
	else
	{
		for(ii=0;ii<3;ii++)
		{
			arrLow[ii]=0;
			arrHigh[ii]=255;
		}
		arrLow[nChannel-1]=low;
    	arrHigh[nChannel-1]=high;
	}	
	
}



static int _image_color_threshold(BITMAPHANDLE* pLBmp,int nOption,int* pnLow,int* pnHigh)
{
	int nRet=0;
	//double dAdjValue=1;
	//int nMaxData=get_image_data_max_val(pLBmp);
	//
	//if(nMaxData!=255)
	//{
		//dAdjValue=nMaxData/255.0;
	//}
	
	vector<uint> vOption = {CLTH_VALUE_MIN,	CLTH_VALUE_MAX,	CLTH_VALUE_CLAMP};
	if(nOption<0 || nOption> vOption.GetSize())
		return INTOPTN_OUT_OF_RANGE;
	

	
	COMPDATA  pCompData[3];
	
	for (int ii = 0; ii < 3; ii++)
	{
		if(pnLow[ii]>pnHigh[ii])
		{
			return XFERR_MIN_LARGER_THAN_MAX;
		}
	    pCompData[ii].nMinRange =pnLow[ii];//*dAdjValue;
	    pCompData[ii].nMaxRange = pnHigh[ii];//*dAdjValue; 
	    pCompData[ii].uFlags = CLTH_TYP_BANDPASS|CLTH_MOD_CHANNEL|vOption[nOption];
	}
	pCompData[0].uStructSize = sizeof(COMPDATA);
	                        
	
	return L_ColorThresholdBitmap( pLBmp, CLTH_RGB_SPACE, pCompData );
		

}


void imgThreshold(const Image& img, const int& low, const int& high, const int& channel, const int& flt, Image& oimg)
{
	
	oimg.SetLBmp(img.GetLBmp(), TRUE);
	pBITMAPHANDLE phBmp = oimg.GetLBmp();
	int arrLow[3],arrHigh[3];
	//int nMaxVal=get_image_data_max_val(phBmp);
	int ii;
	
	if(channel==0)
	{
		for(ii=0;ii<3;ii++)
		{
			arrLow[ii]=low;
			arrHigh[ii]=high;
		}
	}	
	else
	{
		for(ii=0;ii<3;ii++)
		{
			arrLow[ii]=0;
			arrHigh[ii]=255;
		}
		arrLow[channel-1]=low;
	    arrHigh[channel-1]=high;
	}
	
	int nRet = _image_color_threshold(phBmp,flt,arrLow,arrHigh);
	
	if(nRet < MAX_ERROR_CODE_FROM_LT)
		XF_THROW_EX(XFERR_LEADTOOLS_FUNCTION_UNKNOWN_ERR, nRet);
	
	if(nRet !=  SUCCESS)
		XF_THROW(nRet);
		
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int imgThreshold_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return imgThreshold_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	return false;

}

int imgThreshold_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void imgThreshold_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{

}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int imgThreshold_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}


// this is called when the GetNImageBox dialog is open
// bUpdateGrid = false when entering this function
// you need to set bUpdateGrid = true if you need to modify trGetN data and want to see the
// grid updated, for example
// trGetN.angle.nVal = 0; // force rotation to init to 0
// bUpdateGrid = true;
// bOKEnable is default = true, you may add code to check trGetN and decide that the OK button should be disabled, then set this to false
// example: 
// if(0==trGetN.angle.nVal) // no change, no point to click Ok to do nothing
//    bOKEnable = false; 
static void GetNImageBox_OnInit(TreeNode& trGetN, ImageControlBase* pimgCntrl, bool& bUpdateGrid, bool& bOKEnable, string& strErrMsg)
{

	int arrLow[3],arrHigh[3];
	
	_set_threshold_array(arrLow,arrHigh,trGetN.channel.nVal,trGetN.low.nVal,trGetN.high.nVal);


	pBITMAPHANDLE pPreviewBitmap;
	pPreviewBitmap=pimgCntrl->GetBitmapHandlePtr();
	
	int nRet = _image_color_threshold(pPreviewBitmap,trGetN.flt.nVal,arrLow,arrHigh);
	if( SUCCESS != nRet)
	{
		if(nRet == -12)
		{
			strErrMsg = CER_IMAGE_TYPE;
		}
		else
			strErrMsg = nRet;
		bOKEnable = false;
		return;
	}
	
	bUpdateGrid = true;
	
}

// this is called whenever any controls in the grid is modified by the user
// upon entering function
// bUpdatePreview = true;// to update the preview image pPreviewBitmap
// bUpdateGrid = false; // event triggered by grid change, so default no need to update again
// if you want to modify other controls in the grid, then you need to set bUpdateGrid to true
// bOKEnable is default = true, you may add code to check trGetN and decide that the OK button should be disabled, then set this to false
static void GetNImageBox_OnChange(BITMAPHANDLE* pPreviewBitmap, TreeNode& trGetN, TreeNode& trNode, ImageControlBase* pimgCntrl, bool& bUpdatePreview, bool& bUpdateGrid, bool& bOKEnable, string& strErrMsg)
{

	//int nMaxVal=get_image_data_max_val(pPreviewBitmap);
	//String strV;
	//
	//
	//if(trGetN.low.DataID==trNode.DataID)
	//{
		//strV.Format("%d|%d|%d",trGetN.low.nVal,nMaxVal,nMaxVal-trGetN.low.nVal);
		//trGetN.high.SetAttribute(STR_COMBO_ATTRIB,strV);
	//}
	//
	//if(trGetN.high.DataID==trNode.DataID)
	//{
		//strV.Format("%d|%d|%d",0,trGetN.high.nVal,trGetN.high.nVal);
		//trGetN.low.SetAttribute(STR_COMBO_ATTRIB,strV);
	//}


	int arrLow[3],arrHigh[3];
	
	_set_threshold_array(arrLow,arrHigh,trGetN.channel.nVal,trGetN.low.nVal,trGetN.high.nVal);

	int nRet = _image_color_threshold(pPreviewBitmap,trGetN.flt.nVal,arrLow,arrHigh);
	if( SUCCESS != nRet)
	{
		if(nRet == -12)
		{
			strErrMsg = CER_IMAGE_TYPE;
		}
		else
			strErrMsg = nRet;
		bOKEnable = false;
		return;
	}
	
	bUpdateGrid = true;
	bUpdatePreview = true;

}
	
int GetNImageBox_imgThreshold(TreeNode& trGetN, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg, ImageControlBase* pimgCntrl)
{
	return xf_GetNImageBox_event_handler(trGetN, nRow, nCol, trNode, dwCntrl, nType, pimgCntrl,
								GetNImageBox_OnInit, GetNImageBox_OnChange);	
}
