int
main (int argc, char **argv)
{
  OctreePointCloudCompression<PointXYZRGBA>* octreeCoder;

  pcl::io::compression_Profiles_e compressionProfile;

  bool showStatistics;
  double pointResolution;
  float octreeResolution;
  bool doVoxelGridDownDownSampling;
  unsigned int iFrameRate;
  bool doColorEncoding;
  unsigned int colorBitResolution;

  bool bShowInputCloud;

  // default values
  showStatistics = false;
  pointResolution = 0.001;
  octreeResolution = 0.01f;
  doVoxelGridDownDownSampling = false;
  iFrameRate = 30;
  doColorEncoding = false;
  colorBitResolution = 6;
  compressionProfile = pcl::io::MED_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR;

  bShowInputCloud = false;

  std::string fileName = "pc_compressed.pcc";
  std::string hostName = "localhost";

  bool bServerFileMode;
  bool bEnDecode;
  bool validArguments;

  validArguments = false;
  bServerFileMode = false;
  bEnDecode = false;

  float min_v = 0.0f, max_v = 3.0f;
  pcl::console::parse_2x_arguments (argc, argv, "-minmax", min_v, max_v, false);
  std::string field_name ("z");
  pcl::console::parse_argument (argc, argv, "-field", field_name);

  if (pcl::console::find_argument (argc, argv, "-e")>0) 
    bShowInputCloud = true;

  if (pcl::console::find_argument (argc, argv, "-s")>0) 
  {
    bEnDecode = true;
    bServerFileMode = true;
    validArguments = true;
  }

  if (pcl::console::parse_argument (argc, argv, "-c", hostName)>0) 
  {
    bEnDecode = false;
    bServerFileMode = true;
    validArguments = true;
  }

  if (pcl::console::find_argument (argc, argv, "-x")>0) 
  {
    bEnDecode = true;
    bServerFileMode = false;
    validArguments = true;
  }

  if (pcl::console::find_argument (argc, argv, "-d")>0) 
  {
    bEnDecode = false;
    bServerFileMode = false;
    validArguments = true;
  }

  if (pcl::console::find_argument (argc, argv, "-t")>0) 
    showStatistics = true;

  if (pcl::console::find_argument (argc, argv, "-a")>0) 
  {
    doColorEncoding = true;
    compressionProfile = pcl::io::MANUAL_CONFIGURATION;
  }

  if (pcl::console::find_argument (argc, argv, "-v")>0) 
  {
    doVoxelGridDownDownSampling = true;
    compressionProfile = pcl::io::MANUAL_CONFIGURATION;
  }

  pcl::console::parse_argument (argc, argv, "-f", fileName);
  pcl::console::parse_argument (argc, argv, "-r", pointResolution);
  pcl::console::parse_argument (argc, argv, "-i", iFrameRate);
  pcl::console::parse_argument (argc, argv, "-o", octreeResolution);
  pcl::console::parse_argument (argc, argv, "-b", colorBitResolution);

  std::string profile;
  if (pcl::console::parse_argument (argc, argv, "-p", profile)>0)
  {
    if (profile == "lowC")
      compressionProfile = pcl::io::LOW_RES_OFFLINE_COMPRESSION_WITH_COLOR;
    else if (profile == "lowNC")
      compressionProfile = pcl::io::LOW_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR;
    else if (profile == "medC")
      compressionProfile = pcl::io::MED_RES_OFFLINE_COMPRESSION_WITH_COLOR;
    else if (profile =="medNC")
      compressionProfile = pcl::io::MED_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR;
    else if (profile == "highC")
      compressionProfile = pcl::io::HIGH_RES_OFFLINE_COMPRESSION_WITH_COLOR;
    else if (profile == "highNC")
      compressionProfile = pcl::io::HIGH_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR;
    else
    {
      print_usage ("Unknown profile parameter..\n");
      return -1;
    }

    if (compressionProfile != MANUAL_CONFIGURATION)
    {
      // apply selected compression profile
      // retrieve profile settings
      const pcl::io::configurationProfile_t selectedProfile = pcl::io::compressionProfiles_[compressionProfile];

      // apply profile settings
      pointResolution = selectedProfile.pointResolution;
      octreeResolution = float (selectedProfile.octreeResolution);
      doVoxelGridDownDownSampling = selectedProfile.doVoxelGridDownSampling;
      iFrameRate = selectedProfile.iFrameRate;
      doColorEncoding = selectedProfile.doColorEncoding;
      colorBitResolution = selectedProfile.colorBitResolution;
    }
  }

  if (pcl::console::find_argument (argc, argv, "-?")>0) 
  {
    print_usage ("");
    return 1;
  }

  if (!validArguments)
  {
    print_usage ("Please specify compression mode..\n");
    return -1;
  }

  octreeCoder = new OctreePointCloudCompression<PointXYZRGBA> (compressionProfile, showStatistics, pointResolution,
                                                               octreeResolution, doVoxelGridDownDownSampling, iFrameRate,
                                                               doColorEncoding, static_cast<unsigned char> (colorBitResolution));


  if (!bServerFileMode) 
  {
    if (bEnDecode) 
    {
      // ENCODING
      ofstream compressedPCFile;
      compressedPCFile.open (fileName.c_str(), ios::out | ios::trunc | ios::binary);

      if (!bShowInputCloud) 
      {
        EventHelper v (compressedPCFile, octreeCoder, field_name, min_v, max_v);
        v.run ();
      } 
      else
      {
        SimpleOpenNIViewer v (compressedPCFile, octreeCoder);
        v.run ();
      }

    } else
    {
      // DECODING
      ifstream compressedPCFile;
      compressedPCFile.open (fileName.c_str(), ios::in | ios::binary);
      compressedPCFile.seekg (0);
      compressedPCFile.unsetf (ios_base::skipws);

      pcl::visualization::CloudViewer viewer ("PCL Compression Viewer");

      while (!compressedPCFile.eof())
      {
        PointCloud<PointXYZRGBA>::Ptr cloudOut (new PointCloud<PointXYZRGBA> ());
        octreeCoder->decodePointCloud ( compressedPCFile, cloudOut);
        viewer.showCloud (cloudOut);
      }
    }
  } else
  {
    // switch to ONLINE profiles
    if (compressionProfile == pcl::io::LOW_RES_OFFLINE_COMPRESSION_WITH_COLOR)
      compressionProfile = pcl::io::LOW_RES_ONLINE_COMPRESSION_WITH_COLOR;
    else if (compressionProfile == pcl::io::LOW_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR)
      compressionProfile = pcl::io::LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;
    else if (compressionProfile == pcl::io::MED_RES_OFFLINE_COMPRESSION_WITH_COLOR)
      compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;
    else if (compressionProfile == pcl::io::MED_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR)
      compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;
    else if (compressionProfile == pcl::io::HIGH_RES_OFFLINE_COMPRESSION_WITH_COLOR)
      compressionProfile = pcl::io::HIGH_RES_ONLINE_COMPRESSION_WITH_COLOR;
    else if (compressionProfile == pcl::io::HIGH_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR)
      compressionProfile = pcl::io::HIGH_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;

    if (bEnDecode)
    {
      // ENCODING
      try
      {
        boost::asio::io_service io_service;
        tcp::endpoint endpoint (tcp::v4 (), 6666);
        tcp::acceptor acceptor (io_service, endpoint);

        tcp::iostream socketStream;

        std::cout << "Waiting for connection.." << std::endl;

        acceptor.accept (*socketStream.rdbuf ());

        std::cout << "Connected!" << std::endl;

        if (!bShowInputCloud) 
        {
          EventHelper v (socketStream, octreeCoder, field_name, min_v, max_v);
          v.run ();
        } 
        else
        {
          SimpleOpenNIViewer v (socketStream, octreeCoder);
          v.run ();
        }

        std::cout << "Disconnected!" << std::endl;

        boost::this_thread::sleep(boost::posix_time::seconds(3));

      }
      catch (std::exception& e)
      {
        std::cerr << e.what () << std::endl;
      }
    }
    else
    {
      // DECODING
      std::cout << "Connecting to: " << hostName << ".." << std::endl;

      try
      {
        tcp::iostream socketStream (hostName.c_str (), "6666");

        std::cout << "Connected!" << std::endl;

        pcl::visualization::CloudViewer viewer ("Decoded Point Cloud - PCL Compression Viewer");

        while (!socketStream.fail()) 
        {
          FPS_CALC ("drawing");
          PointCloud<PointXYZRGBA>::Ptr cloudOut (new PointCloud<PointXYZRGBA> ());
          octreeCoder->decodePointCloud (socketStream, cloudOut);
          viewer.showCloud (cloudOut);
        }

      }
      catch (std::exception& e)
      {
        std::cout << "Exception: " << e.what () << std::endl;
      }
    }
  }


  delete (octreeCoder);
  return (0);
}
int
main (int argc, char **argv)
{
  OrganizedPointCloudCompression<PointXYZRGBA>* organizedCoder;

  bool showStatistics;
  bool doColorEncoding;
  bool bShowInputCloud;
  bool bRawImageEncoding;
  bool bGrayScaleConversion;

  std::string fileName = "pc_compressed.pcc";
  std::string hostName = "localhost";

  bool bServerFileMode;
  bool bEnDecode;
  bool validArguments;

  validArguments = false;
  bServerFileMode = false;
  bEnDecode = false;

  showStatistics = false;
  doColorEncoding = false;
  bShowInputCloud = false;
  bRawImageEncoding = false;
  bGrayScaleConversion = false;

  if (pcl::console::find_argument (argc, argv, "-e")>0) 
    bShowInputCloud = true;

  if (pcl::console::find_argument (argc, argv, "-r")>0)
    bRawImageEncoding = true;

  if (pcl::console::find_argument (argc, argv, "-g")>0)
    bGrayScaleConversion = true;

  if (pcl::console::find_argument (argc, argv, "-s")>0) 
  {
    bEnDecode = true;
    bServerFileMode = true;
    validArguments = true;
  }

  if (pcl::console::parse_argument (argc, argv, "-c", hostName)>0) 
  {
    bEnDecode = false;
    bServerFileMode = true;
    validArguments = true;
  }

  if (pcl::console::find_argument (argc, argv, "-a")>0)
  {
    doColorEncoding = true;
  }

  if (pcl::console::find_argument (argc, argv, "-x")>0) 
  {
    bEnDecode = true;
    bServerFileMode = false;
    validArguments = true;
  }

  if (pcl::console::find_argument (argc, argv, "-d")>0) 
  {
    bEnDecode = false;
    bServerFileMode = false;
    validArguments = true;
  }

  if (pcl::console::find_argument (argc, argv, "-t")>0) 
    showStatistics = true;

  pcl::console::parse_argument (argc, argv, "-f", fileName);


  if (pcl::console::find_argument (argc, argv, "-?")>0) 
  {
    print_usage ("");
    return 1;
  }

  if (!validArguments)
  {
    print_usage ("Please specify compression mode..\n");
    return -1;
  }

  organizedCoder = new OrganizedPointCloudCompression<PointXYZRGBA> ();


  if (!bServerFileMode) 
  {
    if (bEnDecode) 
    {
      // ENCODING
      ofstream compressedPCFile;
      compressedPCFile.open (fileName.c_str(), ios::out | ios::trunc | ios::binary);

      if (!bShowInputCloud) 
      {
        EventHelper v (compressedPCFile, organizedCoder, doColorEncoding, showStatistics, bRawImageEncoding, bGrayScaleConversion);
        v.run ();
      } 
      else
      {
        SimpleOpenNIViewer v (compressedPCFile, organizedCoder, doColorEncoding, showStatistics, bRawImageEncoding, bGrayScaleConversion);
        v.run ();
      }

    } else
    {
      // DECODING
      ifstream compressedPCFile;
      compressedPCFile.open (fileName.c_str(), ios::in | ios::binary);
      compressedPCFile.seekg (0);
      compressedPCFile.unsetf (ios_base::skipws);

      pcl::visualization::CloudViewer viewer ("PCL Compression Viewer");

      while (!compressedPCFile.eof())
      {
        PointCloud<PointXYZRGBA>::Ptr cloudOut (new PointCloud<PointXYZRGBA> ());
        organizedCoder->decodePointCloud ( compressedPCFile, cloudOut );
        viewer.showCloud (cloudOut);
      }
    }
  } else
  {
    if (bEnDecode)
    {
      // ENCODING
      try
      {
        boost::asio::io_service io_service;
        tcp::endpoint endpoint (tcp::v4 (), 6666);
        tcp::acceptor acceptor (io_service, endpoint);

        tcp::iostream socketStream;

        std::cout << "Waiting for connection.." << std::endl;

        acceptor.accept (*socketStream.rdbuf ());

        std::cout << "Connected!" << std::endl;

        if (!bShowInputCloud) 
        {
          EventHelper v (socketStream, organizedCoder, doColorEncoding, showStatistics, bRawImageEncoding, bGrayScaleConversion);
          v.run ();
        } 
        else
        {
          SimpleOpenNIViewer v (socketStream, organizedCoder, doColorEncoding, showStatistics, bRawImageEncoding, bGrayScaleConversion);
          v.run ();
        }

        std::cout << "Disconnected!" << std::endl;

        std::this_thread::sleep_for(3s);

      }
      catch (std::exception& e)
      {
        std::cerr << e.what () << std::endl;
      }
    }
    else
    {
      // DECODING
      std::cout << "Connecting to: " << hostName << ".." << std::endl;

      try
      {
        tcp::iostream socketStream (hostName.c_str (), "6666");

        std::cout << "Connected!" << std::endl;

        pcl::visualization::CloudViewer viewer ("Decoded Point Cloud - PCL Compression Viewer");

        while (!socketStream.fail()) 
        {
          FPS_CALC ("drawing");
          PointCloud<PointXYZRGBA>::Ptr cloudOut (new PointCloud<PointXYZRGBA> ());
          organizedCoder->decodePointCloud (socketStream, cloudOut);
          viewer.showCloud (cloudOut);
        }

      }
      catch (std::exception& e)
      {
        std::cout << "Exception: " << e.what () << std::endl;
      }
    }
  }

  delete (organizedCoder);
  return (0);
}