tahoma2d/toonz/sources/include/tcg/hpp/image_iterator.hpp

250 lines
7.1 KiB
C++
Raw Normal View History

2016-05-17 03:04:11 +12:00
#pragma once
2016-03-19 06:57:51 +13:00
#ifndef TCG_IMAGE_ITERATOR_HPP
#define TCG_IMAGE_ITERATOR_HPP
// tcg includes
#include "../image_iterator.h"
#include "../pixel_ops.h"
2016-06-15 18:43:10 +12:00
namespace tcg {
2016-03-19 06:57:51 +13:00
//***************************************************************************
// image_edge_iterator implementation
//***************************************************************************
template <typename It, _iei_adherence_policy _adherence>
template <typename Img>
2016-06-15 18:43:10 +12:00
image_edge_iterator<It, _adherence>::image_edge_iterator(const Img &img, int x,
int y, int dirX,
int dirY)
: m_lx_1(image_traits<Img>::width(img) - 1)
, m_ly_1(image_traits<Img>::height(img) - 1)
, m_wrap(image_traits<Img>::wrap(img))
, m_pos(x, y)
, m_dir(dirX, dirY)
, m_outsideColor(image_traits<Img>::outsideColor(img))
, m_elbowColor(m_outsideColor)
, m_pix(image_traits<Img>::pixel(img, x, y))
, m_turn(UNKNOWN) {
pixels(m_leftPix, m_rightPix);
colors(m_leftColor, m_rightColor);
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
2016-06-15 18:43:10 +12:00
inline void image_edge_iterator<It, _adherence>::pixels(iter pixLeft,
iter pixRight) {
if (m_dir.y)
if (m_dir.y > 0)
pixLeft = m_pix - 1, pixRight = m_pix;
else
pixLeft = m_pix - m_wrap, pixRight = pixLeft - 1;
else if (m_dir.x > 0)
pixLeft = m_pix, pixRight = m_pix - m_wrap;
else
pixRight = m_pix - 1, pixLeft = pixRight - m_wrap;
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
inline void image_edge_iterator<It, _adherence>::colors(
2016-06-15 18:43:10 +12:00
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_outsideColor;
else {
leftColor = (m_pos.x > 0) ? *m_leftPix : m_outsideColor;
rightColor = (m_pos.x <= m_lx_1) ? *m_rightPix : m_outsideColor;
}
} else {
if (m_pos.y < 1)
leftColor = rightColor = m_outsideColor;
else {
leftColor = (m_pos.x <= m_lx_1) ? *m_leftPix : m_outsideColor;
rightColor = (m_pos.x > 0) ? *m_rightPix : m_outsideColor;
}
}
else if (m_dir.x > 0) {
if (m_pos.x > m_lx_1)
leftColor = rightColor = m_outsideColor;
else {
leftColor = (m_pos.y <= m_ly_1) ? *m_leftPix : m_outsideColor;
rightColor = (m_pos.y > 0) ? *m_rightPix : m_outsideColor;
}
} else {
if (m_pos.x < 1)
leftColor = rightColor = m_outsideColor;
else {
leftColor = (m_pos.y > 0) ? *m_leftPix : m_outsideColor;
rightColor = (m_pos.y <= m_ly_1) ? *m_rightPix : m_outsideColor;
}
}
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
inline void image_edge_iterator<It, _adherence>::turn(
2016-06-15 18:43:10 +12:00
const value_type &newLeftColor, const value_type &newRightColor,
policy<RIGHT_ADHERENCE>) {
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;
pixels(m_leftPix, m_rightPix);
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
inline void image_edge_iterator<It, _adherence>::turn(
2016-06-15 18:43:10 +12:00
const value_type &newLeftColor, const value_type &newRightColor,
policy<LEFT_ADHERENCE>) {
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);
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
inline void image_edge_iterator<It, _adherence>::turnAmbiguous(
2016-06-15 18:43:10 +12:00
const value_type &newLeftColor, const value_type &newRightColor) {
UCHAR count1 = 0, count2 = 0;
value_type val;
// Check the 4x4 neighbourhood and connect the minority color
if (m_pos.x > 2) {
val = *(m_pix - 2);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
val = *(m_pix - 2 - m_wrap);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
}
if (m_pos.x < m_lx_1) {
val = *(m_pix + 1);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
val = *(m_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_pix - wrap2);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
val = *(m_pix - wrap2 - 1);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
}
if (m_pos.y < m_ly_1) {
val = *(m_pix + m_wrap);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
val = *(m_pix + m_wrap - 1);
if (val == m_leftColor)
++count1;
else if (val == m_rightColor)
++count2;
}
// Minority connection - join the one with less count
if (count1 <= count2)
turnRight(); // Join m_leftColor == newRightColor
else if (count1 > count2)
turnLeft(); // Join m_rightColor == newLeftColor
m_turn |= AMBIGUOUS;
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
2016-06-15 18:43:10 +12:00
void image_edge_iterator<It, _adherence>::advance(policy<RIGHT_ADHERENCE>) {
value_type newLeftColor = m_leftColor, newRightColor = m_rightColor;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int pixAdd = m_dir.y * m_wrap + m_dir.x;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
m_pos.x += m_dir.x, m_pos.y += m_dir.y;
m_pix += pixAdd, m_leftPix += pixAdd, m_rightPix += pixAdd;
m_leftColor = newLeftColor;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
colors(newLeftColor, newRightColor);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
turn(newLeftColor, newRightColor);
colors(m_leftColor, m_rightColor);
2016-03-19 06:57:51 +13:00
}
//---------------------------------------------------------------------------------------------
template <typename It, _iei_adherence_policy _adherence>
2016-06-15 18:43:10 +12:00
void image_edge_iterator<It, _adherence>::advance(policy<LEFT_ADHERENCE>) {
value_type newLeftColor = m_leftColor, newRightColor = m_rightColor;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int pixAdd = m_dir.y * m_wrap + m_dir.x;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
m_pos.x += m_dir.x, m_pos.y += m_dir.y;
m_pix += pixAdd, m_leftPix += pixAdd, m_rightPix += pixAdd;
m_rightColor = newRightColor;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
colors(newLeftColor, newRightColor);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
turn(newLeftColor, newRightColor);
colors(m_leftColor, m_rightColor);
2016-03-19 06:57:51 +13:00
}
2016-06-15 18:43:10 +12:00
} // namespace tcg
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
#endif // TCG_IMAGE_ITERATOR_HPP