<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt 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 notices for more information.

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

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {qb_RoadExtract.tif}
//    OUTPUTS: {OBIARadiometricAttribute1.tif}, {qb_ExtractRoad_Radiometry_pretty.jpg}
//    STATS::Ndvi::Mean 0 0.5 16 16 50 1.0
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example shows the basic approach to perform object based analysis on a image.
//  The input image is firstly segmented using the \doxygen{otb}{MeanShiftImageFilter}
//  Then each segmented region is converted to a Map of labeled objects.
//  Afterwards the \doxygen{otb}{RadiometricAttributesLabelMapFilter} computes
//  radiometric attributes for each object.
//
//  This filter internally applies the
//  \doxygen{otb}{StatisticsAttributesLabelMapFilter} to the following features:
//  \begin{itemize}
//  \item GEMI
//  \item NDVI
//  \item IR
//  \item IC
//  \item IB
//  \item NDWI2
//  \item Intensity
//  \item and original B, G, R and NIR channels
//  \end{itemize}
//  Here we use the \doxygen{otb}{AttributesMapOpeningLabelMapFilter} to extract vegetated areas.
//  Let's get to the source code explanation.
//
//  Software Guide : EndLatex

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

#include "otbMeanShiftVectorImageFilter.h"
#include "itkLabelImageToLabelMapFilter.h"
#include "otbAttributesMapLabelObject.h"
#include "itkLabelMap.h"
#include "otbShapeAttributesLabelMapFilter.h"
#include "otbStatisticsAttributesLabelMapFilter.h"
#include "otbBandsStatisticsAttributesLabelMapFilter.h"
#include "otbAttributesMapOpeningLabelMapFilter.h"
#include "itkLabelMapToBinaryImageFilter.h"
#include "otbMultiChannelExtractROI.h"
#include "otbVectorRescaleIntensityImageFilter.h"
#include "otbVegetationIndicesFunctor.h"
#include "otbMultiChannelRAndNIRIndexImageFilter.h"
#include "otbImageToVectorImageCastFilter.h"

int main(int argc, char * argv[])
{
  if (argc != 11)
    {
    std::cerr << "Usage: " << argv[0] <<
    " reffname outfname outprettyfname attribute_name ";
    std::cerr <<
    "lowerThan tresh spatialRadius rangeRadius minregionsize scale" <<
    std::endl;
    return EXIT_FAILURE;
    }

  const char * reffname = argv[1];
  const char * outfname = argv[2];
  const char * outprettyfname = argv[3];
  const char * attr     = argv[4];
  double       lowerThan      = atof(argv[5]);
  double       thresh         = atof(argv[6]);

  const unsigned int spatialRadius          = atoi(argv[7]);
  const double       rangeRadius            = atof(argv[8]);
  const unsigned int minRegionSize          = atoi(argv[9]);
  const double       scale                  = atoi(argv[10]);

  const unsigned int Dimension = 2;

  // Labeled image type
  typedef unsigned short                              LabelType;
  typedef double                                      PixelType;
  typedef otb::Image<LabelType, Dimension>            LabeledImageType;
  typedef otb::Image<PixelType, Dimension>            ImageType;
  typedef otb::VectorImage<PixelType, Dimension>      VectorImageType;
  typedef otb::VectorImage<unsigned char, Dimension>  OutputVectorImageType;
  typedef otb::ImageFileReader<LabeledImageType>      LabeledReaderType;
  typedef otb::ImageFileReader<ImageType>             ReaderType;
  typedef otb::ImageFileReader<VectorImageType>       VectorReaderType;
  typedef otb::ImageFileWriter<LabeledImageType>      WriterType;
  typedef otb::ImageFileWriter<OutputVectorImageType> VectorWriterType;
  typedef otb::VectorRescaleIntensityImageFilter
  <VectorImageType, OutputVectorImageType> VectorRescalerType;
  typedef otb::MultiChannelExtractROI<unsigned char,
      unsigned char> ChannelExtractorType;
  // Label map typedef
  typedef otb::AttributesMapLabelObject<LabelType, Dimension,
      double>
  LabelObjectType;
  typedef itk::LabelMap<LabelObjectType>
  LabelMapType;
  typedef itk::LabelImageToLabelMapFilter<LabeledImageType,
      LabelMapType>
  LabelMapFilterType;
  typedef otb::ShapeAttributesLabelMapFilter<LabelMapType>
  ShapeLabelMapFilterType;
  typedef otb::BandsStatisticsAttributesLabelMapFilter<LabelMapType,
      ImageType>
  StatisticsLabelMapFilterType;
  typedef otb::BandsStatisticsAttributesLabelMapFilter<LabelMapType,
      VectorImageType>
  RadiometricLabelMapFilterType;
  typedef otb::AttributesMapOpeningLabelMapFilter<LabelMapType>
  OpeningLabelMapFilterType;
  typedef itk::LabelMapToBinaryImageFilter<LabelMapType,
      LabeledImageType>
  LabelMapToBinaryImageFilterType;
  typedef otb::MultiChannelRAndNIRIndexImageFilter<VectorImageType,
      ImageType> NDVIImageFilterType;
  typedef otb::ImageToVectorImageCastFilter<ImageType,VectorImageType>
  ImageToVectorImageCastFilterType;

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(reffname);

  LabeledReaderType::Pointer lreader = LabeledReaderType::New();
  lreader->SetFileName(reffname);

  VectorReaderType::Pointer vreader = VectorReaderType::New();
  vreader->SetFileName(reffname);
  vreader->Update();
  //  Software Guide : BeginLatex
  //
  // Firstly, segment the input image by using the Mean Shift algorithm (see \ref{sec:MeanShift} for deeper
  // explanations).
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::MeanShiftVectorImageFilter
  <VectorImageType, VectorImageType, LabeledImageType> FilterType;
  FilterType::Pointer filter = FilterType::New();
  filter->SetSpatialRadius(spatialRadius);
  filter->SetRangeRadius(rangeRadius);
  filter->SetMinimumRegionSize(minRegionSize);
  filter->SetScale(scale);
  // Software Guide : EndCodeSnippet

  // For non regression tests, set the number of threads to 1
  // because MeanShift results depends on the number of threads
  filter->SetNumberOfThreads(1);

  //  Software Guide : BeginLatex
  //
  // The \doxygen{otb}{MeanShiftImageFilter} type is instantiated using the image
  // types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetInput(vreader->GetOutput());
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // The \doxygen{itk}{LabelImageToLabelMapFilter} type is instantiated using the output
  // of the \doxygen{otb}{MeanShiftImageFilter}. This filter produces a labeled image
  // where each segmented region has a unique label.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  LabelMapFilterType::Pointer labelMapFilter = LabelMapFilterType::New();
  labelMapFilter->SetInput(filter->GetLabeledClusteredOutput());
  labelMapFilter->SetBackgroundValue(itk::NumericTraits<LabelType>::min());

  ShapeLabelMapFilterType::Pointer shapeLabelMapFilter =
    ShapeLabelMapFilterType::New();
  shapeLabelMapFilter->SetInput(labelMapFilter->GetOutput());
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  // Instantiate the  \doxygen{otb}{BandsStatisticsAttributesLabelMapFilter} to
  // compute radiometric value on each label object.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  RadiometricLabelMapFilterType::Pointer radiometricLabelMapFilter
    = RadiometricLabelMapFilterType::New();
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  //  Feature image could be one of the following image:
  //  \item GEMI
  //  \item NDVI
  //  \item IR
  //  \item IC
  //  \item IB
  //  \item NDWI2
  //  \item Intensity
  //
  //  Input image must be convert to the desired coefficient.
  //  In our case, radiometric label map will be process on a NDVI coefficient.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  NDVIImageFilterType:: Pointer ndviImageFilter = NDVIImageFilterType::New();

  ndviImageFilter->SetRedIndex(3);
  ndviImageFilter->SetNIRIndex(4);
  ndviImageFilter->SetInput(vreader->GetOutput());

  ImageToVectorImageCastFilterType::Pointer ndviVectorImageFilter =
      ImageToVectorImageCastFilterType::New();

  ndviVectorImageFilter->SetInput(ndviImageFilter->GetOutput());

  radiometricLabelMapFilter->SetInput(shapeLabelMapFilter->GetOutput());
  radiometricLabelMapFilter->SetFeatureImage(ndviVectorImageFilter->GetOutput());
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  // The \doxygen{otb}{AttributesMapOpeningLabelMapFilter} will perform the selection.
  // There are three parameters. \code{AttributeName} specifies the radiometric attribute, \code{Lambda}
  // controls the thresholding of the input and \code{ReverseOrdering} make this filter to remove the
  // object with an attribute value greater than \code{Lambda} instead.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  OpeningLabelMapFilterType::Pointer opening = OpeningLabelMapFilterType::New();
  opening->SetInput(radiometricLabelMapFilter->GetOutput());
  opening->SetAttributeName(attr);
  opening->SetLambda(thresh);
  opening->SetReverseOrdering(lowerThan);
  opening->Update();
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  Then, Label objects selected are transform in a Label Image using the
  //  \doxygen{itk}{LabelMapToLabelImageFilter}.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  LabelMapToBinaryImageFilterType::Pointer labelMap2LabeledImage
    = LabelMapToBinaryImageFilterType::New();
  labelMap2LabeledImage->SetInput(opening->GetOutput());
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // And finally, we declare the writer and call its \code{Update()} method to
  // trigger the full pipeline execution.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  WriterType::Pointer writer = WriterType::New();

  writer->SetFileName(outfname);
  writer->SetInput(labelMap2LabeledImage->GetOutput());
  writer->Update();
  // Software Guide : EndCodeSnippet

  OutputVectorImageType::PixelType minimum, maximum;
  minimum.SetSize(vreader->GetOutput()->GetNumberOfComponentsPerPixel());
  maximum.SetSize(vreader->GetOutput()->GetNumberOfComponentsPerPixel());
  minimum.Fill(0);
  maximum.Fill(255);

  VectorRescalerType::Pointer vr = VectorRescalerType::New();
  vr->SetInput(filter->GetClusteredOutput());
  vr->SetOutputMinimum(minimum);
  vr->SetOutputMaximum(maximum);
  vr->SetClampThreshold(0.01);

  ChannelExtractorType::Pointer selecter = ChannelExtractorType::New();
  selecter->SetInput(vr->GetOutput());
  selecter->SetExtractionRegion(vreader->GetOutput()->GetLargestPossibleRegion());
  selecter->SetChannel(3);
  selecter->SetChannel(2);
  selecter->SetChannel(1);

  VectorWriterType::Pointer vectWriter = VectorWriterType::New();
  vectWriter->SetFileName(outprettyfname);
  vectWriter->SetInput(selecter->GetOutput());
  vectWriter->Update();

  return EXIT_SUCCESS;
}

// Software Guide : BeginLatex
//
// Figure~\ref{fig:RADIOMETRIC_LABEL_MAP_FILTER} shows the result of applying
// the object selection based on radiometric attributes.
// \begin{figure} [htbp]
// \center
// \includegraphics[width=0.44\textwidth]{qb_ExtractRoad_Radiometry_pretty.eps}
// \includegraphics[width=0.44\textwidth]{OBIARadiometricAttribute1.eps}
// \itkcaption[Object based extraction based on ]{Vegetation mask resulting from processing.}
// \label{fig:RADIOMETRIC_LABEL_MAP_FILTER}
// \end{figure}
//
// Software Guide : EndLatex
<commit_msg>DOC:replace STATS:Ndvi:Mean by STATS::Band1::Mean and update the associated documentation<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt 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 notices for more information.

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

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {qb_RoadExtract.tif}
//    OUTPUTS: {OBIARadiometricAttribute1.tif}, {qb_ExtractRoad_Radiometry_pretty.jpg}
//    STATS::Band1::Mean 0 0.5 16 16 50 1.0
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example shows the basic approach to perform object based analysis on a image.
//  The input image is firstly segmented using the \doxygen{otb}{MeanShiftImageFilter}
//  Then each segmented region is converted to a Map of labeled objects.
//  Afterwards the \doxygen{otb}{otbMultiChannelRAndNIRIndexImageFilter} computes
//  radiometric attributes for each object. In this example the NDVI is computed.
//  The computed feature is passed to the \doxygen{otb}{BandsStatisticsAttributesLabelMapFilter}
//  which computes statistics over the resulting band.
//  Therefore, region's statistics over each band can be access by concatening
//  STATS, the band number and the statistical attribute separated by colons. In this example
//  the mean of the first band (which contains the NDVI) is access over all the regions
//  with the attribute: 'STATS::Band1::Mean'.
//
//  Software Guide : EndLatex

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

