<commit_before>//=-- ExprEngineObjC.cpp - ExprEngine support for Objective-C ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines ExprEngine's support for Objective-C expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/Analysis/Support/SaveAndRestore.h"

using namespace clang;
using namespace ento;

void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
                                          ExplodedNode *Pred,
                                          ExplodedNodeSet &Dst) {

  const ProgramState *state = Pred->getState();
  SVal baseVal = state->getSVal(Ex->getBase());
  SVal location = state->getLValue(Ex->getDecl(), baseVal);

  ExplodedNodeSet dstIvar;
  MakeNode(dstIvar, Ex, Pred, state->BindExpr(Ex, location));

  // Perform the post-condition check of the ObjCIvarRefExpr and store
  // the created nodes in 'Dst'.
  getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
}

void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
                                             ExplodedNode *Pred,
                                             ExplodedNodeSet &Dst) {
  getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
}

void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
                                            ExplodedNode *Pred,
                                            ExplodedNodeSet &Dst) {

  // ObjCForCollectionStmts are processed in two places.  This method
  // handles the case where an ObjCForCollectionStmt* occurs as one of the
  // statements within a basic block.  This transfer function does two things:
  //
  //  (1) binds the next container value to 'element'.  This creates a new
  //      node in the ExplodedGraph.
  //
  //  (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
  //      whether or not the container has any more elements.  This value
  //      will be tested in ProcessBranch.  We need to explicitly bind
  //      this value because a container can contain nil elements.
  //
  // FIXME: Eventually this logic should actually do dispatches to
  //   'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
  //   This will require simulating a temporary NSFastEnumerationState, either
  //   through an SVal or through the use of MemRegions.  This value can
  //   be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
  //   terminates we reclaim the temporary (it goes out of scope) and we
  //   we can test if the SVal is 0 or if the MemRegion is null (depending
  //   on what approach we take).
  //
  //  For now: simulate (1) by assigning either a symbol or nil if the
  //    container is empty.  Thus this transfer function will by default
  //    result in state splitting.

  const Stmt *elem = S->getElement();
  const ProgramState *state = Pred->getState();
  SVal elementV;

  if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
    const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
    assert(elemD->getInit() == 0);
    elementV = state->getLValue(elemD, Pred->getLocationContext());
  }
  else {
    elementV = state->getSVal(elem);
  }

  ExplodedNodeSet dstLocation;
  evalLocation(dstLocation, elem, Pred, state, elementV, NULL, false);

  if (dstLocation.empty())
    return;

  for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
       NE = dstLocation.end(); NI!=NE; ++NI) {
    Pred = *NI;
    const ProgramState *state = Pred->getState();

    // Handle the case where the container still has elements.
    SVal TrueV = svalBuilder.makeTruthVal(1);
    const ProgramState *hasElems = state->BindExpr(S, TrueV);

    // Handle the case where the container has no elements.
    SVal FalseV = svalBuilder.makeTruthVal(0);
    const ProgramState *noElems = state->BindExpr(S, FalseV);

    if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
      if (const TypedValueRegion *R =
          dyn_cast<TypedValueRegion>(MV->getRegion())) {
        // FIXME: The proper thing to do is to really iterate over the
        //  container.  We will do this with dispatch logic to the store.
        //  For now, just 'conjure' up a symbolic value.
        QualType T = R->getValueType();
        assert(Loc::isLocType(T));
        unsigned Count = Builder->getCurrentBlockCount();
        SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
        SVal V = svalBuilder.makeLoc(Sym);
        hasElems = hasElems->bindLoc(elementV, V);

        // Bind the location to 'nil' on the false branch.
        SVal nilV = svalBuilder.makeIntVal(0, T);
        noElems = noElems->bindLoc(elementV, nilV);
      }

    // Create the new nodes.
    MakeNode(Dst, S, Pred, hasElems);
    MakeNode(Dst, S, Pred, noElems);
  }
}

void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
                                  ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {

  // Handle the previsits checks.
  ExplodedNodeSet dstPrevisit;
  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
                                                   msg, *this);

  // Proceed with evaluate the message expression.
  ExplodedNodeSet dstEval;

  for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(),
       DE = dstPrevisit.end(); DI != DE; ++DI) {

    ExplodedNode *Pred = *DI;
    bool RaisesException = false;
    unsigned oldSize = dstEval.size();
    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
    SaveOr OldHasGen(Builder->hasGeneratedNode);

    if (const Expr *Receiver = msg.getInstanceReceiver()) {
      const ProgramState *state = Pred->getState();
      SVal recVal = state->getSVal(Receiver);
      if (!recVal.isUndef()) {
        // Bifurcate the state into nil and non-nil ones.
        DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);

        const ProgramState *notNilState, *nilState;
        llvm::tie(notNilState, nilState) = state->assume(receiverVal);

        // There are three cases: can be nil or non-nil, must be nil, must be
        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
        if (nilState && !notNilState) {
          dstEval.insert(Pred);
          continue;
        }

        // Check if the "raise" message was sent.
        assert(notNilState);
        if (msg.getSelector() == RaiseSel)
          RaisesException = true;

        // Check if we raise an exception.  For now treat these as sinks.
        // Eventually we will want to handle exceptions properly.
        if (RaisesException)
          Builder->BuildSinks = true;

        // Dispatch to plug-in transfer function.
        evalObjCMessage(dstEval, msg, Pred, notNilState);
      }
    }
    else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
      IdentifierInfo* ClsName = Iface->getIdentifier();
      Selector S = msg.getSelector();

      // Check for special instance methods.
      if (!NSExceptionII) {
        ASTContext &Ctx = getContext();
        NSExceptionII = &Ctx.Idents.get("NSException");
      }

      if (ClsName == NSExceptionII) {
        enum { NUM_RAISE_SELECTORS = 2 };

        // Lazily create a cache of the selectors.
        if (!NSExceptionInstanceRaiseSelectors) {
          ASTContext &Ctx = getContext();
          NSExceptionInstanceRaiseSelectors =
          new Selector[NUM_RAISE_SELECTORS];
          SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
          unsigned idx = 0;

          // raise:format:
          II.push_back(&Ctx.Idents.get("raise"));
          II.push_back(&Ctx.Idents.get("format"));
          NSExceptionInstanceRaiseSelectors[idx++] =
          Ctx.Selectors.getSelector(II.size(), &II[0]);

          // raise:format::arguments:
          II.push_back(&Ctx.Idents.get("arguments"));
          NSExceptionInstanceRaiseSelectors[idx++] =
          Ctx.Selectors.getSelector(II.size(), &II[0]);
        }

        for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
          if (S == NSExceptionInstanceRaiseSelectors[i]) {
            RaisesException = true;
            break;
          }
      }

      // Check if we raise an exception.  For now treat these as sinks.
      // Eventually we will want to handle exceptions properly.
      if (RaisesException)
        Builder->BuildSinks = true;

      // Dispatch to plug-in transfer function.
      evalObjCMessage(dstEval, msg, Pred, Pred->getState());
    }

    // Handle the case where no nodes where generated.  Auto-generate that
    // contains the updated state if we aren't generating sinks.
    if (!Builder->BuildSinks && dstEval.size() == oldSize &&
        !Builder->hasGeneratedNode)
      MakeNode(dstEval, msg.getOriginExpr(), Pred, Pred->getState());
  }

  // Finally, perform the post-condition check of the ObjCMessageExpr and store
  // the created nodes in 'Dst'.
  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
}

void ExprEngine::evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg,
                                 ExplodedNode *Pred,
                                 const ProgramState *state) {
  assert (Builder && "StmtNodeBuilder must be defined.");

  // First handle the return value.
  SVal ReturnValue = UnknownVal();

  // Some method families have known return values.
  switch (msg.getMethodFamily()) {
  default:
    break;
  case OMF_autorelease:
  case OMF_retain:
  case OMF_self: {
    // These methods return their receivers.
    // FIXME: Should OMF_init be included here?
    const Expr *ReceiverE = msg.getInstanceReceiver();
    if (ReceiverE)
      ReturnValue = state->getSVal(ReceiverE);
    break;
  }
  }

  // If we failed to figure out the return value, use a conjured value instead.
  if (ReturnValue.isUnknown()) {
    SValBuilder &SVB = getSValBuilder();
    QualType ResultTy = msg.getResultType(getContext());
    unsigned Count = Builder->getCurrentBlockCount();
    const Expr *CurrentE = cast<Expr>(currentStmt);
    ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, ResultTy, Count);
  }

  // Bind the return value.
  state = state->BindExpr(currentStmt, ReturnValue);

  // Now we can handle the other aspects of the message.
  getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
}

<commit_msg>[analyzer] Remove FIXME; Ted reminded me that -init is not guaranteed to return its receiver and pretending that it does won't actually buy us anything. (Comment change only.)<commit_after>//=-- ExprEngineObjC.cpp - ExprEngine support for Objective-C ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines ExprEngine's support for Objective-C expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/Analysis/Support/SaveAndRestore.h"

using namespace clang;
using namespace ento;

void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
                                          ExplodedNode *Pred,
                                          ExplodedNodeSet &Dst) {

  const ProgramState *state = Pred->getState();
  SVal baseVal = state->getSVal(Ex->getBase());
  SVal location = state->getLValue(Ex->getDecl(), baseVal);

  ExplodedNodeSet dstIvar;
  MakeNode(dstIvar, Ex, Pred, state->BindExpr(Ex, location));

  // Perform the post-condition check of the ObjCIvarRefExpr and store
  // the created nodes in 'Dst'.
  getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
}

