<commit_before>/*************************************************************************
 *
 *  $RCSfile: ZipOutputStream.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: mtg $ $Date: 2000-12-19 21:55:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_OUTPUT_STREAM_HXX
#define _ZIP_OUTPUT_STREAM_HXX

#ifndef _BYTE_CHUCKER_HXX_
#include "ByteChucker.hxx"
#endif

#ifndef _ZIP_ENTRY_IMPL_HXX
#include "ZipEntryImpl.hxx"
#endif

#ifndef _ZIP_FILE_HXX
#include "ZipFile.hxx"
#endif

#ifndef _DEFLATER_HXX
#include "Deflater.hxx"
#endif

#ifndef _CRC32_HXX
#include "CRC32.hxx"
#endif

#ifndef _COM_SUN_STAR_PACKAGE_XZIPOUTPUTSTREAM_HPP_
#include <com/sun/star/package/XZipOutputStream.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx> // helper for implementations
#endif

#ifndef __SGI_STL_VECTOR
#include <stl/vector>
#endif

#ifndef _VOS_DIAGNOSE_H_
#include <vos/diagnose.hxx>
#endif

#include <time.h>
#include <utime.h>

class ZipOutputStream : public cppu::WeakImplHelper1< com::sun::star::package::XZipOutputStream >
{
private:
    com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > xStream;
    Deflater            aDeflater;
    com::sun::star::uno::Sequence < sal_Int8 > aBuffer;
    ::rtl::OUString     sComment;
    sal_Int16           nMethod;
    sal_Int16           nLevel;
    com::sun::star::package::ZipEntry           *pCurrentEntry;
    CRC32               aCRC;
    sal_Bool            bFinished;
    ByteChucker         aChucker;
    ::std::vector < ::com::sun::star::package::ZipEntry* >          aZipList;

public:
    ZipOutputStream( com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > &xOStream, sal_Int32 nNewBufferSize);
    virtual ~ZipOutputStream(void);

    // rawWrite to support a direct write to the output stream
    void SAL_CALL rawWrite( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer)
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void SAL_CALL rawCloseEntry(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL setComment( const ::rtl::OUString& rComment )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setMethod( sal_Int32 nNewMethod )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setLevel( sal_Int32 nNewLevel )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL putNextEntry( const ::com::sun::star::package::ZipEntry& rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL closeEntry(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL write( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL finish(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL close(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    static sal_uInt32 tmDateToDosDate ( tm &rTime);
    static void dosDateToTMDate ( tm &rTime, sal_uInt32 nDosDate);
private:
    void doDeflate();
    void writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void writeCEN( const com::sun::star::package::ZipEntry &rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void writeEXT( const com::sun::star::package::ZipEntry &rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void writeLOC( const com::sun::star::package::ZipEntry &rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

};

#endif
<commit_msg>remove stl/ from the inlcude statement<commit_after>/*************************************************************************
 *
 *  $RCSfile: ZipOutputStream.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: jp $ $Date: 2001-02-05 09:24:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_OUTPUT_STREAM_HXX
#define _ZIP_OUTPUT_STREAM_HXX

#ifndef _BYTE_CHUCKER_HXX_
#include "ByteChucker.hxx"
#endif

#ifndef _ZIP_ENTRY_IMPL_HXX
#include "ZipEntryImpl.hxx"
#endif

#ifndef _ZIP_FILE_HXX
#include "ZipFile.hxx"
#endif

#ifndef _DEFLATER_HXX
#include "Deflater.hxx"
#endif

#ifndef _CRC32_HXX
#include "CRC32.hxx"
#endif

#ifndef _COM_SUN_STAR_PACKAGE_XZIPOUTPUTSTREAM_HPP_
#include <com/sun/star/package/XZipOutputStream.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx> // helper for implementations
#endif

#ifndef __SGI_STL_VECTOR
#include <vector>
#endif

#ifndef _VOS_DIAGNOSE_H_
#include <vos/diagnose.hxx>
#endif

#include <time.h>
#include <utime.h>

class ZipOutputStream : public cppu::WeakImplHelper1< com::sun::star::package::XZipOutputStream >
{
private:
    com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > xStream;
    Deflater            aDeflater;
    com::sun::star::uno::Sequence < sal_Int8 > aBuffer;
    ::rtl::OUString     sComment;
    sal_Int16           nMethod;
    sal_Int16           nLevel;
    com::sun::star::package::ZipEntry           *pCurrentEntry;
    CRC32               aCRC;
    sal_Bool            bFinished;
    ByteChucker         aChucker;
    ::std::vector < ::com::sun::star::package::ZipEntry* >          aZipList;

public:
    ZipOutputStream( com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > &xOStream, sal_Int32 nNewBufferSize);
    virtual ~ZipOutputStream(void);

    // rawWrite to support a direct write to the output stream
    void SAL_CALL rawWrite( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer)
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void SAL_CALL rawCloseEntry(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL setComment( const ::rtl::OUString& rComment )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setMethod( sal_Int32 nNewMethod )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setLevel( sal_Int32 nNewLevel )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL putNextEntry( const ::com::sun::star::package::ZipEntry& rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL closeEntry(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL write( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL finish(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL close(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    static sal_uInt32 tmDateToDosDate ( tm &rTime);
    static void dosDateToTMDate ( tm &rTime, sal_uInt32 nDosDate);
private:
    void doDeflate();
    void writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void writeCEN( const com::sun::star::package::ZipEntry &rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void writeEXT( const com::sun::star::package::ZipEntry &rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    void writeLOC( const com::sun::star::package::ZipEntry &rEntry )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

};

#endif
<|endoftext|>


<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.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbChangeLabelImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbStatisticsXMLFileReader.h"
#include "otbShiftScaleVectorImageFilter.h"
#include "otbImageClassificationFilter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbImageToVectorImageCastFilter.h"
#include "otbMachineLearningModelFactory.h"

namespace otb
{
namespace Wrapper
{

class ImageClassifier : public Application
{
public:
  /** Standard class typedefs. */
  typedef ImageClassifier            Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(ImageClassifier, otb::Application);

  /** Filters typedef */
  typedef UInt16ImageType                                                                      OutputImageType;
  typedef UInt8ImageType                                                                       MaskImageType;
  typedef itk::VariableLengthVector<FloatVectorImageType::InternalPixelType>                   MeasurementType;
  typedef otb::StatisticsXMLFileReader<MeasurementType>                                        StatisticsReader;
  typedef otb::ShiftScaleVectorImageFilter<FloatVectorImageType, FloatVectorImageType>         RescalerType;
  typedef otb::ImageClassificationFilter<FloatVectorImageType, OutputImageType, MaskImageType> ClassificationFilterType;
  typedef ClassificationFilterType::Pointer                                                    ClassificationFilterPointerType;
  typedef ClassificationFilterType::ModelType                                                  ModelType;
  typedef ModelType::Pointer                                                                   ModelPointerType;
  typedef ClassificationFilterType::ValueType                                                  ValueType;
  typedef ClassificationFilterType::LabelType                                                  LabelType;
  typedef otb::MachineLearningModelFactory<ValueType, LabelType>                               MachineLearningModelFactoryType;

private:
  void DoInit()
  {
    SetName("ImageClassifier");
    SetDescription("Performs a classification of the input image according to a model file.");

    // Documentation
    SetDocName("Image Classification");
    SetDocLongDescription("This application performs an image classification based on a model file produced by the TrainImagesClassifier application. Pixels of the output image will contain the class labels decided by the classifier (maximal class label = 65535). The input pixels can be optionally centered and reduced according to the statistics file produced by the ComputeImagesStatistics application. An optional input mask can be provided, in which case only input image pixels whose corresponding mask value is greater than 0 will be classified. The remaining of pixels will be given the label 0 in the output image.");

    SetDocLimitations("The input image must have the same type, order and number of bands than the images used to produce the statistics file and the SVM model file. If a statistics file was used during training by the TrainImagesClassifier, it is mandatory to use the same statistics file for classification. If an input mask is used, its size must match the input image size.");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("TrainImagesClassifier, ValidateImagesClassifier, ComputeImagesStatistics");

    AddDocTag(Tags::Learning);

    AddParameter(ParameterType_InputImage, "in",  "Input Image");
    SetParameterDescription( "in", "The input image to classify.");

    AddParameter(ParameterType_InputImage,  "mask",   "Input Mask");
    SetParameterDescription( "mask", "The mask allows to restrict classification of the input image to the area where mask pixel values are greater than 0.");
    MandatoryOff("mask");

    AddParameter(ParameterType_InputFilename, "model", "Model file");
    SetParameterDescription("model", "A model file (produced by TrainImagesClassifier application, maximal class label = 65535).");

    AddParameter(ParameterType_InputFilename, "imstat", "Statistics file");
    SetParameterDescription("imstat", "A XML file containing mean and standard deviation to center and reduce samples before classification (produced by ComputeImagesStatistics application).");
    MandatoryOff("imstat");

    AddParameter(ParameterType_OutputImage, "out",  "Output Image");
    SetParameterDescription( "out", "Output image containing class labels");
    SetParameterOutputImagePixelType( "out", ImagePixelType_uint8);

    AddRAMParameter();

   // Doc example parameter settings
    SetDocExampleParameterValue("in", "QB_1_ortho.tif");
    SetDocExampleParameterValue("imstat", "EstimateImageStatisticsQB1.xml");
    SetDocExampleParameterValue("model", "clsvmModelQB1.svm");
    SetDocExampleParameterValue("out", "clLabeledImageQB1.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    // Load input image
    FloatVectorImageType::Pointer inImage = GetParameterImage("in");
    inImage->UpdateOutputInformation();

    // Load svm model
    otbAppLogINFO("Loading model");
    m_Model = MachineLearningModelFactoryType::CreateMachineLearningModel(GetParameterString("model"),
                                                                          MachineLearningModelFactoryType::ReadMode);

    if (m_Model.IsNull())
      {
      otbAppLogFATAL(<< "Error when loading model " << GetParameterString("model") << " : unsupported model type");
      }

    m_Model->Load(GetParameterString("model"));
    otbAppLogINFO("Model loaded");

    // Normalize input image (optional)
    StatisticsReader::Pointer  statisticsReader = StatisticsReader::New();
    MeasurementType  meanMeasurementVector;
    MeasurementType  stddevMeasurementVector;
    m_Rescaler = RescalerType::New();

    // Classify
    m_ClassificationFilter = ClassificationFilterType::New();
    m_ClassificationFilter->SetModel(m_Model);

    // Normalize input image if asked
    if(IsParameterEnabled("imstat")  )
      {
      otbAppLogINFO("Input image normalization activated.");
      // Load input image statistics
      statisticsReader->SetFileName(GetParameterString("imstat"));
      meanMeasurementVector   = statisticsReader->GetStatisticVectorByName("mean");
      stddevMeasurementVector = statisticsReader->GetStatisticVectorByName("stddev");
      otbAppLogINFO( "mean used: " << meanMeasurementVector );
      otbAppLogINFO( "standard deviation used: " << stddevMeasurementVector );
      // Rescale vector image
      m_Rescaler->SetScale(stddevMeasurementVector);
      m_Rescaler->SetShift(meanMeasurementVector);
      m_Rescaler->SetInput(inImage);

      m_ClassificationFilter->SetInput(m_Rescaler->GetOutput());
      }
    else
      {
      otbAppLogINFO("Input image normalization deactivated.");
      m_ClassificationFilter->SetInput(inImage);
      }

    if(IsParameterEnabled("mask"))
      {
      otbAppLogINFO("Using input mask");
      // Load mask image and cast into LabeledImageType
      MaskImageType::Pointer inMask = GetParameterUInt8Image("mask");

      m_ClassificationFilter->SetInputMask(inMask);
      }

    SetParameterOutputImage<OutputImageType>("out", m_ClassificationFilter->GetOutput());
  }

  ClassificationFilterType::Pointer m_ClassificationFilter;
  ModelPointerType m_Model;
  RescalerType::Pointer m_Rescaler;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::ImageClassifier)