#include "otbMeanShiftVectorImageFilter.h"
#include "itkLabelImageToLabelMapFilter.h"
#include "otbAttributesMapLabelObject.h"
#include "itkLabelMap.h"
#include "otbShapeAttributesLabelMapFilter.h"
#include "otbStatisticsAttributesLabelMapFilter.h"
#include "otbBandsStatisticsAttributesLabelMapFilter.h"
#include "itkLabelMapToBinaryImageFilter.h"
#include "otbMultiChannelExtractROI.h"
#include "otbAttributesMapOpeningLabelMapFilter.h"
#include "otbVectorRescaleIntensityImageFilter.h"
#include "otbVegetationIndicesFunctor.h"
#include "otbMultiChannelRAndNIRIndexImageFilter.h"
#include "otbImageToVectorImageCastFilter.h"

int main(int argc, char * argv[])
{
  if (argc != 11)
    {
    std::cerr << "Usage: " << argv[0] <<
    " reffname outfname outprettyfname attribute_name ";
    std::cerr <<
    "lowerThan tresh spatialRadius rangeRadius minregionsize scale" <<
    std::endl;
    return EXIT_FAILURE;
    }

  const char * reffname = argv[1];
  const char * outfname = argv[2];
  const char * outprettyfname = argv[3];
  const char * attr     = argv[4];
  double       lowerThan      = atof(argv[5]);
  double       thresh         = atof(argv[6]);

  const unsigned int spatialRadius          = atoi(argv[7]);
  const double       rangeRadius            = atof(argv[8]);
  const unsigned int minRegionSize          = atoi(argv[9]);
  const double       scale                  = atoi(argv[10]);

  const unsigned int Dimension = 2;

  // Labeled image type
  typedef unsigned short                              LabelType;
  typedef double                                      PixelType;
  typedef otb::Image<LabelType, Dimension>            LabeledImageType;
  typedef otb::Image<PixelType, Dimension>            ImageType;
  typedef otb::VectorImage<PixelType, Dimension>      VectorImageType;
  typedef otb::VectorImage<unsigned char, Dimension>  OutputVectorImageType;
  typedef otb::ImageFileReader<LabeledImageType>      LabeledReaderType;
  typedef otb::ImageFileReader<ImageType>             ReaderType;
  typedef otb::ImageFileReader<VectorImageType>       VectorReaderType;
  typedef otb::ImageFileWriter<LabeledImageType>      WriterType;
  typedef otb::ImageFileWriter<OutputVectorImageType> VectorWriterType;
  typedef otb::VectorRescaleIntensityImageFilter
  <VectorImageType, OutputVectorImageType> VectorRescalerType;
  typedef otb::MultiChannelExtractROI<unsigned char,
      unsigned char> ChannelExtractorType;
  // Label map typedef
  typedef otb::AttributesMapLabelObject<LabelType, Dimension,
      double>
  LabelObjectType;
  typedef itk::LabelMap<LabelObjectType>
  LabelMapType;
  typedef itk::LabelImageToLabelMapFilter<LabeledImageType,
      LabelMapType>
  LabelMapFilterType;
  typedef otb::ShapeAttributesLabelMapFilter<LabelMapType>
  ShapeLabelMapFilterType;
  typedef otb::BandsStatisticsAttributesLabelMapFilter<LabelMapType,
      ImageType>
  StatisticsLabelMapFilterType;
  typedef otb::BandsStatisticsAttributesLabelMapFilter<LabelMapType,
      VectorImageType>
  RadiometricLabelMapFilterType;
  typedef otb::AttributesMapOpeningLabelMapFilter<LabelMapType>
  OpeningLabelMapFilterType;
  typedef itk::LabelMapToBinaryImageFilter<LabelMapType,
      LabeledImageType>
  LabelMapToBinaryImageFilterType;
  typedef otb::MultiChannelRAndNIRIndexImageFilter<VectorImageType,
      ImageType> NDVIImageFilterType;
  typedef otb::ImageToVectorImageCastFilter<ImageType,VectorImageType>
  ImageToVectorImageCastFilterType;

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(reffname);

  LabeledReaderType::Pointer lreader = LabeledReaderType::New();
  lreader->SetFileName(reffname);

  VectorReaderType::Pointer vreader = VectorReaderType::New();
  vreader->SetFileName(reffname);
  vreader->Update();
  //  Software Guide : BeginLatex
  //
  // Firstly, segment the input image by using the Mean Shift algorithm (see \ref{sec:MeanShift} for deeper
  // explanations).
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::MeanShiftVectorImageFilter
  <VectorImageType, VectorImageType, LabeledImageType> FilterType;
  FilterType::Pointer filter = FilterType::New();
  filter->SetSpatialRadius(spatialRadius);
  filter->SetRangeRadius(rangeRadius);
  filter->SetMinimumRegionSize(minRegionSize);
  filter->SetScale(scale);
  // Software Guide : EndCodeSnippet

  // For non regression tests, set the number of threads to 1
  // because MeanShift results depends on the number of threads
  filter->SetNumberOfThreads(1);

  //  Software Guide : BeginLatex
  //
  // The \doxygen{otb}{MeanShiftImageFilter} type is instantiated using the image
  // types.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  filter->SetInput(vreader->GetOutput());
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  // The \doxygen{itk}{LabelImageToLabelMapFilter} type is instantiated using the output
  // of the \doxygen{otb}{MeanShiftImageFilter}. This filter produces a labeled image
  // where each segmented region has a unique label.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  LabelMapFilterType::Pointer labelMapFilter = LabelMapFilterType::New();
  labelMapFilter->SetInput(filter->GetLabeledClusteredOutput());
  labelMapFilter->SetBackgroundValue(itk::NumericTraits<LabelType>::min());

  ShapeLabelMapFilterType::Pointer shapeLabelMapFilter =
    ShapeLabelMapFilterType::New();
  shapeLabelMapFilter->SetInput(labelMapFilter->GetOutput());
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  // Instantiate the  \doxygen{otb}{BandsStatisticsAttributesLabelMapFilter} to
  // compute radiometric value on each label object.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  RadiometricLabelMapFilterType::Pointer radiometricLabelMapFilter
    = RadiometricLabelMapFilterType::New();
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  //  Feature image could be one of the following image:
  //  \item GEMI
  //  \item NDVI
  //  \item IR
  //  \item IC
  //  \item IB
  //  \item NDWI2
  //  \item Intensity
  //
  //  Input image must be convert to the desired coefficient.
  //  In our case, radiometric label map will be process on a NDVI coefficient.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  NDVIImageFilterType:: Pointer ndviImageFilter = NDVIImageFilterType::New();

  ndviImageFilter->SetRedIndex(3);
  ndviImageFilter->SetNIRIndex(4);
  ndviImageFilter->SetInput(vreader->GetOutput());

  ImageToVectorImageCastFilterType::Pointer ndviVectorImageFilter =
      ImageToVectorImageCastFilterType::New();

  ndviVectorImageFilter->SetInput(ndviImageFilter->GetOutput());

  radiometricLabelMapFilter->SetInput(shapeLabelMapFilter->GetOutput());
  radiometricLabelMapFilter->SetFeatureImage(ndviVectorImageFilter->GetOutput());
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  // The \doxygen{otb}{AttributesMapOpeningLabelMapFilter} will perform the selection.
  // There are three parameters. \code{AttributeName} specifies the radiometric attribute, \code{Lambda}
  // controls the thresholding of the input and \code{ReverseOrdering} make this filter to remove the
  // object with an attribute value greater than \code{Lambda} instead.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  OpeningLabelMapFilterType::Pointer opening = OpeningLabelMapFilterType::New();
  opening->SetInput(radiometricLabelMapFilter->GetOutput());
  opening->SetAttributeName(attr);
  opening->SetLambda(thresh);
  opening->SetReverseOrdering(lowerThan);
  opening->Update();
  // Software Guide : EndCodeSnippet
  //  Software Guide : BeginLatex
  //
  //  Then, Label objects selected are transform in a Label Image using the
  //  \doxygen{itk}{LabelMapToLabelImageFilter}.
  //
  //  Software Guide : EndLatex
  // Software Guide : BeginCodeSnippet
  LabelMapToBinaryImageFilterType::Pointer labelMap2LabeledImage
    = LabelMapToBinaryImageFilterType::New();
  labelMap2LabeledImage->SetInput(opening->GetOutput());
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // And finally, we declare the writer and call its \code{Update()} method to
  // trigger the full pipeline execution.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  WriterType::Pointer writer = WriterType::New();

  writer->SetFileName(outfname);
  writer->SetInput(labelMap2LabeledImage->GetOutput());
  writer->Update();
  // Software Guide : EndCodeSnippet

  OutputVectorImageType::PixelType minimum, maximum;
  minimum.SetSize(vreader->GetOutput()->GetNumberOfComponentsPerPixel());
  maximum.SetSize(vreader->GetOutput()->GetNumberOfComponentsPerPixel());
  minimum.Fill(0);
  maximum.Fill(255);

  VectorRescalerType::Pointer vr = VectorRescalerType::New();
  vr->SetInput(filter->GetClusteredOutput());
  vr->SetOutputMinimum(minimum);
  vr->SetOutputMaximum(maximum);
  vr->SetClampThreshold(0.01);

  ChannelExtractorType::Pointer selecter = ChannelExtractorType::New();
  selecter->SetInput(vr->GetOutput());
  selecter->SetExtractionRegion(vreader->GetOutput()->GetLargestPossibleRegion());
  selecter->SetChannel(3);
  selecter->SetChannel(2);
  selecter->SetChannel(1);

  VectorWriterType::Pointer vectWriter = VectorWriterType::New();
  vectWriter->SetFileName(outprettyfname);
  vectWriter->SetInput(selecter->GetOutput());
  vectWriter->Update();

  return EXIT_SUCCESS;
}

// Software Guide : BeginLatex
//
// Figure~\ref{fig:RADIOMETRIC_LABEL_MAP_FILTER} shows the result of applying
// the object selection based on radiometric attributes.
// \begin{figure} [htbp]
// \center
// \includegraphics[width=0.44\textwidth]{qb_ExtractRoad_Radiometry_pretty.eps}
// \includegraphics[width=0.44\textwidth]{OBIARadiometricAttribute1.eps}
// \itkcaption[Object based extraction based on ]{Vegetation mask resulting from processing.}
// \label{fig:RADIOMETRIC_LABEL_MAP_FILTER}
// \end{figure}
//
// Software Guide : EndLatex
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2021 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "HeadIstream.hxx"
#include "ForwardIstream.hxx"
#include "UnusedPtr.hxx"
#include "Bucket.hxx"
#include "New.hxx"

#include <algorithm>

#include <assert.h>

class HeadIstream final : public ForwardIstream {
	off_t rest;
	const bool authoritative;

public:
	HeadIstream(struct pool &p, UnusedIstreamPtr _input,
		    size_t size, bool _authoritative) noexcept
		:ForwardIstream(p, std::move(_input)),
		 rest(size), authoritative(_authoritative) {}

	/* virtual methods from class Istream */

	off_t _GetAvailable(bool partial) noexcept override;
	off_t _Skip(off_t length) noexcept override;
	void _Read() noexcept override;

	void _FillBucketList(IstreamBucketList &list) override;

	int _AsFd() noexcept override {
		return -1;
	}

	/* virtual methods from class IstreamHandler */
	size_t OnData(const void *data, size_t length) noexcept override;
	ssize_t OnDirect(FdType type, int fd, size_t max_length) noexcept override;
};

/*
 * istream handler
 *
 */

size_t
HeadIstream::OnData(const void *data, size_t length) noexcept
{
	if (rest == 0) {
		DestroyEof();
		return 0;
	}

	if ((off_t)length > rest)
		length = rest;

	size_t nbytes = InvokeData(data, length);
	assert((off_t)nbytes <= rest);

	if (nbytes > 0) {
		rest -= nbytes;
		if (rest == 0) {
			DestroyEof();
			return 0;
		}
	}

	return nbytes;
}