void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
                                             ExplodedNode *Pred,
                                             ExplodedNodeSet &Dst) {
  getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this);
}

void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
                                            ExplodedNode *Pred,
                                            ExplodedNodeSet &Dst) {

  // ObjCForCollectionStmts are processed in two places.  This method
  // handles the case where an ObjCForCollectionStmt* occurs as one of the
  // statements within a basic block.  This transfer function does two things:
  //
  //  (1) binds the next container value to 'element'.  This creates a new
  //      node in the ExplodedGraph.
  //
  //  (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
  //      whether or not the container has any more elements.  This value
  //      will be tested in ProcessBranch.  We need to explicitly bind
  //      this value because a container can contain nil elements.
  //
  // FIXME: Eventually this logic should actually do dispatches to
  //   'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
  //   This will require simulating a temporary NSFastEnumerationState, either
  //   through an SVal or through the use of MemRegions.  This value can
  //   be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
  //   terminates we reclaim the temporary (it goes out of scope) and we
  //   we can test if the SVal is 0 or if the MemRegion is null (depending
  //   on what approach we take).
  //
  //  For now: simulate (1) by assigning either a symbol or nil if the
  //    container is empty.  Thus this transfer function will by default
  //    result in state splitting.

  const Stmt *elem = S->getElement();
  const ProgramState *state = Pred->getState();
  SVal elementV;

  if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
    const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
    assert(elemD->getInit() == 0);
    elementV = state->getLValue(elemD, Pred->getLocationContext());
  }
  else {
    elementV = state->getSVal(elem);
  }

  ExplodedNodeSet dstLocation;
  evalLocation(dstLocation, elem, Pred, state, elementV, NULL, false);

  if (dstLocation.empty())
    return;

  for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
       NE = dstLocation.end(); NI!=NE; ++NI) {
    Pred = *NI;
    const ProgramState *state = Pred->getState();

    // Handle the case where the container still has elements.
    SVal TrueV = svalBuilder.makeTruthVal(1);
    const ProgramState *hasElems = state->BindExpr(S, TrueV);

    // Handle the case where the container has no elements.
    SVal FalseV = svalBuilder.makeTruthVal(0);
    const ProgramState *noElems = state->BindExpr(S, FalseV);

    if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
      if (const TypedValueRegion *R =
          dyn_cast<TypedValueRegion>(MV->getRegion())) {
        // FIXME: The proper thing to do is to really iterate over the
        //  container.  We will do this with dispatch logic to the store.
        //  For now, just 'conjure' up a symbolic value.
        QualType T = R->getValueType();
        assert(Loc::isLocType(T));
        unsigned Count = Builder->getCurrentBlockCount();
        SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
        SVal V = svalBuilder.makeLoc(Sym);
        hasElems = hasElems->bindLoc(elementV, V);

        // Bind the location to 'nil' on the false branch.
        SVal nilV = svalBuilder.makeIntVal(0, T);
        noElems = noElems->bindLoc(elementV, nilV);
      }

    // Create the new nodes.
    MakeNode(Dst, S, Pred, hasElems);
    MakeNode(Dst, S, Pred, noElems);
  }
}

void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
                                  ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {

  // Handle the previsits checks.
  ExplodedNodeSet dstPrevisit;
  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
                                                   msg, *this);

  // Proceed with evaluate the message expression.
  ExplodedNodeSet dstEval;

  for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(),
       DE = dstPrevisit.end(); DI != DE; ++DI) {

    ExplodedNode *Pred = *DI;
    bool RaisesException = false;
    unsigned oldSize = dstEval.size();
    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
    SaveOr OldHasGen(Builder->hasGeneratedNode);

    if (const Expr *Receiver = msg.getInstanceReceiver()) {
      const ProgramState *state = Pred->getState();
      SVal recVal = state->getSVal(Receiver);
      if (!recVal.isUndef()) {
        // Bifurcate the state into nil and non-nil ones.
        DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);

        const ProgramState *notNilState, *nilState;
        llvm::tie(notNilState, nilState) = state->assume(receiverVal);

        // There are three cases: can be nil or non-nil, must be nil, must be
        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
        if (nilState && !notNilState) {
          dstEval.insert(Pred);
          continue;
        }

        // Check if the "raise" message was sent.
        assert(notNilState);
        if (msg.getSelector() == RaiseSel)
          RaisesException = true;

        // Check if we raise an exception.  For now treat these as sinks.
        // Eventually we will want to handle exceptions properly.
        if (RaisesException)
          Builder->BuildSinks = true;

        // Dispatch to plug-in transfer function.
        evalObjCMessage(dstEval, msg, Pred, notNilState);
      }
    }
    else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
      IdentifierInfo* ClsName = Iface->getIdentifier();
      Selector S = msg.getSelector();

      // Check for special instance methods.
      if (!NSExceptionII) {
        ASTContext &Ctx = getContext();
        NSExceptionII = &Ctx.Idents.get("NSException");
      }

      if (ClsName == NSExceptionII) {
        enum { NUM_RAISE_SELECTORS = 2 };

        // Lazily create a cache of the selectors.
        if (!NSExceptionInstanceRaiseSelectors) {
          ASTContext &Ctx = getContext();
          NSExceptionInstanceRaiseSelectors =
          new Selector[NUM_RAISE_SELECTORS];
          SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
          unsigned idx = 0;

          // raise:format:
          II.push_back(&Ctx.Idents.get("raise"));
          II.push_back(&Ctx.Idents.get("format"));
          NSExceptionInstanceRaiseSelectors[idx++] =
          Ctx.Selectors.getSelector(II.size(), &II[0]);

          // raise:format::arguments:
          II.push_back(&Ctx.Idents.get("arguments"));
          NSExceptionInstanceRaiseSelectors[idx++] =
          Ctx.Selectors.getSelector(II.size(), &II[0]);
        }

        for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
          if (S == NSExceptionInstanceRaiseSelectors[i]) {
            RaisesException = true;
            break;
          }
      }

      // Check if we raise an exception.  For now treat these as sinks.
      // Eventually we will want to handle exceptions properly.
      if (RaisesException)
        Builder->BuildSinks = true;

      // Dispatch to plug-in transfer function.
      evalObjCMessage(dstEval, msg, Pred, Pred->getState());
    }

    // Handle the case where no nodes where generated.  Auto-generate that
    // contains the updated state if we aren't generating sinks.
    if (!Builder->BuildSinks && dstEval.size() == oldSize &&
        !Builder->hasGeneratedNode)
      MakeNode(dstEval, msg.getOriginExpr(), Pred, Pred->getState());
  }

  // Finally, perform the post-condition check of the ObjCMessageExpr and store
  // the created nodes in 'Dst'.
  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
}

void ExprEngine::evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg,
                                 ExplodedNode *Pred,
                                 const ProgramState *state) {
  assert (Builder && "StmtNodeBuilder must be defined.");

  // First handle the return value.
  SVal ReturnValue = UnknownVal();

  // Some method families have known return values.
  switch (msg.getMethodFamily()) {
  default:
    break;
  case OMF_autorelease:
  case OMF_retain:
  case OMF_self: {
    // These methods return their receivers.
    const Expr *ReceiverE = msg.getInstanceReceiver();
    if (ReceiverE)
      ReturnValue = state->getSVal(ReceiverE);
    break;
  }
  }

  // If we failed to figure out the return value, use a conjured value instead.
  if (ReturnValue.isUnknown()) {
    SValBuilder &SVB = getSValBuilder();
    QualType ResultTy = msg.getResultType(getContext());
    unsigned Count = Builder->getCurrentBlockCount();
    const Expr *CurrentE = cast<Expr>(currentStmt);
    ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, ResultTy, Count);
  }

  // Bind the return value.
  state = state->BindExpr(currentStmt, ReturnValue);

  // Now we can handle the other aspects of the message.
  getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
}

<|endoftext|>


<commit_before>//
// file : genseq.hpp
// in : file:///home/tim/projects/nkark/src/genseq.hpp
//
// created by : Timothée Feuillet on linux-coincoin.tim
// date: 11/08/2013 15:42:19
//
//
// Copyright (C) 2013-2014 Timothée Feuillet
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#ifndef __GENSEQ_HPP__
# define __GENSEQ_HPP__

#include <cstdint>

namespace neam
{
  namespace cr
  {
    // a sequence generator (doesn't work on some mingw :( )
    // this comes from a stackoverflow answer.
    template <uint64_t... Idx> struct seq{};
    template <uint64_t Cr, size_t... Idx> struct gen_seq : gen_seq<Cr - 1, Cr - 1, Idx...> {};
    template <uint64_t... Idx> struct gen_seq<0, Idx...> : seq<Idx...> {};

  } // namespace internal
} // namespace nkark

#endif /*__GENSEQ_HPP__*/
<commit_msg>[TOOLS/GENSEQ]: change sequence type from uint64_t to size_t<commit_after>//
// file : genseq.hpp
// in : file:///home/tim/projects/nkark/src/genseq.hpp
//
// created by : Timothée Feuillet on linux-coincoin.tim
// date: 11/08/2013 15:42:19
//
//
// Copyright (C) 2013-2014 Timothée Feuillet
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#ifndef __GENSEQ_HPP__
# define __GENSEQ_HPP__

#include <cstdint>

