#include "mil.h"
#include "HistogramDisplay.h"
static const MIL_INT MAX_LEGEND_DIGIT = 4;
static const MIL_INT HIST_BORDER = (MAX_LEGEND_DIGIT + 6) * 8 + 1;
static const MIL_INT DEFAULT_HIST_SIZE_X = 256;
static const MIL_INT DEFAULT_HIST_SIZE_Y = 256;
CHistogramDisplay::CHistogramDisplay(MIL_ID MilSystem, MIL_CONST_TEXT_PTR Title , MIL_INT TitleColor )
: m_MilSystem(MilSystem),
m_MilHistResult(M_NULL),
m_MilDisplay(M_NULL),
m_MilBackImage(M_NULL),
m_MilGraList(M_NULL),
m_MilGraContext(M_NULL),
m_NbEntries(0),
m_pHistIndexes(NULL),
m_TitleColor(TitleColor),
m_Title(NULL),
m_HistSizeX(DEFAULT_HIST_SIZE_X),
m_HistSizeY(DEFAULT_HIST_SIZE_Y)
{
m_pHistValues[0] = NULL;
m_pHistValues[1] = NULL;
m_pHistValues[2] = NULL;
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_WINDOWED, &m_MilDisplay);
MgraAllocList(MilSystem, M_DEFAULT, &m_MilGraList);
MdispControl(m_MilDisplay, M_ASSOCIATED_GRAPHIC_LIST_ID, m_MilGraList);
MgraAlloc(m_MilSystem, &m_MilGraContext);
if(Title)
{
MdispControl(m_MilDisplay, M_TITLE, M_PTR_TO_DOUBLE(Title));
MIL_INT TitleSize = MosStrlen(Title)+1;
m_Title = new MIL_TEXT_CHAR[TitleSize];
MosStrcpy(m_Title, TitleSize, Title);
}
}
CHistogramDisplay::~CHistogramDisplay()
{
FreeHistObjects();
MgraFree(m_MilGraContext);
MgraFree(m_MilGraList);
MdispFree(m_MilDisplay);
if(m_Title)
delete [] m_Title;
}
void CHistogramDisplay::AllocateHistObjects()
{
FreeHistObjects();
m_pHistIndexes = new MIL_DOUBLE[m_NbEntries + 2];
MIL_DOUBLE InvPixelSizeX = (MIL_DOUBLE)m_HistSizeX / m_NbEntries;
for(MIL_UINT HistIdx = 0; HistIdx < m_NbEntries; HistIdx++)
m_pHistIndexes[HistIdx] = HistIdx * InvPixelSizeX;
m_pHistIndexes[m_NbEntries] = (m_NbEntries-1) * InvPixelSizeX;
m_pHistIndexes[m_NbEntries+1] = 0;
for (MIL_INT BandIdx = 0; BandIdx < 3; BandIdx++)
{
m_pHistValues[BandIdx] = new MIL_DOUBLE[m_NbEntries + 2];
m_pHistValues[BandIdx][m_NbEntries] = 0;
m_pHistValues[BandIdx][m_NbEntries + 1] = 0;
}
MimAllocResult(m_MilSystem, m_NbEntries, M_HIST_LIST, &m_MilHistResult);
MbufAlloc2d(m_MilSystem, m_HistSizeX + 2*HIST_BORDER, m_HistSizeY + 2*HIST_BORDER, 8+M_UNSIGNED, M_IMAGE+M_DISP, &m_MilBackImage);
MbufClear(m_MilBackImage, 0);
}
void CHistogramDisplay::FreeHistObjects()
{
delete [] m_pHistIndexes;
delete [] m_pHistValues[0];
delete [] m_pHistValues[1];
delete [] m_pHistValues[2];
if(m_MilHistResult)
{
MimFree(m_MilHistResult);
m_MilHistResult = M_NULL;
}
if(m_MilBackImage)
{
MbufFree(m_MilBackImage);
m_MilBackImage = M_NULL;
}
}
void CHistogramDisplay::Preprocess(MIL_ID MilTypicalImage)
{
MIL_INT ImageSizeBit = MbufInquire(MilTypicalImage, M_SIZE_BIT, M_NULL);
if(m_NbEntries == 0 || m_NbEntries != (1 << ImageSizeBit))
{
m_NbEntries = 1 << ImageSizeBit;
AllocateHistObjects();
MdispSelect(m_MilDisplay, m_MilBackImage);
DrawDisplayTitle();
}
}
void CHistogramDisplay::SetWindowInitialPosition(MIL_INT WindowPosX, MIL_INT WindowPosY)
{
MdispControl(m_MilDisplay, M_WINDOW_INITIAL_POSITION_X, WindowPosX);
MdispControl(m_MilDisplay, M_WINDOW_INITIAL_POSITION_Y, WindowPosY);
}
void CHistogramDisplay::DrawDisplayTitle()
{
if(m_Title)
{
MgraControl(m_MilGraContext, M_INPUT_UNITS, M_DISPLAY);
MgraControl(m_MilGraContext, M_TEXT_ALIGN_HORIZONTAL, M_LEFT);
MgraControl(m_MilGraContext, M_TEXT_ALIGN_VERTICAL, M_TOP);
MgraColor(m_MilGraContext, (MIL_DOUBLE)m_TitleColor);
MgraText(m_MilGraContext, m_MilGraList, 0, 0, m_Title);
MgraControl(m_MilGraContext, M_INPUT_UNITS, M_PIXEL);
}
}
MIL_DOUBLE CHistogramDisplay::Update(MIL_ID MilImage, MIL_DOUBLE MaxVal)
{
MdispControl(m_MilDisplay, M_UPDATE, M_DISABLE);
Preprocess(MilImage);
MgraClear(M_DEFAULT, m_MilGraList);
MIL_INT SizeBand = MbufInquire(MilImage, M_SIZE_BAND, M_NULL);
MIL_DOUBLE MaxValToUse = MaxVal;
for (MIL_INT BandIdx = 0; BandIdx < SizeBand; BandIdx++)
{
MIL_ID MilBand = MbufChildColor(MilImage, BandIdx, M_NULL);
MimHistogram(MilBand, m_MilHistResult);
MimGetResult(m_MilHistResult, M_VALUE + M_TYPE_MIL_DOUBLE, m_pHistValues[BandIdx]);
if (MaxVal == M_NULL)
{
for (MIL_UINT ValIdx = 0; ValIdx < m_NbEntries; ValIdx++)
{ MaxValToUse = (MaxValToUse < m_pHistValues[BandIdx][ValIdx]) ? m_pHistValues[BandIdx][ValIdx] : MaxValToUse; }
}
MbufFree(MilBand);
}
for (MIL_INT BandIdx = 0; BandIdx < SizeBand; BandIdx++)
{
MIL_DOUBLE InvPixelSizeY = (MIL_DOUBLE)m_HistSizeY / MaxValToUse;
for (MIL_UINT ValIdx = 0; ValIdx < m_NbEntries; ValIdx++)
m_pHistValues[BandIdx][ValIdx] = -m_pHistValues[BandIdx][ValIdx] * InvPixelSizeY;
MgraColor(m_MilGraContext, M_COLOR_MAGENTA);
MgraControl(m_MilGraContext, M_TEXT_ALIGN_HORIZONTAL, M_RIGHT);
MgraControl(m_MilGraContext, M_TEXT_ALIGN_VERTICAL, M_CENTER);
MIL_TEXT_CHAR Legend[MAX_LEGEND_DIGIT + 10];
MosSprintf(Legend, MAX_LEGEND_DIGIT + 10, MIL_TEXT("%.*g"), MAX_LEGEND_DIGIT, (MIL_DOUBLE)MaxValToUse);
MgraText(m_MilGraContext, m_MilGraList, HIST_BORDER - 1, HIST_BORDER, Legend);
const MIL_DOUBLE PolygonColors[3] = { M_COLOR_RED, M_COLOR_GREEN, M_COLOR_BLUE };
MgraControl(m_MilGraContext, M_DRAW_OFFSET_X, -HIST_BORDER);
MgraControl(m_MilGraContext, M_DRAW_OFFSET_Y, -(HIST_BORDER + m_HistSizeY));
MgraColor(m_MilGraContext, PolygonColors[BandIdx]);
MIL_INT ControlFlag = M_POLYLINE;
MIL_INT NbEntriesToUse = m_NbEntries;
if (SizeBand == 1)
{
ControlFlag = M_POLYGON + M_FILLED;
NbEntriesToUse = m_NbEntries + 2;
}
MgraLines(m_MilGraContext, m_MilGraList, NbEntriesToUse, m_pHistIndexes, m_pHistValues[BandIdx], M_NULL, M_NULL, ControlFlag);
MgraControl(m_MilGraContext, M_DRAW_OFFSET_X, 0);
MgraControl(m_MilGraContext, M_DRAW_OFFSET_Y, 0);
MgraColor(m_MilGraContext, M_COLOR_YELLOW);
MgraLine(m_MilGraContext, m_MilGraList, HIST_BORDER, HIST_BORDER, HIST_BORDER, HIST_BORDER + m_HistSizeY);
MgraLine(m_MilGraContext, m_MilGraList, HIST_BORDER, HIST_BORDER + m_HistSizeY,
HIST_BORDER + m_HistSizeX, HIST_BORDER + m_HistSizeY);
}
DrawDisplayTitle();
MdispControl(m_MilDisplay, M_UPDATE, M_ENABLE);
return MaxValToUse;
}