void
HeadIstream::_FillBucketList(IstreamBucketList &list)
{
	if (rest == 0)
		return;

	IstreamBucketList tmp1;

	try {
		input.FillBucketList(tmp1);
	} catch (...) {
		Destroy();
		throw;
	}

	size_t nbytes = list.SpliceBuffersFrom(std::move(tmp1), rest);
	if ((off_t)nbytes >= rest)
		list.SetMore(false);
}

ssize_t
HeadIstream::OnDirect(FdType type, int fd, size_t max_length) noexcept
{
	if (rest == 0) {
		DestroyEof();
		return ISTREAM_RESULT_CLOSED;
	}

	if ((off_t)max_length > rest)
		max_length = rest;

	ssize_t nbytes = InvokeDirect(type, fd, max_length);
	assert(nbytes < 0 || (off_t)nbytes <= rest);

	if (nbytes > 0) {
		rest -= (size_t)nbytes;
		if (rest == 0) {
			DestroyEof();
			return ISTREAM_RESULT_CLOSED;
		}
	}

	return nbytes;
}

/*
 * istream implementation
 *
 */

off_t
HeadIstream::_GetAvailable(bool partial) noexcept
{
	if (authoritative) {
		assert(partial ||
		       input.GetAvailable(partial) < 0 ||
		       input.GetAvailable(partial) >= (off_t)rest);
		return rest;
	}

	off_t available = input.GetAvailable(partial);
	return std::min(available, rest);
}

off_t
HeadIstream::_Skip(off_t length) noexcept
{
	if (length >= rest)
		length = rest;

	off_t nbytes = ForwardIstream::_Skip(length);
	assert(nbytes <= length);

	if (nbytes > 0)
		rest -= nbytes;

	return nbytes;
}

void
HeadIstream::_Read() noexcept
{
	if (rest == 0) {
		DestroyEof();
	} else {
		ForwardIstream::_Read();
	}
}

/*
 * constructor
 *
 */

UnusedIstreamPtr
istream_head_new(struct pool &pool, UnusedIstreamPtr input,
		 size_t size, bool authoritative) noexcept
{
	return NewIstreamPtr<HeadIstream>(pool, std::move(input),
					  size, authoritative);
}
<commit_msg>istream/head: implement _ConsumeBucketList() to fix assertion failure<commit_after>/*
 * Copyright 2007-2021 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "HeadIstream.hxx"
#include "ForwardIstream.hxx"
#include "UnusedPtr.hxx"
#include "Bucket.hxx"
#include "New.hxx"

#include <algorithm>

#include <assert.h>

class HeadIstream final : public ForwardIstream {
	off_t rest;
	const bool authoritative;

public:
	HeadIstream(struct pool &p, UnusedIstreamPtr _input,
		    size_t size, bool _authoritative) noexcept
		:ForwardIstream(p, std::move(_input)),
		 rest(size), authoritative(_authoritative) {}

	/* virtual methods from class Istream */

	off_t _GetAvailable(bool partial) noexcept override;
	size_t _ConsumeBucketList(size_t nbytes) noexcept override;
	off_t _Skip(off_t length) noexcept override;
	void _Read() noexcept override;

	void _FillBucketList(IstreamBucketList &list) override;

	int _AsFd() noexcept override {
		return -1;
	}

	/* virtual methods from class IstreamHandler */
	size_t OnData(const void *data, size_t length) noexcept override;
	ssize_t OnDirect(FdType type, int fd, size_t max_length) noexcept override;
};

/*
 * istream handler
 *
 */

size_t
HeadIstream::OnData(const void *data, size_t length) noexcept
{
	if (rest == 0) {
		DestroyEof();
		return 0;
	}

	if ((off_t)length > rest)
		length = rest;

	size_t nbytes = InvokeData(data, length);
	assert((off_t)nbytes <= rest);

	if (nbytes > 0) {
		rest -= nbytes;
		if (rest == 0) {
			DestroyEof();
			return 0;
		}
	}

	return nbytes;
}

void
HeadIstream::_FillBucketList(IstreamBucketList &list)
{
	if (rest == 0)
		return;

	IstreamBucketList tmp1;

	try {
		input.FillBucketList(tmp1);
	} catch (...) {
		Destroy();
		throw;
	}

	size_t nbytes = list.SpliceBuffersFrom(std::move(tmp1), rest);
	if ((off_t)nbytes >= rest)
		list.SetMore(false);
}

size_t
HeadIstream::_ConsumeBucketList(size_t nbytes) noexcept
{
	if ((off_t)nbytes > rest)
		nbytes = rest;

	nbytes = ForwardIstream::_ConsumeBucketList(nbytes);
	rest -= nbytes;
	return nbytes;
}

ssize_t
HeadIstream::OnDirect(FdType type, int fd, size_t max_length) noexcept
{
	if (rest == 0) {
		DestroyEof();
		return ISTREAM_RESULT_CLOSED;
	}

	if ((off_t)max_length > rest)
		max_length = rest;

	ssize_t nbytes = InvokeDirect(type, fd, max_length);
	assert(nbytes < 0 || (off_t)nbytes <= rest);

	if (nbytes > 0) {
		rest -= (size_t)nbytes;
		if (rest == 0) {
			DestroyEof();
			return ISTREAM_RESULT_CLOSED;
		}
	}

	return nbytes;
}

/*
 * istream implementation
 *
 */

off_t
HeadIstream::_GetAvailable(bool partial) noexcept
{
	if (authoritative) {
		assert(partial ||
		       input.GetAvailable(partial) < 0 ||
		       input.GetAvailable(partial) >= (off_t)rest);
		return rest;
	}

	off_t available = input.GetAvailable(partial);
	return std::min(available, rest);
}

off_t
HeadIstream::_Skip(off_t length) noexcept
{
	if (length >= rest)
		length = rest;

	off_t nbytes = ForwardIstream::_Skip(length);
	assert(nbytes <= length);

	if (nbytes > 0)
		rest -= nbytes;

	return nbytes;
}

void
HeadIstream::_Read() noexcept
{
	if (rest == 0) {
		DestroyEof();
	} else {
		ForwardIstream::_Read();
	}
}

/*
 * constructor
 *
 */

UnusedIstreamPtr
istream_head_new(struct pool &pool, UnusedIstreamPtr input,
		 size_t size, bool authoritative) noexcept
{
	return NewIstreamPtr<HeadIstream>(pool, std::move(input),
					  size, authoritative);
}
<|endoftext|>


<commit_before>/*
  Adplug - Replayer for many OPL2/OPL3 audio file formats.
  Copyright (C) 1999 - 2007 Simon Peter <dn.tlp@gmx.net>, et al.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  fmc.cpp - FMC Loader by Riven the Mage <riven@ok.ru>
*/

#include <cstring>
#include "fmc.h"

/* -------- Public Methods -------------------------------- */

CPlayer *CfmcLoader::factory(Copl *newopl)
{
  return new CfmcLoader(newopl);
}

bool CfmcLoader::load(const std::string &filename, const CFileProvider &fp)
{
  binistream *f = fp.open(filename); if(!f) return false;
  const unsigned char conv_fx[16] = {0,1,2,3,4,8,255,255,255,255,26,11,12,13,14,15};

  int i,j,k,t=0;

  // read header
  f->readString(header.id, 4);
  f->readString(header.title, 21);
  header.numchan = f->readInt(1);

  // 'FMC!' - signed ?
  if (strncmp(header.id,"FMC!",4)) { fp.close(f); return false; }

  // init CmodPlayer
  realloc_instruments(32);
  realloc_order(256);
  realloc_patterns(64,64,header.numchan);
  init_trackord();

  // load order
  for(i = 0; i < 256; i++) order[i] = f->readInt(1);

  f->ignore(2);

  // load instruments
  for(i = 0; i < 32; i++) {
    instruments[i].synthesis = f->readInt(1);
    instruments[i].feedback = f->readInt(1);

    instruments[i].mod_attack = f->readInt(1);
    instruments[i].mod_decay = f->readInt(1);
    instruments[i].mod_sustain = f->readInt(1);
    instruments[i].mod_release = f->readInt(1);
    instruments[i].mod_volume = f->readInt(1);
    instruments[i].mod_ksl = f->readInt(1);
    instruments[i].mod_freq_multi = f->readInt(1);
    instruments[i].mod_waveform = f->readInt(1);
    instruments[i].mod_sustain_sound = f->readInt(1);
    instruments[i].mod_ksr = f->readInt(1);
    instruments[i].mod_vibrato = f->readInt(1);
    instruments[i].mod_tremolo = f->readInt(1);

    instruments[i].car_attack = f->readInt(1);
    instruments[i].car_decay = f->readInt(1);
    instruments[i].car_sustain = f->readInt(1);
    instruments[i].car_release = f->readInt(1);
    instruments[i].car_volume = f->readInt(1);
    instruments[i].car_ksl = f->readInt(1);
    instruments[i].car_freq_multi = f->readInt(1);
    instruments[i].car_waveform = f->readInt(1);
    instruments[i].car_sustain_sound = f->readInt(1);
    instruments[i].car_ksr = f->readInt(1);
    instruments[i].car_vibrato = f->readInt(1);
    instruments[i].car_tremolo = f->readInt(1);

    instruments[i].pitch_shift = f->readInt(1);

    f->readString(instruments[i].name, 21);
  }

  // load tracks
  for (i=0;i<64;i++)
    {
      if(f->ateof()) break;

      for (j=0;j<header.numchan;j++)
	{
	  for (k=0;k<64;k++)
	    {
	      fmc_event event;

	      // read event
	      event.byte0 = f->readInt(1);
	      event.byte1 = f->readInt(1);
	      event.byte2 = f->readInt(1);

	      // convert event
	      tracks[t][k].note = event.byte0 & 0x7F;
	      tracks[t][k].inst = ((event.byte0 & 0x80) >> 3) + (event.byte1 >> 4) + 1;
	      tracks[t][k].command = conv_fx[event.byte1 & 0x0F];
	      tracks[t][k].param1 = event.byte2 >> 4;
	      tracks[t][k].param2 = event.byte2 & 0x0F;

	      // fix effects
	      if (tracks[t][k].command == 0x0E)   // 0x0E (14): Retrig
		tracks[t][k].param1 = 3;
	      if (tracks[t][k].command == 0x1A) { // 0x1A (26): Volume Slide
		if (tracks[t][k].param1 > tracks[t][k].param2)
		  {
		    tracks[t][k].param1 -= tracks[t][k].param2;
		    tracks[t][k].param2 = 0;
		  }
		else
		  {
		    tracks[t][k].param2 -= tracks[t][k].param1;
		    tracks[t][k].param1 = 0;
		  }
	      }
	    }

	  t++;
	}
    }
  fp.close(f);

  // convert instruments
  for (i=0;i<31;i++)
    buildinst(i);

  // order length
  for (i=0;i<256;i++)
    {
      if (order[i] >= 0xFE)
	{
	  length = i;
	  break;
	}
    }

  // data for Protracker
  activechan = (0xffffffff >> (32 - header.numchan)) << (32 - header.numchan);
  nop = t / header.numchan;
  restartpos = 0;

  // flags
  flags = Faust;

  rewind(0);

  return true;
}

float CfmcLoader::getrefresh()
{
  return 50.0f;
}

std::string CfmcLoader::gettype()
{
  return std::string("Faust Music Creator");
}

std::string CfmcLoader::gettitle()
{
  return std::string(header.title);
}

std::string CfmcLoader::getinstrument(unsigned int n)
{
  return std::string(instruments[n].name);
}

unsigned int CfmcLoader::getinstruments()
{
  return 32;
}

/* -------- Private Methods ------------------------------- */