<commit_msg>ENH: update classification appli to output confidence mask<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.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbChangeLabelImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbStatisticsXMLFileReader.h"
#include "otbShiftScaleVectorImageFilter.h"
#include "otbImageClassificationFilter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbImageToVectorImageCastFilter.h"
#include "otbMachineLearningModelFactory.h"

namespace otb
{
namespace Wrapper
{

class ImageClassifier : public Application
{
public:
  /** Standard class typedefs. */
  typedef ImageClassifier            Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(ImageClassifier, otb::Application);

  /** Filters typedef */
  typedef UInt16ImageType                                                                      OutputImageType;
  typedef UInt8ImageType                                                                       MaskImageType;
  typedef itk::VariableLengthVector<FloatVectorImageType::InternalPixelType>                   MeasurementType;
  typedef otb::StatisticsXMLFileReader<MeasurementType>                                        StatisticsReader;
  typedef otb::ShiftScaleVectorImageFilter<FloatVectorImageType, FloatVectorImageType>         RescalerType;
  typedef otb::ImageClassificationFilter<FloatVectorImageType, OutputImageType, MaskImageType> ClassificationFilterType;
  typedef ClassificationFilterType::Pointer                                                    ClassificationFilterPointerType;
  typedef ClassificationFilterType::ModelType                                                  ModelType;
  typedef ModelType::Pointer                                                                   ModelPointerType;
  typedef ClassificationFilterType::ValueType                                                  ValueType;
  typedef ClassificationFilterType::LabelType                                                  LabelType;
  typedef otb::MachineLearningModelFactory<ValueType, LabelType>                               MachineLearningModelFactoryType;
  typedef ClassificationFilterType::ConfidenceImageType                                        ConfidenceImageType;

private:
  void DoInit()
  {
    SetName("ImageClassifier");
    SetDescription("Performs a classification of the input image according to a model file.");

    // Documentation
    SetDocName("Image Classification");
    SetDocLongDescription("This application performs an image classification based on a model file produced by the TrainImagesClassifier application. Pixels of the output image will contain the class labels decided by the classifier (maximal class label = 65535). The input pixels can be optionally centered and reduced according to the statistics file produced by the ComputeImagesStatistics application. An optional input mask can be provided, in which case only input image pixels whose corresponding mask value is greater than 0 will be classified. The remaining of pixels will be given the label 0 in the output image.");

    SetDocLimitations("The input image must have the same type, order and number of bands than the images used to produce the statistics file and the SVM model file. If a statistics file was used during training by the TrainImagesClassifier, it is mandatory to use the same statistics file for classification. If an input mask is used, its size must match the input image size.");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("TrainImagesClassifier, ValidateImagesClassifier, ComputeImagesStatistics");

    AddDocTag(Tags::Learning);

    AddParameter(ParameterType_InputImage, "in",  "Input Image");
    SetParameterDescription( "in", "The input image to classify.");

    AddParameter(ParameterType_InputImage,  "mask",   "Input Mask");
    SetParameterDescription( "mask", "The mask allows to restrict classification of the input image to the area where mask pixel values are greater than 0.");
    MandatoryOff("mask");

    AddParameter(ParameterType_InputFilename, "model", "Model file");
    SetParameterDescription("model", "A model file (produced by TrainImagesClassifier application, maximal class label = 65535).");

    AddParameter(ParameterType_InputFilename, "imstat", "Statistics file");
    SetParameterDescription("imstat", "A XML file containing mean and standard deviation to center and reduce samples before classification (produced by ComputeImagesStatistics application).");
    MandatoryOff("imstat");

    AddParameter(ParameterType_OutputImage, "out",  "Output Image");
    SetParameterDescription( "out", "Output image containing class labels");
    SetParameterOutputImagePixelType( "out", ImagePixelType_uint8);

    AddParameter(ParameterType_OutputImage, "confmap",  "Confidence map");
    SetParameterDescription( "confmap", "Confidence map of the produced classification. Meaning depends on the model.");
    SetParameterOutputImagePixelType( "confmap", ImagePixelType_double);
    MandatoryOff("confmap");

    AddRAMParameter();

   // Doc example parameter settings
    SetDocExampleParameterValue("in", "QB_1_ortho.tif");
    SetDocExampleParameterValue("imstat", "EstimateImageStatisticsQB1.xml");
    SetDocExampleParameterValue("model", "clsvmModelQB1.svm");
    SetDocExampleParameterValue("out", "clLabeledImageQB1.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    // Load input image
    FloatVectorImageType::Pointer inImage = GetParameterImage("in");
    inImage->UpdateOutputInformation();

    // Load svm model
    otbAppLogINFO("Loading model");
    m_Model = MachineLearningModelFactoryType::CreateMachineLearningModel(GetParameterString("model"),
                                                                          MachineLearningModelFactoryType::ReadMode);

    if (m_Model.IsNull())
      {
      otbAppLogFATAL(<< "Error when loading model " << GetParameterString("model") << " : unsupported model type");
      }

    m_Model->Load(GetParameterString("model"));
    otbAppLogINFO("Model loaded");

    // Normalize input image (optional)
    StatisticsReader::Pointer  statisticsReader = StatisticsReader::New();
    MeasurementType  meanMeasurementVector;
    MeasurementType  stddevMeasurementVector;
    m_Rescaler = RescalerType::New();

    // Classify
    m_ClassificationFilter = ClassificationFilterType::New();
    m_ClassificationFilter->SetModel(m_Model);

    // Normalize input image if asked
    if(IsParameterEnabled("imstat")  )
      {
      otbAppLogINFO("Input image normalization activated.");
      // Load input image statistics
      statisticsReader->SetFileName(GetParameterString("imstat"));
      meanMeasurementVector   = statisticsReader->GetStatisticVectorByName("mean");
      stddevMeasurementVector = statisticsReader->GetStatisticVectorByName("stddev");
      otbAppLogINFO( "mean used: " << meanMeasurementVector );
      otbAppLogINFO( "standard deviation used: " << stddevMeasurementVector );
      // Rescale vector image
      m_Rescaler->SetScale(stddevMeasurementVector);
      m_Rescaler->SetShift(meanMeasurementVector);
      m_Rescaler->SetInput(inImage);

      m_ClassificationFilter->SetInput(m_Rescaler->GetOutput());
      }
    else
      {
      otbAppLogINFO("Input image normalization deactivated.");
      m_ClassificationFilter->SetInput(inImage);
      }

    if(IsParameterEnabled("mask"))
      {
      otbAppLogINFO("Using input mask");
      // Load mask image and cast into LabeledImageType
      MaskImageType::Pointer inMask = GetParameterUInt8Image("mask");

      m_ClassificationFilter->SetInputMask(inMask);
      }

    SetParameterOutputImage<OutputImageType>("out", m_ClassificationFilter->GetOutput());

    // output confidence map
    if (IsParameterEnabled("confmap") && HasValue("confmap"))
      {
      if (m_Model->HasConfidenceIndex())
        {
        SetParameterOutputImage<ConfidenceImageType>("confmap",m_ClassificationFilter->GetOutputConfidence());
        }
      }
  }

  ClassificationFilterType::Pointer m_ClassificationFilter;
  ModelPointerType m_Model;
  RescalerType::Pointer m_Rescaler;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::ImageClassifier)
<|endoftext|>


<commit_before>
#include "afgreader/src/reader.h"
#include "graph/edges_set.cpp"
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>

using std::shared_ptr;
using AMOS::Overlap;
using AMOS::Read;
using AMOS::Reader;
using Graph::EdgesSet;

const double EPSILON = 0.15;
const double ALPHA = 3;

bool compare_edges(const pair<int, shared_ptr<Overlap>>& lhs, const pair<int, shared_ptr<Overlap>>& rhs) {
  return lhs.first < rhs.first;
}

inline bool eq(double x, double y, double eps) {
  return y <= x + eps && x <= y + eps;
}

// tests if o1 is transitive edge considering o2 and o3.
bool is_transitive(const Overlap& o1, const Overlap& o2, const Overlap& o3) {
  auto A = o1.a_id;
  auto B = o1.b_id;
  auto C = o2.a_id;
  if (C == A) {
    C = o2.b_id;
  }
  if (o2.use_suffix(C) == o3.use_suffix(C)) {
    return false;
  }
  if (o1.use_suffix(A) != o2.use_suffix(A)) {
    return false;
  }
  if (o1.use_suffix(B) != o3.use_suffix(B)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(A) + o3.hanging_length(C),
        o1.hanging_length(A),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(C) + o3.hanging_length(B),
        o1.hanging_length(B),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  return true;
}

int get_non_transitives(vector<shared_ptr<Overlap>>* dst_container, vector<shared_ptr<Overlap>>& edges_list) {
  int valid = 0;

  // create that data structure to allow fast access to all edges coincident
  // with particular node.
  EdgesSet<shared_ptr<Overlap>> edges_set;
  for (const auto& edge : edges_list) {
    edges_set.add(edge->a_id, edge->b_id, edge);
    edges_set.add(edge->b_id, edge->a_id, edge);
  }

  // sort so we can reduce complexity on iterating edges.
  for (auto unsorted : edges_set) {
    unsorted.second.sort();
  }

  // we are iterating all (x, y), (x, a), (y, a) in hope that we will find that
  // (x,y) is transitive edge when considering (x, a) and (y, a).
  // x -> y, x -> a -> y; x -> y can be information overhead.
  for (const auto& overlap : edges_list) {
    auto& src = overlap->a_id;
    auto& dst = overlap->b_id;

    auto& v1 = edges_set[src], v2 = edges_set[dst];
    auto it1 = v1.begin(), it2 = v2.begin();

    bool transitive = false;
    while (!transitive && it1 != v1.end() && it2 != v2.end()) {
      if (it1->first == overlap->a_id || it1->first == overlap->b_id) {
        ++it1;
        continue;
      }
      if (it2->first == overlap->a_id || it2->first == overlap->b_id) {
        ++it2;
        continue;
      }
      if (it1->first == it2->first) {
        if (is_transitive(*overlap, *it1->second, *it2->second)) {
          transitive = true;
        }
        ++it1;
        ++it2;
      } else if (it1->first < it2->first) {
        ++it1;
      } else {
        ++it2;
      }
    }

    if (!transitive) {
      dst_container->emplace_back(overlap);
    }
  }

  return valid;
}

void fill_reads(vector<shared_ptr<Overlap>>& overlaps, map<uint32_t, shared_ptr<Read>>& reads) {
  for (auto o : overlaps) {
    o->a = reads[o->a_id];
    o->b = reads[o->b_id];
  }
}

int read_from_stream(istream& input, map<uint32_t, shared_ptr<Read>>& reads, vector<shared_ptr<Overlap>>& edges) {
  Reader reader(input);

  int stored = 0;
  while (reader.has_next()) {
    if (reader.next_type() == AMOS::OVERLAP) {
      Overlap* overlap = new Overlap();
      if (!reader.next(overlap)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      edges.emplace_back(shared_ptr<Overlap>(overlap));
      stored++;
    } else if (reader.next_type() == AMOS::READ) {
      Read *read = new Read();
      if (!reader.next(read)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      reads[read->iid] = shared_ptr<Read>(read);
      stored++;
    } else {
      reader.skip_next();
      continue;
    }
  }

  return stored;
}

int main(int argc, char **argv) {
  vector<istream*> input_streams;

  if (argc == 2) {
    input_streams.emplace_back(&cin);
  } else {
    for (int i = 1; i < argc; ++i) {
      istream* in_stream;
      if (strcmp(argv[i], "-") == 0) {
        in_stream = &cin;
      } else {
        in_stream = new ifstream(argv[i]);
      }

      input_streams.emplace_back(&cin);
    }
  }

  vector<shared_ptr<Overlap>> overlaps;
  map<uint32_t, shared_ptr<Read>> reads;

  for (auto in_stream : input_streams) {
    read_from_stream(*in_stream, reads, overlaps);
  }

  cerr << "Read " << overlaps.size() << " reads" << endl;
  cerr << "Read " << reads.size() << " overlaps" << endl;

  fill_reads(overlaps, reads);

  vector<shared_ptr<Overlap>> non_transitive_edges;
  get_non_transitives(&non_transitive_edges, overlaps);

  cerr << "Filtered " << (overlaps.size() - non_transitive_edges.size()) << " overlaps" << endl;
}
<commit_msg>add logs for reading<commit_after>
#include "afgreader/src/reader.h"
#include "graph/edges_set.cpp"
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>

using std::shared_ptr;
using std::string;
using AMOS::Overlap;
using AMOS::Read;
using AMOS::Reader;
using Graph::EdgesSet;

const double EPSILON = 0.15;
const double ALPHA = 3;

bool compare_edges(const pair<int, shared_ptr<Overlap>>& lhs, const pair<int, shared_ptr<Overlap>>& rhs) {
  return lhs.first < rhs.first;
}

inline bool eq(double x, double y, double eps) {
  return y <= x + eps && x <= y + eps;
}

// tests if o1 is transitive edge considering o2 and o3.
bool is_transitive(const Overlap& o1, const Overlap& o2, const Overlap& o3) {
  auto A = o1.a_id;
  auto B = o1.b_id;
  auto C = o2.a_id;
  if (C == A) {
    C = o2.b_id;
  }
  if (o2.use_suffix(C) == o3.use_suffix(C)) {
    return false;
  }
  if (o1.use_suffix(A) != o2.use_suffix(A)) {
    return false;
  }
  if (o1.use_suffix(B) != o3.use_suffix(B)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(A) + o3.hanging_length(C),
        o1.hanging_length(A),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  if (!eq(
        o2.hanging_length(C) + o3.hanging_length(B),
        o1.hanging_length(B),
        EPSILON * o1.length() + ALPHA)) {
    return false;
  }
  return true;
}

int get_non_transitives(vector<shared_ptr<Overlap>>* dst_container, vector<shared_ptr<Overlap>>& edges_list) {
  int valid = 0;

  // create that data structure to allow fast access to all edges coincident
  // with particular node.
  EdgesSet<shared_ptr<Overlap>> edges_set;
  for (const auto& edge : edges_list) {
    edges_set.add(edge->a_id, edge->b_id, edge);
    edges_set.add(edge->b_id, edge->a_id, edge);
  }

  // sort so we can reduce complexity on iterating edges.
  for (auto unsorted : edges_set) {
    unsorted.second.sort();
  }

  // we are iterating all (x, y), (x, a), (y, a) in hope that we will find that
  // (x,y) is transitive edge when considering (x, a) and (y, a).
  // x -> y, x -> a -> y; x -> y can be information overhead.
  for (const auto& overlap : edges_list) {
    auto& src = overlap->a_id;
    auto& dst = overlap->b_id;

    auto& v1 = edges_set[src], v2 = edges_set[dst];
    auto it1 = v1.begin(), it2 = v2.begin();

    bool transitive = false;
    while (!transitive && it1 != v1.end() && it2 != v2.end()) {
      if (it1->first == overlap->a_id || it1->first == overlap->b_id) {
        ++it1;
        continue;
      }
      if (it2->first == overlap->a_id || it2->first == overlap->b_id) {
        ++it2;
        continue;
      }
      if (it1->first == it2->first) {
        if (is_transitive(*overlap, *it1->second, *it2->second)) {
          transitive = true;
        }
        ++it1;
        ++it2;
      } else if (it1->first < it2->first) {
        ++it1;
      } else {
        ++it2;
      }
    }

    if (!transitive) {
      dst_container->emplace_back(overlap);
    }
  }

  return valid;
}

void fill_reads(vector<shared_ptr<Overlap>>& overlaps, map<uint32_t, shared_ptr<Read>>& reads) {
  for (auto o : overlaps) {
    o->a = reads[o->a_id];
    o->b = reads[o->b_id];
  }
}

int read_from_stream(istream& input, map<uint32_t, shared_ptr<Read>>& reads, vector<shared_ptr<Overlap>>& edges) {
  Reader reader(input);

  int stored = 0;
  while (reader.has_next()) {
    if (reader.next_type() == AMOS::OVERLAP) {
      Overlap* overlap = new Overlap();
      if (!reader.next(overlap)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      edges.emplace_back(shared_ptr<Overlap>(overlap));
      stored++;
    } else if (reader.next_type() == AMOS::READ) {
      Read *read = new Read();
      if (!reader.next(read)) {
        cerr << "Error while reading overlap" << endl;
        continue;
      }

      reads[read->iid] = shared_ptr<Read>(read);
      stored++;
    } else {
      reader.skip_next();
      continue;
    }
  }

  return stored;
}

int main(int argc, char **argv) {
  vector<string> input_streams;

  for (int i = 1; i < argc; ++i) {
    input_streams.emplace_back(argv[i]);
  }
  if (argc == 2) {
    input_streams.emplace_back("-");
  }

  vector<shared_ptr<Overlap>> overlaps;
  map<uint32_t, shared_ptr<Read>> reads;

  for (auto stream_name : input_streams) {
    cerr << "Starting reading from " << stream_name << endl;
    if (stream_name == "-") {
      read_from_stream(cin, reads, overlaps);
    } else {
      fstream file(stream_name);
      read_from_stream(file, reads, overlaps);
      file.close();
    }
    cerr << "Finished reading from " << stream_name << endl;
  }

  cerr << "Read " << overlaps.size() << " reads" << endl;
  cerr << "Read " << reads.size() << " overlaps" << endl;

  fill_reads(overlaps, reads);

  vector<shared_ptr<Overlap>> non_transitive_edges;
  get_non_transitives(&non_transitive_edges, overlaps);

  cerr << "Filtered " << (overlaps.size() - non_transitive_edges.size()) << " overlaps" << endl;
}
<|endoftext|>


<commit_before>#include "GL_Header.h"

#include "texture-font.h"
#include "texture-atlas.h"

#include "font.h"
#include "shader.h"
#include "color.h"
#include "staticfont.h"
#include "render_target.h"

#include <coreutils/utils.h>
#include <coreutils/log.h>

#define _USE_MATH_DEFINES
#include <cmath>

#include <vector>
using namespace std;

namespace grappix {

std::vector<std::weak_ptr<Font::FontRef>> Font::fontRefs;

uint8_t *make_distance_map(uint8_t *img, int width, int height);

Font::Font(bool stfont) : size(32) {
	ref = make_shared<FontRef>(0, 0, "", 0.0, 0);
	texture_atlas_t *atlas = new texture_atlas_t();
	ref->atlas = atlas;
	atlas->width = static_font.tex_width;
	atlas->height = static_font.tex_height;
	atlas->id = 0;
	atlas->data = static_font.tex_data;
    texture_atlas_upload(atlas);
    LOGD("Static font created");
}

const static wchar_t *fontLetters = L"@!ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
const static wchar_t *fontLettersUpper = L"@!ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";

Font::Font(const string &ttfName, int size, int flags) : size(size) {

	program = flags & DISTANCE_MAP ? get_program(FONT_PROGRAM_DF) : get_program(FONT_PROGRAM);

	int tsize = flags & 0xffffc0;
	if(tsize == 0) tsize = 128;
	flags &= 0x3f;

	for(auto &fr : fontRefs) {
		auto r = fr.lock();
		if(r) {
			LOGD("%s(%d) vs %s(%d)",r->ttfName, r->w, ttfName, tsize);
			if(r->ttfName == ttfName && r->w == tsize && r->h == tsize && r->flags == flags) {
				ref = r;
				LOGD("Reusing %s (%d)", ttfName, size);
				return;
			}
		}
	}

	ref = make_shared<FontRef>(tsize, tsize, ttfName, size, flags);
	fontRefs.push_back(ref);

	auto text = fontLetters;
	if(flags & UPPER_CASE)
		text = fontLettersUpper;

	texture_font_load_glyphs((texture_font_t*)ref->font, text);

	texture_atlas_t *atlas = (texture_atlas_t*)ref->atlas;
	if(flags & DISTANCE_MAP) {
		uint8_t *data = make_distance_map(atlas->data, atlas->width, atlas->height);
		LOGD("Distance map created");
		free(atlas->data);
		atlas->data = data;
	}
    texture_atlas_upload(atlas);
}

//static float scale = 1.0;

TextBuf Font::make_text2(const string &text) const {

	//LOGD("Make text2");

	//auto tl = text.length();
	//vector<GLfloat> p;
	vector<GLfloat> verts;
	vector<GLushort> indexes;

	//char lastChar = 0;
	int i = 0;
	float x = 0;
	float y = 0;

	auto t2 = utils::utf8_decode(text);

	for(auto c : t2) {

        texture_glyph2_t *glyph = 0;
        for(unsigned int j=0; j<static_font.glyphs_count; ++j) {
            if(static_font.glyphs[j].charcode == c) {
                glyph = &static_font.glyphs[j];
                break;
            }
        }
        if(!glyph) {
   			x += 8.0;
            continue;
        }

		//texture_glyph_t *glyph = texture_font_get_glyph(font, c);
		//LOGD("Glyph %p", glyph);
		//if( glyph == NULL )
		//if(lastChar)
		//	x += texture_glyph_get_kerning(glyph, lastChar);
		float x0  = x + glyph->offset_x;
		float y0  = y + static_font.height;//gl;//+ glyph->offset_y;
		float x1  = x0 + glyph->width;
		float y1  = y0 - glyph->offset_y;
		//LOGD("%d %d", glyph->height, glyph->offset_y);

		float s0 = glyph->s0;
		float t0 = glyph->t0;
		float s1 = glyph->s1;
		float t1 = glyph->t1;

		x += glyph->advance_x;

		verts.push_back(x0);
		verts.push_back(y1);
		verts.push_back(s0);
		verts.push_back(t0);
		verts.push_back(x1);
		verts.push_back(y1);
		verts.push_back(s1);
		verts.push_back(t0);
		verts.push_back(x0);
		verts.push_back(y0);
		verts.push_back(s0);
		verts.push_back(t1);
		verts.push_back(x1);
		verts.push_back(y0);
		verts.push_back(s1);
		verts.push_back(t1);

		indexes.push_back(i);
		indexes.push_back(i+1);
		indexes.push_back(i+2);
		indexes.push_back(i+1);
		indexes.push_back(i+3);
		indexes.push_back(i+2);
		i += 4;
		//break;
	}

	TextBuf tbuf;
	//vector<GLuint> vbuf(2);
	tbuf.text = text;
	tbuf.size = i/4;
	glGenBuffers(2, &tbuf.vbuf[0]);
	glBindBuffer(GL_ARRAY_BUFFER, tbuf.vbuf[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tbuf.vbuf[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexes.size() * 2, &indexes[0], GL_STATIC_DRAW);
	glBufferData(GL_ARRAY_BUFFER, verts.size() * 4, &verts[0], GL_STATIC_DRAW);

	return tbuf;
}

TextBuf Font::make_text(const string &text) const {

	if(!ref->font)
		return make_text2(text);

	//LOGD("Make text");

	//auto tl = text.length();
	//vector<GLfloat> p;
	vector<GLfloat> verts;
	vector<GLushort> indexes;

	char lastChar = 0;
	int i = 0;
	float x = 0;
	texture_font_t *font = (texture_font_t*)ref->font;

	float y = font->ascender;

	//auto t2 = utils::utf8_decode(text);

	for(auto c : text) {

		texture_glyph_t *glyph = texture_font_get_glyph(font, c);
		if(!glyph)
			continue;
		//LOGD("Glyph %p", glyph);
		//if( glyph == NULL )
		if(lastChar)
			x += texture_glyph_get_kerning(glyph, lastChar);
		lastChar = c;

		//LOGD("%d vs %d", glyph->height, font->height);

		float x0  = x + glyph->offset_x;
		float x1  = x0 + glyph->width;

		float y1  = y - glyph->offset_y;
		float y0  = y1 + glyph->height;
		//LOGD("%f %f %f", glyph->height, glyph->offset_y, font->height);

		float s0 = glyph->s0;
		float t0 = glyph->t0;
		float s1 = glyph->s1;
		float t1 = glyph->t1;

		verts.push_back(x0);
		verts.push_back(y1);
		verts.push_back(s0);
		verts.push_back(t0);
		verts.push_back(x1);
		verts.push_back(y1);
		verts.push_back(s1);
		verts.push_back(t0);
		verts.push_back(x0);
		verts.push_back(y0);
		verts.push_back(s0);
		verts.push_back(t1);
		verts.push_back(x1);
		verts.push_back(y0);
		verts.push_back(s1);
		verts.push_back(t1);

		indexes.push_back(i);
		indexes.push_back(i+1);
		indexes.push_back(i+2);
		indexes.push_back(i+1);
		indexes.push_back(i+3);
		indexes.push_back(i+2);
		i += 4;

		x += glyph->advance_x;

		//break;
	}

	TextBuf tbuf;
	//vector<GLuint> vbuf(2);
	tbuf.text = text;
	tbuf.size = i/4;
	tbuf.rec[0] = verts[0];
	tbuf.rec[1] = verts[1];
	tbuf.rec[2] = verts[verts.size()-4];
	tbuf.rec[3] = verts[verts.size()-3];

	//LOGD("Text %s covers %f to %f", text, tbuf.rec[0], tbuf.rec[2]);

	glGenBuffers(2, &tbuf.vbuf[0]);
	glBindBuffer(GL_ARRAY_BUFFER, tbuf.vbuf[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tbuf.vbuf[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexes.size() * 2, &indexes[0], GL_STATIC_DRAW);
	glBufferData(GL_ARRAY_BUFFER, verts.size() * 4, &verts[0], GL_STATIC_DRAW);

	return tbuf;
}

void Font::render_text(const RenderTarget &target, const TextBuf &text, float x, float y, uint32_t color, float scale) const {

	scale = scale * 32.0 / (float)size;

	glBindFramebuffer(GL_FRAMEBUFFER, target.buffer());
	glViewport(0,0,target.width(), target.height());

	program.use();

	glBindBuffer(GL_ARRAY_BUFFER, text.vbuf[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, text.vbuf[1]);

	utils::mat4f matrix = make_scale(scale, scale);
	matrix = make_translate(x, y) * matrix;
	matrix = target.get_view_matrix() * matrix;
	program.setUniform("matrix", matrix.transpose());

	// Needed for DF shader
	program.setUniform("vScale", scale);

	auto c = make_color(color);
	program.setUniform("color", c.red, c.green, c.blue, c.alpha);

	program.vertexAttribPointer("vertex", 2, GL_FLOAT, GL_FALSE, 16, 0);
	program.vertexAttribPointer("uv", 2, GL_FLOAT, GL_FALSE, 16, 8);

	texture_atlas_t *atlas = (texture_atlas_t*)ref->atlas;
	glBindTexture( GL_TEXTURE_2D, atlas->id );
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	//int tl = text.text.length();
	glDrawElements(GL_TRIANGLES, 6*text.size, GL_UNSIGNED_SHORT, 0);

	//LOGD("Drew %d\n", tl);

	//glDisableVertexAttribArray(uvHandle);
	//glDisableVertexAttribArray(vertHandle);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void Font::render_text(const RenderTarget &target, const std::string &text, float x, float y, uint32_t col, float scale) const {
	if(text == "")
		return;
	auto buf = cache.get(text);
	if(buf.text == "") {
		buf = make_text(text);
		cache.put(text, buf);
	}
	render_text(target, buf, x, y, col, scale);
}

void clean_cache() {
}

int Font::get_width(const string &text, float scale) {
	if(text == "")
		return 0;
	auto buf = cache.get(text);
	if(buf.text == "") {
		buf = make_text(text);
		cache.put(text, buf);
	}
	scale = scale * 32.0 / (float)size;
	return (buf.rec[2] - buf.rec[0]) * scale;
}

Font::FontRef::FontRef(int w, int h, const std::string &ttfName, int fsize, int flags) : w(w), h(h), flags(flags), ttfName(ttfName), atlas(nullptr), font(nullptr) {
	LOGD("FONTREF CONSTRUCT");
	texture_atlas_t *a = nullptr;
	if(w > 0 && h > 0)
		a = texture_atlas_new(w, h, 1);
	if(a && fsize > 0) {
		font = (texture_font_t*)texture_font_new(a, ttfName.c_str(), fsize);
		LOGD("FONTREF DONE");
	}
	atlas = a;
}
Font::FontRef::~FontRef() {
	//LOGD("FONTREF DESTROY");
	if(font)
		texture_font_delete((texture_font_t*)font);
	if(atlas)
		texture_atlas_delete((texture_atlas_t*)atlas);
	font = nullptr;
	atlas = nullptr;
}

}

<commit_msg>Cache font distance fields<commit_after>#include "GL_Header.h"

#include "texture-font.h"
#include "texture-atlas.h"

#include "font.h"
#include "shader.h"
#include "color.h"
#include "staticfont.h"
#include "render_target.h"

#include <coreutils/utils.h>
#include <coreutils/log.h>

#define _USE_MATH_DEFINES
#include <cmath>

#include <vector>
using namespace std;
using namespace utils;

namespace grappix {

std::vector<std::weak_ptr<Font::FontRef>> Font::fontRefs;

uint8_t *make_distance_map(uint8_t *img, int width, int height);

Font::Font(bool stfont) : size(32) {
	ref = make_shared<FontRef>(0, 0, "", 0.0, 0);
	texture_atlas_t *atlas = new texture_atlas_t();
	ref->atlas = atlas;
	atlas->width = static_font.tex_width;
	atlas->height = static_font.tex_height;
	atlas->id = 0;
	atlas->data = static_font.tex_data;
    texture_atlas_upload(atlas);
    LOGD("Static font created");
}

const static wchar_t *fontLetters = L"@!ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
const static wchar_t *fontLettersUpper = L"@!ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";

Font::Font(const string &ttfName, int size, int flags) : size(size) {

	program = flags & DISTANCE_MAP ? get_program(FONT_PROGRAM_DF) : get_program(FONT_PROGRAM);

	int tsize = flags & 0xffffc0;
	if(tsize == 0) tsize = 128;
	flags &= 0x3f;

	for(auto &fr : fontRefs) {
		auto r = fr.lock();
		if(r) {
			LOGD("%s(%d) vs %s(%d)",r->ttfName, r->w, ttfName, tsize);
			if(r->ttfName == ttfName && r->w == tsize && r->h == tsize && r->flags == flags) {
				ref = r;
				LOGD("Reusing %s (%d)", ttfName, size);
				return;
			}
		}
	}

	ref = make_shared<FontRef>(tsize, tsize, ttfName, size, flags);
	fontRefs.push_back(ref);

	auto text = fontLetters;
	if(flags & UPPER_CASE)
		text = fontLettersUpper;

	texture_font_load_glyphs((texture_font_t*)ref->font, text);

	texture_atlas_t *atlas = (texture_atlas_t*)ref->atlas;
	if(flags & DISTANCE_MAP) {
		File f { format("%s.%d.%d.dat", ttfName, size, tsize) };
		if(f.exists()) {
			f.read(atlas->data, atlas->width*atlas->height);
			LOGD("Distance map loaded");
		} else {
			uint8_t *data = make_distance_map(atlas->data, atlas->width, atlas->height);
			LOGD("Distance map created");
			free(atlas->data);
			atlas->data = data;
			f.write(atlas->data, atlas->width*atlas->height);
		}
		f.close();
	}
    texture_atlas_upload(atlas);
}

//static float scale = 1.0;

TextBuf Font::make_text2(const string &text) const {

	//LOGD("Make text2");

	//auto tl = text.length();
	//vector<GLfloat> p;
	vector<GLfloat> verts;
	vector<GLushort> indexes;

	//char lastChar = 0;
	int i = 0;
	float x = 0;
	float y = 0;

	auto t2 = utf8_decode(text);

	for(auto c : t2) {

        texture_glyph2_t *glyph = 0;
        for(unsigned int j=0; j<static_font.glyphs_count; ++j) {
            if(static_font.glyphs[j].charcode == c) {
                glyph = &static_font.glyphs[j];
                break;
            }
        }
        if(!glyph) {
   			x += 8.0;
            continue;
        }

		//texture_glyph_t *glyph = texture_font_get_glyph(font, c);
		//LOGD("Glyph %p", glyph);
		//if( glyph == NULL )
		//if(lastChar)
		//	x += texture_glyph_get_kerning(glyph, lastChar);
		float x0  = x + glyph->offset_x;
		float y0  = y + static_font.height;//gl;//+ glyph->offset_y;
		float x1  = x0 + glyph->width;
		float y1  = y0 - glyph->offset_y;
		//LOGD("%d %d", glyph->height, glyph->offset_y);

		float s0 = glyph->s0;
		float t0 = glyph->t0;
		float s1 = glyph->s1;
		float t1 = glyph->t1;

		x += glyph->advance_x;

		verts.push_back(x0);
		verts.push_back(y1);
		verts.push_back(s0);
		verts.push_back(t0);
		verts.push_back(x1);
		verts.push_back(y1);
		verts.push_back(s1);
		verts.push_back(t0);
		verts.push_back(x0);
		verts.push_back(y0);
		verts.push_back(s0);
		verts.push_back(t1);
		verts.push_back(x1);
		verts.push_back(y0);
		verts.push_back(s1);
		verts.push_back(t1);

		indexes.push_back(i);
		indexes.push_back(i+1);
		indexes.push_back(i+2);
		indexes.push_back(i+1);
		indexes.push_back(i+3);
		indexes.push_back(i+2);
		i += 4;
		//break;
	}

	TextBuf tbuf;
	//vector<GLuint> vbuf(2);
	tbuf.text = text;
	tbuf.size = i/4;
	glGenBuffers(2, &tbuf.vbuf[0]);
	glBindBuffer(GL_ARRAY_BUFFER, tbuf.vbuf[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tbuf.vbuf[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexes.size() * 2, &indexes[0], GL_STATIC_DRAW);
	glBufferData(GL_ARRAY_BUFFER, verts.size() * 4, &verts[0], GL_STATIC_DRAW);

	return tbuf;
}

TextBuf Font::make_text(const string &text) const {

	if(!ref->font)
		return make_text2(text);

	//LOGD("Make text");

	//auto tl = text.length();
	//vector<GLfloat> p;
	vector<GLfloat> verts;
	vector<GLushort> indexes;

	char lastChar = 0;
	int i = 0;
	float x = 0;
	texture_font_t *font = (texture_font_t*)ref->font;

	float y = font->ascender;

	//auto t2 = utf8_decode(text);

	for(auto c : text) {

		texture_glyph_t *glyph = texture_font_get_glyph(font, c);
		if(!glyph)
			continue;
		//LOGD("Glyph %p", glyph);
		//if( glyph == NULL )
		if(lastChar)
			x += texture_glyph_get_kerning(glyph, lastChar);
		lastChar = c;

		//LOGD("%d vs %d", glyph->height, font->height);

		float x0  = x + glyph->offset_x;
		float x1  = x0 + glyph->width;

		float y1  = y - glyph->offset_y;
		float y0  = y1 + glyph->height;
		//LOGD("%f %f %f", glyph->height, glyph->offset_y, font->height);

		float s0 = glyph->s0;
		float t0 = glyph->t0;
		float s1 = glyph->s1;
		float t1 = glyph->t1;

		verts.push_back(x0);
		verts.push_back(y1);
		verts.push_back(s0);
		verts.push_back(t0);
		verts.push_back(x1);
		verts.push_back(y1);
		verts.push_back(s1);
		verts.push_back(t0);
		verts.push_back(x0);
		verts.push_back(y0);
		verts.push_back(s0);
		verts.push_back(t1);
		verts.push_back(x1);
		verts.push_back(y0);
		verts.push_back(s1);
		verts.push_back(t1);

		indexes.push_back(i);
		indexes.push_back(i+1);
		indexes.push_back(i+2);
		indexes.push_back(i+1);
		indexes.push_back(i+3);
		indexes.push_back(i+2);
		i += 4;

		x += glyph->advance_x;

		//break;
	}

	TextBuf tbuf;
	//vector<GLuint> vbuf(2);
	tbuf.text = text;
	tbuf.size = i/4;
	tbuf.rec[0] = verts[0];
	tbuf.rec[1] = verts[1];
	tbuf.rec[2] = verts[verts.size()-4];
	tbuf.rec[3] = verts[verts.size()-3];

	//LOGD("Text %s covers %f to %f", text, tbuf.rec[0], tbuf.rec[2]);

	glGenBuffers(2, &tbuf.vbuf[0]);
	glBindBuffer(GL_ARRAY_BUFFER, tbuf.vbuf[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tbuf.vbuf[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexes.size() * 2, &indexes[0], GL_STATIC_DRAW);
	glBufferData(GL_ARRAY_BUFFER, verts.size() * 4, &verts[0], GL_STATIC_DRAW);

	return tbuf;
}

void Font::render_text(const RenderTarget &target, const TextBuf &text, float x, float y, uint32_t color, float scale) const {

	scale = scale * 32.0 / (float)size;

	glBindFramebuffer(GL_FRAMEBUFFER, target.buffer());
	glViewport(0,0,target.width(), target.height());

	program.use();

	glBindBuffer(GL_ARRAY_BUFFER, text.vbuf[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, text.vbuf[1]);

	mat4f matrix = make_scale(scale, scale);
	matrix = make_translate(x, y) * matrix;
	matrix = target.get_view_matrix() * matrix;
	program.setUniform("matrix", matrix.transpose());

	// Needed for DF shader
	program.setUniform("vScale", scale);

	auto c = make_color(color);
	program.setUniform("color", c.red, c.green, c.blue, c.alpha);

	program.vertexAttribPointer("vertex", 2, GL_FLOAT, GL_FALSE, 16, 0);
	program.vertexAttribPointer("uv", 2, GL_FLOAT, GL_FALSE, 16, 8);

	texture_atlas_t *atlas = (texture_atlas_t*)ref->atlas;
	glBindTexture( GL_TEXTURE_2D, atlas->id );
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	//int tl = text.text.length();
	glDrawElements(GL_TRIANGLES, 6*text.size, GL_UNSIGNED_SHORT, 0);

	//LOGD("Drew %d\n", tl);

	//glDisableVertexAttribArray(uvHandle);
	//glDisableVertexAttribArray(vertHandle);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

void Font::render_text(const RenderTarget &target, const std::string &text, float x, float y, uint32_t col, float scale) const {
	if(text == "")
		return;
	auto buf = cache.get(text);
	if(buf.text == "") {
		buf = make_text(text);
		cache.put(text, buf);
	}
	render_text(target, buf, x, y, col, scale);
}

void clean_cache() {
}

int Font::get_width(const string &text, float scale) {
	if(text == "")
		return 0;
	auto buf = cache.get(text);
	if(buf.text == "") {
		buf = make_text(text);
		cache.put(text, buf);
	}
	scale = scale * 32.0 / (float)size;
	return (buf.rec[2] - buf.rec[0]) * scale;
}

Font::FontRef::FontRef(int w, int h, const std::string &ttfName, int fsize, int flags) : w(w), h(h), flags(flags), ttfName(ttfName), atlas(nullptr), font(nullptr) {
	LOGD("FONTREF CONSTRUCT");
	texture_atlas_t *a = nullptr;
	if(w > 0 && h > 0)
		a = texture_atlas_new(w, h, 1);
	if(a && fsize > 0) {
		font = (texture_font_t*)texture_font_new(a, ttfName.c_str(), fsize);
		LOGD("FONTREF DONE");
	}
	atlas = a;
}
Font::FontRef::~FontRef() {
	//LOGD("FONTREF DESTROY");
	if(font)
		texture_font_delete((texture_font_t*)font);
	if(atlas)
		texture_atlas_delete((texture_atlas_t*)atlas);
	font = nullptr;
	atlas = nullptr;
}

}

<|endoftext|>


<commit_before>#include <cstdlib>
#include <fstream>
#include <iostream>
#include <ostream>
#include <string>
#include "Getopt.hpp"
#include "snarkfront.hpp"

using namespace snarkfront;
using namespace snarklib;
using namespace std;

void printUsage(const char* exeName) {
    const string
        PAIR = " -p BN128|Edwards",
        KEY = " -k",
        OUT = " [-o output_file]";

    cout << "key pair entropy: " << exeName << PAIR << KEY << OUT << endl
         << "proof entropy:    " << exeName << PAIR << OUT << endl;

    exit(EXIT_FAILURE);
}

template <typename PAIRING>
void writeEntropy(ostream& os, const bool is_keypair) {
    if (is_keypair) {
        PPZK_LagrangePoint<typename PAIRING::Fr> lagrangeRand(0);
        PPZK_BlindGreeks<typename PAIRING::Fr, typename PAIRING::Fr> blindRand(0);
        os << lagrangeRand << blindRand;

    } else {
        PPZK_ProofRandomness<typename PAIRING::Fr> entropy(0);
        os << entropy;
    }
}

int main(int argc, char *argv[])
{
    Getopt cmdLine(argc, argv, "po", "", "k");
    if (!cmdLine || cmdLine.empty()) printUsage(argv[0]);

    const auto pairing = cmdLine.getString('p');
    const auto outfile = cmdLine.getString('o');
    const auto is_keypair = cmdLine.getFlag('k');

    if (!validPairingName(pairing)) {
        cerr << "error: elliptic curve pairing " << pairing << endl;
        exit(EXIT_FAILURE);
    }

    ofstream ofs(outfile);
    if (!outfile.empty() && !ofs) {
        cerr << "error: output file " << outfile << endl;
        exit(EXIT_FAILURE);
    }

    ostream& os = outfile.empty() ? cout : ofs;

    if (pairingBN128(pairing)) {
        // Barreto-Naehrig 128 bits
        init_BN128();
        writeEntropy<BN128_PAIRING>(os, is_keypair);

    } else if (pairingEdwards(pairing)) {
        // Edwards 80 bits
        init_Edwards();
        writeEntropy<EDWARDS_PAIRING>(os, is_keypair);
    }

    exit(EXIT_SUCCESS);
}
<commit_msg>mostly blinded key pair entropy<commit_after>#include <cstdlib>
#include <fstream>
#include <iostream>
#include <ostream>
#include <string>
#include "Getopt.hpp"
#include "snarkfront.hpp"

using namespace snarkfront;
using namespace snarklib;
using namespace std;

void printUsage(const char* exeName) {
    const string
        PAIR = " -p BN128|Edwards",
        CLEAR_KEY = " -k",
        BLIND_KEY = " -B clear_file",
        OUT = " [-o output_file]";

    // note: random sample point for Lagrange coefficients is not blinded

    cout << "generate key pair entropy: " << exeName << PAIR << CLEAR_KEY << OUT << endl
         << "blind key pair entropy:    " << exeName << PAIR << BLIND_KEY << OUT << endl
         << "proof entropy:             " << exeName << PAIR << OUT << endl;

    exit(EXIT_FAILURE);
}

template <typename PAIRING>
void writeEntropy(ostream& os,
                  const bool is_clear_keypair,
                  const string& blind)
{
    typedef typename PAIRING::Fr Fr;
    typedef typename PAIRING::G1 G1;
    typedef typename PAIRING::G2 G2;

    if (is_clear_keypair) {
        PPZK_LagrangePoint<Fr> lagrangeRand(0);
        PPZK_BlindGreeks<Fr, Fr> blindRand(0);
        os << lagrangeRand << blindRand;

    } else if (!blind.empty()) {
        PPZK_LagrangePoint<Fr> lagrangePoint;
        PPZK_BlindGreeks<Fr, Fr> clearGreeks;

        ifstream ifs(blind);
        if (!ifs || !lagrangePoint.marshal_in(ifs) || !clearGreeks.marshal_in(ifs)) {
            cerr << "error: corrupt key pair" << endl;
            exit(EXIT_FAILURE);
        }

        const PPZK_BlindGreeks<Fr, Pairing<G1, G2>> blindGreeks(clearGreeks);
        os << lagrangePoint << blindGreeks;

    } else {
        PPZK_ProofRandomness<typename PAIRING::Fr> entropy(0);
        os << entropy;
    }
}

int main(int argc, char *argv[])
{
    Getopt cmdLine(argc, argv, "poB", "", "k");
    if (!cmdLine || cmdLine.empty()) printUsage(argv[0]);

    const auto pairing = cmdLine.getString('p');
    const auto outfile = cmdLine.getString('o');
    const auto blind = cmdLine.getString('B');
    const auto is_clear_keypair = cmdLine.getFlag('k');

    if (!validPairingName(pairing)) {
        cerr << "error: elliptic curve pairing " << pairing << endl;
        exit(EXIT_FAILURE);
    }

    if (is_clear_keypair && !blind.empty()) {
        cerr << "error: generate and blind are mutually exclusive" << endl;
        exit(EXIT_FAILURE);
    }

    ofstream ofs(outfile);
    if (!outfile.empty() && !ofs) {
        cerr << "error: output file " << outfile << endl;
        exit(EXIT_FAILURE);
    }

    ostream& os = outfile.empty() ? cout : ofs;

    if (pairingBN128(pairing)) {
        // Barreto-Naehrig 128 bits
        init_BN128();
        writeEntropy<BN128_PAIRING>(os, is_clear_keypair, blind);

    } else if (pairingEdwards(pairing)) {
        // Edwards 80 bits
        init_Edwards();
        writeEntropy<EDWARDS_PAIRING>(os, is_clear_keypair, blind);
    }

    exit(EXIT_SUCCESS);
}
<|endoftext|>


<commit_before><commit_msg>Create ranged_for.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>al_NavControl lacked virtual qualifiers<commit_after><|endoftext|>


<commit_before><commit_msg>use error_or.move_value<commit_after><|endoftext|>


<commit_before><commit_msg>minor fixes<commit_after><|endoftext|>


<commit_before><commit_msg>delete warning.<commit_after><|endoftext|>


<commit_before>#define _WINSOCK_DEPRECATED_NO_WARNINGS

#ifndef _LINUX
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif

#include "UDT_Transport.h"

#include <udt.h>
#include <test_util.h>

#include <mutex>
#include <fplog_exceptions.h>
#include <thread>

#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>

using namespace fplog;

namespace spipc
{
    class UDT_Transport::UDT_Transport_Impl
    {
        public:

            UDT_Transport_Impl():
            client_sock_(-1),
            serv_sock_(-1),
            localhost_(false)
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);
            }

            ~UDT_Transport_Impl()
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);
            }

            void connect(const Params& params)
            {
                static UDTUpDown udt_initer;

                std::lock_guard<std::recursive_mutex> lock(mutex_);
                std::string UIDstr;

                if (params.find("uid") == params.end())
                {
                    if (params.find("UID") == params.end())
                    {
                        THROW(fplog::exceptions::Incorrect_Parameter);
                    }
                    else
                        UIDstr = (*params.find("UID")).second;
                }
                else
                    UIDstr = (*params.find("uid")).second;

                localhost_ = true;
                auto get_ip = [this](const std::string& ip)
                {
                    int count = 0;
                    unsigned char addr[4];

                    try
                    {
                        boost::char_separator<char> sep(".");
                        boost::tokenizer<boost::char_separator<char>> tok(ip, sep);

                        for(boost::tokenizer<boost::char_separator<char>>::iterator it = tok.begin(); it != tok.end(); ++it)
                        {
                            if (count >= 4)
                                THROW(fplog::exceptions::Incorrect_Parameter);
                            std::string token(*it);
                            unsigned int byte = boost::lexical_cast<unsigned int>(token);
                            if (byte > 255)
                                THROW(fplog::exceptions::Incorrect_Parameter);
                            addr[count] = byte;
                            count++;
                        }
                    }
                    catch(boost::exception&)
                    {
                        THROW(fplog::exceptions::Incorrect_Parameter);
                    }

                    memcpy(ip_, addr, sizeof(ip_));
                };

                if (params.find("ip") != params.end())
                {
                    get_ip(params.find("ip")->second);
                    localhost_ = false;
                }

                if (params.find("IP") != params.end())
                {
                    get_ip(params.find("IP")->second);
                    localhost_ = false;
                }

                const unsigned char localhost[4] = {127, 0, 0, 1};
                if (memcmp(ip_, localhost, sizeof(localhost)) == 0)
                    localhost_ = true;

                fplog::UID uid;
                uid.from_string(UIDstr);

                if ((uid.high > 65535) || (uid.high < 1))
                    THROW(fplog::exceptions::Incorrect_Parameter);

                if ((uid.low > 65535) || (uid.low < 1))
                    THROW(fplog::exceptions::Incorrect_Parameter);

                if (check_socket(client_sock_))
                    UDT::close(client_sock_);

                if (check_socket(serv_sock_))
                    UDT::close(serv_sock_);

                init_socket(client_sock_);
                init_socket(serv_sock_);

                uid_ = uid;
            }

            void disconnect()
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);

                if (check_socket(client_sock_))
                {
                    UDT::close(client_sock_);
                }

                if (check_socket(serv_sock_))
                {
                    UDT::close(serv_sock_);
                }

                init_socket(client_sock_);
                init_socket(serv_sock_);

                connected_ = false;
            }

            size_t read(void* buf, size_t buf_size, size_t timeout = infinite_wait)
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);

                accept_connection();

                UDT::UDSET read_set;

                timeval to;
                to.tv_sec = timeout / 1000;
                to.tv_usec = (timeout % 1000) * 1000;

                UD_SET(client_sock_, &read_set);

                if (UDT::select(client_sock_ + 1, &read_set, 0, 0, &to) < 0)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Read_Failed, "Cannot select socket for reading!");
                }

                if (read_set.size() == 0)
                    THROW(fplog::exceptions::Timeout);

                int sz = UDT::recv(client_sock_, (char*)buf, buf_size, 0);
                if (sz == UDT::ERROR)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Read_Failed, UDT::getlasterror().getErrorMessage());
                }

                return sz;
            }

            size_t write(const void* buf, size_t buf_size, size_t timeout = infinite_wait)
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);

                initiate_connection();

                UDT::UDSET write_set;

                timeval to;
                to.tv_sec = timeout / 1000;
                to.tv_usec = (timeout % 1000) * 1000;

                UD_SET(client_sock_, &write_set);
                if (UDT::select(client_sock_ + 1, 0, &write_set, 0, &to) < 0)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Read_Failed, "Cannot select socket for writing!");
                }

                if (write_set.size() == 0)
                    THROW(fplog::exceptions::Timeout);

                int sz = UDT::send(client_sock_, (char*)buf, buf_size, 0);
                if (sz == UDT::ERROR)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Write_Failed, UDT::getlasterror().getErrorMessage());
                }

                return sz;
            }

