|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tropcm.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop_borders.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "pixelselectors.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "runsmap.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
#include "raster_edge_iterator.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "borders_extractor.h"
|
|
Toshihiro Shimizu |
890ddd |
#define INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// tcg includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/deleter_types.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// STL includes
|
|
Toshihiro Shimizu |
890ddd |
#include <deque></deque>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*============================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Explanation
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Despeckling is a noise-removal procedure which aims at eliminating small blots of color
|
|
Toshihiro Shimizu |
890ddd |
from an image.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
We will assume that speckles are recognized with uniform color (which means - image
|
|
Toshihiro Shimizu |
890ddd |
discretization should be externally performed).
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
We will currently assume that the despeckling procedure works only on the ink or paint plane of a
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32 instance, not both (should be extended in the future).
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The image is traversed to isolate regions with the same color and, if their area is
|
|
Toshihiro Shimizu |
890ddd |
below the specified threshold, they get removed or changed of color.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Color change looks at the area's neighbouring pixels for the most used color to use for
|
|
Toshihiro Shimizu |
890ddd |
replacement. If NO neighbouring color can be found, the area is made transparent.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
==============================================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace TRop::borders;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Pixel Selectors
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class InkSelectorCM32
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef TPixelCM32 pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef TUINT32 value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
InkSelectorCM32() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type transparent() const { return 0; }
|
|
Toshihiro Shimizu |
890ddd |
bool transparent(const pixel_type &pix) const { return value(pix) == 0; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type value(const pixel_type &pix) const { return pix.getInk(); }
|
|
Toshihiro Shimizu |
890ddd |
bool equal(const pixel_type &a, const pixel_type &b) const { return value(a) == value(b); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class InkSelectorRGBM
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
bool m_transparentIsWhite;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef PIXEL pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef CHANNEL value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
InkSelectorRGBM(bool transparentIsWhite) : m_transparentIsWhite(transparentIsWhite) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type transparent() const { return 0; }
|
|
Toshihiro Shimizu |
890ddd |
bool transparent(const pixel_type &pix) const { return value(pix) == 0; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type value(const pixel_type &pix) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_transparentIsWhite)
|
|
Toshihiro Shimizu |
890ddd |
return (pix == PIXEL::White) ? 0 : 1;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return (pix.m == 0) ? 0 : 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
bool equal(const pixel_type &a, const pixel_type &b) const { return value(a) == value(b); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class InkSelectorGR
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef PIXEL pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef CHANNEL value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
InkSelectorGR() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type transparent() const { return PIXEL::maxChannelValue; }
|
|
Toshihiro Shimizu |
890ddd |
bool transparent(const pixel_type &pix) const { return value(pix) == 0; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type value(const pixel_type &pix) const { return (pix.value == PIXEL::maxChannelValue) ? 0 : 1; }
|
|
Toshihiro Shimizu |
890ddd |
bool equal(const pixel_type &a, const pixel_type &b) const { return value(a) == value(b); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Border class
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct Border {
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tpoint> m_points;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
int m_x0, m_y0, m_x1, m_y1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Border() : m_x0((std::numeric_limits<int>::max)()), m_y0(m_x0), m_x1(-m_x0), m_y1(m_x1) {}</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void addPoint(const TPoint &p)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Update the region box
|
|
Toshihiro Shimizu |
890ddd |
if (p.x < m_x0)
|
|
Toshihiro Shimizu |
890ddd |
m_x0 = p.x;
|
|
Toshihiro Shimizu |
890ddd |
if (p.x > m_x1)
|
|
Toshihiro Shimizu |
890ddd |
m_x1 = p.x;
|
|
Toshihiro Shimizu |
890ddd |
if (p.y < m_y0)
|
|
Toshihiro Shimizu |
890ddd |
m_y0 = p.y;
|
|
Toshihiro Shimizu |
890ddd |
if (p.y > m_y1)
|
|
Toshihiro Shimizu |
890ddd |
m_y1 = p.y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Add the vertex
|
|
Toshihiro Shimizu |
890ddd |
m_points.push_back(p);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void clear()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_points.clear();
|
|
Toshihiro Shimizu |
890ddd |
m_x0 = (std::numeric_limits<int>::max)(), m_y0 = m_x0, m_x1 = -m_x0, m_y1 = m_x1;</int>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Base classes
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Borders Painter
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class BordersPainter
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef Pix pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Toshihiro Shimizu |
890ddd |
TRasterPT<pixel_type> m_ras;</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
RunsMapP m_runsMap;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
BordersPainter(const TRasterPT<pixel_type> &ras) : m_ras(ras) {}</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TRasterPT<pixel_type> &ras() { return m_ras; }</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
RunsMapP &runsMap() { return m_runsMap; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void paintLine(int x, int y0, int y1) const;
|
|
Toshihiro Shimizu |
890ddd |
void paintBorder(const Border &border) const;
|
|
Toshihiro Shimizu |
890ddd |
void paintBorders(const std::deque<border *=""> &borders) const</border>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
size_t i, size = borders.size();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < size; ++i)
|
|
Toshihiro Shimizu |
890ddd |
paintBorder(*borders[i]);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Toshihiro Shimizu |
890ddd |
virtual void paintPixel(pixel_type *pix) const = 0;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void BordersPainter<pix>::paintBorder(const Border &border) const</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<tpoint> &points = border.m_points;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
size_t i, size_1 = points.size() - 1;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < size_1; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
const TPoint &p = points[i];
|
|
Toshihiro Shimizu |
890ddd |
paintLine(p.x, p.y, points[i + 1].y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
paintLine(points[size_1].x, points[size_1].y, points[0].y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void BordersPainter<pix>::paintLine(int x, int y0, int y1) const</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
for (int j = y0; j < y1; ++j) {
|
|
Toshihiro Shimizu |
890ddd |
TPixelGR8 *runPix = m_runsMap->pixels(j) + x;
|
|
Toshihiro Shimizu |
890ddd |
int l, runLength = 0, hierarchy = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
do {
|
|
Toshihiro Shimizu |
890ddd |
if (runPix->value & TRop::borders::_HIERARCHY_INCREASE)
|
|
Toshihiro Shimizu |
890ddd |
++hierarchy;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Update vars
|
|
Toshihiro Shimizu |
890ddd |
runLength += l = m_runsMap->runLength(runPix);
|
|
Toshihiro Shimizu |
890ddd |
runPix += l;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((runPix - 1)->value & TRop::borders::_HIERARCHY_DECREASE)
|
|
Toshihiro Shimizu |
890ddd |
--hierarchy;
|
|
Toshihiro Shimizu |
890ddd |
} while (hierarchy > 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pixel_type *pix = m_ras->pixels(j) + x, *pixEnd = pix + runLength;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (; pix < pixEnd; ++pix)
|
|
Toshihiro Shimizu |
890ddd |
paintPixel(pix);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Despeckling Reader
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class DespecklingReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Toshihiro Shimizu |
890ddd |
std::deque<border *=""> m_borders;</border>
|
|
Toshihiro Shimizu |
890ddd |
Border m_border;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_sizeTol;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader(int sizeTol) : m_sizeTol(sizeTol) {}
|
|
Toshihiro Shimizu |
890ddd |
~DespecklingReader();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int sizeTol() const { return m_sizeTol; }
|
|
Toshihiro Shimizu |
890ddd |
bool isSpeckle(const Border &border)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return border.m_x1 - border.m_x0 <= m_sizeTol &&
|
|
Toshihiro Shimizu |
890ddd |
border.m_y1 - border.m_y0 <= m_sizeTol;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void openContainer(const TPoint &pos);
|
|
Toshihiro Shimizu |
890ddd |
void addElement(const TPoint &pos);
|
|
Toshihiro Shimizu |
890ddd |
virtual void closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const std::deque<border *=""> &borders() const { return m_borders; }</border>
|
|
Toshihiro Shimizu |
890ddd |
std::deque<border *=""> &borders() { return m_borders; }</border>
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::~DespecklingReader()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::for_each(m_borders.begin(), m_borders.end(), tcg::deleter<border>());</border>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void DespecklingReader::openContainer(const TPoint &pos)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_border.clear();
|
|
Toshihiro Shimizu |
890ddd |
m_border.addPoint(pos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void DespecklingReader::addElement(const TPoint &pos)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_border.addPoint(pos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void DespecklingReader::closeContainer()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (isSpeckle(m_border))
|
|
Toshihiro Shimizu |
890ddd |
m_borders.push_back(new Border(m_border));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Specialized classes
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Replace Painters
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class ReplacePainter : public BordersPainter<pix></pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typename ReplacePainter::pixel_type m_color;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter(const TRasterPT<typename replacepainter::pixel_type=""> &ras)</typename>
|
|
Toshihiro Shimizu |
890ddd |
: BordersPainter<pix>(ras) {}</pix>
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter(const TRasterPT<typename replacepainter::pixel_type=""> &ras, const typename ReplacePainter::pixel_type &color)</typename>
|
|
Toshihiro Shimizu |
890ddd |
: BordersPainter<pix>(ras), m_color(color) {}</pix>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const typename ReplacePainter::pixel_type &color() const { return m_color; }
|
|
Toshihiro Shimizu |
890ddd |
typename ReplacePainter::pixel_type &color() { return m_color; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void paintPixel(typename ReplacePainter::pixel_type *pix) const { *pix = m_color; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <>
|
|
Toshihiro Shimizu |
890ddd |
class ReplacePainter<tpixelcm32> : public BordersPainter<tpixelcm32></tpixelcm32></tpixelcm32>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 m_value;
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 m_keepMask;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter(const TRasterPT<pixel_type> &ras)</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
: BordersPainter<tpixelcm32>(ras), m_value(0), m_keepMask(0) {}</tpixelcm32>
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter(const TRasterPT<pixel_type> &ras, TUINT32 value, TUINT32 keepMask)</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
: BordersPainter<tpixelcm32>(ras), m_value(value), m_keepMask(keepMask) {}</tpixelcm32>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TUINT32 &value() const { return m_value; }
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 &value() { return m_value; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TUINT32 &keepMask() const { return m_keepMask; }
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 &keepMask() { return m_keepMask; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void paintPixel(pixel_type *pix) const { *pix = TPixelCM32(m_value | (pix->getValue() & m_keepMask)); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Isolated Despeckling
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class IsolatedReader : public DespecklingReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef typename PixelSelector::pixel_type pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef typename PixelSelector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
const PixelSelector &m_selector;
|
|
Toshihiro Shimizu |
890ddd |
bool m_ok;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
IsolatedReader(const PixelSelector &selector, int sizeTol);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void openContainer(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
void addElement(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
void closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
IsolatedReader<pixelselector>::IsolatedReader(const PixelSelector &selector, int sizeTol)</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
: DespecklingReader(sizeTol), m_selector(selector)
|
|
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 |
void IsolatedReader<pixelselector>::openContainer(const RasterEdgeIterator<pixelselector> &it)</pixelselector></pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_ok = (it.leftColor() == m_selector.transparent());
|
|
Toshihiro Shimizu |
890ddd |
if (!m_ok)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::openContainer(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void IsolatedReader<pixelselector>::addElement(const RasterEdgeIterator<pixelselector> &it)</pixelselector></pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_ok)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
m_ok = (it.leftColor() == m_selector.transparent());
|
|
Toshihiro Shimizu |
890ddd |
if (!m_ok)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::addElement(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void IsolatedReader<pixelselector>::closeContainer()</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_ok)
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Despeckling Mains
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
Applies despeckling (paint or removal of small blots of uniform color) to the image.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void doDespeckleRGBM(const TRasterPT<pixel> &ras, int sizeThreshold, bool transparentIsWhite)</pixel>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
InkSelectorRGBM<pixel, channel=""> selector(transparentIsWhite);</pixel,>
|
|
Toshihiro Shimizu |
890ddd |
IsolatedReader<inkselectorrgbm<pixel, channel="">> reader(selector, sizeThreshold);</inkselectorrgbm<pixel,>
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter<pixel> painter(ras, transparentIsWhite ? PIXEL::White : PIXEL::Transparent);</pixel>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::borders::readBorders(ras, selector, reader, &painter.runsMap());
|
|
Toshihiro Shimizu |
890ddd |
painter.paintBorders(reader.borders());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void doDespeckleGR(const TRasterPT<pixel> &ras, int sizeThreshold)</pixel>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
InkSelectorGR<pixel, channel=""> selector;</pixel,>
|
|
Toshihiro Shimizu |
890ddd |
IsolatedReader<inkselectorgr<pixel, channel="">> reader(selector, sizeThreshold);</inkselectorgr<pixel,>
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter<pixel> painter(ras, PIXEL::maxChannelValue);</pixel>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::borders::readBorders(ras, selector, reader, &painter.runsMap());
|
|
Toshihiro Shimizu |
890ddd |
painter.paintBorders(reader.borders());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void doDespeckleCM32(const TRasterPT<tpixelcm32> &ras, int sizeThreshold, bool check)</tpixelcm32>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P rasCM(ras);
|
|
Toshihiro Shimizu |
890ddd |
rasCM->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
InkSelectorCM32 selector;
|
|
Toshihiro Shimizu |
890ddd |
IsolatedReader<inkselectorcm32> reader(selector, sizeThreshold);</inkselectorcm32>
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter<tpixelcm32> painter(rasCM, check ? 0xffffff00 : 0x000000ff, 0); // 0xffffff00 is a special non-mapped full ink pixel</tpixelcm32>
|
|
Toshihiro Shimizu |
890ddd |
// 0x000000ff is a full transparent paint pixel
|
|
Toshihiro Shimizu |
890ddd |
TRop::borders::readBorders(rasCM, selector, reader, &painter.runsMap());
|
|
Toshihiro Shimizu |
890ddd |
painter.paintBorders(reader.borders());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rasCM->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TRop::despeckle(const TRasterP &ras, int sizeThreshold, bool check, bool transparentIsWhite)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
ras->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (TRasterCM32P(ras)) {
|
|
Toshihiro Shimizu |
890ddd |
doDespeckleCM32(ras, sizeThreshold, check);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (TRaster32P(ras)) {
|
|
Toshihiro Shimizu |
890ddd |
doDespeckleRGBM<tpixel32, uchar="">(ras, sizeThreshold, transparentIsWhite);</tpixel32,>
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (TRaster64P(ras)) {
|
|
Toshihiro Shimizu |
890ddd |
doDespeckleRGBM<tpixel64, ushort="">(ras, sizeThreshold, transparentIsWhite);</tpixel64,>
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (TRasterGR8P(ras)) {
|
|
Toshihiro Shimizu |
890ddd |
doDespeckleGR<tpixelgr8, uchar="">(ras, sizeThreshold);</tpixelgr8,>
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (TRasterGR16P(ras)) {
|
|
Toshihiro Shimizu |
890ddd |
doDespeckleGR<tpixelgr16, ushort="">(ras, sizeThreshold);</tpixelgr16,>
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
Performs a copy of rin and then applies despeckling.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
void TRop::despeckle(const TRasterP &rout, const TRasterP &rin, int sizeThreshold, bool check)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRop::copy(rout, rin);
|
|
Toshihiro Shimizu |
890ddd |
TRop::despeckle(rout, sizeThreshold, check);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Majority Despeckling
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class FillingReader : public DespecklingReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef typename PixelSelector::pixel_type pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef typename PixelSelector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter<tpixelgr8> m_painter;</tpixelgr8>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
FillingReader(const TRasterGR8P &rasGR, int sizeTol)
|
|
Toshihiro Shimizu |
890ddd |
: DespecklingReader(sizeTol), m_painter(rasGR, TPixelGR8::Black) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void openContainer(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
void addElement(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
void closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RunsMapP &runsMap() { return m_painter.runsMap(); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void FillingReader<pixelselector>::openContainer(const RasterEdgeIterator<pixelselector> &it)</pixelselector></pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::openContainer(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void FillingReader<pixelselector>::addElement(const RasterEdgeIterator<pixelselector> &it)</pixelselector></pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::addElement(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void FillingReader<pixelselector>::closeContainer()</pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (isSpeckle(m_border))
|
|
Toshihiro Shimizu |
890ddd |
m_painter.paintBorder(m_border);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DespecklingReader::closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline TPoint direction(const TPoint &a, const TPoint &b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return TPoint((b.x > a.x) ? 1 : (b.x < a.x) ? -1 : 0,
|
|
Toshihiro Shimizu |
890ddd |
(b.y > a.y) ? 1 : (b.y < a.y) ? -1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixel,="" pixelselector="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
bool majority(const TRasterPT<pixel> ras, const TRasterGR8P &rasGR,</pixel>
|
|
Toshihiro Shimizu |
890ddd |
const PixelSelector &selector, const Border &border,
|
|
Toshihiro Shimizu |
890ddd |
typename PixelSelector::value_type &color)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef typename PixelSelector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build a histogram of all found colors around the border
|
|
Toshihiro Shimizu |
890ddd |
std::map<value_type, int=""> histogram;</value_type,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Pixel *pix, *basePix = ras->pixels(0);
|
|
Toshihiro Shimizu |
890ddd |
TPixelGR8 *grPix;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int diff, x, y, lx = ras->getLx(), ly = ras->getLy(), wrap = ras->getWrap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(border.m_points[1].y > border.m_points[0].y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Iterate the raster along the border
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<tpoint> &points = border.m_points;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RasterEdgeIterator<pixelselector></pixelselector>
|
|
Toshihiro Shimizu |
890ddd |
start(ras, selector, points[0], direction(points[0], points[1])),
|
|
Toshihiro Shimizu |
890ddd |
it(start);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
size_t next = 1, size = points.size();
|
|
Toshihiro Shimizu |
890ddd |
do {
|
|
Toshihiro Shimizu |
890ddd |
while (it.pos() != points[next]) {
|
|
Toshihiro Shimizu |
890ddd |
pix = it.leftPix();
|
|
Toshihiro Shimizu |
890ddd |
diff = pix - basePix;
|
|
Toshihiro Shimizu |
890ddd |
x = diff % wrap;
|
|
Toshihiro Shimizu |
890ddd |
y = diff / wrap;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (x >= 0 && y >= 0 && x < lx && y < ly) {
|
|
Toshihiro Shimizu |
890ddd |
grPix = rasGR->pixels(y) + x;
|
|
Toshihiro Shimizu |
890ddd |
if (grPix->value)
|
|
Toshihiro Shimizu |
890ddd |
++histogram[it.leftColor()];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
it.setEdge(it.pos() + it.dir(), it.dir());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
next = (next + 1) % size;
|
|
Toshihiro Shimizu |
890ddd |
it.setEdge(it.pos(), direction(it.pos(), points[next]));
|
|
Toshihiro Shimizu |
890ddd |
} while (it != start);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!histogram.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
//Return the most found color
|
|
Toshihiro Shimizu |
890ddd |
color = histogram.begin()->first;
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void majorityDespeckle(const TRasterPT<pix> &ras, int sizeThreshold)</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef typename TRop::borders::PixelSelector<pix> pixel_selector;</pix>
|
|
Toshihiro Shimizu |
890ddd |
typedef typename pixel_selector::pixel_type pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef typename pixel_selector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ras->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Use a temporary bitmap (well, a bytemap - for now?) to store the found speckles
|
|
Toshihiro Shimizu |
890ddd |
TRasterGR8P rasGR(ras->getSize());
|
|
Toshihiro Shimizu |
890ddd |
rasGR->fill(TPixelGR8::White);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Find the speckles and draw them on the bitmap
|
|
Toshihiro Shimizu |
890ddd |
pixel_selector selector;
|
|
Toshihiro Shimizu |
890ddd |
FillingReader<pixel_selector> reader(rasGR, sizeThreshold);</pixel_selector>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::borders::readBorders(ras, selector, reader, &reader.runsMap());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Now, operate each speckle. Try to apply a majority color to the speckle
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter<pixel_type> painter(ras);</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
painter.runsMap() = reader.runsMap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ReplacePainter<tpixelgr8> painterGR(rasGR, TPixelGR8::White);</tpixelgr8>
|
|
Toshihiro Shimizu |
890ddd |
painterGR.runsMap() = reader.runsMap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::deque<border *=""> borders = reader.borders(); //Note that the DEEP copy is NEEDED</border>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int processedCount = 1;
|
|
Toshihiro Shimizu |
890ddd |
while (processedCount > 0 && !borders.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
processedCount = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Traverse the speckles list. Try to apply majority.
|
|
Toshihiro Shimizu |
890ddd |
Border *current, *last = borders.back();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
do {
|
|
Toshihiro Shimizu |
890ddd |
current = borders.front();
|
|
Toshihiro Shimizu |
890ddd |
borders.pop_front();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
value_type color;
|
|
Toshihiro Shimizu |
890ddd |
if (majority(ras, rasGR, selector, *current, color)) {
|
|
Toshihiro Shimizu |
890ddd |
++processedCount;
|
|
Toshihiro Shimizu |
890ddd |
painter.color() = color;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
painter.paintBorder(*current);
|
|
Toshihiro Shimizu |
890ddd |
painterGR.paintBorder(*current);
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
borders.push_back(current);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} while (current != last);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Speckles may remain. In this case, fill with transparent.
|
|
Toshihiro Shimizu |
890ddd |
painter.color() = selector.transparent();
|
|
Toshihiro Shimizu |
890ddd |
while (!borders.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
Border *current = borders.front();
|
|
Toshihiro Shimizu |
890ddd |
painter.paintBorder(*current);
|
|
Toshihiro Shimizu |
890ddd |
borders.pop_front();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//================================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TRop::majorityDespeckle(const TRasterP &ras, int sizeThreshold)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P ras32(ras);
|
|
Toshihiro Shimizu |
890ddd |
if (ras32) {
|
|
Toshihiro Shimizu |
890ddd |
::majorityDespeckle(ras32, sizeThreshold);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRaster64P ras64(ras);
|
|
Toshihiro Shimizu |
890ddd |
if (ras64) {
|
|
Toshihiro Shimizu |
890ddd |
::majorityDespeckle(ras64, sizeThreshold);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterGR8P rasGR8(ras);
|
|
Toshihiro Shimizu |
890ddd |
if (rasGR8) {
|
|
Toshihiro Shimizu |
890ddd |
::majorityDespeckle(rasGR8, sizeThreshold);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterGR16P rasGR16(ras);
|
|
Toshihiro Shimizu |
890ddd |
if (rasGR16) {
|
|
Toshihiro Shimizu |
890ddd |
::majorityDespeckle(rasGR16, sizeThreshold);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P rasCM32(ras);
|
|
Toshihiro Shimizu |
890ddd |
if (rasCM32) {
|
|
Toshihiro Shimizu |
890ddd |
//Not yet implemented
|
|
Toshihiro Shimizu |
890ddd |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//::majorityDespeckleCM(rasCM32, sizeThreshold, toneTol);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|