namespace neam
{
  namespace cr
  {
    // a sequence generator (doesn't work on some mingw :( )
    // this comes from a stackoverflow answer.
    template <size_t... Idx> struct seq{};
    template <size_t Cr, size_t... Idx> struct gen_seq : gen_seq<Cr - 1, Cr - 1, Idx...> {};
    template <size_t... Idx> struct gen_seq<0, Idx...> : seq<Idx...> {};

  } // namespace internal
} // namespace nkark

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


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "perfetto/ext/base/file_utils.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <direct.h>
#include <io.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif

namespace perfetto {
namespace base {
namespace {
constexpr size_t kBufSize = 2048;
}  // namespace

ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _read(fd, dst, static_cast<unsigned>(dst_size));
#else
  return PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
}

bool ReadFileDescriptor(int fd, std::string* out) {
  // Do not override existing data in string.
  size_t i = out->size();

  struct stat buf {};
  if (fstat(fd, &buf) != -1) {
    if (buf.st_size > 0)
      out->resize(i + static_cast<size_t>(buf.st_size));
  }

  ssize_t bytes_read;
  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);

    bytes_read = Read(fd, &((*out)[i]), kBufSize);
    if (bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      return bytes_read == 0;
    }
  }
}

bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Do not override existing data in string.
  size_t i = out->size();

  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);
    DWORD bytes_read = 0;
    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
    if (res && bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      const bool is_eof = res && bytes_read == 0;
      auto err = res ? 0 : GetLastError();
      // The "Broken pipe" error on Windows is slighly different than Unix:
      // On Unix: a "broken pipe" error can happen only on the writer side. On
      // the reader there is no broken pipe, just a EOF.
      // On windows: the reader also sees a broken pipe error.
      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
      return is_eof || err == ERROR_BROKEN_PIPE;
    }
  }
#else
  return ReadFileDescriptor(h, out);
#endif
}

bool ReadFileStream(FILE* f, std::string* out) {
  return ReadFileDescriptor(fileno(f), out);
}

bool ReadFile(const std::string& path, std::string* out) {
  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
  if (!fd)
    return false;

  return ReadFileDescriptor(*fd, out);
}

ssize_t WriteAll(int fd, const void* buf, size_t count) {
  size_t written = 0;
  while (written < count) {
    // write() on windows takes an unsigned int size.
    uint32_t bytes_left = static_cast<uint32_t>(
        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
    ssize_t wr = PERFETTO_EINTR(
        write(fd, static_cast<const char*>(buf) + written, bytes_left));
    if (wr == 0)
      break;
    if (wr < 0)
      return wr;
    written += static_cast<size_t>(wr);
  }
  return static_cast<ssize_t>(written);
}

ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  DWORD wsize = 0;
  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
    return wsize;
  } else {
    return -1;
  }
#else
  return WriteAll(h, buf, count);
#endif
}

bool FlushFile(int fd) {
  PERFETTO_DCHECK(fd != 0);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  return !PERFETTO_EINTR(fdatasync(fd));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return !PERFETTO_EINTR(_commit(fd));
#else
  return !PERFETTO_EINTR(fsync(fd));
#endif
}

bool Mkdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _mkdir(path.c_str()) == 0;
#else
  return mkdir(path.c_str(), 0755) == 0;
#endif
}

bool Rmdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _rmdir(path.c_str()) == 0;
#else
  return rmdir(path.c_str()) == 0;
#endif
}

int CloseFile(int fd) {
  return close(fd);
}

ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Always use O_BINARY on Windows, to avoid silly EOL translations.
  ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
#else
  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
#endif
  return fd;
}

bool FileExists(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _access(path.c_str(), 0) == 0;
#else
  return access(path.c_str(), F_OK) == 0;
#endif
}

// Declared in base/platform_handle.h.
int ClosePlatformHandle(PlatformHandle handle) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Make the return value UNIX-style.
  return CloseHandle(handle) ? 0 : -1;
#else
  return close(handle);
#endif
}

base::Status ListFilesRecursive(const std::string& dir_path,
                                std::vector<std::string>& output) {
  std::string root_dir_path = dir_path;
  if (root_dir_path.back() == '\\') {
    root_dir_path.back() = '/';
  } else if (root_dir_path.back() != '/') {
    root_dir_path.push_back('/');
  }

  // dir_queue contains full paths to the directories. The paths include the
  // root_dir_path at the beginning and the trailing slash at the end.
  std::deque<std::string> dir_queue;
  dir_queue.push_back(root_dir_path);

  while (!dir_queue.empty()) {
    const std::string cur_dir = std::move(dir_queue.front());
    dir_queue.pop_front();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
    return base::ErrStatus("ListFilesRecursive not supported yet");
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
    std::string glob_path = cur_dir + "*";
    // + 1 because we also have to count the NULL terminator.
    if (glob_path.length() + 1 > MAX_PATH)
      return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
    WIN32_FIND_DATAA ffd;

    // Wrap FindClose to: (1) make the return unix-style; (2) deal w/ stdcall.
    static auto find_close = [](HANDLE h) { return FindClose(h) ? 0 : -1; };
    base::ScopedResource<HANDLE, find_close, nullptr, false,
                         base::PlatformHandleChecker>
        hFind(FindFirstFileA(glob_path.c_str(), &ffd));
    if (!hFind) {
      // For empty directories, there should be at least one entry '.'.
      // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
      // couldn't be accessed.
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    do {
      if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
        continue;
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        std::string subdir_path = cur_dir + ffd.cFileName + '/';
        dir_queue.push_back(subdir_path);
      } else {
        const std::string full_path = cur_dir + ffd.cFileName;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    } while (FindNextFileA(*hFind, &ffd));
#else
    ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
    if (!dir) {
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    for (auto* dirent = readdir(dir.get()); dirent != nullptr;
         dirent = readdir(dir.get())) {
      if (strcmp(dirent->d_name, ".") == 0 ||
          strcmp(dirent->d_name, "..") == 0) {
        continue;
      }
      if (dirent->d_type == DT_DIR) {
        dir_queue.push_back(cur_dir + dirent->d_name + '/');
      } else if (dirent->d_type == DT_REG) {
        const std::string full_path = cur_dir + dirent->d_name;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    }
#endif
  }
  return base::OkStatus();
}

std::string GetFileExtension(const std::string& filename) {
  auto ext_idx = filename.rfind('.');
  if (ext_idx == std::string::npos)
    return std::string();
  return filename.substr(ext_idx);
}

base::Optional<size_t> GetFileSize(const std::string& file_path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  HANDLE file =
      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    return nullopt;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  BOOL ok = GetFileSizeEx(file, &file_size);
  CloseHandle(file);
  if (!ok) {
    return nullopt;
  }
  return static_cast<size_t>(file_size.QuadPart);
#else
  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    return nullopt;
  }
  struct stat buf{};
  if (fstat(*fd, &buf) == -1) {
    return nullopt;
  }
  return static_cast<size_t>(buf.st_size);
#endif
}

}  // namespace base
}  // namespace perfetto
<commit_msg>base: Fix Windows standalone build am: 02aa3eada2 am: 19bf04dbc0<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "perfetto/ext/base/file_utils.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <direct.h>
#include <io.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif

namespace perfetto {
namespace base {
namespace {
constexpr size_t kBufSize = 2048;

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Wrap FindClose to: (1) make the return unix-style; (2) deal with stdcall.
int CloseFindHandle(HANDLE h) {
  return FindClose(h) ? 0 : -1;
};
#endif

}  // namespace

ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _read(fd, dst, static_cast<unsigned>(dst_size));
#else
  return PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
}

bool ReadFileDescriptor(int fd, std::string* out) {
  // Do not override existing data in string.
  size_t i = out->size();

  struct stat buf {};
  if (fstat(fd, &buf) != -1) {
    if (buf.st_size > 0)
      out->resize(i + static_cast<size_t>(buf.st_size));
  }

  ssize_t bytes_read;
  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);

    bytes_read = Read(fd, &((*out)[i]), kBufSize);
    if (bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      return bytes_read == 0;
    }
  }
}

bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Do not override existing data in string.
  size_t i = out->size();

  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);
    DWORD bytes_read = 0;
    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
    if (res && bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      const bool is_eof = res && bytes_read == 0;
      auto err = res ? 0 : GetLastError();
      // The "Broken pipe" error on Windows is slighly different than Unix:
      // On Unix: a "broken pipe" error can happen only on the writer side. On
      // the reader there is no broken pipe, just a EOF.
      // On windows: the reader also sees a broken pipe error.
      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
      return is_eof || err == ERROR_BROKEN_PIPE;
    }
  }
#else
  return ReadFileDescriptor(h, out);
#endif
}

bool ReadFileStream(FILE* f, std::string* out) {
  return ReadFileDescriptor(fileno(f), out);
}

bool ReadFile(const std::string& path, std::string* out) {
  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
  if (!fd)
    return false;

  return ReadFileDescriptor(*fd, out);
}

ssize_t WriteAll(int fd, const void* buf, size_t count) {
  size_t written = 0;
  while (written < count) {
    // write() on windows takes an unsigned int size.
    uint32_t bytes_left = static_cast<uint32_t>(
        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
    ssize_t wr = PERFETTO_EINTR(
        write(fd, static_cast<const char*>(buf) + written, bytes_left));
    if (wr == 0)
      break;
    if (wr < 0)
      return wr;
    written += static_cast<size_t>(wr);
  }
  return static_cast<ssize_t>(written);
}

ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  DWORD wsize = 0;
  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
    return wsize;
  } else {
    return -1;
  }