        private:

            std::recursive_mutex mutex_;

            UDTSOCKET serv_sock_, client_sock_;
            bool connected_;

            fplog::UID uid_;
            bool high_uid_;

            unsigned char ip_[4];
            std::string ip_str_;

            bool localhost_;

            bool check_socket(UDTSOCKET& socket)
            {
                if (socket > -1)
                {
                    if (socket == CUDTException::EINVSOCK)
                        return false;
                }
                else
                    return false;

                return true;
            }

            void init_socket(UDTSOCKET& socket)
            {
                socket = -1;
            }

            void accept_connection()
            {
                sockaddr_storage clientaddr;
                int addrlen = sizeof(clientaddr);

                int retries = 5;

                while (!connected_)
                {
                    if (retries <= 0)
                        THROWM(fplog::exceptions::Connect_Failed, "Failed to accept connection.");

                    addrinfo hints;
                    addrinfo* res;

                    memset(&hints, 0, sizeof(struct addrinfo));

                    hints.ai_flags = AI_PASSIVE;
                    hints.ai_family = AF_INET;
                    hints.ai_socktype = SOCK_STREAM;

                    std::string port(std::to_string(uid_.high));
                    high_uid_ = true;

                    disconnect();

                    int err = getaddrinfo(NULL, port.c_str(), &hints, &res);
                    if (err != 0)
                        THROWM(fplog::exceptions::Connect_Failed, ("Port is in use, cannot connect. Error = " + std::to_string(err)).c_str());

                    serv_sock_ = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                    if (UDT::ERROR == UDT::bind(serv_sock_, res->ai_addr, res->ai_addrlen))
                    {
                        UDT::close(serv_sock_);
                        init_socket(serv_sock_);

                        freeaddrinfo(res);

                        THROWM(fplog::exceptions::Connect_Failed, UDT::getlasterror().getErrorMessage());
                    }

                    freeaddrinfo(res);

                    if (UDT::ERROR == UDT::listen(serv_sock_, 10))
                    {
                        UDT::close(serv_sock_);
                        init_socket(serv_sock_);

                        THROWM(fplog::exceptions::Connect_Failed, std::string("Socket cannot accept connections, err = " + std::to_string(UDT::getlasterror().getErrorCode())).c_str());
                    }

                    if (UDT::INVALID_SOCK == (client_sock_ = UDT::accept(serv_sock_, (sockaddr*)&clientaddr, &addrlen)))
                    {
                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
                        retries--;
                        continue;
                    }

                    char clienthost[NI_MAXHOST];
                    char clientservice[NI_MAXSERV];

                    getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST | NI_NUMERICSERV);

                    std::string ip_address(std::to_string(ip_[0]) + "." + std::to_string(ip_[1]) + "." + std::to_string(ip_[2]) + "." + std::to_string(ip_[3]));
                    std::string host_addr(clienthost), host_name, host_name_local;

                    getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NOFQDN);
                    host_name = clienthost;

#ifdef _LINUX
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[0] = 127;
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[1] = 0;
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[2] = 0;
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[3] = 1;
#else
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b1 = 127;
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b2 = 0;
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b3 = 0;
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b4 = 1;
#endif

