Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef RASTER_EDGE_ITERATOR_HPP
Toshihiro Shimizu 890ddd
#define RASTER_EDGE_ITERATOR_HPP
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "raster_edge_iterator.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace TRop
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
namespace borders
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
RasterEdgeIterator<pixelselector>::RasterEdgeIterator(</pixelselector>
Toshihiro Shimizu 890ddd
	const raster_typeP &rin, const selector_type &selector,
Toshihiro Shimizu 890ddd
	const TPoint &pos, const TPoint &dir, int adherence)
Toshihiro Shimizu 890ddd
	: m_ras(rin), m_lx_1(rin->getLx() - 1), m_ly_1(rin->getLy() - 1), m_wrap(rin->getWrap()), m_selector(selector), m_pos(pos), m_dir(dir), m_elbowColor(selector.transparent()), m_rightSide(adherence == RIGHT), m_turn(UNKNOWN)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixels(m_leftPix, m_rightPix);
Toshihiro Shimizu 890ddd
	colors(m_leftColor, m_rightColor);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
void RasterEdgeIterator<pixelselector>::setEdge(const TPoint &pos, const TPoint &dir)</pixelselector>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_pos = pos, m_dir = dir;
Toshihiro Shimizu 890ddd
	pixels(m_leftPix, m_rightPix);
Toshihiro Shimizu 890ddd
	colors(m_leftColor, m_rightColor);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
inline void RasterEdgeIterator<pixelselector>::pixels(</pixelselector>
Toshihiro Shimizu 890ddd
	pixel_type *&pixLeft, pixel_type *&pixRight)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x;
Toshihiro Shimizu 890ddd
	if (m_dir.y)
Toshihiro Shimizu 890ddd
		if (m_dir.y > 0)
Toshihiro Shimizu 890ddd
			pixLeft = pix - 1, pixRight = pix;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			pixLeft = pix - m_wrap, pixRight = pixLeft - 1;
Toshihiro Shimizu 890ddd
	else if (m_dir.x > 0)
Toshihiro Shimizu 890ddd
		pixLeft = pix, pixRight = pix - m_wrap;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		pixRight = pix - 1, pixLeft = pixRight - m_wrap;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
inline void RasterEdgeIterator<pixelselector>::colors(</pixelselector>
Toshihiro Shimizu 890ddd
	value_type &leftColor, value_type &rightColor)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_dir.y)
Toshihiro Shimizu 890ddd
		if (m_dir.y > 0) {
Toshihiro Shimizu 890ddd
			if (m_pos.y > m_ly_1)
Toshihiro Shimizu 890ddd
				leftColor = rightColor = m_selector.transparent();
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				leftColor = (m_pos.x > 0) ? m_selector.value(*m_leftPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
				rightColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_rightPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (m_pos.y < 1)
Toshihiro Shimizu 890ddd
				leftColor = rightColor = m_selector.transparent();
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				leftColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_leftPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
				rightColor = (m_pos.x > 0) ? m_selector.value(*m_rightPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	else if (m_dir.x > 0) {
Toshihiro Shimizu 890ddd
		if (m_pos.x > m_lx_1)
Toshihiro Shimizu 890ddd
			leftColor = rightColor = m_selector.transparent();
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			leftColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_leftPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
			rightColor = (m_pos.y > 0) ? m_selector.value(*m_rightPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		if (m_pos.x < 1)
Toshihiro Shimizu 890ddd
			leftColor = rightColor = m_selector.transparent();
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			leftColor = (m_pos.y > 0) ? m_selector.value(*m_leftPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
			rightColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_rightPix) : m_selector.transparent();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
inline void RasterEdgeIterator<pixelselector>::turn(const value_type &newLeftColor, const value_type &newRightColor)</pixelselector>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_rightSide) {
Toshihiro Shimizu 890ddd
		if (newLeftColor == m_rightColor) {
Toshihiro Shimizu 890ddd
			if (newRightColor == m_leftColor)
Toshihiro Shimizu 890ddd
				turnAmbiguous(newLeftColor, newRightColor);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				turnLeft();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (newRightColor != m_rightColor)
Toshihiro Shimizu 890ddd
				turnRight();
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				m_turn = STRAIGHT;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_elbowColor = newLeftColor;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		if (newRightColor == m_leftColor) {
Toshihiro Shimizu 890ddd
			if (newLeftColor == m_rightColor)
Toshihiro Shimizu 890ddd
				turnAmbiguous(newLeftColor, newRightColor);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				turnRight();
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			if (newLeftColor != m_leftColor)
Toshihiro Shimizu 890ddd
				turnLeft();
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				m_turn = STRAIGHT;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_elbowColor = newRightColor;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pixels(m_leftPix, m_rightPix);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
inline void RasterEdgeIterator<pixelselector>::turnAmbiguous(</pixelselector>
Toshihiro Shimizu 890ddd
	const value_type &newLeftColor, const value_type &newRightColor)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x;
Toshihiro Shimizu 890ddd
	UCHAR count1 = 0, count2 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	value_type val;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Check the 4x4 neighbourhood and connect the minority color
Toshihiro Shimizu 890ddd
	if (m_pos.x > 2) {
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix - 2));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix - 2 - m_wrap));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_pos.x < m_lx_1) {
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix + 1));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix + 1 - m_wrap));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_pos.y > 2) {
Toshihiro Shimizu 890ddd
		int wrap2 = m_wrap << 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix - wrap2));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix - wrap2 - 1));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_pos.y < m_ly_1) {
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix + m_wrap));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		val = m_selector.value(*(pix + m_wrap - 1));
Toshihiro Shimizu 890ddd
		if (val == m_leftColor)
