///////////////////////////////////////////////////////////////////////////////
// Compressor.cpp
// 
//     This compressor class compresses (or decompresses) a graphics image.
// Currently this class holds an implementation that recreates the original
// image.  You should use this as a template for your solution.
///////////////////////////////////////////////////////////////////////////////

#include "Compressor.h"


///////////////////////////////////////////////////////////////////////////////
// Compressor::Compressor ()                                Default Constructor
//
//      This constructor currently does nothing.  You may initialize any
// private class variables here.
///////////////////////////////////////////////////////////////////////////////

Compressor::Compressor ()
{
  // You may optionally add code here.
}


///////////////////////////////////////////////////////////////////////////////
// Compressor::~Compressor ()                                        Destructor
//
//      This destructor currently does nothing.  If you allocated any
// 'new' memory and you haven't deleted it yet, you must 'delete' it here.
///////////////////////////////////////////////////////////////////////////////

Compressor::~Compressor ()
{
  // You may optionally add code here.
}


///////////////////////////////////////////////////////////////////////////////
// void Compressor::compress (Image & source, ostream & out)
//
//      This routine compresses an image and writes the compressed
// data to the output stream.
//
//      A default implementation has been provided for you, you may change
// any or all of this code.
//
//      The default implementation simply writes out the size of the file, and
// then writes out red, blue, and green values for each pixel in the image.
// Note that no compression is done here.
///////////////////////////////////////////////////////////////////////////////

void Compressor::compress (Image & source, ostream & OutputFile)
{
  // You may change any or all of this code.
  
  // Assume the parameters are valid.  You do not need to check for
  //   parameter errors.
  
  // Output the dimensions of the image.

  int width  = source.getWidth ();
  int height = source.getHeight ();
  
  OutputFile << width << endl;
  OutputFile << height << endl;

  // Output a seperator character to separate the ASCII values output above
  //   from the non-ascii (binary) values output below.

  OutputFile << '=';

  // Output each pixel of the image as red, blue, and green numerical
  //   values.  This is not very efficient.

  Pixel p;
  double a, b, c;
  unsigned char av, bv, cv, dv;
  
  for (int y = 0; y < height; y++)
    for (int x = 0; x < width; x++)
    {
      // Get the pixel.

      p = source.getPixel (x, y);
      
      a = p.getRed ();
      b = p.getGreen ();
      c = p.getBlue ();

      av = (unsigned char) (a * 255 + 0.5);
      bv = (unsigned char) (b * 255 + 0.5);
      cv = (unsigned char) (c * 255 + 0.5);

      OutputFile.put( av );
      OutputFile.put( bv );
      OutputFile.put( cv );
    }

  // Done!  (Do not close the output stream.)

  return;
}

///////////////////////////////////////////////////////////////////////////////
// compressor::Image Compressor::decompress (istream & InputFile)
//
//      This routine reads compressed data from the input stream and
// rebuilds an image from the compressed data.  The resulting image
// is returned.
//
//      This code must exactly reverse the compression step.
//
//      A default implementation has been provided for you, you may change
// any or all of this code.
//
//      The default implementation simply reverses the compression step.
///////////////////////////////////////////////////////////////////////////////

Image Compressor::decompress (istream & InputFile)
{
  // You may change any or all of this code.
  
  // Assume the parameters are valid.  You do not need to check for
  //   parameter errors.
  
  // Read the dimensions of the image.  Make sure to do this in the same
  //   order as they were written.

  int width, height;

  InputFile >> width;
  InputFile >> height;

  // Read the separator character and ignore it.

  char separator;

  InputFile >> separator;

  // Build an image of the appropriate size by creating a new image variable.

  Image target (width, height);

  // Loop reading red, green, and blue values from the file.  Again, order
  //   matters.  Set each pixel in the image.

  Pixel p;
  double a, b, c;
  unsigned char av, bv, cv;
  
  for (int y = 0; y < height; y++)
    for (int x = 0; x < width; x++)
    {
      InputFile.get( av );
      InputFile.get( bv );
      InputFile.get( cv );

      a = double( av )/ 255;
      b = double( bv )/ 255;
      c = double( cv )/ 255;
      
      p.setRGBColor (a, b, c);
      
      target.setPixel (x, y, p);
    }

  // Done, the image is built.  Return it.

  return target;
}

