From 157c4cbb4a54bd9646209cb683555f2a5bc42ef6 Mon Sep 17 00:00:00 2001 From: E Sommerlade Date: Mon, 25 Jan 2016 17:25:47 +0000 Subject: [PATCH 1/2] cmake based windows port --- source/CMakeLists.txt | 109 +++++++++ source/src/lib/windows/dirent.h | 372 ++++++++++++++++++++++++++++++ source/src/lib/windows/getopt.cpp | 76 ++++++ source/src/lib/windows/getopt.h | 32 +++ source/src/tool/timer.cpp | 99 ++++++++ source/src/tool/timer.h | 19 ++ 6 files changed, 707 insertions(+) create mode 100755 source/CMakeLists.txt create mode 100755 source/src/lib/windows/dirent.h create mode 100755 source/src/lib/windows/getopt.cpp create mode 100755 source/src/lib/windows/getopt.h create mode 100755 source/src/tool/timer.cpp create mode 100755 source/src/tool/timer.h diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100755 index 0000000..a823129 --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,109 @@ +project(DeepBeliefSDK) +cmake_minimum_required(VERSION 2.8) + +if ( WIN32 ) + add_definitions(-DUSE_EIGEN_GEMM=1 -D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) + # for +#include +#include +#include +#include +#include + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat() */ +#if defined(_MSC_VER) && !defined(S_IREAD) +# define S_IFMT _S_IFMT /* file type mask */ +# define S_IFDIR _S_IFDIR /* directory */ +# define S_IFCHR _S_IFCHR /* character device */ +# define S_IFFIFO _S_IFFIFO /* pipe */ +# define S_IFREG _S_IFREG /* regular file */ +# define S_IREAD _S_IREAD /* read permission */ +# define S_IWRITE _S_IWRITE /* write permission */ +# define S_IEXEC _S_IEXEC /* execute permission */ +#endif +#define S_IFBLK 0 /* block device */ +#define S_IFLNK 0 /* link */ +#define S_IFSOCK 0 /* socket */ + +#if defined(_MSC_VER) +# define S_IRUSR S_IREAD /* read, user */ +# define S_IWUSR S_IWRITE /* write, user */ +# define S_IXUSR 0 /* execute, user */ +# define S_IRGRP 0 /* read, group */ +# define S_IWGRP 0 /* write, group */ +# define S_IXGRP 0 /* execute, group */ +# define S_IROTH 0 /* read, others */ +# define S_IWOTH 0 /* write, others */ +# define S_IXOTH 0 /* execute, others */ +#endif + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO) +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct dirent +{ + char d_name[MAX_PATH + 1]; /* File name */ + size_t d_namlen; /* Length of name without \0 */ + int d_type; /* File type */ +} dirent; + + +typedef struct DIR +{ + dirent curentry; /* Current directory entry */ + WIN32_FIND_DATAA find_data; /* Private file data */ + int cached; /* True if data is valid */ + HANDLE search_handle; /* Win32 search handle */ + char patt[MAX_PATH + 3]; /* Initial directory name */ +} DIR; + + +/* Forward declarations */ +static DIR *opendir(const char *dirname); +static struct dirent *readdir(DIR *dirp); +static int closedir(DIR *dirp); +static void rewinddir(DIR* dirp); + + +/* Use the new safe string functions introduced in Visual Studio 2005 */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE) +#else +# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size)) +#endif + +/* Set errno variable */ +#if defined(_MSC_VER) +#define DIRENT_SET_ERRNO(x) _set_errno (x) +#else +#define DIRENT_SET_ERRNO(x) (errno = (x)) +#endif + + +/***************************************************************************** + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static DIR *opendir(const char *dirname) +{ + DIR *dirp; + + /* ensure that the resulting search pattern will be a valid file name */ + if (dirname == NULL) { + DIRENT_SET_ERRNO (ENOENT); + return NULL; + } + if (strlen (dirname) + 3 >= MAX_PATH) { + DIRENT_SET_ERRNO (ENAMETOOLONG); + return NULL; + } + + /* construct new DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (dirp != NULL) { + int error; + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly when the current working + * directory is changed between opendir() and rewinddir(). + */ + if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) { + char *p; + + /* append the search pattern "\\*\0" to the directory name */ + p = strchr (dirp->patt, '\0'); + if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') { + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* open directory stream and retrieve the first entry */ + dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data); + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + /* a directory entry is now waiting in memory */ + dirp->cached = 1; + error = 0; + } else { + /* search pattern is not a directory name? */ + DIRENT_SET_ERRNO (ENOENT); + error = 1; + } + } else { + /* buffer too small */ + DIRENT_SET_ERRNO (ENOMEM); + error = 1; + } + + if (error) { + free (dirp); + dirp = NULL; + } + } + + return dirp; +} + + +/***************************************************************************** + * Read a directory entry, and return a pointer to a dirent structure + * containing the name of the entry in d_name field. Individual directory + * entries returned by this very function include regular files, + * sub-directories, pseudo-directories "." and "..", but also volume labels, + * hidden files and system files may be returned. + */ +static struct dirent *readdir(DIR *dirp) +{ + DWORD attr; + if (dirp == NULL) { + /* directory stream did not open */ + DIRENT_SET_ERRNO (EBADF); + return NULL; + } + + /* get next directory entry */ + if (dirp->cached != 0) { + /* a valid directory entry already in memory */ + dirp->cached = 0; + } else { + /* get the next directory entry from stream */ + if (dirp->search_handle == INVALID_HANDLE_VALUE) { + return NULL; + } + if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) { + /* the very last entry has been processed or an error occured */ + FindClose (dirp->search_handle); + dirp->search_handle = INVALID_HANDLE_VALUE; + return NULL; + } + } + + /* copy as a multibyte character string */ + DIRENT_STRNCPY ( dirp->curentry.d_name, + dirp->find_data.cFileName, + sizeof(dirp->curentry.d_name) ); + dirp->curentry.d_name[MAX_PATH] = '\0'; + + /* compute the length of name */ + dirp->curentry.d_namlen = strlen (dirp->curentry.d_name); + + /* determine file type */ + attr = dirp->find_data.dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + dirp->curentry.d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + dirp->curentry.d_type = DT_DIR; + } else { + dirp->curentry.d_type = DT_REG; + } + return &dirp->curentry; +} + + +/***************************************************************************** + * Close directory stream opened by opendir() function. Close of the + * directory stream invalidates the DIR structure as well as any previously + * read directory entry. + */ +static int closedir(DIR *dirp) +{ + if (dirp == NULL) { + /* invalid directory stream */ + DIRENT_SET_ERRNO (EBADF); + return -1; + } + + /* release search handle */ + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->search_handle); + dirp->search_handle = INVALID_HANDLE_VALUE; + } + + /* release directory structure */ + free (dirp); + return 0; +} + + +/***************************************************************************** + * Resets the position of the directory stream to which dirp refers to the + * beginning of the directory. It also causes the directory stream to refer + * to the current state of the corresponding directory, as a call to opendir() + * would have done. If dirp does not refer to a directory stream, the effect + * is undefined. + */ +static void rewinddir(DIR* dirp) +{ + if (dirp != NULL) { + /* release search handle */ + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->search_handle); + } + + /* open new search handle and retrieve the first entry */ + dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data); + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + /* a directory entry is now waiting in memory */ + dirp->cached = 1; + } else { + /* failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + } + } +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff --git a/source/src/lib/windows/getopt.cpp b/source/src/lib/windows/getopt.cpp new file mode 100755 index 0000000..8699a47 --- /dev/null +++ b/source/src/lib/windows/getopt.cpp @@ -0,0 +1,76 @@ +/* +POSIX getopt for Windows + +AT&T Public License + +Code given out at the 1985 UNIFORUM conference in Dallas. +*/ + +#ifndef __GNUC__ + +#include "getopt.h" +#include +#include + +#define NULL 0 +#define EOF (-1) +#define ERR(s, c) if(opterr){\ + char errbuf[2];\ + errbuf[0] = c; errbuf[1] = '\n';\ + fputs(argv[0], stderr);\ + fputs(s, stderr);\ + fputc(c, stderr);} + //(void) write(2, argv[0], (unsigned)strlen(argv[0]));\ + //(void) write(2, s, (unsigned)strlen(s));\ + //(void) write(2, errbuf, 2);} + +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +int +getopt(int argc, char** argv, char* opts) +{ + static int sp = 1; + register int c; + register char *cp; + + if(sp == 1) + if(optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') + return(EOF); + else if(strcmp(argv[optind], "--") == NULL) { + optind++; + return(EOF); + } + optopt = c = argv[optind][sp]; + if(c == ':' || (cp=strchr(opts, c)) == NULL) { + ERR(": illegal option -- ", c); + if(argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return('?'); + } + if(*++cp == ':') { + if(argv[optind][sp+1] != '\0') + optarg = &argv[optind++][sp+1]; + else if(++optind >= argc) { + ERR(": option requires an argument -- ", c); + sp = 1; + return('?'); + } else + optarg = argv[optind++]; + sp = 1; + } else { + if(argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + return(c); +} + +#endif /* __GNUC__ */ diff --git a/source/src/lib/windows/getopt.h b/source/src/lib/windows/getopt.h new file mode 100755 index 0000000..7ccef54 --- /dev/null +++ b/source/src/lib/windows/getopt.h @@ -0,0 +1,32 @@ +/* +POSIX getopt for Windows + +AT&T Public License + +Code given out at the 1985 UNIFORUM conference in Dallas. +*/ + +#ifdef __GNUC__ +#include +#endif +#ifndef __GNUC__ + +#ifndef _WINGETOPT_H_ +#define _WINGETOPT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int opterr; +extern int optind; +extern int optopt; +extern char *optarg; +extern int getopt(int argc, char **argv, char *opts); + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H_ */ +#endif /* __GNUC__ */ diff --git a/source/src/tool/timer.cpp b/source/src/tool/timer.cpp new file mode 100755 index 0000000..524982f --- /dev/null +++ b/source/src/tool/timer.cpp @@ -0,0 +1,99 @@ +#include "timer.h" +#include + +#if !defined(WIN32) || (defined(WIN32) && (_MSC_VER >= 1800) ) +// support for stl chrono in high resolution from VS 2013 onwards: + +typedef std::chrono::high_resolution_clock high_resolution_clock; + +#else +#include +// we want more than 0.5ms accuracy +struct HighResClock +{ + typedef long long rep; + typedef std::nano period; + typedef std::chrono::duration duration; + typedef std::chrono::time_point time_point; + static const bool is_steady = true; + + static time_point now(); +}; + +// static +namespace +{ + const long long g_Frequency = []() -> long long + { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return frequency.QuadPart; + }(); +} + +HighResClock::time_point HighResClock::now() +{ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return time_point(duration(count.QuadPart * static_cast(period::den) / g_Frequency)); +} +typedef HighResClock high_resolution_clock; +#endif + +struct Timer::Data { + high_resolution_clock::time_point m_start; + Data() + : m_start(high_resolution_clock::now()) + { + } +}; + + +Timer::Timer() +: d(0) +{ + d = new Data; +} + +Timer::~Timer() +{ + delete d; +} + +void +Timer::restart() +{ + d->m_start = high_resolution_clock::now(); +} + +double +Timer::getElapsedTimeMs() const +{ + return 1.0*std::chrono::duration_cast(high_resolution_clock::now() - d->m_start).count() / (1000 * 1000); +} + +/* +this is the default implementation of the timer class -- which fails on VS2012 as high_resolution_clock is not using QueryPerformanceCounter(). +Once the shift to VS2013 is done, this implementation can be used. +class LRTimer { +private: +typedef std::chrono::high_resolution_clock high_resolution_clock; +high_resolution_clock::time_point m_start; + +public: +//! default constructor starts immediately. +LRTimer() +: m_start(high_resolution_clock::now()) +{ +} +void restart() +{ +m_start = high_resolution_clock::now(); +} +//! gets the elapsed time since start in milliseconds. +double getElapsedTimeMs() const +{ +return 1.0*std::chrono::duration_cast(high_resolution_clock::now() - m_start).count()/(1000*1000); +} +}; // end class Timer +*/ diff --git a/source/src/tool/timer.h b/source/src/tool/timer.h new file mode 100755 index 0000000..03c0869 --- /dev/null +++ b/source/src/tool/timer.h @@ -0,0 +1,19 @@ +#ifndef INCLUDED_TIMER_H +#define INCLUDED_TIMER_H + +class Timer { +private: + struct Data; + Data* d; +public: + /*! default constructor starts immediately. */ + Timer(); + ~Timer(); + void restart(); + /*! gets the elapsed time since start in milliseconds. + */ + double getElapsedTimeMs() const; +}; // end class Timer + + +#endif \ No newline at end of file From 7ee6313ef7f48afdbc7d774f4029c5e5cb21b89e Mon Sep 17 00:00:00 2001 From: E Sommerlade Date: Mon, 25 Jan 2016 17:30:16 +0000 Subject: [PATCH 2/2] cmake based windows port -- vs issue fixes --- examples/SimpleOpenCV/deepbeliefopencv.cpp | 9 +++--- examples/SimpleOpenCV/deepbeliefopencv.h | 2 +- examples/SimpleOpenCV/main.cpp | 4 +-- source/src/lib/graph/graph.cpp | 2 +- source/src/lib/libjpcnn.cpp | 8 +++--- source/src/lib/math/matrix_max.cpp | 5 ++-- source/src/lib/utility/binary_format.cpp | 17 ++++++++++-- source/src/tool/main.cpp | 32 ++++++++++++---------- 8 files changed, 48 insertions(+), 31 deletions(-) diff --git a/examples/SimpleOpenCV/deepbeliefopencv.cpp b/examples/SimpleOpenCV/deepbeliefopencv.cpp index 569a9eb..cf1c63f 100644 --- a/examples/SimpleOpenCV/deepbeliefopencv.cpp +++ b/examples/SimpleOpenCV/deepbeliefopencv.cpp @@ -11,16 +11,17 @@ #include "deepbeliefopencv.h" #include +#include #include #include #include #include -#include "opencv2/core/utility.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/imgproc/types_c.h" -#include "opencv2/highgui/highgui_c.h" +#include +#include +#include +#include #include "libjpcnn.h" diff --git a/examples/SimpleOpenCV/deepbeliefopencv.h b/examples/SimpleOpenCV/deepbeliefopencv.h index e3902ec..08d8aef 100644 --- a/examples/SimpleOpenCV/deepbeliefopencv.h +++ b/examples/SimpleOpenCV/deepbeliefopencv.h @@ -13,7 +13,7 @@ #include -#include "opencv2/core/utility.hpp" +#include "opencv2/core/core.hpp" namespace DeepBelief { diff --git a/examples/SimpleOpenCV/main.cpp b/examples/SimpleOpenCV/main.cpp index e21ef77..2855fd3 100644 --- a/examples/SimpleOpenCV/main.cpp +++ b/examples/SimpleOpenCV/main.cpp @@ -1,5 +1,5 @@ -#include "opencv2/highgui.hpp" -#include "opencv2/core/utility.hpp" +#include +#include #include diff --git a/source/src/lib/graph/graph.cpp b/source/src/lib/graph/graph.cpp index 01daf58..a4763e2 100644 --- a/source/src/lib/graph/graph.cpp +++ b/source/src/lib/graph/graph.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +//#include #include "buffer.h" #include "binary_format.h" diff --git a/source/src/lib/libjpcnn.cpp b/source/src/lib/libjpcnn.cpp index fccf435..4e4dc94 100644 --- a/source/src/lib/libjpcnn.cpp +++ b/source/src/lib/libjpcnn.cpp @@ -11,7 +11,7 @@ #include "libjpcnn.h" #include -#include +//#include #include "buffer.h" #include "prepareinput.h" @@ -111,8 +111,8 @@ void* jpcnn_create_image_buffer_from_uint8_data(unsigned char* pixelData, int wi void jpcnn_classify_image(void* networkHandle, void* inputHandle, unsigned int flags, int layerOffset, float** outPredictionsValues, int* outPredictionsLength, char*** outPredictionsNames, int* outPredictionsNamesLength) { - const bool doMultiSample = (flags & JPCNN_MULTISAMPLE); - const bool doRandomSample = (flags & JPCNN_RANDOM_SAMPLE); + const bool doMultiSample = (flags & JPCNN_MULTISAMPLE) != 0; + const bool doRandomSample = (flags & JPCNN_RANDOM_SAMPLE) != 0; Graph* graph = (Graph*)(networkHandle); Buffer* input = (Buffer*)(inputHandle); @@ -231,7 +231,7 @@ float jpcnn_predict(void* predictorHandle, float* predictions, int predictionsLe svm_predict_probability(model, nodes, probabilityEstimates); const double predictionValue = probabilityEstimates[0]; destroy_node_list(nodes); - return predictionValue; + return (float)predictionValue; } diff --git a/source/src/lib/math/matrix_max.cpp b/source/src/lib/math/matrix_max.cpp index c66e157..c1bb38c 100644 --- a/source/src/lib/math/matrix_max.cpp +++ b/source/src/lib/math/matrix_max.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "buffer.h" @@ -72,9 +73,9 @@ Buffer* matrix_max_patch(Buffer* input, int patchWidth, int stride) { for (int outputChannel = 0; outputChannel < outputChannels; outputChannel += 1) { jpfloat_t patchMax = -FLT_MAX; for (int patchY = 0; patchY < patchWidth; patchY += 1) { - const int inputY = (int)fmin((inputHeight - 1), (inputOriginY + patchY)); + const int inputY = (int)std::min((inputHeight - 1), (inputOriginY + patchY)); for (int patchX = 0; patchX < patchWidth; patchX += 1) { - const int inputX = (int)fmin((inputWidth - 1), (inputOriginX + patchX)); + const int inputX = (int)std::min((inputWidth - 1), (inputOriginX + patchX)); const int inputOffset = inputDims.offset(imageIndex, inputY, inputX, outputChannel); const jpfloat_t inputValue = *(input->_data + inputOffset); patchMax = fmaxf(patchMax, inputValue); diff --git a/source/src/lib/utility/binary_format.cpp b/source/src/lib/utility/binary_format.cpp index 2652573..1398b24 100644 --- a/source/src/lib/utility/binary_format.cpp +++ b/source/src/lib/utility/binary_format.cpp @@ -11,7 +11,11 @@ #include #include #include + +#ifndef _WIN32 #include +#endif + #include #include @@ -22,14 +26,18 @@ SBinaryTag* read_tag_from_file(const char* filename, bool useMemoryMap) { return NULL; } + SBinaryTag* result; +#ifndef _WIN32 if (useMemoryMap) { const int fileHandle = open(filename, O_RDONLY); struct stat statBuffer; fstat(fileHandle, &statBuffer); const size_t bytesInFile = (size_t)(statBuffer.st_size); result = (SBinaryTag*)(mmap(NULL, bytesInFile, PROT_READ, MAP_SHARED, fileHandle, 0)); - } else { + } else +#endif + { FILE* file = fopen(filename, "rb"); if (file == NULL) { fprintf(stderr, "read_tag_from_file() - couldn't open '%s'\n", filename); @@ -53,12 +61,15 @@ SBinaryTag* read_tag_from_file(const char* filename, bool useMemoryMap) { } void deallocate_file_tag(SBinaryTag* fileTag, bool useMemoryMap) { - if (useMemoryMap) { +#ifndef _WIN32 + if ( useMemoryMap ) { // This assumes that there's only a single root tag in a binary file, so we can // calculate the file length based on the tag length. const size_t tagTotalBytes = get_total_sizeof_tag(fileTag); munmap(fileTag, tagTotalBytes); - } else { + } else +#endif + { free(fileTag); } } diff --git a/source/src/tool/main.cpp b/source/src/tool/main.cpp index 5f4408b..59846fa 100644 --- a/source/src/tool/main.cpp +++ b/source/src/tool/main.cpp @@ -7,7 +7,6 @@ // #include -#include #include #include #include @@ -15,11 +14,16 @@ #include #include #include +#ifndef _WIN32 #include +#endif #include #include "libjpcnn.h" +#include "timer.h" +#include + #define STATIC_ARRAY_LEN(x) (sizeof(x) / sizeof(x[0])) enum EToolMode {eSingleImage, eLibSvmTrain, eLibSvmTest, eLibSvmPredict}; @@ -148,7 +152,7 @@ void parse_command_line_args(int argc, const char* argv[], SToolArgumentValues* fprintf(stderr, "Unknown option '%s'\n", fullArg); print_usage_and_exit(argc, argv); } - const bool hasArgument = foundToolOption->hasArgument; + const bool hasArgument = foundToolOption->hasArgument!=0; const char* valueString; if (hasArgument) { if (argIndex == (argc - 1)) { @@ -215,7 +219,7 @@ void parse_command_line_args(int argc, const char* argv[], SToolArgumentValues* const int optionIntValue = atoi(optionStringValue); outValues->doTime = optionIntValue; } else if (strcmp("threshold", longName) == 0) { - const float optionFloatValue = atof(optionStringValue); + const float optionFloatValue = (float)atof(optionStringValue); outValues->threshold = optionFloatValue; } else if (strcmp("layer", longName) == 0) { const int optionIntValue = atoi(optionStringValue); @@ -262,7 +266,7 @@ void print_usage_and_exit(int argc, const char* argv[]) { void do_classify_image(void* network, const char* inputFilename, int doMultisample, int layerOffset, float** predictions, int* predictionsLength, char*** predictionsLabels, long* outDuration) { void* input = jpcnn_create_image_buffer_from_file(inputFilename); - if (input == NULL) { + if ( input == NULL ) { *predictions = NULL; *predictionsLength = 0; *predictionsLabels = NULL; @@ -270,19 +274,16 @@ void do_classify_image(void* network, const char* inputFilename, int doMultisamp } int predictionsLabelsLength; int actualPredictionsLength; - struct timeval start; - gettimeofday(&start, NULL); uint32_t flags = 0; - if (doMultisample) { + if ( doMultisample ) { flags = (flags | JPCNN_MULTISAMPLE); } - jpcnn_classify_image(network, input, flags, layerOffset, predictions, &actualPredictionsLength, predictionsLabels, &predictionsLabelsLength); - struct timeval end; - gettimeofday(&end, NULL); + { + Timer timer; + jpcnn_classify_image(network, input, flags, layerOffset, predictions, &actualPredictionsLength, predictionsLabels, &predictionsLabelsLength); + *outDuration = (long)timer.getElapsedTimeMs(); + } jpcnn_destroy_image_buffer(input); - long seconds = end.tv_sec - start.tv_sec; - long useconds = end.tv_usec - start.tv_usec; - *outDuration = ((seconds) * 1000 + useconds/1000.0) + 0.5; if (doMultisample) { for (int index = 0; index < actualPredictionsLength; index += 1) { const float predictionValue = (*predictions)[index]; @@ -426,11 +427,14 @@ void prediction_callback(void* cookie, float* predictions, int predictionsLength const size_t outPathLength = outputDirectoryNameLength + 1 + outnameLength; char* outPath = (char*)(malloc(outPathLength + 1)); snprintf(outPath, (outPathLength + 1), "%s/%s", outputDirectory, outname); - + + fprintf(stderr, "'%s' -> '%s' with error number %d\n", outPath, fullPath, errno); +#ifndef _WIN32 const int symlinkResult = symlink(fullPath, outPath); if (symlinkResult != 0) { fprintf(stderr, "symlink failed for '%s' -> '%s' with error number %d\n", outPath, fullPath, errno); } +#endif free(outPath); }