#ifndef __WLTCOMPRESS_H__
#define __WLTCOMPRESS_H__

#include "wavelet.h"
#include "image2d.h"
#include "databuffer.h"
#include <bzlib.h>


/// compression of a wavelet tree
/**
 * uses the bzlib to compress data
 * 
 * data format:
 * [im size][ numentries ][entry sizes][ level entry 1] [..] 
 * 
 * im size:
 * [height][width] both are integers
 *
 * entry sizes:
 * [size of entry 1][size of entry 2]...
 * unsigned integer
 *
 * level entry:
 * [ bzipped raw image ]
 * 
 * numentries:
 * [ unsigned int ]
 *
 * each data entry is a bzstream containing height, width 
 * followed by data as raster scan of hl, lh, hh images
 * in that order
 * 
 * @todo error checks for bzlib
*/
class wltcompress
{
 public:
  wltcompress();
  ~wltcompress();

  /// clears the compression buffer
  int clear();

  /// compresses the given wavelet tree
  /**
   * @param wlt wavelet tree to compress
   */
  char *compress( wavelet &wlt);
  /// returns pointer to compressed data
  char *compressdata();
  /// return the compressed size
  int compresssize();
  /// decompresses the given data to a wavelet tree
  int decompress( wavelet &wlt, char *ptr, int size);
 private:
  /// perps the bz_stream for another run
  /**
   * @param bz pointer to bz_stream
   * @param b data buffer to use
   * @param bs data buffer size
   * @param buf data buffer to copy to
   */
  int bzprepout( bz_stream *bz, char *b, int bs, databuffer &buf);

  /// checks the bz return code
  int bzretcheck( int bzret );

  /// compresses a data with a bz stream
  /**
   * will call bzcompress until the input buffer 
   * is used
   * @param bz pointer to properly initialized bz stream
   * @param data pointer to data to compress
   * @param datas size of data in bytes
   * @param tb temp buffer to use
   * @param tbs temp buffer size
   * @param buf location of data that is extracted
   */
  int bzcompdata( bz_stream *bz, 
                  char *data, int datas,
                  char *tb, int tbs,
                  databuffer &buf );

  /// compresses a level in the wavelet tree
  int compresslevel( wavelet::wavelettree *wt, 
                     databuffer *d );
  /// compresses a the lowpass data
  int compresslowpass( image2d *im,
                       databuffer *d);

  int decompresslevel( wavelet::wavelettree *wt, 
                       char *data,
                       int size);
  
  int decompresslowpass( image2d *im, 
                         char *data,
                         int size);

  int converttodouble( int *si, double *d, int h, int w );
  
  databuffer cdata;
};

#endif
