text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    $RCSfile: vtkImageToPolyDataFilter.h,v $
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       This software is distributed WITHOUT ANY WARRANTY; without even
       the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the above copyright notice for more information.
  
  =========================================================================*/
  // .NAME vtkImageToPolyDataFilter - generate linear primitives (vtkPolyData) from an image
  // .SECTION Description
  // vtkImageToPolyDataFilter converts raster data (i.e., an image) into
  // polygonal data (i.e., quads or n-sided polygons), with each polygon
  // assigned a constant color. This is useful for writers that generate vector
  // formats (i.e., CGM or PostScript). To use this filter, you specify how to
  // quantize the color (or whether to use an image with a lookup table), and
  // what style the output should be. The output is always polygons, but the
  // choice is n x m quads (where n and m define the input image dimensions)
  // "Pixelize" option; arbitrary polygons "Polygonalize" option; or variable
  // number of quads of constant color generated along scan lines "RunLength"
  // option.
  //
  // The algorithm quantizes color in order to create coherent regions that the
  // polygons can represent with good compression. By default, the input image
  // is quantized to 256 colors using a 3-3-2 bits for red-green-blue. However,
  // you can also supply a single component image and a lookup table, with the
  // single component assumed to be an index into the table.  (Note: a quantized
  // image can be generated with the filter vtkImageQuantizeRGBToIndex.) The
  // number of colors on output is equal to the number of colors in the input
  // lookup table (or 256 if the built in linear ramp is used).
  //
  // The output of the filter is polygons with a single color per polygon cell.
  // If the output style is set to "Polygonalize", the polygons may have an
  // large number of points (bounded by something like 2*(n+m)); and the
  // polygon may not be convex which may cause rendering problems on some
  // systems (use vtkTriangleFilter). Otherwise, each polygon will have four
  // vertices. The output also contains scalar data defining RGB color in
  // unsigned char form.
  //
  // .SECTION Caveats
  // The input linear lookup table must
  // be of the form of 3-component unsigned char.
  //
  // This filter defines constant cell colors. If you have a plotting
  // device that supports Gouraud shading (linear interpolation of color), then 
  // superior algorithms are available for generating polygons from images.
  //
  // Note that many plotting devices/formats support only a limited number of
  // colors.
  // 
  // .SECTION See Also
  // vtkCGMWriter vtkImageQuantizeRGBToIndex vtkTriangleFilter
  
  #ifndef __vtkImageToPolyDataFilter_h
  #define __vtkImageToPolyDataFilter_h
  
  #include "vtkPolyDataAlgorithm.h"
  
  #define VTK_STYLE_PIXELIZE 0
  #define VTK_STYLE_POLYGONALIZE 1
  #define VTK_STYLE_RUN_LENGTH 2
  
  #define VTK_COLOR_MODE_LUT 0
  #define VTK_COLOR_MODE_LINEAR_256 1
  
  class vtkAppendPolyData;
  class vtkDataArray;
  class vtkEdgeTable;
  class vtkIdTypeArray;
  class vtkIntArray;
  class vtkScalarsToColors;
  class vtkStructuredPoints;
  class vtkTimeStamp;
  class vtkUnsignedCharArray;
  
  class VTK_HYBRID_EXPORT vtkImageToPolyDataFilter : public vtkPolyDataAlgorithm
  {
  public:
    vtkTypeRevisionMacro(vtkImageToPolyDataFilter,vtkPolyDataAlgorithm);
    void PrintSelf(ostream& os, vtkIndent indent);
  
    // Description:
    // Instantiate object with initial number of colors 256.
    static vtkImageToPolyDataFilter* New();
  
    // Description:
    // Specify how to create the output. Pixelize means converting the image
    // to quad polygons with a constant color per quad. Polygonalize means
    // merging colors together into polygonal regions, and then smoothing
    // the regions (if smoothing is turned on). RunLength means creating
    // quad polygons that may encompass several pixels on a scan line. The
    // default behavior is Polygonalize.
    vtkSetClampMacro(OutputStyle,int,VTK_STYLE_PIXELIZE,VTK_STYLE_RUN_LENGTH);
    vtkGetMacro(OutputStyle,int);
    void SetOutputStyleToPixelize() 
      {this->SetOutputStyle(VTK_STYLE_PIXELIZE);};
    void SetOutputStyleToPolygonalize() 
      {this->SetOutputStyle(VTK_STYLE_POLYGONALIZE);};
    void SetOutputStyleToRunLength() 
      {this->SetOutputStyle(VTK_STYLE_RUN_LENGTH);};
  
    // Description:
    // Specify how to quantize color.
    vtkSetClampMacro(ColorMode,int,VTK_COLOR_MODE_LUT,VTK_COLOR_MODE_LINEAR_256);
    vtkGetMacro(ColorMode,int);
    void SetColorModeToLUT() 
      {this->SetColorMode(VTK_COLOR_MODE_LUT);};
    void SetColorModeToLinear256() 
      {this->SetColorMode(VTK_COLOR_MODE_LINEAR_256);};
  
    // Description:
    // Set/Get the vtkLookupTable to use. The lookup table is used when the
    // color mode is set to LUT and a single component scalar is input.
    virtual void SetLookupTable(vtkScalarsToColors*);
    vtkGetObjectMacro(LookupTable,vtkScalarsToColors);
  
    // Description:
    // If the output style is set to polygonalize, then you can control
    // whether to smooth boundaries.
    vtkSetMacro(Smoothing, int);
    vtkGetMacro(Smoothing, int);
    vtkBooleanMacro(Smoothing, int);
    
    // Description:
    // Specify the number of smoothing iterations to smooth polygons. (Only
    // in effect if output style is Polygonalize and smoothing is on.)
    vtkSetClampMacro(NumberOfSmoothingIterations,int,0,VTK_LARGE_INTEGER);
    vtkGetMacro(NumberOfSmoothingIterations,int);
    
    // Description:
    // Turn on/off whether the final polygons should be decimated.
    // whether to smooth boundaries.
    vtkSetMacro(Decimation, int);
    vtkGetMacro(Decimation, int);
    vtkBooleanMacro(Decimation, int);
    
    // Description:
    // Specify the error to use for decimation (if decimation is on).
    // The error is an absolute number--the image spacing and
    // dimensions are used to create points so the error should be
    // consistent with the image size.
    vtkSetClampMacro(DecimationError,double,0.0,VTK_DOUBLE_MAX);
    vtkGetMacro(DecimationError,double);
    
    // Description:
    // Specify the error value between two colors where the colors are 
    // considered the same. Only use this if the color mode uses the
    // default 256 table.
    vtkSetClampMacro(Error,int,0,VTK_LARGE_INTEGER);
    vtkGetMacro(Error,int);
  
    // Description:
    // Specify the size (n by n pixels) of the largest region to 
    // polygonalize. When the OutputStyle is set to VTK_STYLE_POLYGONALIZE,
    // large amounts of memory are used. In order to process large images,
    // the image is broken into pieces that are at most Size pixels in
    // width and height.
    vtkSetClampMacro(SubImageSize,int,10,VTK_LARGE_INTEGER);
    vtkGetMacro(SubImageSize,int);
    
  protected:
    vtkImageToPolyDataFilter();
    ~vtkImageToPolyDataFilter();
  
    virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
    virtual int FillInputPortInformation(int port, vtkInformation *info);
  
    int OutputStyle;
    int ColorMode;
    int Smoothing;
    int NumberOfSmoothingIterations;
    int Decimation;
    double DecimationError;
    int Error;
    int SubImageSize;
    vtkScalarsToColors *LookupTable;
  
    virtual void PixelizeImage(vtkUnsignedCharArray *pixels, int dims[3], 
                               double origin[3], double spacing[3], 
                               vtkPolyData *output);
    virtual void PolygonalizeImage(vtkUnsignedCharArray *pixels, int dims[3], 
                                   double origin[3], double spacing[3], 
                                   vtkPolyData *output);
    virtual void RunLengthImage(vtkUnsignedCharArray *pixels, int dims[3], 
                                double origin[3], double spacing[3], 
                                vtkPolyData *output);
  private:
    vtkUnsignedCharArray *Table;      // color table used to quantize points
    vtkTimeStamp         TableMTime;
    int                  *Visited;    // traverse & mark connected regions
    vtkUnsignedCharArray *PolyColors; // the colors of each region -> polygon
    vtkEdgeTable         *EdgeTable;  // keep track of intersection points
    vtkEdgeTable         *EdgeUseTable; // keep track of polygons use of edges
    vtkIntArray          *EdgeUses; //the two polygons that use an edge
                                    //and point id associated with edge (if any)
  
    vtkAppendPolyData    *Append;
  
    void BuildTable(unsigned char *inPixels);
    vtkUnsignedCharArray *QuantizeImage(vtkDataArray *inScalars, int numComp,
                                            int type, int dims[3], int ext[4]);
    int ProcessImage(vtkUnsignedCharArray *pixels, int dims[2]);
    int BuildEdges(vtkUnsignedCharArray *pixels, int dims[3], double origin[3],
                   double spacing[3], vtkUnsignedCharArray *pointDescr, 
                   vtkPolyData *edges);
    void BuildPolygons(vtkUnsignedCharArray *pointDescr, vtkPolyData *edges,
                       int numPolys, vtkUnsignedCharArray *polyColors);
    void SmoothEdges(vtkUnsignedCharArray *pointDescr, vtkPolyData *edges);
    void DecimateEdges(vtkPolyData *edges, vtkUnsignedCharArray *pointDescr,
                       double tol2);
    void GeneratePolygons(vtkPolyData *edges, int numPolys, vtkPolyData *output,
                          vtkUnsignedCharArray *polyColors,
                          vtkUnsignedCharArray *pointDescr);
    
    int GetNeighbors(unsigned char *ptr, int &i, int &j, int dims[3],
                     unsigned char *neighbors[4], int mode);
  
    void GetIJ(int id, int &i, int &j, int dims[3]);
    unsigned char *GetColor(unsigned char *rgb);
    int IsSameColor(unsigned char *p1, unsigned char *p2);
    
  private:
    vtkImageToPolyDataFilter(const vtkImageToPolyDataFilter&);  // Not implemented.
    void operator=(const vtkImageToPolyDataFilter&);  // Not implemented.
  };
  
  #endif
  