void CfmcLoader::buildinst(unsigned char i)
{
  inst[i].data[0]   = ((instruments[i].synthesis & 1) ^ 1);
  inst[i].data[0]  |= ((instruments[i].feedback & 7) << 1);

  inst[i].data[3]   = ((instruments[i].mod_attack & 15) << 4);
  inst[i].data[3]  |=  (instruments[i].mod_decay & 15);
  inst[i].data[5]   = ((15 - (instruments[i].mod_sustain & 15)) << 4);
  inst[i].data[5]  |=  (instruments[i].mod_release & 15);
  inst[i].data[9]   =  (63 - (instruments[i].mod_volume & 63));
  inst[i].data[9]  |= ((instruments[i].mod_ksl & 3) << 6);
  inst[i].data[1]   =  (instruments[i].mod_freq_multi & 15);
  inst[i].data[7]   =  (instruments[i].mod_waveform & 3);
  inst[i].data[1]  |= ((instruments[i].mod_sustain_sound & 1) << 5);
  inst[i].data[1]  |= ((instruments[i].mod_ksr & 1) << 4);
  inst[i].data[1]  |= ((instruments[i].mod_vibrato & 1) << 6);
  inst[i].data[1]  |= ((instruments[i].mod_tremolo & 1) << 7);

  inst[i].data[4]   = ((instruments[i].car_attack & 15) << 4);
  inst[i].data[4]  |=  (instruments[i].car_decay & 15);
  inst[i].data[6]   = ((15 - (instruments[i].car_sustain & 15)) << 4);
  inst[i].data[6]  |=  (instruments[i].car_release & 15);
  inst[i].data[10]  =  (63 - (instruments[i].car_volume & 63));
  inst[i].data[10] |= ((instruments[i].car_ksl & 3) << 6);
  inst[i].data[2]   =  (instruments[i].car_freq_multi & 15);
  inst[i].data[8]   =  (instruments[i].car_waveform & 3);
  inst[i].data[2]  |= ((instruments[i].car_sustain_sound & 1) << 5);
  inst[i].data[2]  |= ((instruments[i].car_ksr & 1) << 4);
  inst[i].data[2]  |= ((instruments[i].car_vibrato & 1) << 6);
  inst[i].data[2]  |= ((instruments[i].car_tremolo & 1) << 7);

  inst[i].slide     =   instruments[i].pitch_shift;
}
<commit_msg>Fix division by zero and unterminated strings in CfmcLoader::load()<commit_after>/*
  Adplug - Replayer for many OPL2/OPL3 audio file formats.
  Copyright (C) 1999 - 2007 Simon Peter <dn.tlp@gmx.net>, et al.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  fmc.cpp - FMC Loader by Riven the Mage <riven@ok.ru>
*/

#include <cstring>
#include "fmc.h"

/* -------- Public Methods -------------------------------- */

CPlayer *CfmcLoader::factory(Copl *newopl)
{
  return new CfmcLoader(newopl);
}

bool CfmcLoader::load(const std::string &filename, const CFileProvider &fp)
{
  binistream *f = fp.open(filename); if(!f) return false;
  const unsigned char conv_fx[16] = {0,1,2,3,4,8,255,255,255,255,26,11,12,13,14,15};

  int i,j,k,t=0;

  // read header
  f->readString(header.id, 4);
  f->readString(header.title, 21);
  header.title[20] = 0;
  header.numchan = f->readInt(1);

  // 'FMC!' - signed ?
  if (memcmp(header.id, "FMC!", 4) ||
      header.numchan < 1 || header.numchan > 32) {
    fp.close(f); return false;
  }

  // init CmodPlayer
  realloc_instruments(32);
  realloc_order(256);
  realloc_patterns(64,64,header.numchan);
  init_trackord();

  // load order
  for(i = 0; i < 256; i++) order[i] = f->readInt(1);

  f->ignore(2);

  // load instruments
  for(i = 0; i < 32; i++) {
    instruments[i].synthesis = f->readInt(1);
    instruments[i].feedback = f->readInt(1);

    instruments[i].mod_attack = f->readInt(1);
    instruments[i].mod_decay = f->readInt(1);
    instruments[i].mod_sustain = f->readInt(1);
    instruments[i].mod_release = f->readInt(1);
    instruments[i].mod_volume = f->readInt(1);
    instruments[i].mod_ksl = f->readInt(1);
    instruments[i].mod_freq_multi = f->readInt(1);
    instruments[i].mod_waveform = f->readInt(1);
    instruments[i].mod_sustain_sound = f->readInt(1);
    instruments[i].mod_ksr = f->readInt(1);
    instruments[i].mod_vibrato = f->readInt(1);
    instruments[i].mod_tremolo = f->readInt(1);

    instruments[i].car_attack = f->readInt(1);
    instruments[i].car_decay = f->readInt(1);
    instruments[i].car_sustain = f->readInt(1);
    instruments[i].car_release = f->readInt(1);
    instruments[i].car_volume = f->readInt(1);
    instruments[i].car_ksl = f->readInt(1);
    instruments[i].car_freq_multi = f->readInt(1);
    instruments[i].car_waveform = f->readInt(1);
    instruments[i].car_sustain_sound = f->readInt(1);
    instruments[i].car_ksr = f->readInt(1);
    instruments[i].car_vibrato = f->readInt(1);
    instruments[i].car_tremolo = f->readInt(1);

    instruments[i].pitch_shift = f->readInt(1);

    f->readString(instruments[i].name, 21);
    instruments[i].name[20] = 0;
  }

  // load tracks
  for (i=0;i<64;i++)
    {
      if(f->ateof()) break;

      for (j=0;j<header.numchan;j++)
	{
	  for (k=0;k<64;k++)
	    {
	      fmc_event event;

	      // read event
	      event.byte0 = f->readInt(1);
	      event.byte1 = f->readInt(1);
	      event.byte2 = f->readInt(1);

	      // convert event
	      tracks[t][k].note = event.byte0 & 0x7F;
	      tracks[t][k].inst = ((event.byte0 & 0x80) >> 3) + (event.byte1 >> 4) + 1;
	      tracks[t][k].command = conv_fx[event.byte1 & 0x0F];
	      tracks[t][k].param1 = event.byte2 >> 4;
	      tracks[t][k].param2 = event.byte2 & 0x0F;

	      // fix effects
	      if (tracks[t][k].command == 0x0E)   // 0x0E (14): Retrig
		tracks[t][k].param1 = 3;
	      if (tracks[t][k].command == 0x1A) { // 0x1A (26): Volume Slide
		if (tracks[t][k].param1 > tracks[t][k].param2)
		  {
		    tracks[t][k].param1 -= tracks[t][k].param2;
		    tracks[t][k].param2 = 0;
		  }
		else
		  {
		    tracks[t][k].param2 -= tracks[t][k].param1;
		    tracks[t][k].param1 = 0;
		  }
	      }
	    }

	  t++;
	}
    }
  fp.close(f);

  // convert instruments
  for (i=0;i<31;i++)
    buildinst(i);

  // order length
  for (i=0;i<256;i++)
    {
      if (order[i] >= 0xFE)
	{
	  length = i;
	  break;
	}
    }

  // data for Protracker
  activechan = (0xffffffffUL >> (32 - header.numchan)) << (32 - header.numchan);
  nop = t / header.numchan;
  restartpos = 0;

  // flags
  flags = Faust;

  rewind(0);

  return true;
}

float CfmcLoader::getrefresh()
{
  return 50.0f;
}

std::string CfmcLoader::gettype()
{
  return std::string("Faust Music Creator");
}

std::string CfmcLoader::gettitle()
{
  return std::string(header.title);
}

std::string CfmcLoader::getinstrument(unsigned int n)
{
  return n < 32 ? std::string(instruments[n].name) : std::string();
}

unsigned int CfmcLoader::getinstruments()
{
  return 32;
}

/* -------- Private Methods ------------------------------- */

void CfmcLoader::buildinst(unsigned char i)
{
  inst[i].data[0]   = ((instruments[i].synthesis & 1) ^ 1);
  inst[i].data[0]  |= ((instruments[i].feedback & 7) << 1);

  inst[i].data[3]   = ((instruments[i].mod_attack & 15) << 4);
  inst[i].data[3]  |=  (instruments[i].mod_decay & 15);
  inst[i].data[5]   = ((15 - (instruments[i].mod_sustain & 15)) << 4);
  inst[i].data[5]  |=  (instruments[i].mod_release & 15);
  inst[i].data[9]   =  (63 - (instruments[i].mod_volume & 63));
  inst[i].data[9]  |= ((instruments[i].mod_ksl & 3) << 6);
  inst[i].data[1]   =  (instruments[i].mod_freq_multi & 15);
  inst[i].data[7]   =  (instruments[i].mod_waveform & 3);
  inst[i].data[1]  |= ((instruments[i].mod_sustain_sound & 1) << 5);
  inst[i].data[1]  |= ((instruments[i].mod_ksr & 1) << 4);
  inst[i].data[1]  |= ((instruments[i].mod_vibrato & 1) << 6);
  inst[i].data[1]  |= ((instruments[i].mod_tremolo & 1) << 7);

  inst[i].data[4]   = ((instruments[i].car_attack & 15) << 4);
  inst[i].data[4]  |=  (instruments[i].car_decay & 15);
  inst[i].data[6]   = ((15 - (instruments[i].car_sustain & 15)) << 4);
  inst[i].data[6]  |=  (instruments[i].car_release & 15);
  inst[i].data[10]  =  (63 - (instruments[i].car_volume & 63));
  inst[i].data[10] |= ((instruments[i].car_ksl & 3) << 6);
  inst[i].data[2]   =  (instruments[i].car_freq_multi & 15);
  inst[i].data[8]   =  (instruments[i].car_waveform & 3);
  inst[i].data[2]  |= ((instruments[i].car_sustain_sound & 1) << 5);
  inst[i].data[2]  |= ((instruments[i].car_ksr & 1) << 4);
  inst[i].data[2]  |= ((instruments[i].car_vibrato & 1) << 6);
  inst[i].data[2]  |= ((instruments[i].car_tremolo & 1) << 7);

  inst[i].slide     =   instruments[i].pitch_shift;
}
<|endoftext|>


<commit_before>#include "desktop_media_manager.h"

#include <cassert>

DesktopMediaManager::DesktopMediaManager(const std::string& hostname)
  : hostname_(hostname),
    format_() {
}

void DesktopMediaManager::Play() {
  assert(gst_pipeline_);
  gst_pipeline_->SetState(GST_STATE_PLAYING);
}

void DesktopMediaManager::Pause() {
  assert(gst_pipeline_);
  gst_pipeline_->SetState(GST_STATE_PAUSED);
}

void DesktopMediaManager::Teardown() {
  if (gst_pipeline_)
    gst_pipeline_->SetState(GST_STATE_READY);
}

bool DesktopMediaManager::IsPaused() const {
  return (gst_pipeline_->GetState() != GST_STATE_PLAYING);
}

void DesktopMediaManager::SetSinkRtpPorts(int port1, int port2) {
  sink_port1_ = port1;
  sink_port2_ = port2;
  gst_pipeline_.reset(new MiracGstTestSource(WFD_DESKTOP, hostname_, port1));
  gst_pipeline_->SetState(GST_STATE_READY);
}

std::pair<int, int> DesktopMediaManager::SinkRtpPorts() const {
  return std::pair<int, int>(sink_port1_, sink_port2_);
}

int DesktopMediaManager::SourceRtpPort() const {
  return gst_pipeline_->UdpSourcePort();
}

std::vector<wfd::SelectableH264VideoFormat>
DesktopMediaManager::GetSelectableH264VideoFormats() const {
  return {wfd::SelectableH264VideoFormat()};
}

bool DesktopMediaManager::SetOptimalFormat(
    const wfd::SelectableH264VideoFormat& optimal_format) {
  format_ = optimal_format;
  return true;
}

wfd::SelectableH264VideoFormat DesktopMediaManager::GetOptimalFormat() const {
  return format_;
}
<commit_msg>Make gstreamer source support full set of resolutions<commit_after>#include "desktop_media_manager.h"

#include <cassert>

DesktopMediaManager::DesktopMediaManager(const std::string& hostname)
  : hostname_(hostname),
    format_() {
}

void DesktopMediaManager::Play() {
  assert(gst_pipeline_);
  gst_pipeline_->SetState(GST_STATE_PLAYING);
}

void DesktopMediaManager::Pause() {
  assert(gst_pipeline_);
  gst_pipeline_->SetState(GST_STATE_PAUSED);
}

void DesktopMediaManager::Teardown() {
  if (gst_pipeline_)
    gst_pipeline_->SetState(GST_STATE_READY);
}

bool DesktopMediaManager::IsPaused() const {
  return (gst_pipeline_->GetState() != GST_STATE_PLAYING);
}

