//
//  Olaf Ronneberger
//  Sample Solution for Exercise 1 (Lecture "3D Image Analysis" Summer 2015) 
//  Extracts the middle slices (xy), (xz) and (yz) of the given data set
//
//  compile with:
//  g++ -Wall -O2 -g slices.cc -o slices



#include <iostream>
#include <fstream>

int main( int argc, char** argv)
{
  /*-----------------------------------------------------------------------
   *  size of 3D data
   *-----------------------------------------------------------------------*/
  const int nLevels = 124;
  const int nRows   = 216;
  const int nCols   = 181;

  /*-----------------------------------------------------------------------
   *  positions of slices
   *-----------------------------------------------------------------------*/
  const int sliceLevel = 62;
  const int sliceRow   = 108;
  const int sliceCol   = 90;

  /*-----------------------------------------------------------------------
   *  allocate memory for volume
   *-----------------------------------------------------------------------*/
  int nVoxels = nLevels * nRows * nCols;
  unsigned char* volume = new unsigned char[nVoxels];
  
  /*-----------------------------------------------------------------------
   *   read volume from disk
   *-----------------------------------------------------------------------*/
  std::ifstream inFile( "whatisit_124x216x181_8bit.raw", std::ifstream::binary);
  inFile.read( reinterpret_cast<char*>(volume), nVoxels);

  
  /*-----------------------------------------------------------------------
   *  extract xy slice
   *-----------------------------------------------------------------------*/
  int slice_nRows = nRows;
  int slice_nCols = nCols;
  
  unsigned char* slice = new unsigned char[ slice_nRows * slice_nCols];
  
  for( int row = 0; row < nRows; ++row)
  {
    for( int col = 0; col < nCols; ++col)
    {
      int trgRow = row;
      int trgCol = col;
      slice[ trgRow * slice_nCols + trgCol] = volume[sliceLevel * nRows * nCols 
                                                     + row * nCols 
                                                     + col];
    }
  }
  
  /*-----------------------------------------------------------------------
   *  save xy slice and free its  memory
   *-----------------------------------------------------------------------*/
  std::ofstream outFileXY( "slice_xy.pgm", std::ofstream::binary);
  outFileXY << "P5\n"
          << slice_nCols << " " << slice_nRows << " 255\n";
  outFileXY.write( reinterpret_cast<char*>(slice), slice_nRows * slice_nCols);

  delete[] slice;
  

  /*-----------------------------------------------------------------------
   *  extract xz slice
   *-----------------------------------------------------------------------*/
  slice_nRows = nLevels;
  slice_nCols = nCols;
  
  slice = new unsigned char[ slice_nRows * slice_nCols];
  
  for( int lev = 0;  lev < nLevels; ++lev)
  {
    for( int col = 0; col < nCols; ++col)
    {
      int trgRow = lev;
      int trgCol = col;
      slice[ trgRow * slice_nCols + trgCol] = volume[ lev * nRows * nCols 
                                                      + sliceRow * nCols 
                                                      + col];
    }
  }
  
  /*-----------------------------------------------------------------------
   *  save  slice and free its  memory
   *-----------------------------------------------------------------------*/
  std::ofstream outFileXZ( "slice_xz.pgm", std::ofstream::binary);
  outFileXZ << "P5\n"
          << slice_nCols << " " << slice_nRows << " 255\n";
  outFileXZ.write( reinterpret_cast<char*>(slice), slice_nRows * slice_nCols);

  delete[] slice;
  


  /*-----------------------------------------------------------------------
   *  extract yz slice
   *-----------------------------------------------------------------------*/
  slice_nRows = nRows;
  slice_nCols = nLevels;
  
  slice = new unsigned char[ slice_nRows * slice_nCols];
  
  for( int lev = 0;  lev < nLevels; ++lev)
  {
    for( int row = 0; row < nRows; ++row)
    {
      int trgRow = row;
      int trgCol = lev;
      slice[ trgRow * slice_nCols + trgCol] = volume[ lev * nRows * nCols 
                                                      + row * nCols 
                                                      + sliceCol];
    }
  }
  
  /*-----------------------------------------------------------------------
   *  save  slice and free its  memory
   *-----------------------------------------------------------------------*/
  std::ofstream outFileYZ( "slice_yz.pgm", std::ofstream::binary);
  outFileYZ << "P5\n"
            << slice_nCols << " " << slice_nRows << " 255\n";
  outFileYZ.write( reinterpret_cast<char*>(slice), slice_nRows * slice_nCols);

  delete[] slice;
  
  /*-----------------------------------------------------------------------
   *  and finally free volume memory
   *-----------------------------------------------------------------------*/
  delete[] volume;
  



  return 0;
  
}
