/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.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 vtkVVLODDataItemVolumeHelper 
// .SECTION Description
// .SECTION See Also

#ifndef __vtkVVLODDataItemVolumeHelper_h
#define __vtkVVLODDataItemVolumeHelper_h

#include "vtkObject.h"
#include "vtkSmartPointer.h"
#include <vtksys/stl/string>
#include "XML/vtkXMLIOBaseMacros.h" // Needed for XML reader/writer macros

class vtkVVDataItemVolume;
class vtkImageReslice;
class vtkImageData;
class vtkUnsignedCharArray;

class VTK_EXPORT vtkVVLODDataItemVolumeHelper : public vtkObject
{
public:
 
  // Description:
  // Standard VTK methods
  static vtkVVLODDataItemVolumeHelper *New();
  vtkTypeRevisionMacro(vtkVVLODDataItemVolumeHelper, vtkObject);
  void PrintSelf(ostream& os, vtkIndent indent);
  //BTX
  vtkKWGetXMLReaderWriterObjectsMacro();
  //ETX

  // Description:
  virtual void SetDataItemVolume( vtkVVDataItemVolume * d ) 
    { this->DataItemVolume = d; }
  vtkGetObjectMacro( DataItemVolume, vtkVVDataItemVolume );

  //BTX
  enum LODLevel
    {
    LODLevelHigh = 0,
    LODLevelLow
    };
  enum LODMode
    {
    LODModeToExtent = 0,
    LODModeToTargetSize,
    LODModeToFactor
    };
  enum CompressionStrategy
    {
    VTK_COMPRESSION_DEFLATE = 0,   // The one used in zip (LZ77)
    VTK_COMPRESSION_JPEG2000   // 2D Compression strategy.
    };
  //ETX

  // Description:
  // Set the LOD Level
  vtkSetMacro( LODLevel, int );
  vtkGetMacro( LODLevel, int );

  // Description:
  // Get the current LODLevel. After a call to Update(), this will generally, 
  // (but not always, if we run into boundary conditions, examples are - 
  // not being able to decimate, too small already etc.), be the same as 
  // GetLODLevel().
  vtkGetMacro( CurrentLODLevel, int );
  
  // Description:
  // Set the LOD mode to construct the low resolution dataset from the higg
  // resolution dataset. Default is LODModeToFactor.
  vtkSetMacro( LODMode, int );
  vtkGetMacro( LODMode, int );

  // Description:
  // Set the shrink factors. This will be used if the LODMode is set 
  // to Factor. Default is 4.
  vtkSetMacro( LODShrinkFactor, double );
  vtkGetMacro( LODShrinkFactor, double );  
  
  // Description:
  // Set the compression level. This will be used for some compression scheme
  // like VTK_COMPRESSION_JPEG2000
  vtkSetMacro( CompressionRatio, double );
  vtkGetMacro( CompressionRatio, double );  
  
  // Description:
  // Update. (create the LOD's for the LODLevel that has been set).
  virtual void Update();

  // Description:
  // Get the data that corresponds to a particular LOD. Make sure you call
  // Update() first.
  vtkImageData * GetImageAtLevel( int lodLevel );

  // Description:
  // Get the last used shrink factor. This was the factor that was used to
  // downsample the data along each dimension. Generally this will be the 
  // same as the ShrinkFactor, unless we run into boundary conditions such 
  // as (see documentation of SetMinimumSize).
  vtkGetVector3Macro( LastUsedLODShrinkFactor, double );
  
  // Description:
  // Set the minimum size in bytes of data that will be shrunk. Data whose
  // uncompressed size is less than this will not have a low LOD level at
  // all. Default is 3000000 (3MB)
  vtkSetMacro( MinimumSizeInBytes, unsigned long );
  vtkGetMacro( MinimumSizeInBytes, unsigned long );

  // Description:
  // The minimum extent that we will use along any dimension. No matter what the 
  // shrink factors or the shrink mode, etc, we will not subsample smaller than 
  // extent. It is recommended that you do not set this smaller than 4 along any
  // dimension. VolView might get confused if you create single slice data 
  // from a 4 slice data... VolumeWidgets may disappear.
  // Default (4,4,4)
  vtkSetVector3Macro( MinimumSize, int );
  vtkGetVector3Macro( MinimumSize, int );

  // Description:
  // Set the interpolation mode during downsample. Default is cubic.
  // Set it to VTK_RESLICE_NEAREST / VTK_RESLICE_LINEAR / VTK_RESLICE_CUBIC.
  vtkSetMacro( InterpolationMode, int );
  vtkGetMacro( InterpolationMode, int );  

  // Description:
  // Get the compressed volume for the input. The resulting object must be
  // deleted by the user. 
  //   ptr: Raw pointer to the data
  //   size: size in bytes of the data.
  unsigned long Compress( unsigned char *ptr, unsigned long size );

  // Description:
  // Get the compressed volume for the current LOD Level
  unsigned long Compress();

  // Description:
  // Compress using the supplied paramters. The LODShrinkFactor that you've
  // set on this class will be applied prior to compression.
  //
  // strategy:         See enum CompressionStrategy. Set this to -1 if you
  //                   want the writer to pick the best possible strategy 
  //                   for you (JPEG2000 if possible, DEFLATE if not)
  //
  // filename:     Set the base of the filename that you wish to write out,
  //                   for example: /home/karthik/ChestCT
  //                   The write extensions will be expanded out and returned 
  //                   to you depending on the strategy. 
  //
  // RETURNS 1 on success. 0 on failure.
  //
  //BTX
  int Write( 
      const char * filename, // filename string to write result   
      int strategy = -1);
  //ETX

  // Description:
  // Can the image be compressed by the supplied strategy at the 
  // current LODLevel ?
  int SupportsCompression( int strategy );

  // Description:
  // Compute the output extents and spacing depending on the decimation
  // factors set here.
  int GetOutputExtentOriginAndSpacing( int outputExtent[6], double outputSpacing[3], double outputOrigin[3] );

protected:
  vtkVVLODDataItemVolumeHelper();
  ~vtkVVLODDataItemVolumeHelper();

  // The volume that the user can revert to after looking at the lowres volume
  //BTX
  vtkSmartPointer< vtkImageData > HighResVolume;
  //ETX

  int                             InterpolationMode;
  vtkImageReslice               * Resample;
  vtkVVDataItemVolume           * DataItemVolume;
  int                             MinimumSize[3];
  double                          LODShrinkFactor;
  double                          LastUsedLODShrinkFactor[3];
  double                          CompressionRatio;
  int                             LODMode;
  int                             LODLevel;
  int                             CurrentLODLevel;
  vtkTimeStamp                    BuildTime;
  unsigned long                   MinimumSizeInBytes;

private:
  vtkVVLODDataItemVolumeHelper(const vtkVVLODDataItemVolumeHelper&);  //Not implemented
  void operator=(const vtkVVLODDataItemVolumeHelper&);  //Not implemented
};

#endif