                    getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NOFQDN);
                    host_name_local = clienthost;

                    if ((host_addr.find(ip_address) == std::string::npos) && (host_name.find(host_name_local) == std::string::npos))
                    {
                        UDT::close(client_sock_);

                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
                        retries--;
                        continue;
                    }
                    else
                    {
                        ip_str_ = ip_address;
                        connected_ = true;
                    }
                }
            }

            void initiate_connection()
            {
                while (!connected_)
                {
                    addrinfo hints;

                    memset(&hints, 0, sizeof(struct addrinfo));

                    hints.ai_flags = AI_PASSIVE;
                    hints.ai_family = AF_INET;
                    hints.ai_socktype = SOCK_STREAM;

                    high_uid_ = false;

                    struct addrinfo *peer;

                    client_sock_ = UDT::socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);

                    // Windows UDP issue
                    // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold
                    #ifdef WIN32
                        UDT::setsockopt(client_sock_, 0, UDT_MSS, new int(1052), sizeof(int));
                    #endif

                    std::string peer_port = (high_uid_ ? std::to_string(uid_.low) : std::to_string(uid_.high));
                    if (0 != getaddrinfo(ip_str_.c_str(), peer_port.c_str(), &hints, &peer))
                        THROWM(fplog::exceptions::Connect_Failed, (std::string("Cannot connect to ") + ip_str_ + ":" + peer_port).c_str());

                    // connect to the server, implict bind
                    if (UDT::ERROR == UDT::connect(client_sock_, peer->ai_addr, peer->ai_addrlen))
                    {
                        freeaddrinfo(peer);
                        THROWM(fplog::exceptions::Connect_Failed, UDT::getlasterror().getErrorMessage());
                    }

                    connected_ = true;

                    freeaddrinfo(peer);
                }
            }
    };

    void UDT_Transport::connect(const Params& params)
    {
        impl_->connect(params);
    }

    void UDT_Transport::disconnect()
    {
        impl_->disconnect();
    }

    size_t UDT_Transport::read(void* buf, size_t buf_size, size_t timeout = infinite_wait)
    {
        return impl_->read(buf, buf_size, timeout);
    }

    size_t UDT_Transport::write(const void* buf, size_t buf_size, size_t timeout = infinite_wait)
    {
        return impl_->write(buf, buf_size, timeout);
    }

    UDT_Transport::UDT_Transport()
    {
        impl_ = new UDT_Transport_Impl();
    }

    UDT_Transport::~UDT_Transport()
    {
        delete impl_;
    }
};
<commit_msg>Messages are now going between all fplog components, however still functions somewhat incorrectly on Linux, needs more debugging.<commit_after>#define _WINSOCK_DEPRECATED_NO_WARNINGS