void DesktopMediaManager::SetSinkRtpPorts(int port1, int port2) {
  sink_port1_ = port1;
  sink_port2_ = port2;
  gst_pipeline_.reset(new MiracGstTestSource(WFD_DESKTOP, hostname_, port1));
  gst_pipeline_->SetState(GST_STATE_READY);
}

std::pair<int, int> DesktopMediaManager::SinkRtpPorts() const {
  return std::pair<int, int>(sink_port1_, sink_port2_);
}

int DesktopMediaManager::SourceRtpPort() const {
  return gst_pipeline_->UdpSourcePort();
}

std::vector<wfd::SelectableH264VideoFormat>
DesktopMediaManager::GetSelectableH264VideoFormats() const {
  std::vector<wfd::SelectableH264VideoFormat> formats;

  wfd::RateAndResolution i;

  for (i = wfd::CEA640x480p60; i <= wfd::CEA1920x1080p24; i = i + 1)
      formats.push_back(wfd::SelectableH264VideoFormat(wfd::CHP, wfd::k4_2, wfd::CEARatesAndResolutions(i)));
  for (i = wfd::VESA800x600p30; i <= wfd::VESA1920x1200p30; i = i + 1)
      formats.push_back(wfd::SelectableH264VideoFormat(wfd::CHP, wfd::k4_2, wfd::VESARatesAndResolutions(i)));
  for (i = wfd::HH800x480p30; i <= wfd::HH848x480p60; i = i + 1)
      formats.push_back(wfd::SelectableH264VideoFormat(wfd::CHP, wfd::k4_2, wfd::HHRatesAndResolutions(i)));

  return formats;
}

bool DesktopMediaManager::SetOptimalFormat(
    const wfd::SelectableH264VideoFormat& optimal_format) {
  format_ = optimal_format;
  return true;
}

wfd::SelectableH264VideoFormat DesktopMediaManager::GetOptimalFormat() const {
  return format_;
}
<|endoftext|>


<commit_before>#include "blockdevices.h"

#include <list>
#include <cxxutils/posix_helpers.h>

#include <unistd.h>

#if defined(__linux__)
#include <linux/fs.h>
#else // *BSD/Darwin
#include <sys/disklabel.h>
#include <sys/disk.h>
#endif

#include <arpa/inet.h>

#ifndef DEVFS_PATH
#define DEVFS_PATH          "/dev"
#endif

#define EXT_MAGIC_NUMBER                  0xEF53
#define EXT_COMPAT_FLAG_HAS_JOURNAL       0x00000004
#define EXT_INCOMPAT_FLAG_JOURNAL_DEV     0x00000008

#define EXT_BLOCK_COUNT_OFFSET            (superblock + 0x04)
#define EXT_BLOCK_SIZE_OFFSET             (superblock + 0x18)
#define EXT_MAGIC_NUMBER_OFFSET           (superblock + 0x38)
#define EXT_COMPAT_FLAGS_OFFSET           (superblock + 0x5C)
#define EXT_INCOMPAT_FLAGS_OFFSET         (superblock + 0x60)
#define EXT_UUID_OFFSET                   (superblock + 0x68)
#define EXT_LABEL_OFFSET                  (superblock + 0x78)

uint64_t read(posix::fd_t fd, off_t offset, uint8_t* buffer, uint64_t length)
{
  if(::lseek(fd, offset, SEEK_SET) != offset)
    return 0;

  uint64_t remaining = length;
  ssize_t rval;
  for(uint8_t* pos = buffer; remaining > 0; pos += rval, remaining -= rval)
    rval = posix::read(fd, pos, remaining);

  return length - remaining;
}

#ifndef BLOCK_SIZE
#define BLOCK_SIZE 0x400
#endif

struct uintle16_t
{
  uint8_t low;
  uint8_t high;
  constexpr operator uint16_t(void) const { return low + (high << 8); }
};
static_assert(sizeof(uintle16_t) == sizeof(uint16_t), "naughty compiler!");

struct uintle32_t
{
  uint8_t bottom;
  uint8_t low;
  uint8_t high;
  uint8_t top;
  constexpr operator uint32_t(void) const
  {
    return bottom +
        (low  <<  8) +
        (high << 16) +
        (top  << 24);
  }
};
static_assert(sizeof(uintle32_t) == sizeof(uint32_t), "naughty compiler!");

template<typename T> constexpr uint16_t get16(T* x) { return *reinterpret_cast<uint16_t*>(x); }
template<typename T> constexpr uint32_t get32(T* x) { return *reinterpret_cast<uint32_t*>(x); }
template<typename T> constexpr uint16_t getLE16(T* x) { return *reinterpret_cast<uintle16_t*>(x); }
template<typename T> constexpr uint32_t getLE32(T* x) { return *reinterpret_cast<uintle32_t*>(x); }

constexpr char uuid_digit(uint8_t* data, uint8_t digit)
  { return  "0123456789ABCDEF"[(digit & 1) ? (data[digit/2] & 0x0F) : (data[digit/2] >> 4)]; }

static bool uuid_matches(const char* str, uint8_t* data)
{
  size_t length = std::strlen(str);
  for(uint8_t digit = 0; digit < 32; ++digit, ++str)
  {
    if(!std::isxdigit(*str))
      { --length; ++str; }
    if(digit >= length || std::toupper(*str) != uuid_digit(data, digit))
      return false;
  }
  return true;
}

/*
static void uuid_decode(uint8_t* data, std::string& uuid)
{
  for(uint8_t digit = 0; digit < 32; ++digit)
    uuid.push_back(uuid_digit(data, digit));
}
*/

namespace blockdevices
{
  static std::list<blockdevice_t> devices;
  void detect(void);

#if defined(WANT_PROCFS)
  void init(const char* procfs_path)
  {
    devices.clear();
    char filename[PATH_MAX] = { 0 };
    std::strcpy(filename, procfs_path);
    std::strcat(filename, "/partitions");

    std::FILE* file = posix::fopen(filename, "r");
    if(file == nullptr)
      return;

    posix::ssize_t count = 0;
    posix::size_t size = 0;
    char* line = nullptr;
    char* begin = nullptr;
    while((count = ::getline(&line, &size, file)) != posix::error_response)
    {
      char* pos = line;
      if(!std::isspace(*pos)) // if line doesn't start with a space then it's not an entry!
        continue;

      while(*pos && std::isspace(*pos))
        ++pos;
      while(*pos && std::isdigit(*pos))
        ++pos;

      while(*pos && std::isspace(*pos))
        ++pos;
      while(*pos && std::isdigit(*pos))
        ++pos;

      while(*pos && std::isspace(*pos))
        ++pos;
      while(*pos && std::isdigit(*pos))
        ++pos;

      while(*pos && std::isspace(*pos))
        ++pos;

      if(!*pos) // if at end of line, skip
        continue;

      // read device name
      blockdevice_t dev;
      std::strcpy(dev.path, DEVFS_PATH);
      std::strcat(dev.path, "/");
      for(char* field = dev.path + std::strlen(dev.path);
          *pos && pos < dev.path + sizeof(blockdevice_t::path) && std::isgraph(*pos);
          ++pos, ++field)
        *field = *pos;
      {
        devices.emplace_back(dev);
      }
    }
    ::free(line); // use C free() because we're using C getline()
    line = nullptr;

    posix::fclose(file);

    detect();
  }

#else
  void init(void)
  {
#pragma message("Code needed to detect GEOM devices like gpart@")
    detect();
  }
#endif

  blockdevice_t* lookupByPath(const char* path) noexcept // finds device based on absolute path
  {
    for(blockdevice_t& dev : devices)
      if(!std::strcmp(path, dev.path))
        return &dev;
    return nullptr;
  }

  blockdevice_t* lookupByUUID(const char* uuid) noexcept // finds device based on uuid
  {
    for(blockdevice_t& dev : devices)
      if(uuid_matches(uuid, dev.uuid))
        return &dev;
    return nullptr;
  }

  blockdevice_t* lookupByLabel(const char* label) noexcept // finds device based on label
  {
    for(blockdevice_t& dev : devices)
      if(!std::strcmp(label, dev.label))
        return &dev;
    return nullptr;
  }

  blockdevice_t* lookup(const char* id)
  {
    for(blockdevice_t& dev : devices)
    {
      if(!std::strcmp(id, dev.label) ||
         !std::strcmp(id, dev.path) ||
         uuid_matches(id, dev.uuid))
        return &dev;
    }
    return nullptr;
  }

  void detect(void)
  {
    uint8_t superblock[BLOCK_SIZE];
    uint32_t blocksize;
    uint64_t blockcount;

    for(blockdevice_t& dev : devices)
    {
      posix::fd_t fd = posix::open(dev.path, O_RDONLY);
      dev.size = 0;

      if(fd != posix::error_response)
      {
  #if defined(BLKGETSIZE64) // Linux 2.6+
        posix::ioctl(fd, BLKGETSIZE64, &dev.size);

  #elif defined(DKIOCGETBLOCKCOUNT) // Darwin
        blocksize = 0;
        blockcount = 0;
        if(posix::ioctl(fd, DKIOCGETBLOCKSIZE , &blocksize ) > posix::error_response &&
           posix::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockcount) > posix::error_response)
          dev.size = blockcount * blocksize;

  #elif defined(DIOCGMEDIASIZE) // current BSD
        posix::ioctl(fd, DIOCGMEDIASIZE, &dev.size);

  #elif defined(DIOCGDINFO) // old BSD
        struct disklabel info;
        if(posix::ioctl(fd, DIOCGDINFO, &info) > posix::error_response)
          dev.size = info.d_ncylinders * info.d_secpercyl * info.d_secsize;

  #else
        dev.size = ::lseek(fd, 0, SEEK_END); // behavior not defined in POSIX for devices but try as a last resort

  #pragma message("No device interface defined for this operating system.  Please add one to device.cpp!")
  #endif
      }

      std::memset(superblock, 0, BLOCK_SIZE);
      if(read(fd, BLOCK_SIZE, superblock, BLOCK_SIZE) == BLOCK_SIZE) // if read filesystem superblock
      {
        // see "struct ext2_super_block" in https://github.com/torvalds/linux/blob/master/fs/ext2/ext2.h
        // see "struct ext4_super_block" in https://github.com/torvalds/linux/blob/master/fs/ext4/ext4.h
        // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#The_Super_Block
        if(getLE16(EXT_MAGIC_NUMBER_OFFSET) == EXT_MAGIC_NUMBER) // test if Ext2/3/4
        {
          blockcount = getLE32(EXT_BLOCK_COUNT_OFFSET);
          blocksize  = BLOCK_SIZE << getLE32(EXT_BLOCK_SIZE_OFFSET);

        //if(get32(EXT_INCOMPAT_FLAGS_OFFSET) & EXT_INCOMPAT_FLAG_JOURNAL_DEV)

          if(getLE32(EXT_COMPAT_FLAGS_OFFSET) & EXT_COMPAT_FLAG_HAS_JOURNAL)
            std::strcpy(dev.fstype, "ext3");
          else
            std::strcpy(dev.fstype, "ext2");
          std::memcpy(dev.uuid, EXT_UUID_OFFSET, 16);
          std::strncpy(dev.label, (const char*)EXT_LABEL_OFFSET, 16);
        }
      }
/*
      std::string uuid;
      uuid_decode(dev.uuid, uuid);
      printf("PATH: %s - UUID: %s - LABEL: %s - filesystem: %s - size: %lu\n", dev.path, uuid.c_str(), dev.label, dev.fstype, dev.size);
*/
    } // for each device
  } // end detect()
} // end namespace
<commit_msg>detects EXT based partitions<commit_after>#include "blockdevices.h"

#include <list>
#include <cxxutils/posix_helpers.h>

#include <unistd.h>

#if defined(__linux__)
#include <linux/fs.h>
#else // *BSD/Darwin
#include <sys/disklabel.h>
#include <sys/disk.h>
#endif

#include <arpa/inet.h>

#ifndef DEVFS_PATH
#define DEVFS_PATH          "/dev"
#endif

#define EXT_MAGIC_NUMBER                  0xEF53
#define EXT_COMPAT_FLAG_HAS_JOURNAL       0x00000004
#define EXT_INCOMPAT_FLAG_JOURNAL_DEV     0x00000008

