1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageQuantizeRGBToIndex.cxx
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 #include "vtkImageQuantizeRGBToIndex.h"
16 
17 #include "vtkImageData.h"
18 #include "vtkLookupTable.h"
19 #include "vtkInformation.h"
20 #include "vtkInformationVector.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkStreamingDemandDrivenPipeline.h"
23 #include "vtkTimerLog.h"
24 
25 #include <math.h>
26 
27 vtkStandardNewMacro(vtkImageQuantizeRGBToIndex);
28 
29 class vtkColorQuantizeNode
30 {
31 public:
vtkColorQuantizeNode()32   vtkColorQuantizeNode()
33     { this->Axis = -1; this->SplitPoint = -1; this->Index = -1;
34       this->Child1 = NULL; this->Child2 = NULL;
35       this->StdDev[0] = this->StdDev[1] = this->StdDev[2] = 0.0;
36       this->Histogram[0] = this->Histogram[1] = this->Histogram[2] = NULL;
37       this->Image = NULL;
38       this->Bounds[0] = 0; this->Bounds[1] = 256;
39       this->Bounds[2] = 0; this->Bounds[3] = 256;
40       this->Bounds[4] = 0; this->Bounds[5] = 256; };
41 
~vtkColorQuantizeNode()42   ~vtkColorQuantizeNode()
43     { delete []this->Histogram[0];
44       delete []this->Histogram[1];
45       delete []this->Histogram[2];
46       delete this->Child1;
47       delete this->Child2; };
48 
SetImageExtent(int v[6])49   void SetImageExtent( int v[6] )
50     { memcpy( this->ImageExtent, v, 6*sizeof(int) ); };
51 
SetImageIncrement(vtkIdType v[3])52   void SetImageIncrement( vtkIdType v[3] )
53     { memcpy( this->ImageIncrement, v, 3*sizeof(vtkIdType) ); };
54 
SetImageType(double type)55   void SetImageType(double type)
56     {
57       this->ImageType = static_cast<int>(type);
58     }
59 
SetImage(void * image)60   void SetImage( void *image ) { this->Image = image; };
61 
GetAxis()62   int  GetAxis(       ) { return this->Axis; };
SetAxis(int v)63   void SetAxis( int v ) { this->Axis = v; };
64 
GetSplitPoint()65   int  GetSplitPoint(       ) { return this->SplitPoint; };
SetSplitPoint(int v)66   void SetSplitPoint( int v ) { this->SplitPoint = v; };
67 
GetBounds()68   int *GetBounds(          ) { return this->Bounds; };
SetBounds(int v[6])69   void SetBounds( int v[6] ) { memcpy( this->Bounds, v, 6*sizeof(int) ); };
70 
GetIndex()71   int  GetIndex(       ) { return this->Index; };
SetIndex(int v)72   void SetIndex( int v ) { this->Index = v; };
73 
GetStdDev(int axis)74   double GetStdDev( int axis ) { return this->StdDev[axis]; };
75   void  ComputeStdDev();
76 
GetCount()77   int GetCount() { return this->Count; };
78 
GetMean(int axis)79   double GetMean( int axis ) { return this->Mean[axis]; };
80 
81   void Divide( int axis, int nextIndex );
82 
GetChild1()83   vtkColorQuantizeNode *GetChild1() { return this->Child1; };
SetChild1(vtkColorQuantizeNode * n)84   void SetChild1( vtkColorQuantizeNode *n ) { this->Child1 = n; };
85 
GetChild2()86   vtkColorQuantizeNode *GetChild2() { return this->Child2; };
SetChild2(vtkColorQuantizeNode * n)87   void SetChild2( vtkColorQuantizeNode *n ) { this->Child2 = n; };
88 
GetIndex(int c[3])89   int GetIndex( int c[3] )
90     {  if ( this->Index>=0 ) {return this->Index;}
91        if ( c[this->Axis]>this->SplitPoint )
92          {return this->Child2->GetIndex(c);}
93        return this->Child1->GetIndex(c); };
94 
95 
GetAverageColor(int c[3])96   void GetAverageColor(int c[3])
97     {
98       if(this->AverageCount)
99         {
100         c[0] = static_cast<int>(this->AverageColor[0] / this->AverageCount);
101         c[1] = static_cast<int>(this->AverageColor[1] / this->AverageCount);
102         c[2] = static_cast<int>(this->AverageColor[2] / this->AverageCount);
103         }
104     }
105 
StartColorAveraging()106   void StartColorAveraging()
107     {if (this->Child1)
108       {
109       this->Child1->StartColorAveraging(); this->Child2->StartColorAveraging();
110       }
111     else
112       {
113       this->AverageCount = 0;
114       this->AverageColor[0] =
115         this->AverageColor[1] = this->AverageColor[2] = 0.0;
116       }
117     };
118 
AddColor(int c[3])119   void AddColor( int c[3] )
120     { this->AverageCount++; this->AverageColor[0] += c[0];
121       this->AverageColor[1] += c[1]; this->AverageColor[2] += c[2]; };
122 
123 protected:
124   int                  Axis;
125   int                  SplitPoint;
126   int                  Bounds[6];
127   int                  Index;
128   double                StdDev[3];
129   double                Median[3];
130   double                Mean[3];
131   int                  Count;
132   int                  AverageCount;
133   double                AverageColor[3];
134   vtkIdType            ImageIncrement[3];
135   int                  ImageExtent[6];
136   int                  ImageType;
137   void                 *Image;
138   int                  *Histogram[3];
139   vtkColorQuantizeNode *Child1, *Child2;
140 };
141 
142 template <class T>
vtkImageQuantizeRGBToIndexHistogram(T * inPtr,int extent[6],vtkIdType inIncrement[3],int type,int bounds[6],int * histogram[3])143 void vtkImageQuantizeRGBToIndexHistogram( T *inPtr, int extent[6],
144                                           vtkIdType inIncrement[3], int type,
145                                           int bounds[6], int *histogram[3] )
146 {
147   T      *rgbPtr, v[3];
148   int    x, y, z, c;
149   int    value[3];
150   int    max[3];
151 
152   max[0] = bounds[1] - bounds[0] + 1;
153   max[1] = bounds[3] - bounds[2] + 1;
154   max[2] = bounds[5] - bounds[4] + 1;
155 
156   for ( c = 0; c < 3; c++ )
157     {
158     for ( x = 0; x < max[c]; x++ )
159       {
160       histogram[c][x] = 0;
161       }
162     }
163 
164   // Generate the histogram
165   rgbPtr = inPtr;
166   for (z = extent[4]; z <= extent[5]; z++)
167     {
168     for (y = extent[2]; y <= extent[3]; y++)
169       {
170       for (x = extent[0]; x <= extent[1]; x++)
171         {
172         if ( type == VTK_UNSIGNED_CHAR )
173           {
174           v[0] = *(rgbPtr++) - bounds[0];
175           v[1] = *(rgbPtr++) - bounds[2];
176           v[2] = *(rgbPtr++) - bounds[4];
177           if ( static_cast<int>(v[0]) < max[0] &&
178                static_cast<int>(v[1]) < max[1] &&
179                static_cast<int>(v[2]) < max[2] )
180             {
181             histogram[0][static_cast<unsigned char>(v[0])]++;
182             histogram[1][static_cast<unsigned char>(v[1])]++;
183             histogram[2][static_cast<unsigned char>(v[2])]++;
184             }
185           }
186         else if ( type == VTK_UNSIGNED_SHORT )
187           {
188           v[0] = ((static_cast<unsigned short>(*(rgbPtr++)))>>8) - bounds[0];
189           v[1] = ((static_cast<unsigned short>(*(rgbPtr++)))>>8) - bounds[2];
190           v[2] = ((static_cast<unsigned short>(*(rgbPtr++)))>>8) - bounds[4];
191           if (static_cast<int>(v[0]) < max[0] &&
192               static_cast<int>(v[1]) < max[1] &&
193               static_cast<int>(v[2]) < max[2] )
194             {
195             histogram[0][static_cast<unsigned short>(v[0])]++;
196             histogram[1][static_cast<unsigned short>(v[1])]++;
197             histogram[2][static_cast<unsigned short>(v[2])]++;
198             }
199           }
200         else
201           {
202           value[0] = static_cast<int>( *(rgbPtr++) * 255.5 ) - bounds[0];
203           value[1] = static_cast<int>( *(rgbPtr++) * 255.5 ) - bounds[2];
204           value[2] = static_cast<int>( *(rgbPtr++) * 255.5 ) - bounds[4];
205           if ( static_cast<int>(value[0]) < max[0] &&
206                static_cast<int>(value[1]) < max[1] &&
207                static_cast<int>(value[2]) < max[2] )
208             {
209             histogram[0][value[0]]++;
210             histogram[1][value[1]]++;
211             histogram[2][value[2]]++;
212             }
213           }
214         rgbPtr += inIncrement[0];
215         }
216       rgbPtr += inIncrement[1];
217       }
218     rgbPtr += inIncrement[2];
219     }
220 }
221 
222 // This templated function executes the filter for supported types of data.
223 template <class T>
vtkImageQuantizeRGBToIndexExecute(vtkImageQuantizeRGBToIndex * self,vtkImageData * inData,T * inPtr,vtkImageData * outData,unsigned short * outPtr)224 void vtkImageQuantizeRGBToIndexExecute(vtkImageQuantizeRGBToIndex *self,
225                                        vtkImageData *inData, T *inPtr,
226                                        vtkImageData *outData,
227                                        unsigned short *outPtr)
228 {
229   int                  extent[6];
230   vtkIdType            inIncrement[3], outIncrement[3];
231   T                    *rgbPtr;
232   unsigned short       *indexPtr;
233   int                  x, y, z, c;
234   int                  type;
235   vtkColorQuantizeNode *root, *tmp;
236   vtkColorQuantizeNode *leafNodes[65536];
237   int                  numLeafNodes;
238   int                  maxdevAxis = 0, maxdevLeafNode = 0;
239   double                maxdev, dev;
240   int                  leaf, axis;
241   int                  cannotDivideFurther;
242   vtkLookupTable       *lut;
243   double                color[4];
244   int                  rgb[3];
245   vtkTimerLog          *timer;
246   int                  totalCount;
247   double                weight;
248   int                  done=0;
249 
250   timer = vtkTimerLog::New();
251   timer->StartTimer();
252   type = self->GetInputType();
253 
254   // need extent to get increments.
255   // in and out extents are the same
256   inData->GetExtent( extent );
257 
258   inData->GetContinuousIncrements(extent, inIncrement[0],
259                                   inIncrement[1], inIncrement[2]);
260   outData->GetContinuousIncrements(extent, outIncrement[0],
261                                   outIncrement[1], outIncrement[2]);
262 
263   timer->StopTimer();
264 
265   self->SetInitializeExecuteTime( timer->GetElapsedTime() );
266   timer->StartTimer();
267 
268   // Build the tree
269   // Create the root node - it is our only leaf node
270   root = new vtkColorQuantizeNode;
271   root->SetIndex( 0 );
272   root->SetImageExtent( extent );
273   root->SetImageIncrement( inIncrement );
274   root->SetImageType( type );
275   root->SetImage( inPtr );
276   root->ComputeStdDev();
277   leafNodes[0] = root;
278   numLeafNodes = 1;
279 
280   cannotDivideFurther = 0;
281 
282   totalCount =
283     (extent[1] - extent[0] + 1) *
284     (extent[3] - extent[2] + 1) *
285     (extent[5] - extent[4] + 1);
286 
287   // Loop until we've added enough leaf nodes or we can't add any more
288   while ( numLeafNodes < self->GetNumberOfColors() && !cannotDivideFurther )
289     {
290     // Find leaf node / axis with maximum deviation
291     maxdev = 0.0;
292     for ( leaf = 0; leaf < numLeafNodes; leaf++ )
293       {
294       for ( axis = 0; axis < 3; axis++ )
295         {
296         dev = leafNodes[leaf]->GetStdDev( axis );
297         weight = static_cast<double>(leafNodes[leaf]->GetCount())
298           /static_cast<double>(totalCount);
299         dev *= weight;
300         if ( dev > maxdev )
301           {
302           maxdevAxis     = axis;
303           maxdevLeafNode = leaf;
304           maxdev         = dev;
305           }
306         }
307       }
308     if ( maxdev == 0.0 )
309       {
310       cannotDivideFurther = 1;
311       }
312     else
313       {
314       leafNodes[maxdevLeafNode]->Divide( maxdevAxis, numLeafNodes );
315       leafNodes[numLeafNodes]   = leafNodes[maxdevLeafNode]->GetChild1();
316       leafNodes[maxdevLeafNode] = leafNodes[maxdevLeafNode]->GetChild2();
317       numLeafNodes++;
318       }
319 
320     self->UpdateProgress(0.6667*numLeafNodes/self->GetNumberOfColors());
321     }
322 
323   timer->StopTimer();
324   self->SetBuildTreeExecuteTime( timer->GetElapsedTime() );
325   timer->StartTimer();
326 
327   root->StartColorAveraging();
328 
329   // Fill in the indices in the output image
330   indexPtr = outPtr;
331   rgbPtr   = inPtr;
332   for (z = extent[4]; z <= extent[5]; z++)
333     {
334     for (y = extent[2]; !self->AbortExecute && y <= extent[3]; y++)
335       {
336       for (x = extent[0]; x <= extent[1]; x++)
337         {
338         for (c = 0; c < 3; c++)
339           {
340           if ( type == VTK_UNSIGNED_CHAR )
341             {
342             rgb[c]  = static_cast<int>(*rgbPtr);
343             }
344           else if ( type == VTK_UNSIGNED_SHORT )
345             {
346             rgb[c] = (static_cast<unsigned short>(*rgbPtr))>>8;
347             }
348           else
349             {
350             rgb[c] = static_cast<int>(*rgbPtr * 255.5);
351             }
352           rgbPtr++;
353           }
354         tmp = root;
355         while( !done )
356           {
357           if ( tmp->GetIndex() != -1 )
358             {
359             *indexPtr = tmp->GetIndex();
360             break;
361             }
362           if ( rgb[tmp->GetAxis()] > tmp->GetSplitPoint() )
363             {
364             tmp = tmp->GetChild2();
365             }
366           else
367             {
368             tmp = tmp->GetChild1();
369             }
370           }
371         tmp->AddColor( rgb );
372         indexPtr++;
373 
374         rgbPtr   += inIncrement[0];
375         indexPtr += outIncrement[0];
376         }
377       rgbPtr   += inIncrement[1];
378       indexPtr += outIncrement[1];
379       }
380     rgbPtr   += inIncrement[2];
381     indexPtr += outIncrement[2];
382     }
383 
384   self->UpdateProgress(0.90);
385 
386   // Fill in the lookup table
387   lut = self->GetLookupTable();
388   lut->SetNumberOfTableValues( numLeafNodes );
389   lut->SetNumberOfColors( numLeafNodes );
390   lut->SetTableRange( 0, numLeafNodes-1 );
391   color[3] = 1.0;
392   for ( leaf = 0; leaf < numLeafNodes; leaf++ )
393     {
394     leafNodes[leaf]->GetAverageColor( rgb );
395     color[0] = rgb[0] / 255.0;
396     color[1] = rgb[1] / 255.0;
397     color[2] = rgb[2] / 255.0;
398     lut->SetTableValue( leafNodes[leaf]->GetIndex(), color );
399     }
400 
401 
402   timer->StopTimer();
403   self->SetLookupIndexExecuteTime( timer->GetElapsedTime() );
404   timer->Delete();
405 
406   delete root;
407 }
408 
ComputeStdDev()409 void vtkColorQuantizeNode::ComputeStdDev()
410 {
411   int   i, j;
412   double mean;
413   int   count=0;
414   int   medianCount;
415 
416   // Create space for histogram
417   this->Histogram[0] = new int[this->Bounds[1] - this->Bounds[0] + 1];
418   this->Histogram[1] = new int[this->Bounds[3] - this->Bounds[2] + 1];
419   this->Histogram[2] = new int[this->Bounds[5] - this->Bounds[4] + 1];
420 
421   // Create histogram
422   switch (this->ImageType)
423     {
424     vtkTemplateMacro(
425       vtkImageQuantizeRGBToIndexHistogram(
426         static_cast<VTK_TT *>(this->Image), this->ImageExtent,
427         this->ImageIncrement, this->ImageType,
428         this->Bounds, this->Histogram ));
429     }
430 
431 
432   // Compute for r, g, and b
433   for ( i = 0; i < 3; i++ )
434     {
435     // Compute the mean
436     mean  = 0;
437     count = 0;
438     for ( j = 0; j <= (this->Bounds[i*2 + 1] - this->Bounds[i*2]); j++ )
439       {
440       count += this->Histogram[i][j];
441       mean  += this->Histogram[i][j] * (j + this->Bounds[i*2]);
442       }
443     if (count>0)
444       {
445       mean /= static_cast<double>(count);
446       }
447     else
448       {
449       mean = 0;
450       }
451     this->Mean[i] = mean;
452 
453     // Must have some minimum distance to subdivide - if we
454     // are below this distance limit, don't compute a
455     // standard deviation since we don't want to subdivide this
456     // node along this axis. Set the deviation to 0.0 and continue.
457     if ( this->Bounds[i*2 + 1] == this->Bounds[i*2] )
458       {
459       this->StdDev[i] = 0.0;
460       continue;
461       }
462 
463 
464     // Where is the median?
465     medianCount = count / 2;
466 
467     // Initialize the median to unset
468     this->Median[i] = -1;
469 
470     // Compute the standard deviation and the location of the median
471     this->StdDev[i] = 0;
472     count = 0;
473     for ( j = 0; j <= (this->Bounds[i*2 + 1] - this->Bounds[i*2]); j++ )
474       {
475       count += this->Histogram[i][j];
476       this->StdDev[i] += static_cast<double>(this->Histogram[i][j]) *
477         (static_cast<double>(j)+this->Bounds[i*2]-mean) *
478         (static_cast<double>(j)+this->Bounds[i*2]-mean);
479       if ( this->Median[i] == -1 && count > medianCount )
480         {
481         this->Median[i] = j + this->Bounds[i*2];
482         }
483       }
484 
485     // If our median is at the upper bound, bump down by one. This will
486     // help in the cases where we have a distance of 2 in this dimension,
487     // and just over half the entries are in the second bucket. We
488     // still want to divide - the division needs to be at the first
489     // bucket.
490     if ( this->Median[i] == this->Bounds[i*2 + 1] )
491       {
492       this->Median[i]--;
493       }
494 
495     // Do the final division and square root to get the standard deviation
496     if (count>0)
497       {
498       this->StdDev[i] /= static_cast<double>(count);
499       }
500     else
501       {
502       this->StdDev[i] = 0;
503       }
504 
505     this->StdDev[i] = sqrt( this->StdDev[i] );
506     }
507 
508   // Should all be the same - just take the last one
509   this->Count = count;
510 }
511 
Divide(int axis,int nextIndex)512 void vtkColorQuantizeNode::Divide( int axis, int nextIndex )
513 {
514   int newBounds[6];
515 
516   this->Child1 = new vtkColorQuantizeNode;
517   this->Child2 = new vtkColorQuantizeNode;
518 
519   memcpy( newBounds, this->Bounds, 6*sizeof(int) );
520 
521   newBounds[axis*2 + 1] = static_cast<int>(this->Median[axis]);
522   this->Child1->SetBounds( newBounds );
523 
524   newBounds[axis*2] = static_cast<int>(this->Median[axis] + 1);
525   newBounds[axis*2 + 1] = static_cast<int>(this->Bounds[axis*2 + 1]);
526   this->Child2->SetBounds( newBounds );
527 
528   this->SplitPoint = static_cast<int>(this->Median[axis]);
529   this->Axis = axis;
530 
531   this->Child1->SetIndex( this->Index );
532   this->Child2->SetIndex( nextIndex );
533   this->Index = -1;
534 
535   delete [] this->Histogram[0];
536   delete [] this->Histogram[1];
537   delete [] this->Histogram[2];
538 
539   this->Histogram[0] = NULL;
540   this->Histogram[1] = NULL;
541   this->Histogram[2] = NULL;
542 
543   this->Child1->SetImageExtent( this->ImageExtent );
544   this->Child1->SetImageIncrement( this->ImageIncrement );
545   this->Child1->SetImageType( this->ImageType );
546   this->Child1->SetImage( this->Image );
547 
548   this->Child2->SetImageExtent( this->ImageExtent );
549   this->Child2->SetImageIncrement( this->ImageIncrement );
550   this->Child2->SetImageType( this->ImageType );
551   this->Child2->SetImage( this->Image );
552 
553   this->Child1->ComputeStdDev();
554   this->Child2->ComputeStdDev();
555 }
556 
557 // Constructor sets default values
vtkImageQuantizeRGBToIndex()558 vtkImageQuantizeRGBToIndex::vtkImageQuantizeRGBToIndex()
559 {
560   this->LookupTable = vtkLookupTable::New();
561   this->NumberOfColors = 256;
562   this->InputType = VTK_UNSIGNED_SHORT;
563 
564   this->InitializeExecuteTime = 0.0;
565   this->BuildTreeExecuteTime = 0.0;
566   this->LookupIndexExecuteTime = 0.0;
567 }
568 
569 // Destructor deletes used resources
~vtkImageQuantizeRGBToIndex()570 vtkImageQuantizeRGBToIndex::~vtkImageQuantizeRGBToIndex()
571 {
572   if ( this->LookupTable )
573     {
574     this->LookupTable->Delete();
575     }
576 }
577 
578 // This method is passed an input and output Data, and executes the filter
579 // algorithm to fill the output from the input.
580 // It just executes a switch statement to call the correct function for
581 // the Datas data types.
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)582 int vtkImageQuantizeRGBToIndex::RequestData(
583   vtkInformation *vtkNotUsed(request),
584   vtkInformationVector **inputVector,
585   vtkInformationVector *outputVector)
586 {
587   void *inPtr;
588   void *outPtr;
589 
590   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
591   vtkInformation *outInfo = outputVector->GetInformationObject(0);
592 
593   vtkImageData *inData = vtkImageData::SafeDownCast(
594     inInfo->Get(vtkDataObject::DATA_OBJECT()));
595   vtkImageData *outData = vtkImageData::SafeDownCast(
596     outInfo->Get(vtkDataObject::DATA_OBJECT()));
597 
598   outData->SetExtent(
599     outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()));
600   outData->AllocateScalars(outInfo);
601 
602   int inExt[6];
603   inData->GetExtent(inExt);
604   // if the input extent is empty then exit
605   if (inExt[1] < inExt[0] ||
606       inExt[3] < inExt[2] ||
607       inExt[5] < inExt[4])
608     {
609     return 1;
610     }
611 
612   inPtr = inData->GetScalarPointer();
613   outPtr = outData->GetScalarPointer();
614 
615   // Input must be 3 components (rgb)
616   if (inData->GetNumberOfScalarComponents() != 3)
617     {
618     vtkErrorMacro("This filter can handles only 3 components");
619     return 1;
620     }
621 
622   // this filter expects that output is type unsigned short.
623   if (outData->GetScalarType() != VTK_UNSIGNED_SHORT)
624     {
625     vtkErrorMacro(<< "Execute: out ScalarType " << outData->GetScalarType()
626                   << " must be unsigned short\n");
627     return 1;
628     }
629 
630   this->InputType = inData->GetScalarType();
631 
632   switch ( this->InputType )
633     {
634     vtkTemplateMacro(
635       vtkImageQuantizeRGBToIndexExecute(this,
636                                         inData, static_cast<VTK_TT *>(inPtr),
637                                         outData,
638                                         static_cast<unsigned short *>(outPtr)));
639     default:
640       vtkErrorMacro(<< "Execute: This ScalarType is not handled");
641       return 1;
642     }
643 
644   return 1;
645 }
646 
647 // Change the output type and number of components
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)648 int vtkImageQuantizeRGBToIndex::RequestInformation (
649   vtkInformation * vtkNotUsed(request),
650   vtkInformationVector **vtkNotUsed(inputVector),
651   vtkInformationVector *outputVector)
652 {
653   // get the info objects
654   vtkInformation* outInfo = outputVector->GetInformationObject(0);
655 
656   vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_SHORT, 1);
657   return 1;
658 }
659 
660 // Get ALL of the input.
RequestUpdateExtent(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * vtkNotUsed (outputVector))661 int vtkImageQuantizeRGBToIndex::RequestUpdateExtent(
662   vtkInformation * vtkNotUsed(request),
663   vtkInformationVector **inputVector,
664   vtkInformationVector *vtkNotUsed(outputVector))
665 {
666   // get the info objects
667   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
668 
669   int inExt[6];
670   inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt);
671   inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6);
672 
673   return 1;
674 }
675 
PrintSelf(ostream & os,vtkIndent indent)676 void vtkImageQuantizeRGBToIndex::PrintSelf(ostream& os, vtkIndent indent)
677 {
678   this->Superclass::PrintSelf(os,indent);
679 
680   // Input Type is internal so we dont prit it
681   //os << indent << "InputType: " << this->InputType << endl;
682 
683   os << indent << "Number Of Colors: " << this->NumberOfColors << endl;
684   os << indent << "Lookup Table: " << endl << *this->LookupTable;
685   os << indent << "Execute Time (in initialize stage): " <<
686     this->InitializeExecuteTime << endl;
687   os << indent << "Execute Time (in build tree stage): " <<
688     this->BuildTreeExecuteTime << endl;
689   os << indent << "Execute Time (in lookup index stage): " <<
690     this->LookupIndexExecuteTime << endl;
691 }
692