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