1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageToPolyDataFilter.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 /**
16  * @class   vtkImageToPolyDataFilter
17  * @brief   generate linear primitives (vtkPolyData) from an image
18  *
19  * vtkImageToPolyDataFilter converts raster data (i.e., an image) into
20  * polygonal data (i.e., quads or n-sided polygons), with each polygon
21  * assigned a constant color. This is useful for writers that generate vector
22  * formats (i.e., CGM or PostScript). To use this filter, you specify how to
23  * quantize the color (or whether to use an image with a lookup table), and
24  * what style the output should be. The output is always polygons, but the
25  * choice is n x m quads (where n and m define the input image dimensions)
26  * "Pixelize" option; arbitrary polygons "Polygonalize" option; or variable
27  * number of quads of constant color generated along scan lines "RunLength"
28  * option.
29  *
30  * The algorithm quantizes color in order to create coherent regions that the
31  * polygons can represent with good compression. By default, the input image
32  * is quantized to 256 colors using a 3-3-2 bits for red-green-blue. However,
33  * you can also supply a single component image and a lookup table, with the
34  * single component assumed to be an index into the table.  (Note: a quantized
35  * image can be generated with the filter vtkImageQuantizeRGBToIndex.) The
36  * number of colors on output is equal to the number of colors in the input
37  * lookup table (or 256 if the built in linear ramp is used).
38  *
39  * The output of the filter is polygons with a single color per polygon cell.
40  * If the output style is set to "Polygonalize", the polygons may have an
41  * large number of points (bounded by something like 2*(n+m)); and the
42  * polygon may not be convex which may cause rendering problems on some
43  * systems (use vtkTriangleFilter). Otherwise, each polygon will have four
44  * vertices. The output also contains scalar data defining RGB color in
45  * unsigned char form.
46  *
47  * @warning
48  * The input linear lookup table must
49  * be of the form of 3-component unsigned char.
50  *
51  * @warning
52  * This filter defines constant cell colors. If you have a plotting
53  * device that supports Gouraud shading (linear interpolation of color), then
54  * superior algorithms are available for generating polygons from images.
55  *
56  * @warning
57  * Note that many plotting devices/formats support only a limited number of
58  * colors.
59  *
60  * @sa
61  * vtkCGMWriter vtkImageQuantizeRGBToIndex vtkTriangleFilter
62  */
63 
64 #ifndef vtkImageToPolyDataFilter_h
65 #define vtkImageToPolyDataFilter_h
66 
67 #include "vtkFiltersHybridModule.h" // For export macro
68 #include "vtkPolyDataAlgorithm.h"
69 
70 #define VTK_STYLE_PIXELIZE 0
71 #define VTK_STYLE_POLYGONALIZE 1
72 #define VTK_STYLE_RUN_LENGTH 2
73 
74 #define VTK_COLOR_MODE_LUT 0
75 #define VTK_COLOR_MODE_LINEAR_256 1
76 
77 class vtkDataArray;
78 class vtkEdgeTable;
79 class vtkIdTypeArray;
80 class vtkIntArray;
81 class vtkScalarsToColors;
82 class vtkStructuredPoints;
83 class vtkTimeStamp;
84 class vtkUnsignedCharArray;
85 
86 class VTKFILTERSHYBRID_EXPORT vtkImageToPolyDataFilter : public vtkPolyDataAlgorithm
87 {
88 public:
89   vtkTypeMacro(vtkImageToPolyDataFilter, vtkPolyDataAlgorithm);
90   void PrintSelf(ostream& os, vtkIndent indent) override;
91 
92   /**
93    * Instantiate object with initial number of colors 256.
94    */
95   static vtkImageToPolyDataFilter* New();
96 
97   ///@{
98   /**
99    * Specify how to create the output. Pixelize means converting the image
100    * to quad polygons with a constant color per quad. Polygonalize means
101    * merging colors together into polygonal regions, and then smoothing
102    * the regions (if smoothing is turned on). RunLength means creating
103    * quad polygons that may encompass several pixels on a scan line. The
104    * default behavior is Polygonalize.
105    */
106   vtkSetClampMacro(OutputStyle, int, VTK_STYLE_PIXELIZE, VTK_STYLE_RUN_LENGTH);
107   vtkGetMacro(OutputStyle, int);
SetOutputStyleToPixelize()108   void SetOutputStyleToPixelize() { this->SetOutputStyle(VTK_STYLE_PIXELIZE); }
SetOutputStyleToPolygonalize()109   void SetOutputStyleToPolygonalize() { this->SetOutputStyle(VTK_STYLE_POLYGONALIZE); }
SetOutputStyleToRunLength()110   void SetOutputStyleToRunLength() { this->SetOutputStyle(VTK_STYLE_RUN_LENGTH); }
111   ///@}
112 
113   ///@{
114   /**
115    * Specify how to quantize color.
116    */
117   vtkSetClampMacro(ColorMode, int, VTK_COLOR_MODE_LUT, VTK_COLOR_MODE_LINEAR_256);
118   vtkGetMacro(ColorMode, int);
SetColorModeToLUT()119   void SetColorModeToLUT() { this->SetColorMode(VTK_COLOR_MODE_LUT); }
SetColorModeToLinear256()120   void SetColorModeToLinear256() { this->SetColorMode(VTK_COLOR_MODE_LINEAR_256); }
121   ///@}
122 
123   ///@{
124   /**
125    * Set/Get the vtkLookupTable to use. The lookup table is used when the
126    * color mode is set to LUT and a single component scalar is input.
127    */
128   virtual void SetLookupTable(vtkScalarsToColors*);
129   vtkGetObjectMacro(LookupTable, vtkScalarsToColors);
130   ///@}
131 
132   ///@{
133   /**
134    * If the output style is set to polygonalize, then you can control
135    * whether to smooth boundaries.
136    */
137   vtkSetMacro(Smoothing, vtkTypeBool);
138   vtkGetMacro(Smoothing, vtkTypeBool);
139   vtkBooleanMacro(Smoothing, vtkTypeBool);
140   ///@}
141 
142   ///@{
143   /**
144    * Specify the number of smoothing iterations to smooth polygons. (Only
145    * in effect if output style is Polygonalize and smoothing is on.)
146    */
147   vtkSetClampMacro(NumberOfSmoothingIterations, int, 0, VTK_INT_MAX);
148   vtkGetMacro(NumberOfSmoothingIterations, int);
149   ///@}
150 
151   ///@{
152   /**
153    * Turn on/off whether the final polygons should be decimated.
154    * whether to smooth boundaries.
155    */
156   vtkSetMacro(Decimation, vtkTypeBool);
157   vtkGetMacro(Decimation, vtkTypeBool);
158   vtkBooleanMacro(Decimation, vtkTypeBool);
159   ///@}
160 
161   ///@{
162   /**
163    * Specify the error to use for decimation (if decimation is on).
164    * The error is an absolute number--the image spacing and
165    * dimensions are used to create points so the error should be
166    * consistent with the image size.
167    */
168   vtkSetClampMacro(DecimationError, double, 0.0, VTK_DOUBLE_MAX);
169   vtkGetMacro(DecimationError, double);
170   ///@}
171 
172   ///@{
173   /**
174    * Specify the error value between two colors where the colors are
175    * considered the same. Only use this if the color mode uses the
176    * default 256 table.
177    */
178   vtkSetClampMacro(Error, int, 0, VTK_INT_MAX);
179   vtkGetMacro(Error, int);
180   ///@}
181 
182   ///@{
183   /**
184    * Specify the size (n by n pixels) of the largest region to
185    * polygonalize. When the OutputStyle is set to VTK_STYLE_POLYGONALIZE,
186    * large amounts of memory are used. In order to process large images,
187    * the image is broken into pieces that are at most Size pixels in
188    * width and height.
189    */
190   vtkSetClampMacro(SubImageSize, int, 10, VTK_INT_MAX);
191   vtkGetMacro(SubImageSize, int);
192   ///@}
193 
194 protected:
195   vtkImageToPolyDataFilter();
196   ~vtkImageToPolyDataFilter() override;
197 
198   int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
199   int FillInputPortInformation(int port, vtkInformation* info) override;
200 
201   int OutputStyle;
202   int ColorMode;
203   vtkTypeBool Smoothing;
204   int NumberOfSmoothingIterations;
205   vtkTypeBool Decimation;
206   double DecimationError;
207   int Error;
208   int SubImageSize;
209   vtkScalarsToColors* LookupTable;
210 
211   virtual void PixelizeImage(vtkUnsignedCharArray* pixels, int dims[3], double origin[3],
212     double spacing[3], vtkPolyData* output);
213   virtual void PolygonalizeImage(vtkUnsignedCharArray* pixels, int dims[3], double origin[3],
214     double spacing[3], vtkPolyData* output);
215   virtual void RunLengthImage(vtkUnsignedCharArray* pixels, int dims[3], double origin[3],
216     double spacing[3], vtkPolyData* output);
217 
218 private:
219   vtkUnsignedCharArray* Table; // color table used to quantize points
220   vtkTimeStamp TableMTime;
221   int* Visited;                     // traverse & mark connected regions
222   vtkUnsignedCharArray* PolyColors; // the colors of each region -> polygon
223   vtkEdgeTable* EdgeTable;          // keep track of intersection points
224   vtkEdgeTable* EdgeUseTable;       // keep track of polygons use of edges
225   vtkIntArray* EdgeUses;            // the two polygons that use an edge
226                                     // and point id associated with edge (if any)
227 
228   void BuildTable(unsigned char* inPixels);
229   vtkUnsignedCharArray* QuantizeImage(
230     vtkDataArray* inScalars, int numComp, int type, int dims[3], int ext[4]);
231   int ProcessImage(vtkUnsignedCharArray* pixels, int dims[2]);
232   int BuildEdges(vtkUnsignedCharArray* pixels, int dims[3], double origin[3], double spacing[3],
233     vtkUnsignedCharArray* pointDescr, vtkPolyData* edges);
234   void BuildPolygons(vtkUnsignedCharArray* pointDescr, vtkPolyData* edges, int numPolys,
235     vtkUnsignedCharArray* polyColors);
236   void SmoothEdges(vtkUnsignedCharArray* pointDescr, vtkPolyData* edges);
237   void DecimateEdges(vtkPolyData* edges, vtkUnsignedCharArray* pointDescr, double tol2);
238   void GeneratePolygons(vtkPolyData* edges, int numPolys, vtkPolyData* output,
239     vtkUnsignedCharArray* polyColors, vtkUnsignedCharArray* pointDescr);
240 
241   int GetNeighbors(
242     unsigned char* ptr, int& i, int& j, int dims[3], unsigned char* neighbors[4], int mode);
243 
244   void GetIJ(int id, int& i, int& j, int dims[2]);
245   unsigned char* GetColor(unsigned char* rgb);
246   int IsSameColor(unsigned char* p1, unsigned char* p2);
247 
248 private:
249   vtkImageToPolyDataFilter(const vtkImageToPolyDataFilter&) = delete;
250   void operator=(const vtkImageToPolyDataFilter&) = delete;
251 };
252 
253 #endif
254