#else
  return WriteAll(h, buf, count);
#endif
}

bool FlushFile(int fd) {
  PERFETTO_DCHECK(fd != 0);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  return !PERFETTO_EINTR(fdatasync(fd));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return !PERFETTO_EINTR(_commit(fd));
#else
  return !PERFETTO_EINTR(fsync(fd));
#endif
}

bool Mkdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _mkdir(path.c_str()) == 0;
#else
  return mkdir(path.c_str(), 0755) == 0;
#endif
}

bool Rmdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _rmdir(path.c_str()) == 0;
#else
  return rmdir(path.c_str()) == 0;
#endif
}

int CloseFile(int fd) {
  return close(fd);
}

ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Always use O_BINARY on Windows, to avoid silly EOL translations.
  ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
#else
  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
#endif
  return fd;
}

bool FileExists(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _access(path.c_str(), 0) == 0;
#else
  return access(path.c_str(), F_OK) == 0;
#endif
}

// Declared in base/platform_handle.h.
int ClosePlatformHandle(PlatformHandle handle) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Make the return value UNIX-style.
  return CloseHandle(handle) ? 0 : -1;
#else
  return close(handle);
#endif
}

base::Status ListFilesRecursive(const std::string& dir_path,
                                std::vector<std::string>& output) {
  std::string root_dir_path = dir_path;
  if (root_dir_path.back() == '\\') {
    root_dir_path.back() = '/';
  } else if (root_dir_path.back() != '/') {
    root_dir_path.push_back('/');
  }

  // dir_queue contains full paths to the directories. The paths include the
  // root_dir_path at the beginning and the trailing slash at the end.
  std::deque<std::string> dir_queue;
  dir_queue.push_back(root_dir_path);

  while (!dir_queue.empty()) {
    const std::string cur_dir = std::move(dir_queue.front());
    dir_queue.pop_front();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
    return base::ErrStatus("ListFilesRecursive not supported yet");
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
    std::string glob_path = cur_dir + "*";
    // + 1 because we also have to count the NULL terminator.
    if (glob_path.length() + 1 > MAX_PATH)
      return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
    WIN32_FIND_DATAA ffd;

    base::ScopedResource<HANDLE, CloseFindHandle, nullptr, false,
                         base::PlatformHandleChecker>
        hFind(FindFirstFileA(glob_path.c_str(), &ffd));
    if (!hFind) {
      // For empty directories, there should be at least one entry '.'.
      // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
      // couldn't be accessed.
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    do {
      if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
        continue;
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        std::string subdir_path = cur_dir + ffd.cFileName + '/';
        dir_queue.push_back(subdir_path);
      } else {
        const std::string full_path = cur_dir + ffd.cFileName;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    } while (FindNextFileA(*hFind, &ffd));
#else
    ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
    if (!dir) {
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    for (auto* dirent = readdir(dir.get()); dirent != nullptr;
         dirent = readdir(dir.get())) {
      if (strcmp(dirent->d_name, ".") == 0 ||
          strcmp(dirent->d_name, "..") == 0) {
        continue;
      }
      if (dirent->d_type == DT_DIR) {
        dir_queue.push_back(cur_dir + dirent->d_name + '/');
      } else if (dirent->d_type == DT_REG) {
        const std::string full_path = cur_dir + dirent->d_name;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    }
#endif
  }
  return base::OkStatus();
}

std::string GetFileExtension(const std::string& filename) {
  auto ext_idx = filename.rfind('.');
  if (ext_idx == std::string::npos)
    return std::string();
  return filename.substr(ext_idx);
}

base::Optional<size_t> GetFileSize(const std::string& file_path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  HANDLE file =
      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    return nullopt;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  BOOL ok = GetFileSizeEx(file, &file_size);
  CloseHandle(file);
  if (!ok) {
    return nullopt;
  }
  return static_cast<size_t>(file_size.QuadPart);
#else
  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    return nullopt;
  }
  struct stat buf{};
  if (fstat(*fd, &buf) == -1) {
    return nullopt;
  }
  return static_cast<size_t>(buf.st_size);
#endif
}

}  // namespace base
}  // namespace perfetto
<|endoftext|>


<commit_before><commit_msg>Удалены лишние файлы<commit_after><|endoftext|>


<commit_before>/**
 * @file ex1.cpp
 * @author Fabian Wegscheider
 * @date 1.5.17
 */

#include <iostream>
#include <fstream>
#include <math.h>
#include <vector>

using namespace std;

/**
 * The main function. Reads a csv file from the command line that contains
 * measured data from two locations in a specific format. Then the number of
 * valid lines as well as the geometric means of the two data sets are printed
 * to the standard output.
 * @param numargs number of inputs on command line
 * @param args array of inputs on command line
 * @return whether the file was read successfully
 */
int main(int numargs, char *args[]) {

	if (numargs != 2) {
		cerr << "Usage: " << args[0] << " filename" << endl;
		exit(EXIT_FAILURE);
	}

	ifstream inputFile;
	inputFile.open(args[1]);
	if (inputFile.fail()) {
		cerr << "file could not be read" << endl;
		exit(EXIT_FAILURE);
	}

	string line;
	vector<double> values[2];
	double geoMean[2] {.0, .0};
	int nLoc[2] {0, 0};
	long nLines = 0;
	int err = 0;

	while (getline(inputFile, line)) {
		nLines++;

		if (line.empty()) {			// empty lines are ignored
			continue;
		}

		size_t foundComment = line.find("#");

		if (foundComment == 0) {		// comment lines are ignored
			continue;
		}

		if (foundComment != string::npos) {			// anything after # is ignored
			line = line.substr(0, foundComment);
		}

		size_t pos1 = line.find(";");
		if (pos1 == string::npos) {
			err++;
			continue;
		}												// test if line contains two ';'
		size_t pos2 = line.find(";", pos1+1);
		if (pos2 == string::npos) {
			err++;
			continue;
		}

		int seqNum = 0;
		int location = 0;
		double value = 0;

		try {
			string parts[] = {"","",""};
			parts[0] = line.substr(0, pos1);
			parts[1] = line.substr(pos1+1, pos2-pos1-1);					// split line at ';' and trim
			parts[2] = line.substr(pos2+1, line.length()-pos2-1);			// the parts
			bool foundSpace = false;
			for (int i = 0; i < 3; i++) {
				size_t first = parts[i].find_first_not_of(' ');				// if one part still contains
				size_t last = parts[i].find_last_not_of(' ');				// a whitespace, the line is
				parts[i] = parts[i].substr(first, last-first+1);			// treated as an error
				if (parts[i].find(' ') != string::npos) {
					foundSpace = true;
				}
			}
			if (foundSpace) {
				err++;
				continue;
			}
			seqNum = stoi(parts[0]);
			location = stoi(parts[1]);			// if parsing fails, exception is thrown and caught
			value = stod(parts[2]);

		} catch (...) {
			err++;
			continue;
		}

		if (location < 1 || location > 2 || !isnormal(value) || value <= 0. ) {			// value must be positive
			err++;
			continue;
		}

		// here the values are stored
		values[--location].push_back(value);
		geoMean[location] += log(value);
		nLoc[location]++;

	}

	// geometric means are calculated
	for (int i = 0; i < 2; i++) {
		geoMean[i] = exp(geoMean[i] / (double)nLoc[i]);
	}

	// writing output
	cout << "File: " << args[1] << " with " << nLines << " lines" << endl;
	for (int i = 0; i < 2; i++) {
		cout << "Valid values Loc" << (i+1) << ": " << nLoc[i] << " with GeoMean " << geoMean[i] << endl;
	}
	cout << "Number of errors in the file: " << err << endl;

	exit(EXIT_SUCCESS);
}

<commit_msg>Delete ex1.cpp<commit_after><|endoftext|>


<commit_before>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/sfm.hpp"
#include "openMVG/system/timer.hpp"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"

using namespace openMVG;
using namespace openMVG::sfm;

