1 #pragma once
2 
3 #ifndef RUNSMAP_H
4 #define RUNSMAP_H
5 
6 #include "traster.h"
7 
8 //*********************************************************************************************************
9 //    Run Maps
10 //*********************************************************************************************************
11 
12 /*!
13   The RunsMapP is an auxiliary raster greymap type used to store run-length
14   informations
15   about an image.
16 
17   Not every image pixel has valid informations. Only pixels corresponding to
18   run headers do, and those include the position of the next run header.
19   This means that users must always iterate from the beginning of a line to get
20   valid
21   data.
22 
23   The following coding is adopted to extract the run length from the run
24   headers:
25 
26   \li We'll use the last 2 bits only in the headers. With these, we can cover
27   directly
28       those runs up to 4 pixels length.
29   \li When the length >=4, we require that one byte is taken in the run to store
30   the length
31       up to 256 pixels.
32   \li When the length >= 256, we take 4 additional bytes to store the length
33   (which this time
34       could go up to billions).
35 
36   Observe that the runsmap supports a symmetrical representation, useful
37   to traverse runs both forward and backwards. This means that 2 headers are
38   provided for each run, at the opposite ends (unless the run is 1 pixel-width).
39 */
40 class RunsMap final : public TRasterT<TPixelGR8> {
41 public:
RunsMap(int lx,int ly)42   RunsMap(int lx, int ly) : TRasterT<TPixelGR8>(lx, ly) { clear(); }
43 
runHeader(int x,int y)44   const UCHAR &runHeader(int x, int y) const { return pixels(y)[x].value; }
runHeader(int x,int y)45   UCHAR &runHeader(int x, int y) { return pixels(y)[x].value; }
46 
47   TUINT32 runLength(const TPixelGR8 *run, bool reversed = false) const;
48   TUINT32 runLength(int x, int y, bool reversed = false) const {
49     return runLength(pixels(y) + x, reversed);
50   }
51 
52 public:
53   void setRunLength(TPixelGR8 *run, TUINT32 length);
setRunLength(int x,int y,TUINT32 length)54   void setRunLength(int x, int y, TUINT32 length) {
55     setRunLength(pixels(y) + x, length);
56   }
57 };
58 
59 //---------------------------------------------------------------------------------------------
60 
61 #ifdef _WIN32
62 template class DV_EXPORT_API TSmartPointerT<RunsMap>;
63 #endif
64 
65 class RunsMapP final : public TSmartPointerT<RunsMap> {
66 public:
RunsMapP()67   RunsMapP() {}
RunsMapP(int lx,int ly)68   RunsMapP(int lx, int ly) : TSmartPointerT<RunsMap>(new RunsMap(lx, ly)) {}
RunsMapP(const TDimension & d)69   RunsMapP(const TDimension &d)
70       : TSmartPointerT<RunsMap>(new RunsMap(d.lx, d.ly)) {}
71 };
72 
73 //---------------------------------------------------------------------------------------------
74 
75 template <typename Pixel, typename PixelSelector>
buildRunsMap(RunsMapP & runsMap,const TRasterPT<Pixel> & ras,const PixelSelector & selector)76 void buildRunsMap(RunsMapP &runsMap, const TRasterPT<Pixel> &ras,
77                   const PixelSelector &selector) {
78   // Traverse the raster, extracting run lengths
79   int y, ly = ras->getLy();
80   for (y = 0; y < ly; ++y) {
81     Pixel *lineStart = (Pixel *)ras->pixels(y),
82           *lineEnd   = lineStart + ras->getLx();
83 
84     Pixel *pix, *runStart;
85     typename PixelSelector::value_type colorIndex;
86     for (pix = runStart = lineStart, colorIndex = selector.value(*pix);
87          pix < lineEnd; ++pix)
88       if (selector.value(*pix) != colorIndex) {
89         runsMap->setRunLength(runStart - lineStart, y, pix - runStart);
90         runStart   = pix;
91         colorIndex = selector.value(*pix);
92       }
93     runsMap->setRunLength(runStart - lineStart, y, pix - runStart);
94   }
95 }
96 
97 #endif  // RUNSMAP_H
98