2016-05-17 03:04:11 +12:00
|
|
|
#pragma once
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
#ifndef RUNSMAP_H
|
|
|
|
#define RUNSMAP_H
|
|
|
|
|
|
|
|
#include "traster.h"
|
|
|
|
|
|
|
|
//*********************************************************************************************************
|
|
|
|
// Run Maps
|
|
|
|
//*********************************************************************************************************
|
|
|
|
|
|
|
|
/*!
|
2016-06-15 18:43:10 +12:00
|
|
|
The RunsMapP is an auxiliary raster greymap type used to store run-length
|
2021-07-08 13:39:28 +12:00
|
|
|
information
|
2016-03-19 06:57:51 +13:00
|
|
|
about an image.
|
|
|
|
|
2021-07-08 13:39:28 +12:00
|
|
|
Not every image pixel has valid information. Only pixels corresponding to
|
2016-03-19 06:57:51 +13:00
|
|
|
run headers do, and those include the position of the next run header.
|
2016-06-15 18:43:10 +12:00
|
|
|
This means that users must always iterate from the beginning of a line to get
|
|
|
|
valid
|
2016-03-19 06:57:51 +13:00
|
|
|
data.
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
The following coding is adopted to extract the run length from the run
|
|
|
|
headers:
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
\li We'll use the last 2 bits only in the headers. With these, we can cover
|
|
|
|
directly
|
2016-03-19 06:57:51 +13:00
|
|
|
those runs up to 4 pixels length.
|
2016-06-15 18:43:10 +12:00
|
|
|
\li When the length >=4, we require that one byte is taken in the run to store
|
|
|
|
the length
|
2016-03-19 06:57:51 +13:00
|
|
|
up to 256 pixels.
|
2016-06-15 18:43:10 +12:00
|
|
|
\li When the length >= 256, we take 4 additional bytes to store the length
|
|
|
|
(which this time
|
2016-03-19 06:57:51 +13:00
|
|
|
could go up to billions).
|
|
|
|
|
|
|
|
Observe that the runsmap supports a symmetrical representation, useful
|
|
|
|
to traverse runs both forward and backwards. This means that 2 headers are
|
|
|
|
provided for each run, at the opposite ends (unless the run is 1 pixel-width).
|
|
|
|
*/
|
2016-06-29 18:17:12 +12:00
|
|
|
class RunsMap final : public TRasterT<TPixelGR8> {
|
2016-03-19 06:57:51 +13:00
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
RunsMap(int lx, int ly) : TRasterT<TPixelGR8>(lx, ly) { clear(); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
const UCHAR &runHeader(int x, int y) const { return pixels(y)[x].value; }
|
|
|
|
UCHAR &runHeader(int x, int y) { return pixels(y)[x].value; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TUINT32 runLength(const TPixelGR8 *run, bool reversed = false) const;
|
|
|
|
TUINT32 runLength(int x, int y, bool reversed = false) const {
|
|
|
|
return runLength(pixels(y) + x, reversed);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
void setRunLength(TPixelGR8 *run, TUINT32 length);
|
|
|
|
void setRunLength(int x, int y, TUINT32 length) {
|
|
|
|
setRunLength(pixels(y) + x, length);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------
|
|
|
|
|
2016-04-15 17:11:23 +12:00
|
|
|
#ifdef _WIN32
|
2016-03-19 06:57:51 +13:00
|
|
|
template class DV_EXPORT_API TSmartPointerT<RunsMap>;
|
|
|
|
#endif
|
|
|
|
|
2016-06-29 18:17:12 +12:00
|
|
|
class RunsMapP final : public TSmartPointerT<RunsMap> {
|
2016-03-19 06:57:51 +13:00
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
RunsMapP() {}
|
|
|
|
RunsMapP(int lx, int ly) : TSmartPointerT<RunsMap>(new RunsMap(lx, ly)) {}
|
|
|
|
RunsMapP(const TDimension &d)
|
|
|
|
: TSmartPointerT<RunsMap>(new RunsMap(d.lx, d.ly)) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
template <typename Pixel, typename PixelSelector>
|
2016-06-15 18:43:10 +12:00
|
|
|
void buildRunsMap(RunsMapP &runsMap, const TRasterPT<Pixel> &ras,
|
|
|
|
const PixelSelector &selector) {
|
|
|
|
// Traverse the raster, extracting run lengths
|
|
|
|
int y, ly = ras->getLy();
|
|
|
|
for (y = 0; y < ly; ++y) {
|
|
|
|
Pixel *lineStart = (Pixel *)ras->pixels(y),
|
|
|
|
*lineEnd = lineStart + ras->getLx();
|
|
|
|
|
|
|
|
Pixel *pix, *runStart;
|
|
|
|
typename PixelSelector::value_type colorIndex;
|
|
|
|
for (pix = runStart = lineStart, colorIndex = selector.value(*pix);
|
|
|
|
pix < lineEnd; ++pix)
|
|
|
|
if (selector.value(*pix) != colorIndex) {
|
|
|
|
runsMap->setRunLength(runStart - lineStart, y, pix - runStart);
|
|
|
|
runStart = pix;
|
|
|
|
colorIndex = selector.value(*pix);
|
|
|
|
}
|
|
|
|
runsMap->setRunLength(runStart - lineStart, y, pix - runStart);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
#endif // RUNSMAP_H
|