/// Compute the structure of a scene according existing camera poses.
int main(int argc, char **argv)
{
  using namespace std;
  std::cout << "Compute Structure from the provided poses" << std::endl;

  CmdLine cmd;

  std::string sSfM_Data_Filename;
  std::string sMatchesDir;
  std::string sMatchesGeometricModel = "f";
  std::string sOutFile = "";

  cmd.add( make_option('i', sSfM_Data_Filename, "input_file") );
  cmd.add( make_option('m', sMatchesDir, "match_dir") );
  cmd.add( make_option('o', sOutFile, "output_file") );
  cmd.add( make_option('g', sMatchesGeometricModel, "matchesGeometricModel"));

  try {
    if (argc == 1) throw std::string("Invalid command line parameter.");
    cmd.process(argc, argv);
  } catch(const std::string& s) {
    std::cerr << "Usage: " << argv[0] << '\n'
    << "[-i|--input_file] path to a SfM_Data scene\n"
    << "[-o|--output_file] file where the output data will be stored "
    <<    "(i.e. path/sfm_data_structure.bin)\n"
    << "\n[Optional]\n"
    << "[-m|--match_dir] path to the features and descriptors that "
    <<    "corresponds to the provided SfM_Data scene\n"
    << "[-g|--matchesGeometricModel MODEL] matching geometric model used: 'f' (default), 'e' or 'h'"
    << std::endl;

    std::cerr << s << std::endl;
    return EXIT_FAILURE;
  }

  // Load input SfM_Data scene
  SfM_Data sfm_data;
  if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS|EXTRINSICS))) {
    std::cerr << std::endl
      << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  // Init the regions_type from the image describer file (used for image regions extraction)
  using namespace openMVG::features;
  const std::string sImage_describer = stlplus::create_filespec(sMatchesDir, "image_describer", "json");
  std::unique_ptr<Regions> regions_type = Init_region_type_from_file(sImage_describer);
  if (!regions_type)
  {
    std::cerr << "Invalid: "
      << sImage_describer << " regions type file." << std::endl;
    return EXIT_FAILURE;
  }

  // Prepare the Regions provider
  std::shared_ptr<Regions_Provider> regions_provider = std::make_shared<Regions_Provider>();
  if (!regions_provider->load(sfm_data, sMatchesDir, regions_type)) {
    std::cerr << std::endl
      << "Invalid regions." << std::endl;
    return EXIT_FAILURE;
  }

  //--
  //- Pair selection method:
  //  - geometry guided -> camera frustum intersection,
  //  - putative matches guided (photometric matches)
  //     (keep pairs that have valid Intrinsic & Pose ids).
  //--
  Pair_Set pairs;
  if (sMatchesDir.empty())
  {
    // No image pair provided, so we use cameras frustum intersection.
    // Build the list of connected images pairs from frustum intersections
    pairs = Frustum_Filter(sfm_data).getFrustumIntersectionPairs();
  }
  else
  {
    // Load pre-computed matches
    PairWiseMatches matches;
    if (!matching::Load(matches, sfm_data.GetViewsKeys(), sMatchesDir, sMatchesGeometricModel))
    {
      std::cerr<< "Unable to read the matches file." << std::endl;
      return EXIT_FAILURE;
    }
    pairs = getPairs(matches);
    // Keep only Pairs that belong to valid view indexes.
    const std::set<IndexT> valid_viewIdx = Get_Valid_Views(sfm_data);
    pairs = Pair_filter(pairs, valid_viewIdx);
  }

  openMVG::system::Timer timer;

  //------------------------------------------
  // Compute Structure from known camera poses
  //------------------------------------------
  SfM_Data_Structure_Estimation_From_Known_Poses structure_estimator;
  structure_estimator.run(sfm_data, pairs, regions_provider);
  RemoveOutliers_AngleError(sfm_data, 2.0);

  std::cout
    << "\nStructure estimation took (s): " << timer.elapsed() << "." << std::endl
    << "#landmark found: " << sfm_data.GetLandmarks().size() << std::endl;

  if (stlplus::extension_part(sOutFile) != "ply") {
    Save(sfm_data,
      stlplus::create_filespec(
        stlplus::folder_part(sOutFile),
        stlplus::basename_part(sOutFile), "ply"),
      ESfM_Data(ALL));
  }

  if (Save(sfm_data, sOutFile, ESfM_Data(ALL)))
    return EXIT_SUCCESS;

  std::cout << "Error while saving the sfm data!" << std::endl;
  return EXIT_FAILURE;
}
<commit_msg>[software] StructureFromKnownPoses: matchesDir is optional<commit_after>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/sfm.hpp"
#include "openMVG/system/timer.hpp"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"

using namespace openMVG;
using namespace openMVG::sfm;

/// Compute the structure of a scene according existing camera poses.
int main(int argc, char **argv)
{
  using namespace std;
  std::cout << "Compute Structure from the provided poses" << std::endl;

  CmdLine cmd;

  std::string sSfM_Data_Filename;
  std::string sFeaturesDir;
  std::string sMatchesDir;
  std::string sMatchesGeometricModel = "f";
  std::string sOutFile = "";

  cmd.add( make_option('i', sSfM_Data_Filename, "input_file") );
  cmd.add( make_option('f', sFeaturesDir, "feat_dir") );
  cmd.add( make_option('m', sMatchesDir, "match_dir") );
  cmd.add( make_option('o', sOutFile, "output_file") );
  cmd.add( make_option('g', sMatchesGeometricModel, "matchesGeometricModel"));

  try {
    if (argc == 1) throw std::string("Invalid command line parameter.");
    cmd.process(argc, argv);
  } catch(const std::string& s) {
    std::cerr << "Usage: " << argv[0] << "\n"
       "[-i|--input_file] path to a SfM_Data scene\n"
       "[-o|--output_file] file where the output data will be stored "
          "(i.e. path/sfm_data_structure.bin)\n"
       "[-m|--feat_dir] path to the features and descriptors that "
          "corresponds to the provided SfM_Data scene\n"
       "\n[Optional]\n"
       "[-m|--match_dir] path to the matches files "
       "(if not provided the images connections will be computed from Frustrums intersections)\n"
       "[-g|--matchesGeometricModel MODEL] matching geometric model used: 'f' (default), 'e' or 'h'"
    << std::endl;

    std::cerr << s << std::endl;
    return EXIT_FAILURE;
  }

  // Load input SfM_Data scene
  SfM_Data sfm_data;
  if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS|EXTRINSICS))) {
    std::cerr << std::endl
      << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  // Init the regions_type from the image describer file (used for image regions extraction)
  using namespace openMVG::features;
  const std::string sImage_describer = stlplus::create_filespec(sFeaturesDir, "image_describer", "json");
  std::unique_ptr<Regions> regions_type = Init_region_type_from_file(sImage_describer);
  if (!regions_type)
  {
    std::cerr << "Invalid: "
      << sImage_describer << " regions type file." << std::endl;
    return EXIT_FAILURE;
  }

  // Prepare the Regions provider
  std::shared_ptr<Regions_Provider> regions_provider = std::make_shared<Regions_Provider>();
  if (!regions_provider->load(sfm_data, sFeaturesDir, regions_type)) {
    std::cerr << std::endl
      << "Invalid regions." << std::endl;
    return EXIT_FAILURE;
  }

  //--
  //- Pair selection method:
  //  - geometry guided -> camera frustum intersection,
  //  - putative matches guided (photometric matches)
  //     (keep pairs that have valid Intrinsic & Pose ids).
  //--
  Pair_Set pairs;
  if (sMatchesDir.empty())
  {
    // No image pair provided, so we use cameras frustum intersection.
    // Build the list of connected images pairs from frustum intersections
    pairs = Frustum_Filter(sfm_data).getFrustumIntersectionPairs();
  }
  else
  {
    // Load pre-computed matches
    PairWiseMatches matches;
    if (!matching::Load(matches, sfm_data.GetViewsKeys(), sMatchesDir, sMatchesGeometricModel))
    {
      std::cerr<< "Unable to read the matches file." << std::endl;
      return EXIT_FAILURE;
    }
    pairs = getPairs(matches);
    // Keep only Pairs that belong to valid view indexes.
    const std::set<IndexT> valid_viewIdx = Get_Valid_Views(sfm_data);
    pairs = Pair_filter(pairs, valid_viewIdx);
  }

  openMVG::system::Timer timer;

  //------------------------------------------
  // Compute Structure from known camera poses
  //------------------------------------------
  SfM_Data_Structure_Estimation_From_Known_Poses structure_estimator;
  structure_estimator.run(sfm_data, pairs, regions_provider);
  RemoveOutliers_AngleError(sfm_data, 2.0);

  std::cout
    << "\nStructure estimation took (s): " << timer.elapsed() << "." << std::endl
    << "#landmark found: " << sfm_data.GetLandmarks().size() << std::endl;

  if (stlplus::extension_part(sOutFile) != "ply") {
    Save(sfm_data,
      stlplus::create_filespec(
        stlplus::folder_part(sOutFile),
        stlplus::basename_part(sOutFile), "ply"),
      ESfM_Data(ALL));
  }

  if (Save(sfm_data, sOutFile, ESfM_Data(ALL)))
    return EXIT_SUCCESS;

  std::cout << "Error while saving the sfm data!" << std::endl;
  return EXIT_FAILURE;
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkTIFFWriter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm 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 notice for more information.

=========================================================================*/
#include "vtkTIFFWriter.h"

#include "vtkErrorCode.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtk_tiff.h"

vtkCxxRevisionMacro(vtkTIFFWriter, "1.41");
vtkStandardNewMacro(vtkTIFFWriter);

//----------------------------------------------------------------------------
vtkTIFFWriter::vtkTIFFWriter()
{
  this->TIFFPtr = 0;
  this->Compression = vtkTIFFWriter::PackBits;
};

class vtkTIFFWriterIO
{
public:
  // Writing file no reading
  static tsize_t TIFFRead(thandle_t, tdata_t, tsize_t) { return 0; }

  // Write data
  static tsize_t TIFFWrite(thandle_t fd, tdata_t buf, tsize_t size)
    {
    ostream *out = reinterpret_cast<ostream *>(fd);
    out->write(static_cast<char *>(buf), size);
    return out->fail() ? static_cast<tsize_t>(0) : size;
    }

  static toff_t TIFFSeek(thandle_t fd, toff_t off, int whence)
    {
    ostream *out = reinterpret_cast<ostream *>(fd);
    switch (whence)
      {
      case SEEK_SET:
        out->seekp(off, ios::beg);
        break;
      case SEEK_END:
        out->seekp(off, ios::end);
        break;
      case SEEK_CUR:
        out->seekp(off, ios::cur);
        break;
      default:
        return out->tellp();
      }
    return out->tellp();
    }

  // File will be closed by the superclass
  static int TIFFClose(thandle_t) { return 1; }

  static toff_t TIFFSize(thandle_t fd)
    {
    ostream *out = reinterpret_cast<ostream *>(fd);
    out->seekp(0, ios::end);
    return out->tellp();
    }

  static int TIFFMapFile(thandle_t, tdata_t*, toff_t*) { return (0); }
  static void TIFFUnmapFile(thandle_t, tdata_t, toff_t) {}
};

//----------------------------------------------------------------------------
void vtkTIFFWriter::WriteFileHeader(ofstream *file, vtkImageData *data)
{
  int dims[3];
  int width, height;
  data->GetDimensions(dims);
  int scomponents = data->GetNumberOfScalarComponents();
  int stype = data->GetScalarType();
  double resolution = -1;
  uint32 rowsperstrip = (uint32) -1;

  int min0, min1, max0, max1, min2, max2;

  int bps;
  switch (stype)
    {
    case VTK_CHAR:
    case VTK_SIGNED_CHAR:
    case VTK_UNSIGNED_CHAR:
      bps = 8;
      break;
    case VTK_SHORT:
    case VTK_UNSIGNED_SHORT:
      bps = 16;
      break;
    case VTK_FLOAT:
      bps = 32;
      break;
    default:
      vtkErrorMacro(<< "Unsupported data type: " << data->GetScalarTypeAsString());
      this->SetErrorCode(vtkErrorCode::FileFormatError);
      return;
    }

  int predictor;
  ostream* ost = file;

  // Find the length of the rows to write.
  data->GetWholeExtent(min0, max0, min1, max1, min2, max2);
  width = (max0 - min0 + 1);
  height = (max1 - min1 + 1);

  TIFF* tif = TIFFClientOpen(this->GetFileName(), "w",
    (thandle_t) ost,
    reinterpret_cast<TIFFReadWriteProc>(vtkTIFFWriterIO::TIFFRead),
    reinterpret_cast<TIFFReadWriteProc>(vtkTIFFWriterIO::TIFFWrite),
    reinterpret_cast<TIFFSeekProc>(vtkTIFFWriterIO::TIFFSeek),
    reinterpret_cast<TIFFCloseProc>(vtkTIFFWriterIO::TIFFClose),
    reinterpret_cast<TIFFSizeProc>(vtkTIFFWriterIO::TIFFSize),
    reinterpret_cast<TIFFMapFileProc>(vtkTIFFWriterIO::TIFFMapFile),
    reinterpret_cast<TIFFUnmapFileProc>(vtkTIFFWriterIO::TIFFUnmapFile)
    );
  if ( !tif )
    {
    this->TIFFPtr = 0;
    return;
    }
  this->TIFFPtr = tif;

  uint32 w = width;
  uint32 h = height;
  TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
  TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
  TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, scomponents);
  TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); // Fix for stype
  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  if(stype == VTK_FLOAT)
    {
    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
    }

  if ( scomponents > 3 )
    {
    // if number of scalar components is greater than 3, that means we assume
    // there is alpha.
    uint16 extra_samples = scomponents-3;
    uint16 *sample_info = new uint16[scomponents-3];
    sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
    int cc;
    for ( cc = 1; cc < scomponents-3; cc ++ )
      {
      sample_info[cc] = EXTRASAMPLE_UNSPECIFIED;
      }
    TIFFSetField(tif,TIFFTAG_EXTRASAMPLES,extra_samples,
      sample_info);
    delete [] sample_info;
    }

  int compression;
  switch ( this->Compression )
    {
    case vtkTIFFWriter::PackBits: compression = COMPRESSION_PACKBITS; break;
    case vtkTIFFWriter::JPEG:     compression = COMPRESSION_JPEG; break;
    case vtkTIFFWriter::Deflate:  compression = COMPRESSION_DEFLATE; break;
    case vtkTIFFWriter::LZW:      compression = COMPRESSION_LZW; break;
    default: compression = COMPRESSION_NONE;
    }
  //compression = COMPRESSION_JPEG;
  TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); // Fix for compression
  uint16 photometric =
    (scomponents == 1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB);
  if ( compression == COMPRESSION_JPEG )
    {
    TIFFSetField(tif, TIFFTAG_JPEGQUALITY, 75); // Parameter
    TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
    photometric = PHOTOMETRIC_YCBCR;
    }
  else if ( compression == COMPRESSION_LZW )
    {
    predictor = 2;
    TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
    vtkErrorMacro("LZW compression is patented outside US so it is disabled");
    }
  else if ( compression == COMPRESSION_DEFLATE )
    {
    predictor = 2;
    TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
    }

  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); // Fix for scomponents
  TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,
    TIFFDefaultStripSize(tif, rowsperstrip));
  if (resolution > 0)
    {
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, resolution);
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, resolution);
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
    }
}

