tahoma2d/toonz/sources/common/trop/runsmap.h

98 lines
3.3 KiB
C
Raw Normal View History

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
information
2016-03-19 06:57:51 +13:00
about an image.
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).
*/
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
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