#ifndef _LINUX
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif

#include "UDT_Transport.h"

#include <udt.h>
#include <test_util.h>

#include <mutex>
#include <fplog_exceptions.h>
#include <thread>

#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>

using namespace fplog;

namespace spipc
{
    class UDT_Transport::UDT_Transport_Impl
    {
        public:

            UDT_Transport_Impl():
            client_sock_(-1),
            serv_sock_(-1),
            localhost_(false)
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);
            }

            ~UDT_Transport_Impl()
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);
            }

            void connect(const Params& params)
            {
                static UDTUpDown udt_initer;

                std::lock_guard<std::recursive_mutex> lock(mutex_);
                std::string UIDstr;

                if (params.find("uid") == params.end())
                {
                    if (params.find("UID") == params.end())
                    {
                        THROW(fplog::exceptions::Incorrect_Parameter);
                    }
                    else
                        UIDstr = (*params.find("UID")).second;
                }
                else
                    UIDstr = (*params.find("uid")).second;

                localhost_ = true;
                auto get_ip = [this](const std::string& ip)
                {
                    int count = 0;
                    unsigned char addr[4];

                    try
                    {
                        boost::char_separator<char> sep(".");
                        boost::tokenizer<boost::char_separator<char>> tok(ip, sep);

                        for(boost::tokenizer<boost::char_separator<char>>::iterator it = tok.begin(); it != tok.end(); ++it)
                        {
                            if (count >= 4)
                                THROW(fplog::exceptions::Incorrect_Parameter);
                            std::string token(*it);
                            unsigned int byte = boost::lexical_cast<unsigned int>(token);
                            if (byte > 255)
                                THROW(fplog::exceptions::Incorrect_Parameter);
                            addr[count] = byte;
                            count++;
                        }
                    }
                    catch(boost::exception&)
                    {
                        THROW(fplog::exceptions::Incorrect_Parameter);
                    }

                    memcpy(ip_, addr, sizeof(ip_));
                };

                if (params.find("ip") != params.end())
                {
                    get_ip(params.find("ip")->second);
                    localhost_ = false;
                }

                if (params.find("IP") != params.end())
                {
                    get_ip(params.find("IP")->second);
                    localhost_ = false;
                }

                const unsigned char localhost[4] = {127, 0, 0, 1};
                if (memcmp(ip_, localhost, sizeof(localhost)) == 0)
                    localhost_ = true;

                fplog::UID uid;
                uid.from_string(UIDstr);

                if ((uid.high > 65535) || (uid.high < 1))
                    THROW(fplog::exceptions::Incorrect_Parameter);

                if ((uid.low > 65535) || (uid.low < 1))
                    THROW(fplog::exceptions::Incorrect_Parameter);

                if (check_socket(client_sock_))
                    UDT::close(client_sock_);

                if (check_socket(serv_sock_))
                    UDT::close(serv_sock_);

                init_socket(client_sock_);
                init_socket(serv_sock_);

                uid_ = uid;
            }

            void disconnect()
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);

                if (check_socket(client_sock_))
                {
                    UDT::close(client_sock_);
                }

                if (check_socket(serv_sock_))
                {
                    UDT::close(serv_sock_);
                }

                init_socket(client_sock_);
                init_socket(serv_sock_);

                connected_ = false;
            }

            size_t read(void* buf, size_t buf_size, size_t timeout = infinite_wait)
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);

                accept_connection();

                UDT::UDSET read_set;

                timeval to;
                to.tv_sec = timeout / 1000;
                to.tv_usec = (timeout % 1000) * 1000;

                UD_SET(client_sock_, &read_set);

                if (UDT::select(client_sock_ + 1, &read_set, 0, 0, &to) < 0)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Read_Failed, "Cannot select socket for reading!");
                }

                if (read_set.size() == 0)
                    THROW(fplog::exceptions::Timeout);

                int sz = UDT::recv(client_sock_, (char*)buf, buf_size, 0);
                if (sz == UDT::ERROR)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Read_Failed, UDT::getlasterror().getErrorMessage());
                }

                return sz;
            }

            size_t write(const void* buf, size_t buf_size, size_t timeout = infinite_wait)
            {
                std::lock_guard<std::recursive_mutex> lock(mutex_);

                initiate_connection();

                UDT::UDSET write_set;

                timeval to;
                to.tv_sec = timeout / 1000;
                to.tv_usec = (timeout % 1000) * 1000;

                UD_SET(client_sock_, &write_set);
                if (UDT::select(client_sock_ + 1, 0, &write_set, 0, &to) < 0)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Read_Failed, "Cannot select socket for writing!");
                }

                if (write_set.size() == 0)
                    THROW(fplog::exceptions::Timeout);

                int sz = UDT::send(client_sock_, (char*)buf, buf_size, 0);
                if (sz == UDT::ERROR)
                {
                    int status = UDT::getsockstate(client_sock_);
                    if (status >= BROKEN)
                    {
                        UDT::close(client_sock_);
                        init_socket(client_sock_);
                        connected_ = false;
                    }

                    THROWM(fplog::exceptions::Write_Failed, UDT::getlasterror().getErrorMessage());
                }

                return sz;
            }

        private:

            std::recursive_mutex mutex_;

            UDTSOCKET serv_sock_, client_sock_;
            bool connected_;

            fplog::UID uid_;
            bool high_uid_;

            unsigned char ip_[4];
            std::string ip_str_;

            bool localhost_;

            bool check_socket(UDTSOCKET& socket)
            {
                if (socket > -1)
                {
                    if (socket == CUDTException::EINVSOCK)
                        return false;
                }
                else
                    return false;

                return true;
            }

            void init_socket(UDTSOCKET& socket)
            {
                socket = -1;
            }

            void accept_connection()
            {
                sockaddr_storage clientaddr;
                int addrlen = sizeof(clientaddr);

                int retries = 5;

                while (!connected_)
                {
                    if (retries <= 0)
                        THROWM(fplog::exceptions::Connect_Failed, "Failed to accept connection.");

                    addrinfo hints;
                    addrinfo* res;

                    memset(&hints, 0, sizeof(struct addrinfo));

                    hints.ai_flags = AI_PASSIVE;
                    hints.ai_family = AF_INET;
                    hints.ai_socktype = SOCK_STREAM;

                    std::string port(std::to_string(uid_.high));
                    high_uid_ = true;

                    disconnect();

                    int err = getaddrinfo(NULL, port.c_str(), &hints, &res);
                    if (err != 0)
                        THROWM(fplog::exceptions::Connect_Failed, ("Port is in use, cannot connect. Error = " + std::to_string(err)).c_str());

                    serv_sock_ = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                    if (UDT::ERROR == UDT::bind(serv_sock_, res->ai_addr, res->ai_addrlen))
                    {
                        UDT::close(serv_sock_);
                        init_socket(serv_sock_);

                        freeaddrinfo(res);

                        THROWM(fplog::exceptions::Connect_Failed, UDT::getlasterror().getErrorMessage());
                    }

                    freeaddrinfo(res);

                    if (UDT::ERROR == UDT::listen(serv_sock_, 10))
                    {
                        UDT::close(serv_sock_);
                        init_socket(serv_sock_);

                        THROWM(fplog::exceptions::Connect_Failed, std::string("Socket cannot accept connections, err = " + std::to_string(UDT::getlasterror().getErrorCode())).c_str());
                    }

                    if (UDT::INVALID_SOCK == (client_sock_ = UDT::accept(serv_sock_, (sockaddr*)&clientaddr, &addrlen)))
                    {
                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
                        retries--;
                        continue;
                    }

                    char clienthost[NI_MAXHOST];
                    char clientservice[NI_MAXSERV];

                    getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST | NI_NUMERICSERV);

                    std::string ip_address(std::to_string(ip_[0]) + "." + std::to_string(ip_[1]) + "." + std::to_string(ip_[2]) + "." + std::to_string(ip_[3]));
                    std::string host_addr(clienthost), host_name, host_name_local;

                    getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NOFQDN);
                    host_name = clienthost;