//----------------------------------------------------------------------------
void vtkTIFFWriter::WriteFile(ofstream *, vtkImageData *data,
  int extent[6])
{
  int idx1, idx2;
  void *ptr;

  // Make sure we actually have data.
  if ( !data->GetPointData()->GetScalars())
    {
    vtkErrorMacro(<< "Could not get data from input.");
    return;
    }

  TIFF* tif = reinterpret_cast<TIFF*>(this->TIFFPtr);
  if ( !tif )
    {
    vtkErrorMacro("Problem writing trailer.");
    this->SetErrorCode(vtkErrorCode::FileFormatError);
    return;
    }

  // take into consideration the scalar type
  if( data->GetScalarType() != VTK_UNSIGNED_CHAR
   && data->GetScalarType() != VTK_UNSIGNED_SHORT
   && data->GetScalarType() != VTK_FLOAT
   )
    {
    vtkErrorMacro("TIFFWriter only accepts unsigned char/short or float scalars!");
    return;
    }

  int row = 0;
  for (idx2 = extent[4]; idx2 <= extent[5]; ++idx2)
    {
    for (idx1 = extent[3]; idx1 >= extent[2]; idx1--)
      {
      ptr = data->GetScalarPointer(extent[0], idx1, idx2);
      if ( TIFFWriteScanline(tif, static_cast<unsigned char*>(ptr), row, 0) < 0)
        {
        this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
        break;
        }
      row ++;
      }
    }
}

//----------------------------------------------------------------------------
void vtkTIFFWriter::WriteFileTrailer(ofstream *, vtkImageData *)
{
  TIFF* tif = reinterpret_cast<TIFF*>(this->TIFFPtr);
  if ( !tif )
    {
    vtkErrorMacro("Problem writting trailer.");
    this->SetErrorCode(vtkErrorCode::FileFormatError);
    }
  TIFFClose(tif);
  this->TIFFPtr = 0;
}

//----------------------------------------------------------------------------
void vtkTIFFWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Compression: ";
  if ( this->Compression == vtkTIFFWriter::PackBits )
    {
    os << "Pack Bits\n";
    }
  else if ( this->Compression == vtkTIFFWriter::JPEG )
    {
    os << "JPEG\n";
    }
  else if ( this->Compression == vtkTIFFWriter::Deflate )
    {
    os << "Deflate\n";
    }
  else if ( this->Compression == vtkTIFFWriter::LZW )
    {
    os << "LZW\n";
    }
  else //if ( this->Compression == vtkTIFFWriter::NoCompression )
    {
    os << "No Compression\n";
    }
}
<commit_msg>BUG: 3917 vtkTIFFWriter crashes when saving image sequence.      Apply the fix suggested by reporter ( cquammen1 )<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTIFFWriter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm 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 notice for more information.

=========================================================================*/
#include "vtkTIFFWriter.h"

#include "vtkErrorCode.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtk_tiff.h"

vtkCxxRevisionMacro(vtkTIFFWriter, "1.42");
vtkStandardNewMacro(vtkTIFFWriter);

//----------------------------------------------------------------------------
vtkTIFFWriter::vtkTIFFWriter()
{
  this->TIFFPtr = 0;
  this->Compression = vtkTIFFWriter::PackBits;
};

class vtkTIFFWriterIO
{
public:
  // Writing file no reading
  static tsize_t TIFFRead(thandle_t, tdata_t, tsize_t) { return 0; }

  // Write data
  static tsize_t TIFFWrite(thandle_t fd, tdata_t buf, tsize_t size)
    {
    ostream *out = reinterpret_cast<ostream *>(fd);
    out->write(static_cast<char *>(buf), size);
    return out->fail() ? static_cast<tsize_t>(0) : size;
    }

  static toff_t TIFFSeek(thandle_t fd, toff_t off, int whence)
    {
    ostream *out = reinterpret_cast<ostream *>(fd);
    switch (whence)
      {
      case SEEK_SET:
        out->seekp(off, ios::beg);
        break;
      case SEEK_END:
        out->seekp(off, ios::end);
        break;
      case SEEK_CUR:
        out->seekp(off, ios::cur);
        break;
      default:
        return out->tellp();
      }
    return out->tellp();
    }

  // File will be closed by the superclass
  static int TIFFClose(thandle_t) { return 1; }

  static toff_t TIFFSize(thandle_t fd)
    {
    ostream *out = reinterpret_cast<ostream *>(fd);
    out->seekp(0, ios::end);
    return out->tellp();
    }

  static int TIFFMapFile(thandle_t, tdata_t*, toff_t*) { return (0); }
  static void TIFFUnmapFile(thandle_t, tdata_t, toff_t) {}
};