/* for s_flags */
#define EXT_FLAGS_TEST_FILESYS              0x0004

/* for s_feature_compat */
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL     0x0004

/* for s_feature_ro_compat */
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE   0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR    0x0004
#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE    0x0008
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM     0x0010
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK    0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE  0x0040

/* for s_feature_incompat */
#define EXT2_FEATURE_INCOMPAT_FILETYPE      0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER       0x0004
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV   0x0008
#define EXT2_FEATURE_INCOMPAT_META_BG       0x0010
#define EXT4_FEATURE_INCOMPAT_EXTENTS       0x0040 // extents support
#define EXT4_FEATURE_INCOMPAT_64BIT         0x0080
#define EXT4_FEATURE_INCOMPAT_MMP           0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG       0x0200

#define EXT2_FEATURE_RO_COMPAT_SUPP           (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | EXT2_FEATURE_RO_COMPAT_LARGE_FILE | EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#define EXT2_FEATURE_INCOMPAT_SUPP            (EXT2_FEATURE_INCOMPAT_FILETYPE | EXT2_FEATURE_INCOMPAT_META_BG)
#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED     ~EXT2_FEATURE_INCOMPAT_SUPP
#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED    ~EXT2_FEATURE_RO_COMPAT_SUPP

#define EXT3_FEATURE_RO_COMPAT_SUPP           (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | EXT2_FEATURE_RO_COMPAT_LARGE_FILE | EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#define EXT3_FEATURE_INCOMPAT_SUPP            (EXT2_FEATURE_INCOMPAT_FILETYPE | EXT3_FEATURE_INCOMPAT_RECOVER | EXT2_FEATURE_INCOMPAT_META_BG)
#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED     ~EXT3_FEATURE_INCOMPAT_SUPP
#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED    ~EXT3_FEATURE_RO_COMPAT_SUPP

#define EXT_BLOCK_COUNT_OFFSET            (superblock + 0x0004)
#define EXT_BLOCK_SIZE_OFFSET             (superblock + 0x0018)
#define EXT_MAGIC_NUMBER_OFFSET           (superblock + 0x0038)

#define EXT_COMPAT_FLAGS_OFFSET           (superblock + 0x005C) // s_feature_compat
#define EXT_INCOMPAT_FLAGS_OFFSET         (superblock + 0x0060) // s_feature_incompat
#define EXT_RO_COMPAT_FLAGS_OFFSET        (superblock + 0x0064) // s_feature_ro_compat

#define EXT_UUID_OFFSET                   (superblock + 0x0068) // s_uuid[16]
#define EXT_LABEL_OFFSET                  (superblock + 0x0078) // s_volume_name[16]
#define EXT_MISC_FLAGS_OFFSET             (superblock + 0x0160) // s_flags

uint64_t read(posix::fd_t fd, off_t offset, uint8_t* buffer, uint64_t length)
{
  if(::lseek(fd, offset, SEEK_SET) != offset)
    return 0;

  uint64_t remaining = length;
  ssize_t rval;
  for(uint8_t* pos = buffer; remaining > 0; pos += rval, remaining -= rval)
    rval = posix::read(fd, pos, remaining);

  return length - remaining;
}

#ifndef BLOCK_SIZE
#define BLOCK_SIZE 0x400
#endif

struct uintle16_t
{
  uint8_t low;
  uint8_t high;
  constexpr operator uint16_t(void) const { return low + (high << 8); }
};
static_assert(sizeof(uintle16_t) == sizeof(uint16_t), "naughty compiler!");

struct uintle32_t
{
  uint8_t bottom;
  uint8_t low;
  uint8_t high;
  uint8_t top;
  constexpr operator uint32_t(void) const
  {
    return bottom +
        (low  <<  8) +
        (high << 16) +
        (top  << 24);
  }
};
static_assert(sizeof(uintle32_t) == sizeof(uint32_t), "naughty compiler!");

template<typename T> constexpr uint16_t get16(T* x) { return *reinterpret_cast<uint16_t*>(x); }
template<typename T> constexpr uint32_t get32(T* x) { return *reinterpret_cast<uint32_t*>(x); }
template<typename T> constexpr uint16_t getLE16(T* x) { return *reinterpret_cast<uintle16_t*>(x); }
template<typename T> constexpr uint32_t getLE32(T* x) { return *reinterpret_cast<uintle32_t*>(x); }

template<typename T> constexpr uint32_t flagsSet(T addr, uint32_t flags) { return getLE32(addr) & flags; }
template<typename T> constexpr bool flagsAreSet(T addr, uint32_t flags) { return flagsSet(addr, flags) == flags; }
template<typename T> constexpr bool flagsNotSet(T addr, uint32_t flags) { return !flagsSet(addr, flags); }

constexpr char uuid_digit(uint8_t* data, uint8_t digit)
  { return  "0123456789ABCDEF"[(digit & 1) ? (data[digit/2] & 0x0F) : (data[digit/2] >> 4)]; }

static bool uuid_matches(const char* str, uint8_t* data)
{
  size_t length = std::strlen(str);
  for(uint8_t digit = 0; digit < 32; ++digit, ++str)
  {
    if(!std::isxdigit(*str))
      { --length; ++str; }
    if(digit >= length || std::toupper(*str) != uuid_digit(data, digit))
      return false;
  }
  return true;
}

/*
static void uuid_decode(uint8_t* data, std::string& uuid)
{
  for(uint8_t digit = 0; digit < 32; ++digit)
    uuid.push_back(uuid_digit(data, digit));
}
*/

namespace blockdevices
{
  static std::list<blockdevice_t> devices;
  void detect(void);

#if defined(WANT_PROCFS)
  void init(const char* procfs_path)
  {
    devices.clear();
    char filename[PATH_MAX] = { 0 };
    std::strcpy(filename, procfs_path);
    std::strcat(filename, "/partitions");

    std::FILE* file = posix::fopen(filename, "r");
    if(file == nullptr)
      return;

    posix::ssize_t count = 0;
    posix::size_t size = 0;
    char* line = nullptr;
    char* begin = nullptr;
    while((count = ::getline(&line, &size, file)) != posix::error_response)
    {
      char* pos = line;
      if(!std::isspace(*pos)) // if line doesn't start with a space then it's not an entry!
        continue;

      while(*pos && std::isspace(*pos))
        ++pos;
      while(*pos && std::isdigit(*pos))
        ++pos;

      while(*pos && std::isspace(*pos))
        ++pos;
      while(*pos && std::isdigit(*pos))
        ++pos;

      while(*pos && std::isspace(*pos))
        ++pos;
      while(*pos && std::isdigit(*pos))
        ++pos;

      while(*pos && std::isspace(*pos))
        ++pos;

      if(!*pos) // if at end of line, skip
        continue;

      // read device name
      blockdevice_t dev;
      std::strcpy(dev.path, DEVFS_PATH);
      std::strcat(dev.path, "/");
      for(char* field = dev.path + std::strlen(dev.path);
          *pos && pos < dev.path + sizeof(blockdevice_t::path) && std::isgraph(*pos);
          ++pos, ++field)
        *field = *pos;
      {
        devices.emplace_back(dev);
      }
    }
    ::free(line); // use C free() because we're using C getline()
    line = nullptr;

    posix::fclose(file);

    detect();
  }

#else
  void init(void)
  {
#pragma message("Code needed to detect GEOM devices like gpart@")
    detect();
  }
#endif

  blockdevice_t* lookupByPath(const char* path) noexcept // finds device based on absolute path
  {
    for(blockdevice_t& dev : devices)
      if(!std::strcmp(path, dev.path))
        return &dev;
    return nullptr;
  }

  blockdevice_t* lookupByUUID(const char* uuid) noexcept // finds device based on uuid
  {
    for(blockdevice_t& dev : devices)
      if(uuid_matches(uuid, dev.uuid))
        return &dev;
    return nullptr;
  }

  blockdevice_t* lookupByLabel(const char* label) noexcept // finds device based on label
  {
    for(blockdevice_t& dev : devices)
      if(!std::strcmp(label, dev.label))
        return &dev;
    return nullptr;
  }

  blockdevice_t* lookup(const char* id)
  {
    for(blockdevice_t& dev : devices)
    {
      if(!std::strcmp(id, dev.label) ||
         !std::strcmp(id, dev.path) ||
         uuid_matches(id, dev.uuid))
        return &dev;
    }
    return nullptr;
  }