#ifdef _LINUX
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[0] = 127;
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[1] = 0;
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[2] = 0;
                    ((char*)&(((sockaddr_in *)&clientaddr)->sin_addr.s_addr))[3] = 1;
#else
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b1 = 127;
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b2 = 0;
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b3 = 0;
                    ((sockaddr_in *)&clientaddr)->sin_addr.S_un.S_un_b.s_b4 = 1;
#endif

                    getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NOFQDN);
                    host_name_local = clienthost;

                    if ((host_addr.find(ip_address) == std::string::npos) && (host_name.find(host_name_local) == std::string::npos))
                    {
                        UDT::close(client_sock_);

                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
                        retries--;
                        continue;
                    }
                    else
                    {
                        ip_str_ = ip_address;
                        connected_ = true;
                    }
                }
            }

            void initiate_connection()
            {
                while (!connected_)
                {
                    addrinfo hints;

                    memset(&hints, 0, sizeof(struct addrinfo));

                    hints.ai_flags = AI_PASSIVE;
                    hints.ai_family = AF_INET;
                    hints.ai_socktype = SOCK_STREAM;

                    high_uid_ = false;

                    struct addrinfo *peer;

                    client_sock_ = UDT::socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);

                    // Windows UDP issue
                    // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold
                    #ifdef WIN32
                        UDT::setsockopt(client_sock_, 0, UDT_MSS, new int(1052), sizeof(int));
                    #endif

                    std::string peer_port = (high_uid_ ? std::to_string(uid_.low) : std::to_string(uid_.high));
                    std::string ip_address(std::to_string(ip_[0]) + "." + std::to_string(ip_[1]) + "." + std::to_string(ip_[2]) + "." + std::to_string(ip_[3]));

                    if (0 != getaddrinfo(ip_address.c_str(), peer_port.c_str(), &hints, &peer))
                        THROWM(fplog::exceptions::Connect_Failed, (std::string("Cannot connect to ") + ip_str_ + ":" + peer_port).c_str());

                    // connect to the server, implict bind
                    if (UDT::ERROR == UDT::connect(client_sock_, peer->ai_addr, peer->ai_addrlen))
                    {
                        freeaddrinfo(peer);
                        THROWM(fplog::exceptions::Connect_Failed, UDT::getlasterror().getErrorMessage());
                    }

                    ip_str_ = ip_address;
                    connected_ = true;

                    freeaddrinfo(peer);
                }
            }
    };

    void UDT_Transport::connect(const Params& params)
    {
        impl_->connect(params);
    }

    void UDT_Transport::disconnect()
    {
        impl_->disconnect();
    }

    size_t UDT_Transport::read(void* buf, size_t buf_size, size_t timeout = infinite_wait)
    {
        return impl_->read(buf, buf_size, timeout);
    }

    size_t UDT_Transport::write(const void* buf, size_t buf_size, size_t timeout = infinite_wait)
    {
        return impl_->write(buf, buf_size, timeout);
    }

    UDT_Transport::UDT_Transport()
    {
        impl_ = new UDT_Transport_Impl();
    }

    UDT_Transport::~UDT_Transport()
    {
        delete impl_;
    }
};
<|endoftext|>