//----------------------------------------------------------------------------
void vtkTIFFWriter::WriteFileHeader(ofstream *file, vtkImageData *data)
{
  int dims[3];
  int width, height;
  data->GetDimensions(dims);
  int scomponents = data->GetNumberOfScalarComponents();
  int stype = data->GetScalarType();
  double resolution = -1;
  uint32 rowsperstrip = (uint32) -1;

  int min0, min1, max0, max1, min2, max2;

  int bps;
  switch (stype)
    {
    case VTK_CHAR:
    case VTK_SIGNED_CHAR:
    case VTK_UNSIGNED_CHAR:
      bps = 8;
      break;
    case VTK_SHORT:
    case VTK_UNSIGNED_SHORT:
      bps = 16;
      break;
    case VTK_FLOAT:
      bps = 32;
      break;
    default:
      vtkErrorMacro(<< "Unsupported data type: " << data->GetScalarTypeAsString());
      this->SetErrorCode(vtkErrorCode::FileFormatError);
      return;
    }

  int predictor;
  ostream* ost = file;

  // Find the length of the rows to write.
  data->GetWholeExtent(min0, max0, min1, max1, min2, max2);
  width = (max0 - min0 + 1);
  height = (max1 - min1 + 1);

  TIFF* tif = TIFFClientOpen(this->InternalFileName, "w",
    (thandle_t) ost,
    reinterpret_cast<TIFFReadWriteProc>(vtkTIFFWriterIO::TIFFRead),
    reinterpret_cast<TIFFReadWriteProc>(vtkTIFFWriterIO::TIFFWrite),
    reinterpret_cast<TIFFSeekProc>(vtkTIFFWriterIO::TIFFSeek),
    reinterpret_cast<TIFFCloseProc>(vtkTIFFWriterIO::TIFFClose),
    reinterpret_cast<TIFFSizeProc>(vtkTIFFWriterIO::TIFFSize),
    reinterpret_cast<TIFFMapFileProc>(vtkTIFFWriterIO::TIFFMapFile),
    reinterpret_cast<TIFFUnmapFileProc>(vtkTIFFWriterIO::TIFFUnmapFile)
    );
  if ( !tif )
    {
    this->TIFFPtr = 0;
    return;
    }
  this->TIFFPtr = tif;

  uint32 w = width;
  uint32 h = height;
  TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
  TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
  TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, scomponents);
  TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); // Fix for stype
  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  if(stype == VTK_FLOAT)
    {
    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
    }

  if ( scomponents > 3 )
    {
    // if number of scalar components is greater than 3, that means we assume
    // there is alpha.
    uint16 extra_samples = scomponents-3;
    uint16 *sample_info = new uint16[scomponents-3];
    sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
    int cc;
    for ( cc = 1; cc < scomponents-3; cc ++ )
      {
      sample_info[cc] = EXTRASAMPLE_UNSPECIFIED;
      }
    TIFFSetField(tif,TIFFTAG_EXTRASAMPLES,extra_samples,
      sample_info);
    delete [] sample_info;
    }

  int compression;
  switch ( this->Compression )
    {
    case vtkTIFFWriter::PackBits: compression = COMPRESSION_PACKBITS; break;
    case vtkTIFFWriter::JPEG:     compression = COMPRESSION_JPEG; break;
    case vtkTIFFWriter::Deflate:  compression = COMPRESSION_DEFLATE; break;
    case vtkTIFFWriter::LZW:      compression = COMPRESSION_LZW; break;
    default: compression = COMPRESSION_NONE;
    }
  //compression = COMPRESSION_JPEG;
  TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); // Fix for compression
  uint16 photometric =
    (scomponents == 1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB);
  if ( compression == COMPRESSION_JPEG )
    {
    TIFFSetField(tif, TIFFTAG_JPEGQUALITY, 75); // Parameter
    TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
    photometric = PHOTOMETRIC_YCBCR;
    }
  else if ( compression == COMPRESSION_LZW )
    {
    predictor = 2;
    TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
    vtkErrorMacro("LZW compression is patented outside US so it is disabled");
    }
  else if ( compression == COMPRESSION_DEFLATE )
    {
    predictor = 2;
    TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
    }

  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); // Fix for scomponents
  TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,
    TIFFDefaultStripSize(tif, rowsperstrip));
  if (resolution > 0)
    {
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, resolution);
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, resolution);
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
    }
}

//----------------------------------------------------------------------------
void vtkTIFFWriter::WriteFile(ofstream *, vtkImageData *data,
  int extent[6])
{
  int idx1, idx2;
  void *ptr;

  // Make sure we actually have data.
  if ( !data->GetPointData()->GetScalars())
    {
    vtkErrorMacro(<< "Could not get data from input.");
    return;
    }

  TIFF* tif = reinterpret_cast<TIFF*>(this->TIFFPtr);
  if ( !tif )
    {
    vtkErrorMacro("Problem writing trailer.");
    this->SetErrorCode(vtkErrorCode::FileFormatError);
    return;
    }

  // take into consideration the scalar type
  if( data->GetScalarType() != VTK_UNSIGNED_CHAR
   && data->GetScalarType() != VTK_UNSIGNED_SHORT
   && data->GetScalarType() != VTK_FLOAT
   )
    {
    vtkErrorMacro("TIFFWriter only accepts unsigned char/short or float scalars!");
    return;
    }

  int row = 0;
  for (idx2 = extent[4]; idx2 <= extent[5]; ++idx2)
    {
    for (idx1 = extent[3]; idx1 >= extent[2]; idx1--)
      {
      ptr = data->GetScalarPointer(extent[0], idx1, idx2);
      if ( TIFFWriteScanline(tif, static_cast<unsigned char*>(ptr), row, 0) < 0)
        {
        this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
        break;
        }
      row ++;
      }
    }
}

//----------------------------------------------------------------------------
void vtkTIFFWriter::WriteFileTrailer(ofstream *, vtkImageData *)
{
  TIFF* tif = reinterpret_cast<TIFF*>(this->TIFFPtr);
  if ( !tif )
    {
    vtkErrorMacro("Problem writting trailer.");
    this->SetErrorCode(vtkErrorCode::FileFormatError);
    }
  TIFFClose(tif);
  this->TIFFPtr = 0;
}

//----------------------------------------------------------------------------
void vtkTIFFWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Compression: ";
  if ( this->Compression == vtkTIFFWriter::PackBits )
    {
    os << "Pack Bits\n";
    }
  else if ( this->Compression == vtkTIFFWriter::JPEG )
    {
    os << "JPEG\n";
    }
  else if ( this->Compression == vtkTIFFWriter::Deflate )
    {
    os << "Deflate\n";
    }
  else if ( this->Compression == vtkTIFFWriter::LZW )
    {
    os << "LZW\n";
    }
  else //if ( this->Compression == vtkTIFFWriter::NoCompression )
    {
    os << "No Compression\n";
    }
}
<|endoftext|>


<commit_before><commit_msg>nokkur endl fjarlægð<commit_after><|endoftext|>


<commit_before>
#ifdef RAMP_FILTER_TEST_WITHOUT_FFTW
#  include "rtkConfiguration.h"
#  include <itkImageToImageFilter.h>
#  if defined(USE_FFTWF)
#    undef USE_FFTWF
#  endif
#  if defined(USE_FFTWD)
#    undef USE_FFTWD
#  endif
#  include "rtkFFTRampImageFilter.h"
#endif

#include <itkImageRegionConstIterator.h>

#include "rtkTestConfiguration.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"
#include "rtkAdditiveGaussianNoiseImageFilter.h"

#ifdef USE_CUDA
#  include "rtkCudaFDKConeBeamReconstructionFilter.h"
#else
#  include "rtkFDKConeBeamReconstructionFilter.h"
#endif

