| #pragma once |
| |
| #ifndef RASTER_EDGE_ITERATOR_HPP |
| #define RASTER_EDGE_ITERATOR_HPP |
| |
| #include "raster_edge_iterator.h" |
| |
| namespace TRop { |
| namespace borders { |
| |
| template <typename PixelSelector> |
| RasterEdgeIterator<PixelSelector>::RasterEdgeIterator( |
| const raster_typeP &rin, const selector_type &selector, const TPoint &pos, |
| const TPoint &dir, int adherence) |
| : 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) { |
| pixels(m_leftPix, m_rightPix); |
| colors(m_leftColor, m_rightColor); |
| } |
| |
| |
| |
| template <typename PixelSelector> |
| void RasterEdgeIterator<PixelSelector>::setEdge(const TPoint &pos, |
| const TPoint &dir) { |
| m_pos = pos, m_dir = dir; |
| pixels(m_leftPix, m_rightPix); |
| colors(m_leftColor, m_rightColor); |
| } |
| |
| |
| |
| template <typename PixelSelector> |
| inline void RasterEdgeIterator<PixelSelector>::pixels(pixel_type *&pixLeft, |
| pixel_type *&pixRight) { |
| pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x; |
| if (m_dir.y) |
| if (m_dir.y > 0) |
| pixLeft = pix - 1, pixRight = pix; |
| else |
| pixLeft = pix - m_wrap, pixRight = pixLeft - 1; |
| else if (m_dir.x > 0) |
| pixLeft = pix, pixRight = pix - m_wrap; |
| else |
| pixRight = pix - 1, pixLeft = pixRight - m_wrap; |
| } |
| |
| |
| |
| template <typename PixelSelector> |
| inline void RasterEdgeIterator<PixelSelector>::colors(value_type &leftColor, |
| value_type &rightColor) { |
| if (m_dir.y) |
| if (m_dir.y > 0) { |
| if (m_pos.y > m_ly_1) |
| leftColor = rightColor = m_selector.transparent(); |
| else { |
| leftColor = (m_pos.x > 0) ? m_selector.value(*m_leftPix) |
| : m_selector.transparent(); |
| rightColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_rightPix) |
| : m_selector.transparent(); |
| } |
| } else { |
| if (m_pos.y < 1) |
| leftColor = rightColor = m_selector.transparent(); |
| else { |
| leftColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_leftPix) |
| : m_selector.transparent(); |
| rightColor = (m_pos.x > 0) ? m_selector.value(*m_rightPix) |
| : m_selector.transparent(); |
| } |
| } |
| else if (m_dir.x > 0) { |
| if (m_pos.x > m_lx_1) |
| leftColor = rightColor = m_selector.transparent(); |
| else { |
| leftColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_leftPix) |
| : m_selector.transparent(); |
| rightColor = (m_pos.y > 0) ? m_selector.value(*m_rightPix) |
| : m_selector.transparent(); |
| } |
| } else { |
| if (m_pos.x < 1) |
| leftColor = rightColor = m_selector.transparent(); |
| else { |
| leftColor = (m_pos.y > 0) ? m_selector.value(*m_leftPix) |
| : m_selector.transparent(); |
| rightColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_rightPix) |
| : m_selector.transparent(); |
| } |
| } |
| } |
| |
| |
| |
| template <typename PixelSelector> |
| inline void RasterEdgeIterator<PixelSelector>::turn( |
| const value_type &newLeftColor, const value_type &newRightColor) { |
| if (m_rightSide) { |
| if (newLeftColor == m_rightColor) { |
| if (newRightColor == m_leftColor) |
| turnAmbiguous(newLeftColor, newRightColor); |
| else |
| turnLeft(); |
| } else { |
| if (newRightColor != m_rightColor) |
| turnRight(); |
| else |
| m_turn = STRAIGHT; |
| } |
| |
| m_elbowColor = newLeftColor; |
| } else { |
| if (newRightColor == m_leftColor) { |
| if (newLeftColor == m_rightColor) |
| turnAmbiguous(newLeftColor, newRightColor); |
| else |
| turnRight(); |
| } else { |
| if (newLeftColor != m_leftColor) |
| turnLeft(); |
| else |
| m_turn = STRAIGHT; |
| } |
| |
| m_elbowColor = newRightColor; |
| } |
| |
| pixels(m_leftPix, m_rightPix); |
| } |
| |
| |
| |
| template <typename PixelSelector> |
| inline void RasterEdgeIterator<PixelSelector>::turnAmbiguous( |
| const value_type &newLeftColor, const value_type &newRightColor) { |
| pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x; |
| UCHAR count1 = 0, count2 = 0; |
| |
| value_type val; |
| |
| |
| if (m_pos.x > 2) { |
| val = m_selector.value(*(pix - 2)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| |
| val = m_selector.value(*(pix - 2 - m_wrap)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| } |
| |
| if (m_pos.x < m_lx_1) { |
| val = m_selector.value(*(pix + 1)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| |
| val = m_selector.value(*(pix + 1 - m_wrap)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| } |
| |
| if (m_pos.y > 2) { |
| int wrap2 = m_wrap << 1; |
| |
| val = m_selector.value(*(pix - wrap2)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| |
| val = m_selector.value(*(pix - wrap2 - 1)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| } |
| |
| if (m_pos.y < m_ly_1) { |
| val = m_selector.value(*(pix + m_wrap)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| |
| val = m_selector.value(*(pix + m_wrap - 1)); |
| if (val == m_leftColor) |
| ++count1; |
| else if (val == m_rightColor) |
| ++count2; |
| } |
| |
| |
| if (count1 < count2) |
| turnRight(); |
| else if (count1 > count2) |
| turnLeft(); |
| else if (m_rightColor < m_leftColor) |
| turnLeft(); |
| else |
| turnRight(); |
| |
| m_turn |= AMBIGUOUS; |
| } |
| |
| |
| |
| template <typename PixelSelector> |
| RasterEdgeIterator<PixelSelector> |
| &RasterEdgeIterator<PixelSelector>::operator++() { |
| value_type newLeftColor = m_leftColor, newRightColor = m_rightColor; |
| |
| int pixAdd = m_dir.y * m_wrap + m_dir.x; |
| if (m_rightSide) { |
| do { |
| m_pos.x += m_dir.x, m_pos.y += m_dir.y; |
| m_leftPix += pixAdd, m_rightPix += pixAdd; |
| m_leftColor = newLeftColor; |
| |
| colors(newLeftColor, newRightColor); |
| } while ((newRightColor == m_rightColor) && |
| (newLeftColor != newRightColor) && |
| m_selector.skip(m_leftColor, newLeftColor)); |
| } else { |
| do { |
| m_pos.x += m_dir.x, m_pos.y += m_dir.y; |
| m_leftPix += pixAdd, m_rightPix += pixAdd; |
| m_rightColor = newRightColor; |
| |
| colors(newLeftColor, newRightColor); |
| } while ((newLeftColor == m_leftColor) && (newLeftColor != newRightColor) && |
| m_selector.skip(m_rightColor, newRightColor)); |
| } |
| |
| turn(newLeftColor, newRightColor); |
| colors(m_leftColor, m_rightColor); |
| |
| return *this; |
| } |
| } |
| } |
| |
| #endif |