#pragma once #ifndef RUNSMAP_H #define RUNSMAP_H #include "traster.h" //********************************************************************************************************* // Run Maps //********************************************************************************************************* /*! The RunsMapP is an auxiliary raster greymap type used to store run-length information about an image. Not every image pixel has valid information. Only pixels corresponding to run headers do, and those include the position of the next run header. This means that users must always iterate from the beginning of a line to get valid data. The following coding is adopted to extract the run length from the run headers: \li We'll use the last 2 bits only in the headers. With these, we can cover directly those runs up to 4 pixels length. \li When the length >=4, we require that one byte is taken in the run to store the length up to 256 pixels. \li When the length >= 256, we take 4 additional bytes to store the length (which this time 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). */ class RunsMap final : public TRasterT { public: RunsMap(int lx, int ly) : TRasterT(lx, ly) { clear(); } const UCHAR &runHeader(int x, int y) const { return pixels(y)[x].value; } UCHAR &runHeader(int x, int y) { return pixels(y)[x].value; } 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); } public: void setRunLength(TPixelGR8 *run, TUINT32 length); void setRunLength(int x, int y, TUINT32 length) { setRunLength(pixels(y) + x, length); } }; //--------------------------------------------------------------------------------------------- #ifdef _WIN32 template class DV_EXPORT_API TSmartPointerT; #endif class RunsMapP final : public TSmartPointerT { public: RunsMapP() {} RunsMapP(int lx, int ly) : TSmartPointerT(new RunsMap(lx, ly)) {} RunsMapP(const TDimension &d) : TSmartPointerT(new RunsMap(d.lx, d.ly)) {} }; //--------------------------------------------------------------------------------------------- template void buildRunsMap(RunsMapP &runsMap, const TRasterPT &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); } } #endif // RUNSMAP_H