template<class TImage>
void CheckImageQuality(typename TImage::Pointer recon,
                       typename TImage::Pointer ref,
                       double refLowerThreshold,
                       double refUpperThreshold,
                       double snrThreshold,
                       double errorPerPixelThreshold)
{
#if !(FAST_TESTS_NO_CHECKS)
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  unsigned int npix=0;
  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType testVal = itTest.Get();
    typename TImage::PixelType refVal = itRef.Get();
    if( testVal != refVal && (refVal>=refLowerThreshold && refVal<=refUpperThreshold) )
      {
        TestError += vcl_abs(refVal - testVal);
        EnerError += vcl_pow(ErrorType(refVal - testVal), 2.);
        npix++;
      }
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/npix;
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/npix;
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(2.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;

  // Checking results
  if (ErrorPerPixel > errorPerPixelThreshold)
  {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of " << errorPerPixelThreshold << std::endl;
    exit( EXIT_FAILURE);
  }
  if (PSNR < snrThreshold)
  {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of " << snrThreshold << std::endl;
    exit( EXIT_FAILURE);
  }
#endif
}

int main(int , char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
#if FAST_TESTS_NO_CHECKS
  const unsigned int NumberOfProjectionImages = 3;
#else
  const unsigned int NumberOfProjectionImages = 180;
#endif

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  ConstantImageSourceType::Pointer tomographySource  = ConstantImageSourceType::New();
  origin[0] = -127.;
  origin[1] = -127.;
  origin[2] = -127.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 2;
  size[1] = 2;
  size[2] = 2;
  spacing[0] = 254.;
  spacing[1] = 254.;
  spacing[2] = 254.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = 128;
  spacing[0] = 2.;
  spacing[1] = 2.;
  spacing[2] = 2.;
#endif
  tomographySource->SetOrigin( origin );
  tomographySource->SetSpacing( spacing );
  tomographySource->SetSize( size );
  tomographySource->SetConstant( 0. );

  ConstantImageSourceType::Pointer projectionsSource = ConstantImageSourceType::New();
  origin[0] = -254.;
  origin[1] = -254.;
  origin[2] = -254.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 2;
  size[1] = 2;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 508.;
  spacing[1] = 508.;
  spacing[2] = 508.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
#endif
  projectionsSource->SetOrigin( origin );
  projectionsSource->SetSpacing( spacing );
  projectionsSource->SetSize( size );
  projectionsSource->SetConstant( 0. );

  // Geometry object
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int noProj=0; noProj<NumberOfProjectionImages; noProj++)
    geometry->AddProjection(600., 1200., noProj*360./NumberOfProjectionImages);

  // Shepp Logan projections filter
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp=SLPType::New();
  slp->SetInput( projectionsSource->GetOutput() );
  slp->SetGeometry(geometry);

  std::cout << "\n\n****** Test 1: add noise and test Hann window ******" << std::endl;

  // Add noise
  typedef rtk::AdditiveGaussianNoiseImageFilter< OutputImageType > NIFType;
  NIFType::Pointer noisy=NIFType::New();
  noisy->SetInput( slp->GetOutput() );
  noisy->SetMean( 0.0 );
  noisy->SetStandardDeviation( 1. );

  // Create a reference object (in this case a 3D phantom reference).
  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->SetInput( tomographySource->GetOutput() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() );

  // FDK reconstruction filtering
#ifdef USE_CUDA
  typedef rtk::CudaFDKConeBeamReconstructionFilter                FDKType;
#else
  typedef rtk::FDKConeBeamReconstructionFilter< OutputImageType > FDKType;
#endif
  FDKType::Pointer feldkamp = FDKType::New();
  feldkamp->SetInput( 0, tomographySource->GetOutput() );
  feldkamp->SetInput( 1, noisy->GetOutput() );
  feldkamp->SetGeometry( geometry );
  feldkamp->GetRampFilter()->SetHannCutFrequency(0.8);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkamp->Update() );

  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 1.05, 1.06, 40, 0.13);

  std::cout << "\n\n****** Test 1.5: add noise and test HannY window ******" << std::endl;
  feldkamp->GetRampFilter()->SetHannCutFrequencyY(0.8);
  feldkamp->Modified();
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkamp->Update() );
  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 1.05, 1.06, 40, 0.13);

  std::cout << "\n\n****** Test 2: smaller detector and test data padding for truncation ******" << std::endl;

  size[0] = 114;
  projectionsSource->SetSize( size );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( slp->UpdateLargestPossibleRegion() );

  FDKType::Pointer feldkampCropped = FDKType::New();
  feldkampCropped->SetInput( 0, tomographySource->GetOutput() );
  feldkampCropped->SetInput( 1, slp->GetOutput() );
  feldkampCropped->SetGeometry( geometry );
  feldkampCropped->GetRampFilter()->SetTruncationCorrection(0.1);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkampCropped->Update() );

  CheckImageQuality<OutputImageType>(feldkampCropped->GetOutput(), dsl->GetOutput(), 1.015, 1.025, 26, 0.05);

  std::cout << "\n\nTest PASSED! " << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg>Make sure that FFTW is not used with ITK4 as well<commit_after>
#ifdef RAMP_FILTER_TEST_WITHOUT_FFTW
#  include "rtkConfiguration.h"
#  include <itkImageToImageFilter.h>
#  if defined(ITK_USE_FFTWF)
#    undef ITK_USE_FFTWF
#  endif
#  if defined(ITK_USE_FFTWD)
#    undef ITK_USE_FFTWD
#  endif
#  if defined(USE_FFTWF)
#    undef USE_FFTWF
#  endif
#  if defined(USE_FFTWD)
#    undef USE_FFTWD
#  endif
#  include "rtkFFTRampImageFilter.h"
#endif

#include <itkImageRegionConstIterator.h>

#include "rtkTestConfiguration.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"
#include "rtkAdditiveGaussianNoiseImageFilter.h"

#ifdef USE_CUDA
#  include "rtkCudaFDKConeBeamReconstructionFilter.h"
#else
#  include "rtkFDKConeBeamReconstructionFilter.h"
#endif

template<class TImage>
void CheckImageQuality(typename TImage::Pointer recon,
                       typename TImage::Pointer ref,
                       double refLowerThreshold,
                       double refUpperThreshold,
                       double snrThreshold,
                       double errorPerPixelThreshold)
{
#if !(FAST_TESTS_NO_CHECKS)
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  unsigned int npix=0;
  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType testVal = itTest.Get();
    typename TImage::PixelType refVal = itRef.Get();
    if( testVal != refVal && (refVal>=refLowerThreshold && refVal<=refUpperThreshold) )
      {
        TestError += vcl_abs(refVal - testVal);
        EnerError += vcl_pow(ErrorType(refVal - testVal), 2.);
        npix++;
      }
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/npix;
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/npix;
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(2.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;

  // Checking results
  if (ErrorPerPixel > errorPerPixelThreshold)
  {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of " << errorPerPixelThreshold << std::endl;
    exit( EXIT_FAILURE);
  }
  if (PSNR < snrThreshold)
  {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of " << snrThreshold << std::endl;
    exit( EXIT_FAILURE);
  }
#endif
}

int main(int , char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
#if FAST_TESTS_NO_CHECKS
  const unsigned int NumberOfProjectionImages = 3;
#else
  const unsigned int NumberOfProjectionImages = 180;
#endif

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  ConstantImageSourceType::Pointer tomographySource  = ConstantImageSourceType::New();
  origin[0] = -127.;
  origin[1] = -127.;
  origin[2] = -127.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 2;
  size[1] = 2;
  size[2] = 2;
  spacing[0] = 254.;
  spacing[1] = 254.;
  spacing[2] = 254.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = 128;
  spacing[0] = 2.;
  spacing[1] = 2.;
  spacing[2] = 2.;
#endif
  tomographySource->SetOrigin( origin );
  tomographySource->SetSpacing( spacing );
  tomographySource->SetSize( size );
  tomographySource->SetConstant( 0. );

  ConstantImageSourceType::Pointer projectionsSource = ConstantImageSourceType::New();
  origin[0] = -254.;
  origin[1] = -254.;
  origin[2] = -254.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 2;
  size[1] = 2;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 508.;
  spacing[1] = 508.;
  spacing[2] = 508.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
#endif
  projectionsSource->SetOrigin( origin );
  projectionsSource->SetSpacing( spacing );
  projectionsSource->SetSize( size );
  projectionsSource->SetConstant( 0. );

  // Geometry object
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int noProj=0; noProj<NumberOfProjectionImages; noProj++)
    geometry->AddProjection(600., 1200., noProj*360./NumberOfProjectionImages);

  // Shepp Logan projections filter
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp=SLPType::New();
  slp->SetInput( projectionsSource->GetOutput() );
  slp->SetGeometry(geometry);

  std::cout << "\n\n****** Test 1: add noise and test Hann window ******" << std::endl;

  // Add noise
  typedef rtk::AdditiveGaussianNoiseImageFilter< OutputImageType > NIFType;
  NIFType::Pointer noisy=NIFType::New();
  noisy->SetInput( slp->GetOutput() );
  noisy->SetMean( 0.0 );
  noisy->SetStandardDeviation( 1. );

  // Create a reference object (in this case a 3D phantom reference).
  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->SetInput( tomographySource->GetOutput() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() );

  // FDK reconstruction filtering
#ifdef USE_CUDA
  typedef rtk::CudaFDKConeBeamReconstructionFilter                FDKType;
#else
  typedef rtk::FDKConeBeamReconstructionFilter< OutputImageType > FDKType;
#endif
  FDKType::Pointer feldkamp = FDKType::New();
  feldkamp->SetInput( 0, tomographySource->GetOutput() );
  feldkamp->SetInput( 1, noisy->GetOutput() );
  feldkamp->SetGeometry( geometry );
  feldkamp->GetRampFilter()->SetHannCutFrequency(0.8);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkamp->Update() );

  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 1.05, 1.06, 40, 0.13);

  std::cout << "\n\n****** Test 1.5: add noise and test HannY window ******" << std::endl;
  feldkamp->GetRampFilter()->SetHannCutFrequencyY(0.8);
  feldkamp->Modified();
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkamp->Update() );
  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 1.05, 1.06, 40, 0.13);

  std::cout << "\n\n****** Test 2: smaller detector and test data padding for truncation ******" << std::endl;

  size[0] = 114;
  projectionsSource->SetSize( size );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( slp->UpdateLargestPossibleRegion() );

  FDKType::Pointer feldkampCropped = FDKType::New();
  feldkampCropped->SetInput( 0, tomographySource->GetOutput() );
  feldkampCropped->SetInput( 1, slp->GetOutput() );
  feldkampCropped->SetGeometry( geometry );
  feldkampCropped->GetRampFilter()->SetTruncationCorrection(0.1);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkampCropped->Update() );

  CheckImageQuality<OutputImageType>(feldkampCropped->GetOutput(), dsl->GetOutput(), 1.015, 1.025, 26, 0.05);

  std::cout << "\n\nTest PASSED! " << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>