Toshihiro Shimizu 890ddd
			++count1;
Toshihiro Shimizu 890ddd
		else if (val == m_rightColor)
Toshihiro Shimizu 890ddd
			++count2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Minority connection - join the one with less count
Toshihiro Shimizu 890ddd
	if (count1 < count2)
Toshihiro Shimizu 890ddd
		turnRight(); // Join m_leftColor == newRightColor
Toshihiro Shimizu 890ddd
	else if (count1 > count2)
Toshihiro Shimizu 890ddd
		turnLeft(); // Join m_rightColor == newLeftColor
Toshihiro Shimizu 890ddd
	else if (m_rightColor < m_leftColor)
Toshihiro Shimizu 890ddd
		turnLeft();
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		turnRight();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_turn |= AMBIGUOUS;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixelselector=""></typename>
Toshihiro Shimizu 890ddd
RasterEdgeIterator<pixelselector> &RasterEdgeIterator<pixelselector>::operator++()</pixelselector></pixelselector>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	value_type newLeftColor = m_leftColor, newRightColor = m_rightColor;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int pixAdd = m_dir.y * m_wrap + m_dir.x;
Toshihiro Shimizu 890ddd
	if (m_rightSide) {
Toshihiro Shimizu 890ddd
		do {
Toshihiro Shimizu 890ddd
			m_pos.x += m_dir.x, m_pos.y += m_dir.y;
Toshihiro Shimizu 890ddd
			m_leftPix += pixAdd, m_rightPix += pixAdd;
Toshihiro Shimizu 890ddd
			m_leftColor = newLeftColor;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			colors(newLeftColor, newRightColor);
Toshihiro Shimizu 890ddd
		} while ((newRightColor == m_rightColor) && (newLeftColor != newRightColor) &&
Toshihiro Shimizu 890ddd
				 m_selector.skip(m_leftColor, newLeftColor));
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		do {
Toshihiro Shimizu 890ddd
			m_pos.x += m_dir.x, m_pos.y += m_dir.y;
Toshihiro Shimizu 890ddd
			m_leftPix += pixAdd, m_rightPix += pixAdd;
Toshihiro Shimizu 890ddd
			m_rightColor = newRightColor;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			colors(newLeftColor, newRightColor);
Toshihiro Shimizu 890ddd
		} while ((newLeftColor == m_leftColor) && (newLeftColor != newRightColor) &&
Toshihiro Shimizu 890ddd
				 m_selector.skip(m_rightColor, newRightColor));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	turn(newLeftColor, newRightColor);
Toshihiro Shimizu 890ddd
	colors(m_leftColor, m_rightColor);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
} //  namespace TRop::borders
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif // RASTER_EDGE_ITERATOR_HPP