  void detect(void)
  {
    uint8_t superblock[BLOCK_SIZE];
    uint32_t blocksize;
    uint64_t blockcount;

    for(blockdevice_t& dev : devices)
    {
      posix::fd_t fd = posix::open(dev.path, O_RDONLY);
      dev.size = 0;

      if(fd != posix::error_response)
      {
  #if defined(BLKGETSIZE64) // Linux 2.6+
        posix::ioctl(fd, BLKGETSIZE64, &dev.size);

  #elif defined(DKIOCGETBLOCKCOUNT) // Darwin
        blocksize = 0;
        blockcount = 0;
        if(posix::ioctl(fd, DKIOCGETBLOCKSIZE , &blocksize ) > posix::error_response &&
           posix::ioctl(fd, DKIOCGETBLOCKCOUNT, &blockcount) > posix::error_response)
          dev.size = blockcount * blocksize;

  #elif defined(DIOCGMEDIASIZE) // current BSD
        posix::ioctl(fd, DIOCGMEDIASIZE, &dev.size);

  #elif defined(DIOCGDINFO) // old BSD
        struct disklabel info;
        if(posix::ioctl(fd, DIOCGDINFO, &info) > posix::error_response)
          dev.size = info.d_ncylinders * info.d_secpercyl * info.d_secsize;

  #else
        dev.size = ::lseek(fd, 0, SEEK_END); // behavior not defined in POSIX for devices but try as a last resort

  #pragma message("No device interface defined for this operating system.  Please add one to device.cpp!")
  #endif
      }

      std::memset(superblock, 0, BLOCK_SIZE);
      if(read(fd, BLOCK_SIZE, superblock, BLOCK_SIZE) == BLOCK_SIZE) // if read filesystem superblock
      {
        // see "struct ext2_super_block" in https://github.com/torvalds/linux/blob/master/fs/ext2/ext2.h
        // see "struct ext4_super_block" in https://github.com/torvalds/linux/blob/master/fs/ext4/ext4.h
        // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#The_Super_Block
        if(getLE16(EXT_MAGIC_NUMBER_OFFSET) == EXT_MAGIC_NUMBER) // test if Ext2/3/4
        {
          blockcount = getLE32(EXT_BLOCK_COUNT_OFFSET);
          blocksize  = BLOCK_SIZE << getLE32(EXT_BLOCK_SIZE_OFFSET);

          if(flagsAreSet(EXT_INCOMPAT_FLAGS_OFFSET  , EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
            std::strcpy(dev.fstype, "jbd");

          if(flagsNotSet(EXT_INCOMPAT_FLAGS_OFFSET  , EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) &&
             flagsAreSet(EXT_MISC_FLAGS_OFFSET      , EXT_FLAGS_TEST_FILESYS))
            std::strcpy(dev.fstype, "ext4dev");

          if(flagsNotSet(EXT_INCOMPAT_FLAGS_OFFSET  , EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) &&
             (flagsSet(EXT_RO_COMPAT_FLAGS_OFFSET, EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
              flagsSet(EXT_INCOMPAT_FLAGS_OFFSET , EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) &&
             flagsNotSet(EXT_MISC_FLAGS_OFFSET      , EXT_FLAGS_TEST_FILESYS))
            std::strcpy(dev.fstype, "ext4");

          if(flagsAreSet(EXT_COMPAT_FLAGS_OFFSET    , EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
             flagsNotSet(EXT_RO_COMPAT_FLAGS_OFFSET , EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
             flagsNotSet(EXT_INCOMPAT_FLAGS_OFFSET  , EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
            std::strcpy(dev.fstype, "ext3");

          if(flagsNotSet(EXT_COMPAT_FLAGS_OFFSET    , EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
             flagsNotSet(EXT_RO_COMPAT_FLAGS_OFFSET , EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) &&
             flagsNotSet(EXT_INCOMPAT_FLAGS_OFFSET  , EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
            std::strcpy(dev.fstype, "ext2");

          std::memcpy(dev.uuid, EXT_UUID_OFFSET, 16);
          std::strncpy(dev.label, (const char*)EXT_LABEL_OFFSET, 16);
        }
        else if(true) // test other filesystem type
        {

        }

      }
    } // for each device
  } // end detect()
} // end namespace
<|endoftext|>


<commit_before>#ifndef DISSENT_CRYPTO_CPP_DSA_LIBRARY_H_GUARD
#define DISSENT_CRYPTO_CPP_DSA_LIBRARY_H_GUARD

#include "CppDiffieHellman.hpp"
#include "CppHash.hpp"
#include "CppIntegerData.hpp"
#include "CppRandom.hpp"
#include "CppDsaPrivateKey.hpp"
#include "CppDsaPublicKey.hpp"

#include "Library.hpp"

namespace Dissent {
namespace Crypto {
  class CppDsaLibrary : public Library {
    public:
      /**
       * Load a public key from a file
       */
      inline virtual AsymmetricKey *LoadPublicKeyFromFile(const QString &filename)
      {
        return new CppDsaPublicKey(filename);
      }

      /**
       * Loading a public key from a byte array
       */
      inline virtual AsymmetricKey *LoadPublicKeyFromByteArray(const QByteArray &data)
      {
        return new CppDsaPublicKey(data);
      }

      /**
       * Generate a public key using the given data as a seed to a RNG
       */
      inline virtual AsymmetricKey *GeneratePublicKey(const QByteArray &seed)
      {
        return CppDsaPublicKey::GenerateKey(seed);
      }

      /**
       * Load a private key from a file
       */
      inline virtual AsymmetricKey *LoadPrivateKeyFromFile(const QString &filename)
      {
        return new CppDsaPrivateKey(filename);
      }

      /**
       * Loading a private key from a byte array
       */
      inline virtual AsymmetricKey *LoadPrivateKeyFromByteArray(const QByteArray &data)
      {
        return new CppDsaPrivateKey(data);
      }

      /**
       * Generate a private key using the given data as a seed to a RNG
       */
      inline virtual AsymmetricKey *GeneratePrivateKey(const QByteArray &seed)
      {
        return CppDsaPrivateKey::GenerateKey(seed);
      }

      /**
       * Generates a unique (new) private key
       */
      inline virtual AsymmetricKey *CreatePrivateKey()
      {
        return new CppDsaPrivateKey();
      }

      /**
       * Returns the minimum asymmetric key size
       */
      inline virtual int MinimumKeySize() const { return CppDsaPublicKey::GetMinimumKeySize(); }

      /**
       * Returns a deterministic random number generator
       */
      inline virtual Dissent::Utils::Random *GetRandomNumberGenerator(const QByteArray &seed, uint index)
      {
        return new CppRandom(seed, index);
      }

      inline virtual uint RngOptimalSeedSize()
      {
        return CppRandom::OptimalSeedSize();
      }

      /**
       * Returns a hash algorithm
       */
      inline virtual Hash *GetHashAlgorithm()
      {
        return new CppHash();
      }

      /**
       * Returns an integer data
       */
      inline virtual IntegerData *GetIntegerData(int value)
      {
        return new CppIntegerData(value);
      }

      /**
       * Returns an integer data
       */
      inline virtual IntegerData *GetIntegerData(const QByteArray &value)
      {
        return new CppIntegerData(value);
      }

      /**
       * Returns an integer data
       */
      inline virtual IntegerData *GetIntegerData(const QString &value)
      {
        return new CppIntegerData(value);
      }

      /**
       * returns a random integer data
       * @param bit_count the amount of bits in the integer
       * @param mod the modulus of the integer
       * @param prime if the integer should be prime
       */
      virtual IntegerData *GetRandomInteger(int bit_count,
          const IntegerData *mod, bool prime)
      {
        return CppIntegerData::GetRandomInteger(bit_count, mod, prime);
      }

      /**
       * Returns a DiffieHellman operator
       */
      virtual DiffieHellman *CreateDiffieHellman()
      {
        return new CppDiffieHellman();
      }

      /**
       * Generate a DiffieHellman operator using the given data as a seed to a RNG
       * @param seed seed used to generate the DiffieHellman exchange
       */
      virtual DiffieHellman *GenerateDiffieHellman(const QByteArray &seed)
      {
        return new CppDiffieHellman(seed, true);
      }

      /**
       * Loads a DiffieHellman key from a byte array
       * @param private_component the private component in the DH exchange
       */
      virtual DiffieHellman *LoadDiffieHellman(const QByteArray &private_component)
      {
        return new CppDiffieHellman(private_component);
      }
  };
}
}

#endif
<commit_msg>[Crypto] simplified the DSA library<commit_after>#ifndef DISSENT_CRYPTO_CPP_DSA_LIBRARY_H_GUARD
#define DISSENT_CRYPTO_CPP_DSA_LIBRARY_H_GUARD

#include "CppDiffieHellman.hpp"
#include "CppHash.hpp"
#include "CppIntegerData.hpp"
#include "CppRandom.hpp"
#include "CppDsaPrivateKey.hpp"
#include "CppDsaPublicKey.hpp"

#include "CppLibrary.hpp"

namespace Dissent {
namespace Crypto {
  class CppDsaLibrary : public CppLibrary {
    public:
      /**
       * Load a public key from a file
       */
      inline virtual AsymmetricKey *LoadPublicKeyFromFile(const QString &filename)
      {
        return new CppDsaPublicKey(filename);
      }

      /**
       * Loading a public key from a byte array
       */
      inline virtual AsymmetricKey *LoadPublicKeyFromByteArray(const QByteArray &data)
      {
        return new CppDsaPublicKey(data);
      }

      /**
       * Generate a public key using the given data as a seed to a RNG
       */
      inline virtual AsymmetricKey *GeneratePublicKey(const QByteArray &seed)
      {
        return CppDsaPublicKey::GenerateKey(seed);
      }

      /**
       * Load a private key from a file
       */
      inline virtual AsymmetricKey *LoadPrivateKeyFromFile(const QString &filename)
      {
        return new CppDsaPrivateKey(filename);
      }

      /**
       * Loading a private key from a byte array
       */
      inline virtual AsymmetricKey *LoadPrivateKeyFromByteArray(const QByteArray &data)
      {
        return new CppDsaPrivateKey(data);
      }

      /**
       * Generate a private key using the given data as a seed to a RNG
       */
      inline virtual AsymmetricKey *GeneratePrivateKey(const QByteArray &seed)
      {
        return CppDsaPrivateKey::GenerateKey(seed);
      }

      /**
       * Generates a unique (new) private key
       */
      inline virtual AsymmetricKey *CreatePrivateKey()
      {
        return new CppDsaPrivateKey();
      }

      /**
       * Returns the minimum asymmetric key size
       */
      inline virtual int MinimumKeySize() const { return CppDsaPublicKey::GetMinimumKeySize(); }
  };
}
}

#endif
<|endoftext|>


<commit_before>#include <vtkSmartPointer.h>
#include <vtkFillHolesFilter.h>
#include <vtkPolyDataNormals.h>
#include <vtkCleanPolyData.h>

#include <vtkSelectionNode.h>
#include <vtkInformation.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkOBJReader.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSelection.h>
#include <vtkSelectionNode.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkIdTypeArray.h>
#include <vtkExtractSelection.h>
#include <vtkDataSetSurfaceFilter.h>

#include <vtkNamedColors.h>

static void GenerateData(vtkPolyData*);

int main(int argc, char *argv[])
{
  vtkSmartPointer<vtkPolyData> input =
    vtkSmartPointer<vtkPolyData>::New();
  if(argc == 1)
  {
    GenerateData(input);
  }
  else
  {
    std::string inputFilename = argv[1];

    vtkSmartPointer<vtkOBJReader> reader =
      vtkSmartPointer<vtkOBJReader>::New();
    reader->SetFileName(inputFilename.c_str());
    reader->Update();
    vtkSmartPointer<vtkCleanPolyData> clean =
      vtkSmartPointer<vtkCleanPolyData>::New();
    clean->SetInputData(reader->GetOutput());
    clean->Update();
    input->ShallowCopy(clean->GetOutput());
  }

  vtkSmartPointer<vtkNamedColors> colors =
    vtkSmartPointer<vtkNamedColors>::New();

  vtkSmartPointer<vtkFillHolesFilter> fillHolesFilter =
    vtkSmartPointer<vtkFillHolesFilter>::New();
  fillHolesFilter->SetInputData(input);
  fillHolesFilter->SetHoleSize(100000.0);
  fillHolesFilter->Update();

  // Make the triangle winding order consistent
  vtkSmartPointer<vtkPolyDataNormals> normals =
    vtkSmartPointer<vtkPolyDataNormals>::New();
  normals->SetInputData(fillHolesFilter->GetOutput());
  normals->ConsistencyOn();
  normals->SplittingOff();
  normals->Update();

#if 0
  // Restore the original normals
  normals->GetOutput()->GetPointData()->
    SetNormals(input->GetPointData()->GetNormals());
#endif
  // Visualize
  // Define viewport ranges
  // (xmin, ymin, xmax, ymax)
  double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
  double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};

  // Create a mapper and actor
  vtkSmartPointer<vtkPolyDataMapper> originalMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  originalMapper->SetInputData(input);

  vtkSmartPointer<vtkProperty> backfaceProp =
    vtkSmartPointer<vtkProperty>::New();
  backfaceProp->SetDiffuseColor(colors->GetColor3d("Banana").GetData());

  vtkSmartPointer<vtkActor> originalActor =
    vtkSmartPointer<vtkActor>::New();
  originalActor->SetMapper(originalMapper);
  originalActor->SetBackfaceProperty(backfaceProp);
  originalActor->GetProperty()->SetDiffuseColor(
    colors->GetColor3d("Flesh").GetData());

  vtkSmartPointer<vtkPolyDataMapper> filledMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  filledMapper->SetInputData(fillHolesFilter->GetOutput());

  vtkSmartPointer<vtkActor> filledActor =
    vtkSmartPointer<vtkActor>::New();
  filledActor->SetMapper(filledMapper);
  filledActor->GetProperty()->SetDiffuseColor(
    colors->GetColor3d("Flesh").GetData());
  filledActor->SetBackfaceProperty(backfaceProp);

  // Create a renderer, render window, and interactor
  vtkSmartPointer<vtkRenderer> leftRenderer =
    vtkSmartPointer<vtkRenderer>::New();
  leftRenderer->SetViewport(leftViewport);

  vtkSmartPointer<vtkRenderer> rightRenderer =
    vtkSmartPointer<vtkRenderer>::New();
  rightRenderer->SetViewport(rightViewport);

  vtkSmartPointer<vtkRenderWindow> renderWindow =
    vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->SetSize(600,300);

  renderWindow->AddRenderer(leftRenderer);
  renderWindow->AddRenderer(rightRenderer);

  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  renderWindowInteractor->SetRenderWindow(renderWindow);

  // Add the actor to the scene
  leftRenderer->AddActor(originalActor);
  rightRenderer->AddActor(filledActor);
  leftRenderer->SetBackground(colors->GetColor3d("PaleGreen").GetData());

  leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
  leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
  leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
  leftRenderer->GetActiveCamera()->Azimuth(30);
  leftRenderer->GetActiveCamera()->Elevation(30);

  leftRenderer->ResetCamera();

  rightRenderer->SetBackground(colors->GetColor3d("LightGreen").GetData());

  // Share the camera

  rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());
  // Render and interact
  renderWindow->Render();

  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

void GenerateData(vtkPolyData* input)
{
  // Create a sphere
  vtkSmartPointer<vtkSphereSource> sphereSource =
    vtkSmartPointer<vtkSphereSource>::New();
  sphereSource->Update();

  // Remove some cells
  vtkSmartPointer<vtkIdTypeArray> ids =
    vtkSmartPointer<vtkIdTypeArray>::New();
  ids->SetNumberOfComponents(1);

  // Set values
  ids->InsertNextValue(2);
  ids->InsertNextValue(10);

  vtkSmartPointer<vtkSelectionNode> selectionNode =
    vtkSmartPointer<vtkSelectionNode>::New();
  selectionNode->SetFieldType(vtkSelectionNode::CELL);
  selectionNode->SetContentType(vtkSelectionNode::INDICES);
  selectionNode->SetSelectionList(ids);
  selectionNode->GetProperties()->Set(vtkSelectionNode::INVERSE(), 1); //invert the selection

  vtkSmartPointer<vtkSelection> selection =
      vtkSmartPointer<vtkSelection>::New();
  selection->AddNode(selectionNode);

  vtkSmartPointer<vtkExtractSelection> extractSelection =
      vtkSmartPointer<vtkExtractSelection>::New();
  extractSelection->SetInputConnection(0, sphereSource->GetOutputPort());
  extractSelection->SetInputData(1, selection);
  extractSelection->Update();

  // In selection
  vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
    vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
  surfaceFilter->SetInputConnection(extractSelection->GetOutputPort());
  surfaceFilter->Update();

  input->ShallowCopy(surfaceFilter->GetOutput());
}
<commit_msg>ENH: Add ReadPolyData<commit_after>#include <vtkSmartPointer.h>
#include <vtkFillHolesFilter.h>
#include <vtkPolyDataNormals.h>
#include <vtkCleanPolyData.h>

#include <vtkSelectionNode.h>
#include <vtkInformation.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSelection.h>
#include <vtkSelectionNode.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkIdTypeArray.h>
#include <vtkExtractSelection.h>
#include <vtkDataSetSurfaceFilter.h>

#include <vtkBYUReader.h>
#include <vtkOBJReader.h>
#include <vtkPLYReader.h>
#include <vtkPolyDataReader.h>
#include <vtkSTLReader.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkSphereSource.h>
#include <vtksys/SystemTools.hxx>

#include <vtkNamedColors.h>

namespace
{
vtkSmartPointer<vtkPolyData> ReadPolyData(const char *fileName);
}

int main(int argc, char *argv[])
{
  vtkSmartPointer<vtkPolyData> input =
    ReadPolyData(argc > 1 ? argv[1] : "");

  vtkSmartPointer<vtkNamedColors> colors =
    vtkSmartPointer<vtkNamedColors>::New();

  vtkSmartPointer<vtkFillHolesFilter> fillHolesFilter =
    vtkSmartPointer<vtkFillHolesFilter>::New();
  fillHolesFilter->SetInputData(input);
  fillHolesFilter->SetHoleSize(100000.0);
  fillHolesFilter->Update();

  // Make the triangle winding order consistent
  vtkSmartPointer<vtkPolyDataNormals> normals =
    vtkSmartPointer<vtkPolyDataNormals>::New();
  normals->SetInputData(fillHolesFilter->GetOutput());
  normals->ConsistencyOn();
  normals->SplittingOff();
  normals->Update();

#if 0
  // Restore the original normals
  normals->GetOutput()->GetPointData()->
    SetNormals(input->GetPointData()->GetNormals());
#endif
  // Visualize
  // Define viewport ranges
  // (xmin, ymin, xmax, ymax)
  double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
  double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};

  // Create a mapper and actor
  vtkSmartPointer<vtkPolyDataMapper> originalMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  originalMapper->SetInputData(input);

  vtkSmartPointer<vtkProperty> backfaceProp =
    vtkSmartPointer<vtkProperty>::New();
  backfaceProp->SetDiffuseColor(colors->GetColor3d("Banana").GetData());

  vtkSmartPointer<vtkActor> originalActor =
    vtkSmartPointer<vtkActor>::New();
  originalActor->SetMapper(originalMapper);
  originalActor->SetBackfaceProperty(backfaceProp);
  originalActor->GetProperty()->SetDiffuseColor(
    colors->GetColor3d("Flesh").GetData());

  vtkSmartPointer<vtkPolyDataMapper> filledMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  filledMapper->SetInputData(fillHolesFilter->GetOutput());

  vtkSmartPointer<vtkActor> filledActor =
    vtkSmartPointer<vtkActor>::New();
  filledActor->SetMapper(filledMapper);
  filledActor->GetProperty()->SetDiffuseColor(
    colors->GetColor3d("Flesh").GetData());
  filledActor->SetBackfaceProperty(backfaceProp);

  // Create a renderer, render window, and interactor
  vtkSmartPointer<vtkRenderer> leftRenderer =
    vtkSmartPointer<vtkRenderer>::New();
  leftRenderer->SetViewport(leftViewport);

  vtkSmartPointer<vtkRenderer> rightRenderer =
    vtkSmartPointer<vtkRenderer>::New();
  rightRenderer->SetViewport(rightViewport);

  vtkSmartPointer<vtkRenderWindow> renderWindow =
    vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->SetSize(600,300);

  renderWindow->AddRenderer(leftRenderer);
  renderWindow->AddRenderer(rightRenderer);

  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  renderWindowInteractor->SetRenderWindow(renderWindow);

  // Add the actor to the scene
  leftRenderer->AddActor(originalActor);
  rightRenderer->AddActor(filledActor);
  leftRenderer->SetBackground(colors->GetColor3d("PaleGreen").GetData());

  leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
  leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
  leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
  leftRenderer->GetActiveCamera()->Azimuth(30);
  leftRenderer->GetActiveCamera()->Elevation(30);

  leftRenderer->ResetCamera();

  rightRenderer->SetBackground(colors->GetColor3d("LightGreen").GetData());

  // Share the camera

  rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());
  // Render and interact
  renderWindow->Render();

  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

void GenerateData(vtkPolyData* input)
{
  // Create a sphere
  vtkSmartPointer<vtkSphereSource> sphereSource =
    vtkSmartPointer<vtkSphereSource>::New();
  sphereSource->Update();

  // Remove some cells
  vtkSmartPointer<vtkIdTypeArray> ids =
    vtkSmartPointer<vtkIdTypeArray>::New();
  ids->SetNumberOfComponents(1);

  // Set values
  ids->InsertNextValue(2);
  ids->InsertNextValue(10);

  vtkSmartPointer<vtkSelectionNode> selectionNode =
    vtkSmartPointer<vtkSelectionNode>::New();
  selectionNode->SetFieldType(vtkSelectionNode::CELL);
  selectionNode->SetContentType(vtkSelectionNode::INDICES);
  selectionNode->SetSelectionList(ids);
  selectionNode->GetProperties()->Set(vtkSelectionNode::INVERSE(), 1); //invert the selection

  vtkSmartPointer<vtkSelection> selection =
      vtkSmartPointer<vtkSelection>::New();
  selection->AddNode(selectionNode);

  vtkSmartPointer<vtkExtractSelection> extractSelection =
      vtkSmartPointer<vtkExtractSelection>::New();
  extractSelection->SetInputConnection(0, sphereSource->GetOutputPort());
  extractSelection->SetInputData(1, selection);
  extractSelection->Update();

  // In selection
  vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
    vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
  surfaceFilter->SetInputConnection(extractSelection->GetOutputPort());
  surfaceFilter->Update();

  input->ShallowCopy(surfaceFilter->GetOutput());
}
// Snippets
namespace
{
vtkSmartPointer<vtkPolyData> ReadPolyData(const char *fileName)
{
  vtkSmartPointer<vtkPolyData> polyData;
  std::string extension = vtksys::SystemTools::GetFilenameExtension(std::string(fileName));
  if (extension == ".ply")
  {
    vtkSmartPointer<vtkPLYReader> reader =
      vtkSmartPointer<vtkPLYReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".vtp")
  {
    vtkSmartPointer<vtkXMLPolyDataReader> reader =
      vtkSmartPointer<vtkXMLPolyDataReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".obj")
  {
    vtkSmartPointer<vtkOBJReader> reader =
      vtkSmartPointer<vtkOBJReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".stl")
  {
    vtkSmartPointer<vtkSTLReader> reader =
      vtkSmartPointer<vtkSTLReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".vtk")
  {
    vtkSmartPointer<vtkPolyDataReader> reader =
      vtkSmartPointer<vtkPolyDataReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".g")
  {
    vtkSmartPointer<vtkBYUReader> reader =
      vtkSmartPointer<vtkBYUReader>::New();
    reader->SetGeometryFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else
  {
    vtkSmartPointer<vtkSphereSource> source =
      vtkSmartPointer<vtkSphereSource>::New();
    source->Update();
    polyData = source->GetOutput();
  }
  return polyData;
}
}
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#ifndef DO_CORE_STATICASSERT_HPP
#define DO_CORE_STATICASSERT_HPP

//! @file
//! \brief Implementation from:
//! http://stackoverflow.com/questions/1980012/boost-static-assert-without-boost

//! Concatenation macro used for the implementation of DO_STATIC_ASSERT.
#define CAT(arg1, arg2)   CAT1(arg1, arg2)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#define CAT1(arg1, arg2)  CAT2(arg1, arg2)
#define CAT2(arg1, arg2)  arg1##arg2
#endif

/*!
  \ingroup Meta

  \brief Static assertion macro.

  \param expression a boolean expression
  \param message some error message

  Usage:

  DO_STATIC_ASSERT(expression, message);

  When the static assertion test fails, a compiler error message that somehow
  contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated.

  WARNING: message has to be a valid C++ identifier, that is to say it must not
  contain space characters, cannot start with a digit, etc.

  DO_STATIC_ASSERT(true, this_message_will_never_be_displayed);
 */
#define DO_STATIC_ASSERT(expression, message)                               \
struct CAT(__static_assertion_at_line_, __LINE__)                           \
{                                                                           \
  DO::Meta::StaticAssertion<static_cast<bool>((expression))>                \
    CAT(CAT(CAT(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);  \
};                                                                          \
typedef DO::Meta::StaticAssertionTest<                                      \
  sizeof(CAT(__static_assertion_at_line_, __LINE__))  >                     \
    CAT(__static_assertion_test_at_line_, __LINE__)

// Note that we wrap the non existing type inside a struct to avoid warning
// messages about unused variables when static assertions are used at function
// scope
// the use of sizeof makes sure the assertion error is not ignored by SFINAE

namespace DO { namespace Meta {

  //! Used for the implementation of DO_STATIC_ASSERT.
  template <bool> struct StaticAssertion;
  //! Used for the implementation of DO_STATIC_ASSERT.
  template <> struct StaticAssertion<true> {};
  //! Used for the implementation of DO_STATIC_ASSERT.
  template<int i> struct StaticAssertionTest {};

} /* namespace Meta */
} /* namespace DO */

#endif /* DO_CORE_STATICASSERT_HPP */<commit_msg>Add a precision on the usage of DO_STATIC_ASSERT.<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#ifndef DO_CORE_STATICASSERT_HPP
#define DO_CORE_STATICASSERT_HPP

//! @file
//! \brief Implementation from:
//! http://stackoverflow.com/questions/1980012/boost-static-assert-without-boost

//! Concatenation macro used for the implementation of DO_STATIC_ASSERT.
#define CAT(arg1, arg2)   CAT1(arg1, arg2)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#define CAT1(arg1, arg2)  CAT2(arg1, arg2)
#define CAT2(arg1, arg2)  arg1##arg2
#endif

/*!
  \ingroup Meta

  \brief Static assertion macro.

  \param expression a boolean expression
  \param message some error message

  Usage:

  DO_STATIC_ASSERT(expression, message); // **don't forget** the semi-colon!

  When the static assertion test fails, a compiler error message that somehow
  contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated.

  WARNING: message has to be a valid C++ identifier, that is to say it must not
  contain space characters, cannot start with a digit, etc.

  DO_STATIC_ASSERT(true, this_message_will_never_be_displayed);
 */
#define DO_STATIC_ASSERT(expression, message)                               \
struct CAT(__static_assertion_at_line_, __LINE__)                           \
{                                                                           \
  DO::Meta::StaticAssertion<static_cast<bool>((expression))>                \
    CAT(CAT(CAT(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);  \
}

// Note that we wrap the non existing type inside a struct to avoid warning
// messages about unused variables when static assertions are used at function
// scope
// the use of sizeof makes sure the assertion error is not ignored by SFINAE

namespace DO { namespace Meta {

  //! Used for the implementation of DO_STATIC_ASSERT.
  template <bool> struct StaticAssertion;
  //! Used for the implementation of DO_STATIC_ASSERT.
  template <> struct StaticAssertion<true> {};
  //! Used for the implementation of DO_STATIC_ASSERT.
  template<int i> struct StaticAssertionTest {};

} /* namespace Meta */
} /* namespace DO */

#endif /* DO_CORE_STATICASSERT_HPP */
<|endoftext|>