polaroid-pp

Schlieren and contour plot tool
git clone https://git.0xfab.ch/polaroid-pp.git
Log | Files | Refs | Submodules | README | LICENSE

commit 5807b7da0373d7158594a8917ca31b2a2a0153a9
parent 930300bb66eaf35a6a8a94b9202afe5a3769a86c
Author: Fabian Wermelinger <fabianw@mavt.ethz.ch>
Date:   Thu, 28 Apr 2016 12:23:34 +0200

added apps

Diffstat:
MMakefile | 25++++++++++++++++++-------
MMakefile.config | 8++++----
Aapps/OrganizerOMP.cpp | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps/OrganizerOMP.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps/polaroidCamera/Cartridges.h | 12++++++++++++
Aapps/polaroidCamera/NormalizerCartridge.h | 44++++++++++++++++++++++++++++++++++++++++++++
Aapps/polaroidCamera/TransmissionCartridge.h | 33+++++++++++++++++++++++++++++++++
Aapps/polaroidCamera/polaroidCameraMPI.cpp | 40++++++++++++++++++++++++++++++++++++++++
Ainclude/ArgumentParser.h | 375+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/Cartridge.h | 25+++++++++++++++++++++++++
Ainclude/PhotoFormats.h | 13+++++++++++++
Minclude/PhotoHDF5.h | 17++++++++++++++---
Ainclude/PhotoPNG.h | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/PhotoPaper.h | 4+++-
Minclude/Polaroid.h | 20+++++++++++++++-----
Minclude/Types.h | 13++++++-------
Minclude/common.h | 4++--
Msrc/PhotoHDF5.cpp | 54++++++++++++++++++++++++++++++++++++++----------------
Asrc/PhotoPNG.cpp | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Polaroid.cpp | 67+++++++++++++++++++++++++------------------------------------------
20 files changed, 938 insertions(+), 87 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,17 +1,30 @@ include ./Makefile.config -CC = mpic++ +CC = g++ HDR = $(wildcard src/*.h) SRC = $(wildcard src/*.cpp) OBJ = ${SRC:.cpp=.o} -polaroidCamera: Polaroid +INC += -Iapps/polaroidCamera +INC += -Iapps +APPSRC = $(wildcard apps/polaroidCamera/*.cpp) +APPSRC += $(wildcard apps/*.cpp) +APPPOBJ = ${APPSRC:.cpp=.o} -Polaroid: $(HDR) $(OBJ) third_party + +polaroidCamera: third_party Polaroid $(APPOBJ) + $(CC) $(CPPFLAGS) $(INC) -o bin/polaroidCamera $(APPSRC) $(LIB) -lpng -lPolaroid + +Polaroid: third_party $(HDR) $(OBJ) ar rcs lib/libPolaroid.a $(OBJ) +third_party: FORCE + $(MAKE) -C third_party all + +FORCE: + # schlierenCamera: all schlierenCamera.cpp # $(CC) $(CPPFLAGS) $(INC) -o schlierenCamera schlierenCamera.cpp $(OBJ) $(LIB) -lz -lpng -lhdf5 -lWaveletCompressor @@ -24,11 +37,9 @@ Polaroid: $(HDR) $(OBJ) third_party %.o: %.cpp g++ $(CPPFLAGS) $(INC) -c $< -o $@ -third_party: - (cd third_party; make all) - clean: find . -iname "*~" -exec rm -f {} \; rm -f $(OBJ) rm -f lib/libPolaroid.a - (cd third_party; make clean) + rm -f bin/polaroidCamera + $(MAKE) -C third_party clean diff --git a/Makefile.config b/Makefile.config @@ -1,12 +1,12 @@ config ?= release bs ?= 16 align ?= 16 -omp ?= 0 +omp ?= 1 hdf ?= 1 cubismz ?= 1 prec ?= float -INC = -Iinclude +INC = -Iinclude -Ithird_party/pngwriter-0.5.4 LIB = -Llib CFLAGS = @@ -18,7 +18,7 @@ ifeq "$(omp)" "1" endif ifeq "$(hdf)" "1" - INC += -I/opt/hdf5_openmpi/include + INC += -I/usr/local/include LIB += -lhdf5 CPPFLAGS += -D_USE_HDF_ endif @@ -30,7 +30,7 @@ ifeq "$(cubismz)" "1" endif ifeq "$(prec)" "float" - CPPFLAGS += -D_SP_ + CPPFLAGS += -D_FLOAT_PRECISION_ -D_SP_COMP_ endif ifneq "$(config)" "release" diff --git a/apps/OrganizerOMP.cpp b/apps/OrganizerOMP.cpp @@ -0,0 +1,60 @@ +// File : OrganizerOMP.cpp +// Date : Thu Apr 28 10:59:03 2016 +// Author : Fabian Wermelinger +// Description: OpenMP Organizer Implementation +// Copyright 2016 ETH Zurich. All Rights Reserved. +#include <string> +#include <iostream> +#include <cstdio> +#include <cstdlib> +#include "OrganizerOMP.h" + +using namespace std; + +OrganizerOMP::OrganizerOMP(const int argc, char ** const argv) : m_nscenes(0), m_scenes(nullptr), m_argc(1) +{ + // get scenes + bool bfoundScenes = false; + for (int i=1; i < argc; ++i) + { + const string key(argv[i]); + if (key == "-scenes") + { + m_scenes = (argv + (i+1)); + m_nscenes = argc - (i+1); + bfoundScenes = true; + break; + } + ++m_argc; + } + if (!bfoundScenes) + { + // Define input scenes (=input files) at the end of the argument list + // by using the option "-scenes". You can use globbing here if there + // are many scenes. + cerr << "ERROR: No input scenes given. Abort..." << endl; + cerr << " : (Note: -scenes must be the last argument, followed by [list of] input files)" << endl; + abort(); + } +} + +vector<char*> OrganizerOMP::split_work() const +{ + const int myID = tid(); + const int nthreads = size(); + const int myshare = m_nscenes/nthreads; + const int rem = m_nscenes - nthreads * myshare; + vector<char*> myscenes; + + for (int i=0; i < myshare; ++i) // try to distribute work equally + myscenes.push_back(m_scenes[i*nthreads + myID]); + + if (myID < rem) + myscenes.push_back(m_scenes[myshare*nthreads + myID]); + +#pragma omp critical + { + printf("[Thread %d/%d: Load = %d scene(s), start @ %s]\n", myID, nthreads, myscenes.size(), myscenes.front()); + } + return myscenes; +} diff --git a/apps/OrganizerOMP.h b/apps/OrganizerOMP.h @@ -0,0 +1,63 @@ +// File : OrganizerOMP.h +// Date : Thu Apr 28 09:53:58 2016 +// Author : Fabian Wermelinger +// Description: OpenMP Organizer +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef ORGANIZEROMP_H_8HFBYG90 +#define ORGANIZEROMP_H_8HFBYG90 + +#include <vector> +#ifdef _USE_OMP_ +#include <omp.h> +#endif /* _USE_OMP_ */ + + +class OrganizerOMP +{ +private: + int m_nscenes; + char** m_scenes; + int m_argc; + +public: + OrganizerOMP(const int argc, char ** const argv); + + static int max_size() + { +#ifdef _USE_OMP_ + return omp_get_max_threads(); +#else + return 1; +#endif /* _USE_OMP_ */ + } + + static void set_size(const int nthreads) + { +#ifdef _USE_OMP_ + return omp_set_num_threads(nthreads); +#endif /* _USE_OMP_ */ + } + + inline int size() const + { +#ifdef _USE_OMP_ + return omp_get_num_threads(); +#else + return 1; +#endif /* _USE_OMP_ */ + } + + inline int tid() const + { +#ifdef _USE_OMP_ + return omp_get_thread_num(); +#else + return 0; +#endif /* _USE_OMP_ */ + } + + std::vector<char*> split_work() const; + inline int argc() const { return m_argc; } +}; + +#endif /* ORGANIZEROMP_H_8HFBYG90 */ diff --git a/apps/polaroidCamera/Cartridges.h b/apps/polaroidCamera/Cartridges.h @@ -0,0 +1,12 @@ +// File : Cartridges.h +// Date : Wed Apr 27 21:37:25 2016 +// Author : Fabian Wermelinger +// Description: Cartridge Collection +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef CARTRIDGES_H_LTWKNANR +#define CARTRIDGES_H_LTWKNANR + +#include "TransmissionCartridge.h" +#include "NormalizerCartridge.h" + +#endif /* CARTRIDGES_H_LTWKNANR */ diff --git a/apps/polaroidCamera/NormalizerCartridge.h b/apps/polaroidCamera/NormalizerCartridge.h @@ -0,0 +1,44 @@ +// File : NormalizerCartridge.h +// Date : Thu Apr 28 09:32:20 2016 +// Author : Fabian Wermelinger +// Description: Data Normalization Cartridge +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef NORMALIZERCARTRIDGE_H_ONAUDSVX +#define NORMALIZERCARTRIDGE_H_ONAUDSVX + +#include "Cartridge.h" + +class NormalizerCartridge : public Cartridge +{ +public: + NormalizerCartridge(ArgumentParser& parser) : Cartridge(parser) {} + + virtual void capture(PhotoPaper& photo, Slice& data) + { + photo.resize(data.width(), data.height()); + + // set description + string desc("2D Normalized Slice Data"); + photo.set_description(desc.c_str()); + + // compute min/max + Real data_min = data(0,0); + Real data_max = data(0,0); + for (int h=0; h < data.height(); ++h) + for (int w=0; w < data.width(); ++w) + { + data_min = min(data_min, data(w,h)); + data_max = max(data_max, data(w,h)); + } + const Real data_normInv = 1.0 / (data_max - data_min); + + // compute pixel + for (int h=0; h < data.height(); ++h) + for (int w=0; w < data.width(); ++w) + photo.set_pixel(w, h, (data(w,h) - data_min) * data_normInv); + + photo.write(); + } +}; + +#endif /* NORMALIZERCARTRIDGE_H_ONAUDSVX */ diff --git a/apps/polaroidCamera/TransmissionCartridge.h b/apps/polaroidCamera/TransmissionCartridge.h @@ -0,0 +1,33 @@ +// File : TransmissionCartridge.h +// Date : Thu Apr 28 09:29:22 2016 +// Author : Fabian Wermelinger +// Description: Simple Data Transmission Cartridge +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef TRANSMISSIONCARTRIDGE_H_Z4VDKHDO +#define TRANSMISSIONCARTRIDGE_H_Z4VDKHDO + +#include "Cartridge.h" + +class TransmissionCartridge : public Cartridge +{ +public: + TransmissionCartridge(ArgumentParser& parser) : Cartridge(parser) {} + + virtual void capture(PhotoPaper& photo, Slice& data) + { + photo.resize(data.width(), data.height()); + + // set description + string desc("2D Slice Data Propagation"); + photo.set_description(desc.c_str()); + + // put pixel + for (int h=0; h < data.height(); ++h) + for (int w=0; w < data.width(); ++w) + photo.set_pixel(w, h, data(w,h)); + + photo.write(); + } +}; + +#endif /* TRANSMISSIONCARTRIDGE_H_Z4VDKHDO */ diff --git a/apps/polaroidCamera/polaroidCameraMPI.cpp b/apps/polaroidCamera/polaroidCameraMPI.cpp @@ -0,0 +1,40 @@ +// File : polaroidCameraMPI.cpp +// Date : Wed Apr 27 14:40:05 2016 +// Author : Fabian Wermelinger +// Description: Polaroid Cam app +// Copyright 2016 ETH Zurich. All Rights Reserved. +#include <iostream> +#include <vector> +#ifdef _USE_OMP_ +#include <omp.h> +#endif /* _USE_OMP_ */ + +#include "OrganizerOMP.h" +#include "ArgumentParser.h" +#include "Polaroid.h" +#include "Cartridges.h" +#include "PhotoFormats.h" + +using namespace std; + +int main(int argc, char* argv[]) +{ +#pragma omp parallel + { + OrganizerOMP threads(argc, argv); + + ArgumentParser myparser(threads.argc(), (const char**)argv); + myparser.print_args(); + + vector<char*> myscenes = threads.split_work(); + + Polaroid cam; + NormalizerCartridge transmission(myparser); + // PhotoHDF5 photo("hello"); + PNG_MONO photo("hello"); + cam.load_hdf5(myscenes[0], 0.5, 2, 0); + cam.capture(transmission, photo); + } + + return 0; +} diff --git a/include/ArgumentParser.h b/include/ArgumentParser.h @@ -0,0 +1,375 @@ +/* + * ArgumentParser.h + * Cubism + * + * This argument parser assumes that all arguments are optional ie, each of the argument names is preceded by a '-' + * all arguments are however NOT optional to avoid a mess with default values and returned values when not found! + * + * More converter could be required: + * add as needed + * TypeName as{TypeName}() in Value + * + * Created by Christian Conti on 6/7/10. + * Copyright 2010 ETH Zurich. All rights reserved. + * + */ + +#pragma once +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <map> +#include <vector> +#include <string> +#include <iostream> +#include <sstream> +#include <iomanip> +#include <fstream> +#include <limits> + + +using namespace std; + +class Value +{ +private: + string content; + +public: + + Value() : content("") {} + + Value(string content_) : content(content_) { /*printf("%s\n",content.c_str());*/ } + + double asDouble(double def=0) + { + if (content == "") + { + ostringstream sbuf; + sbuf << def; + content = sbuf.str(); + } + return (double) atof(content.c_str()); + } + + int asInt(int def=0) + { + if (content == "") + { + ostringstream sbuf; + sbuf << def; + content = sbuf.str(); + } + return atoi(content.c_str()); + } + + bool asBool(bool def=false) + { + if (content == "") + { + if (def) content = "true"; + else content = "false"; + } + if (content == "0") return false; + if (content == "false") return false; + + return true; + } + + string asString(string def="") + { + if (content == "") content = def; + + return content; + } +}; + +class CommandlineParser +{ +private: + const int iArgC; + const char** vArgV; + bool bStrictMode, bVerbose; + +protected: + map<string,Value> mapArguments; + +public: + + Value& operator()(const string arg) + { + if (bStrictMode) + { + map<string,Value>::const_iterator it = mapArguments.find(arg); + + if (it == mapArguments.end()) + { + printf("Runtime option NOT SPECIFIED! ABORTING! name: %s\n",arg.data()); + abort(); + } + } + + if (bVerbose) printf("%s is %s\n", arg.data(), mapArguments[arg].asString().data()); + return mapArguments[arg]; + } + + bool check(const string arg) const + { + return mapArguments.find(arg) != mapArguments.end(); + } + + CommandlineParser(const int argc, const char ** argv) : mapArguments(), iArgC(argc), vArgV(argv), bStrictMode(false), bVerbose(true) + { + for (int i=1; i<argc; i++) + if (argv[i][0] == '-') + { + string values = ""; + int itemCount = 0; + + for (int j=i+1; j<argc; j++) + if (argv[j][0] == '-') + break; + else + { + if (strcmp(values.c_str(), "")) + values += ' '; + + values += argv[j]; + itemCount++; + } + + if (itemCount == 0) + values = "true"; + + mapArguments[argv[i]] = Value(values); + i += itemCount; + } + + mute(); + //printf("found %ld arguments of %d\n",mapArguments.size(),argc); + } + + int getargc() const { return iArgC; } + + const char** getargv() const { return vArgV; } + + void set_strict_mode() + { + bStrictMode = true; + } + + void unset_strict_mode() + { + bStrictMode = false; + } + + void mute() + { + bVerbose = false; + } + + void loud() + { + bVerbose = true; + } + + void save_options(string path=".") + { + string options; + for(map<string,Value>::iterator it=mapArguments.begin(); it!=mapArguments.end(); it++) + { + options+= it->first + " " + it->second.asString() + " "; + } + string filepath = (path + "/" + string("argumentparser.log")); + FILE * f = fopen(filepath.data(), "a"); + if (f == NULL) + { + printf("impossible to write %s.\n", filepath.data()); + return; + } + fprintf(f, "%s\n", options.data()); + fclose(f); + } + + void print_args() + { + for(map<string,Value>::iterator it=mapArguments.begin(); it!=mapArguments.end(); it++) + { + std::cout.width(50); + std::cout.fill('.'); + std::cout << std::left << it->first; + std::cout << ": " << it->second.asString() << std::endl; + } + } +}; + + +class ArgumentParser: public CommandlineParser +{ + typedef std::map<std::string, Value> ArgMap; + typedef std::map<std::string, Value*> pArgMap; + typedef std::map<std::string, ArgMap* > FileMap; + + // keep a reference form option origin + ArgMap from_commandline; + FileMap from_files; + pArgMap from_code; + + // helper + void _ignoreComments(std::ifstream& stream, const char commentChar = '#') + { + stream >> std::ws; + int nextchar = stream.peek(); + while (nextchar == commentChar) + { + stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); + stream >> std::ws; + nextchar = stream.peek(); + } + } + + bool _existKey(std::string& key) const + { + const std::string og_key = key; + bool bExist = true; + + // look for both possible keys (i.e. with leading "-" and without) + ArgMap::const_iterator it = mapArguments.find(key); + if (it == mapArguments.end()) + { + if (key[0] == '-') key = key.erase(0, 1); + else key = "-" + key; + it = mapArguments.find(key); + if (it == mapArguments.end()) + { + key = og_key; + bExist = false; + } + } + return bExist; + } + + inline std::string _stripKey(std::string key) const + { + if (key[0] == '-') key = key.erase(0, 1); + return key; + } + + +public: + ArgumentParser(const int _argc, const char ** _argv): + CommandlineParser(_argc, _argv) { from_commandline = mapArguments; } + + virtual ~ArgumentParser() + { + for (FileMap::iterator it = from_files.begin(); it != from_files.end(); it++) + delete it->second; + } + + void readFile(const std::string filepath) + { + from_files[filepath] = new ArgMap; + ArgMap& myFMap = *(from_files[filepath]); + + std::ifstream confFile(filepath.c_str()); + if (confFile.is_open()) + { + // read (key value) pairs from input file, ignore comments + // beginning with "#" + std::string key, val; + while (!confFile.eof()) + { + _ignoreComments(confFile); + confFile >> key >> val; + if (_existKey(key)) continue; + std::pair<string, Value> item(key, Value(val)); + mapArguments.insert(item); // add to parent container + myFMap.insert(item); // add to private container + } + } + } + + Value& operator()(std::string key) + { + const bool bDefaultInCode = !_existKey(key); + Value& retval = CommandlineParser::operator()(key); + if (bDefaultInCode) from_code[key] = &retval; + return retval; + } + + inline bool check(std::string key) const { return _existKey(key); } + inline bool exist(std::string key) const { return _existKey(key); } + + void print_args() + { + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + std::cout << "* Summary:" << std::endl; + std::cout << "* Parameter read from command line: " << from_commandline.size() << std::endl; + size_t nFiles = 0; + size_t nFileParameter = 0; + for (FileMap::const_iterator it=from_files.begin(); it!=from_files.end(); ++it) + { + if (it->second->size() > 0) + { + ++nFiles; + nFileParameter += it->second->size(); + } + } + std::cout << "* Parameter read from " << std::setw(3) << std::right << nFiles << " file(s): " << nFileParameter << std::endl; + std::cout << "* Parameter read from defaults in code: " << from_code.size() << std::endl; + std::cout << "* Total number of parameter read from all sources: " << mapArguments.size() << std::endl; + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + + // command line given arguments + if (!from_commandline.empty()) + { + std::cout << "* Command Line:" << std::endl; + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + for(ArgMap::iterator it=from_commandline.begin(); it!=from_commandline.end(); it++) + { + std::cout.width(50); + std::cout.fill('.'); + std::cout << std::left << _stripKey(it->first); + std::cout << ": " << it->second.asString() << std::endl; + } + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + } + + // options read from input files + if (!from_files.empty()) + { + for (FileMap::iterator itFile=from_files.begin(); itFile!=from_files.end(); itFile++) + { + if (!itFile->second->empty()) + { + std::cout << "* File: " << itFile->first << std::endl; + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + ArgMap& fileArgs = *(itFile->second); + for(ArgMap::iterator it=fileArgs.begin(); it!=fileArgs.end(); it++) + { + std::cout.width(50); + std::cout.fill('.'); + std::cout << std::left << _stripKey(it->first); + std::cout << ": " << it->second.asString() << std::endl; + } + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + } + } + } + + // defaults defined in code + if (!from_code.empty()) + { + std::cout << "* Defined in Code:" << std::endl; + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + for(pArgMap::iterator it=from_code.begin(); it!=from_code.end(); it++) + { + std::cout.width(50); + std::cout.fill('.'); + std::cout << std::left << _stripKey(it->first); + std::cout << ": " << it->second->asString() << std::endl; + } + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; + } + } +}; diff --git a/include/Cartridge.h b/include/Cartridge.h @@ -0,0 +1,25 @@ +// File : Cartridge.h +// Date : Wed Apr 27 21:17:10 2016 +// Author : Fabian Wermelinger +// Description: Simple Transmission Cartridge Module for Polaroid Camera +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef CARTRIDGE_H_IRUVKOCT +#define CARTRIDGE_H_IRUVKOCT + +#include "ArgumentParser.h" +#include "Types.h" +#include "PhotoPaper.h" + +class Cartridge +{ +protected: + ArgumentParser& m_parser; + +public: + Cartridge(ArgumentParser& parser) : m_parser(parser) {} + virtual ~Cartridge() {} + + virtual void capture(PhotoPaper& photo, Slice& data) = 0; +}; + +#endif /* CARTRIDGE_H_IRUVKOCT */ diff --git a/include/PhotoFormats.h b/include/PhotoFormats.h @@ -0,0 +1,13 @@ +// File : PhotoFormats.h +// Date : Wed Apr 27 21:39:13 2016 +// Author : Fabian Wermelinger +// Description: Photo Format Collection +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef PHOTOFORMATS_H_3IWQHPAU +#define PHOTOFORMATS_H_3IWQHPAU + +#include "PhotoPaper.h" +#include "PhotoHDF5.h" +#include "PhotoPNG.h" + +#endif /* PHOTOFORMATS_H_3IWQHPAU */ diff --git a/include/PhotoHDF5.h b/include/PhotoHDF5.h @@ -6,10 +6,12 @@ #ifndef PHOTOHDF5_H_VN6WHSEO #define PHOTOHDF5_H_VN6WHSEO +#ifdef _USE_HDF_ #include <hdf5.h> #include <string> #include "common.h" +#include "Polaroid.h" #include "PhotoPaper.h" class PhotoHDF5 : public PhotoPaper @@ -28,22 +30,31 @@ private: hsize_t m_hdf5_offset[4]; // helper + void _open_hdf_file(); + void _close_hdf_file(); void _dump_xmf() const; public: PhotoHDF5(const std::string filename="hdf5", const Real t=0) : PhotoPaper(0,0), m_fname(filename), m_description("data"), m_open(false), m_hdfraw(nullptr), m_time(t) {} + PhotoHDF5(const Polaroid& cam, const std::string filename="hdf5", const Real t=0) : PhotoPaper(0,0), m_fname(filename), m_description("data"), m_open(false), m_hdfraw(nullptr), m_time(t) + { + resize(cam.width(), cam.height()); + } PhotoHDF5(const int width, const int height, const std::string filename="hdf5", const Real t=0) : PhotoPaper(0,0), m_fname(filename), m_description("data"), m_open(false), m_hdfraw(nullptr), m_time(t) { - make_new(width,height); + resize(width,height); } - ~PhotoHDF5() { if (m_hdfraw) delete [] m_hdfraw; } + virtual ~PhotoHDF5() { if (m_hdfraw) delete [] m_hdfraw; } - virtual void make_new(const int width, const int height); + virtual void make_new(const std::string name, const int width, const int height); + virtual void resize(const int width, const int height); virtual void write(); virtual void set_pixel(const int x, const int y, const double phi); virtual std::string suffix() const { return std::string(".h5"); } virtual void set_description(const char* const desc) { m_description = std::string(desc); } inline void set_time(const Real t) { m_time = t; } + inline void set_filename(const std::string new_name) { m_fname = new_name; } }; +#endif /* _USE_HDF_ */ #endif /* PHOTOHDF5_H_VN6WHSEO */ diff --git a/include/PhotoPNG.h b/include/PhotoPNG.h @@ -0,0 +1,95 @@ +// File : PhotoPNG.h +// Date : Tue Apr 26 14:46:18 2016 +// Author : Fabian Wermelinger +// Description: PNG Photos +// Copyright 2016 ETH Zurich. All Rights Reserved. +#ifndef PHOTOPNG_H_7DZT9TLW +#define PHOTOPNG_H_7DZT9TLW + +#include "Polaroid.h" +#include "PhotoPaper.h" +#include "pngwriter.h" + +class PNG_HSV : public PhotoPaper +{ +protected: + std::string m_fname; + std::string m_description; + bool m_open; + pngwriter* m_png; + double m_saturation, m_value, m_background; + std::string m_title, m_author, m_software; + + // helper + inline void _default_info() + { + m_title = "Portable Network Graphics"; + m_author = "Walt Disney"; + m_software = "Polaroid++"; + } + inline void _dispose() { delete m_png; m_png=nullptr; } + +public: + + PNG_HSV(const std::string filename="hsv", const double saturation=1.0, const double value=1.0, const double bg=1.0) : + PhotoPaper(0,0), m_fname(filename), m_description("PNG HSV colorscheme"), m_open(false), m_png(nullptr), + m_saturation(saturation), m_value(value), m_background(bg) + { + _default_info(); + } + PNG_HSV(const Polaroid& cam, const std::string filename="hsv", const double saturation=1.0, const double value=1.0, const double bg=1.0) : + PhotoPaper(0,0), m_fname(filename), m_description("PNG HSV colorscheme"), m_open(false), m_png(nullptr), + m_saturation(saturation), m_value(value), m_background(bg) + { + _default_info(); + resize(cam.width(), cam.height()); + } + PNG_HSV(const int width, const int height, const std::string filename="hsv", const double saturation=1.0, const double value=1.0, const double bg=1.0) : + PhotoPaper(0,0), m_fname(filename), m_description("PNG HSV colorscheme"), m_open(false), m_png(nullptr), + m_saturation(saturation), m_value(value), m_background(bg) + { + _default_info(); + resize(width, height); + } + + virtual ~PNG_HSV() + { + if (m_open) + { + m_png->close(); + _dispose(); + } + } + + virtual void make_new(const std::string name, const int width, const int height); + virtual void resize(const int width, const int height); + virtual void write(); + virtual void set_pixel(const int x, const int y, const double phi); + virtual std::string suffix() const { return std::string(".png"); } + virtual void set_description(const char* const desc) { m_description = desc; } +}; + +class PNG_MONO : public PNG_HSV +{ +public: + PNG_MONO(const std::string filename="mono") : PNG_HSV(filename) { } + PNG_MONO(const Polaroid& cam, const std::string filename="mono") : PNG_HSV(cam, filename) { } + PNG_MONO(const int width, const int height, const std::string filename="mono") : PNG_HSV(width, height, filename) { } + + virtual void set_pixel(const int x, const int y, const double phi); +}; + +class PNG_RGB : public PNG_HSV +{ + PNG_RGB(const std::string filename="rgb") : PNG_HSV(filename) { } + PNG_RGB(const Polaroid& cam, const std::string filename="rgb") : PNG_HSV(cam, filename) { } + PNG_RGB(const int width, const int height, const std::string filename="rgb") : PNG_HSV(width, height, filename) { } + + inline void set_pixel(const int x, const int y, const double R, const double G, const double B) + { + if (m_open) + m_png->plot(x+1, y+1, R, G, B); + } +}; + +#endif /* PHOTOPNG_H_7DZT9TLW */ diff --git a/include/PhotoPaper.h b/include/PhotoPaper.h @@ -6,6 +6,7 @@ #ifndef PHOTOPAPER_H_B0K8P9TO #define PHOTOPAPER_H_B0K8P9TO +#include <string> #include "Types.h" class PhotoPaper @@ -17,7 +18,8 @@ public: PhotoPaper(const int width, const int height) : m_width(width), m_height(height) {}; virtual ~PhotoPaper() {}; - virtual void make_new(const int width, const int height) = 0; + virtual void make_new(const std::string name, const int width, const int height) = 0; + virtual void resize(const int width, const int height) = 0; virtual void write() = 0; virtual void set_pixel(const int x, const int y, const double phi) = 0; virtual std::string suffix() const = 0; diff --git a/include/Polaroid.h b/include/Polaroid.h @@ -7,26 +7,36 @@ #define POLAROID_H_HXFL9YPG #include "Types.h" -#include "PhotoPaper.h" +#include "Cartridge.h" + +class PhotoPaper; class Polaroid { protected: - Slice2D<0,0,-2,2> m_data; + Slice m_data; // Cartridge inserted? bool m_loaded; public: Polaroid() : m_loaded(false) { } + virtual ~Polaroid() {} - // data loader + // scene loader virtual void load_hdf5(const char* filename, const double fraction, const int dir, const int channel=0); virtual void load_wavelet(const char* filename, const double fraction, const int dir, const int channel=0, const bool doswapping=false, const int wtype=1); - // capture image + // capture scene inline bool check_scene() const { return m_loaded; } - virtual void capture(PhotoPaper* const paper); + inline void capture(Cartridge& cartridge, PhotoPaper& photo) + { + if (m_loaded) + cartridge.capture(photo, m_data); + } + + inline int width() const { return m_data.width(); } + inline int height() const { return m_data.height(); } }; #endif /* POLAROID_H_HXFL9YPG */ diff --git a/include/Types.h b/include/Types.h @@ -8,23 +8,18 @@ #include <cassert> #include "common.h" -// #ifdef _USE_OMP_ -// #include <omp.h> -// #endif /* _USE_OMP_ */ - template <int _SX, int _EX, int _SY, int _EY> class Slice2D { int m_width, m_height, m_N; - Real * const m_data; + Real* m_data; public: Slice2D() : m_width(0), m_height(0), m_N(0), m_data(nullptr) {} Slice2D(const int width, const int height) : m_width(width), m_height(height), m_N((width+_EX-_SX)*(height+_EY-_SY)) { m_data = new Real[m_N]; -#pragma omp parallel for for (int i = 0; i < m_N; ++i) m_data[i] = 0.0; } @@ -53,12 +48,16 @@ public: m_N = (width+_EX-_SX)*(height+_EY-_SY); if (m_data) delete [] m_data; m_data = new Real[m_N]; -#pragma omp parallel for for (int i = 0; i < m_N; ++i) m_data[i] = 0.0; } + inline int width() const { return m_width; } inline int height() const { return m_height; } + // inline Real* const data() { return m_data; } + // inline const Real* const data() const { return m_data; } }; +typedef Slice2D<0,0,-2,2> Slice; + #endif /* TYPES_H_QATFIWCK */ diff --git a/include/common.h b/include/common.h @@ -6,14 +6,14 @@ #ifndef COMMON_H_13EQ6YAI #define COMMON_H_13EQ6YAI -#ifdef _SP_ +#ifdef _FLOAT_PRECISION_ typedef float Real; #else typedef double Real; #endif #ifdef _USE_HDF_ -#ifdef _SP_ +#ifdef _FLOAT_PRECISION_ #define HDF_PRECISION H5T_NATIVE_FLOAT #else #define HDF_PRECISION H5T_NATIVE_DOUBLE diff --git a/src/PhotoHDF5.cpp b/src/PhotoHDF5.cpp @@ -3,10 +3,32 @@ // Author : Fabian Wermelinger // Description: HDF5 Photo Implementation // Copyright 2016 ETH Zurich. All Rights Reserved. +#ifdef _USE_HDF_ #include <cassert> #include <cstdio> #include "PhotoHDF5.h" +void PhotoHDF5::_open_hdf_file() +{ + hsize_t tmp[4] = { 1, static_cast<hsize_t>(m_height), static_cast<hsize_t>(m_width), 1 }; + for (int i = 0; i < 4; ++i) + { + m_hdf5_count[i] = tmp[i]; + m_hdf5_dims[i] = tmp[i]; + m_hdf5_offset[i]= 0; + } + H5open(); + hid_t fapl_id = H5Pcreate(H5P_FILE_ACCESS); + m_hdf5_fileid = H5Fcreate((m_fname+this->suffix()).c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + H5Pclose(fapl_id); +} + +void PhotoHDF5::_close_hdf_file() +{ + H5Fclose(m_hdf5_fileid); + H5close(); +} + void PhotoHDF5::_dump_xmf() const { FILE *xmf = 0; @@ -37,29 +59,29 @@ void PhotoHDF5::_dump_xmf() const fclose(xmf); } -void PhotoHDF5::make_new(const int width, const int height) +void PhotoHDF5::make_new(const string name, const int width, const int height) +{ + m_fname = name; + resize(width, height); +} + +void PhotoHDF5::resize(const int width, const int height) { - if (m_hdfraw) delete [] m_hdfraw; + if (m_open) + { + _close_hdf_file(); + if (m_hdfraw) delete [] m_hdfraw; + } m_hdfraw = new Real[width*height]; m_width = width; m_height= height; - hsize_t tmp[4] = { 1, static_cast<hsize_t>(height), static_cast<hsize_t>(width), 1 }; - for (int i = 0; i < 4; ++i) - { - m_hdf5_count[i] = tmp[i]; - m_hdf5_dims[i] = tmp[i]; - m_hdf5_offset[i]= 0; - } - - H5open(); - hid_t fapl_id = H5Pcreate(H5P_FILE_ACCESS); - m_hdf5_fileid = H5Fcreate((m_fname+".h5").c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); - H5Pclose(fapl_id); + _open_hdf_file(); m_open = true; } + void PhotoHDF5::write() { if (m_open) @@ -77,8 +99,7 @@ void PhotoHDF5::write() H5Dclose(dataset_id); H5Pclose(fapl_id); - H5Fclose(m_hdf5_fileid); - H5close(); + _close_hdf_file(); _dump_xmf(); @@ -97,3 +118,4 @@ void PhotoHDF5::set_pixel(const int ix, const int iy, const double phi) m_hdfraw[iy*m_width + ix] = static_cast<Real>(phi); } } +#endif /* _USE_HDF_ */ diff --git a/src/PhotoPNG.cpp b/src/PhotoPNG.cpp @@ -0,0 +1,53 @@ +// File : PhotoPNG.cpp +// Date : Wed Apr 27 22:46:32 2016 +// Author : Fabian Wermelinger +// Description: PNG Photos implementation +// Copyright 2016 ETH Zurich. All Rights Reserved. +#include "PhotoPNG.h" + +void PNG_HSV::make_new(const string name, const int width, const int height) +{ + m_fname = name; + resize(width, height); +} + +void PNG_HSV::resize(const int width, const int height) +{ + if (m_open) + { + m_png->close(); + _dispose(); + } + m_png = new pngwriter(width, height, m_background, (m_fname+this->suffix()).c_str()); + + m_width = width; + m_height = height; + m_open = true; +} + +void PNG_HSV::write() +{ + if (m_open) + { + m_png->settext(m_title.c_str(), m_author.c_str(), m_description.c_str(), m_software.c_str()); + m_png->write_png(); + m_png->close(); + _dispose(); + m_open = false; + } +} + +void PNG_HSV::set_pixel(const int x, const int y, const double phi) +{ + if (m_open) + { + const double hue = 2./3. * (1.0 - phi); + m_png->plotHSV(x+1, y+1, hue, m_saturation, m_value); + } +} + +void PNG_MONO::set_pixel(const int x, const int y, const double phi) +{ + if (m_open) + m_png->plot(x+1, y+1, phi, phi, phi); +} diff --git a/src/Polaroid.cpp b/src/Polaroid.cpp @@ -57,31 +57,25 @@ void Polaroid::load_hdf5(const char* filename, const double fraction, const int if (0 == dir) // y-z plane { const int fixed = static_cast<int>(maxDim[0]*fraction); - width = maxDim[1]; - height = maxDim[2]; - m_data.resize(width, height); - for (int h=0; h < height; ++h) - for (int w=0; w < width; ++w) + m_data.resize(maxDim[1], maxDim[2]); + for (int h=0; h < m_data.height(); ++h) + for (int w=0; w < m_data.width(); ++w) m_data(w,h) = data[channel + NCH * ID3(fixed,w,h,maxDim[0], maxDim[1])]; } else if (1 == dir) // x-z plane { const int fixed = static_cast<int>(maxDim[1]*fraction); - width = maxDim[0]; - height = maxDim[2]; - m_data.resize(width, height); - for (int h=0; h < height; ++h) - for (int w=0; w < width; ++w) + m_data.resize(maxDim[0], maxDim[2]); + for (int h=0; h < m_data.height(); ++h) + for (int w=0; w < m_data.width(); ++w) m_data(w,h) = data[channel + NCH * ID3(w,fixed,h,maxDim[0], maxDim[1])]; } else if (2 == dir) // x-y plane { const int fixed = static_cast<int>(maxDim[2]*fraction); - width = maxDim[0]; - height = maxDim[1]; - m_data.resize(width, height); - for (int h=0; h < height; ++h) - for (int w=0; w < width; ++w) + m_data.resize(maxDim[0], maxDim[1]); + for (int h=0; h < m_data.height(); ++h) + for (int w=0; w < m_data.width(); ++w) m_data(w,h) = data[channel + NCH * ID3(w,h,fixed,maxDim[0], maxDim[1])]; } else @@ -109,15 +103,13 @@ void Polaroid::load_wavelet(const char* filename, const double fraction, const i const int NBZ = myreader.zblocks(); const int maxDim[3] = {NBX*_BLOCKSIZE_, NBY*_BLOCKSIZE_, NBZ*_BLOCKSIZE_}; - static Real blockdata[_BLOCKSIZE_][_BLOCKSIZE_][_BLOCKSIZE_]; + Real blockdata[_BLOCKSIZE_][_BLOCKSIZE_][_BLOCKSIZE_]; /* extract plane */ if (0 == dir) // y-z plane { const int fixed = static_cast<int>(maxDim[0]*fraction); - width = maxDim[1]; - height = maxDim[2]; - m_data.resize(width, height); + m_data.resize(maxDim[1], maxDim[2]); const int fixedBID = fixed/_BLOCKSIZE_; const int BlocalID = fixed % _BLOCKSIZE_; @@ -127,15 +119,17 @@ void Polaroid::load_wavelet(const char* filename, const double fraction, const i const double zratio = myreader.load_block2(fixedBID, iy, iz, blockdata); for (int z=0; z < _BLOCKSIZE_; ++z) for (int y=0; y < _BLOCKSIZE_; ++y) + { + assert(iy*_BLOCKSIZE_+y < m_data.width()); + assert(iz*_BLOCKSIZE_+z < m_data.height()); m_data(iy*_BLOCKSIZE_+y, iz*_BLOCKSIZE_+z) = blockdata[z][y][BlocalID]; + } } } else if (1 == dir) // x-z plane { const int fixed = static_cast<int>(maxDim[1]*fraction); - width = maxDim[0]; - height = maxDim[2]; - m_data.resize(width, height); + m_data.resize(maxDim[0], maxDim[2]); const int fixedBID = fixed/_BLOCKSIZE_; const int BlocalID = fixed % _BLOCKSIZE_; @@ -145,15 +139,17 @@ void Polaroid::load_wavelet(const char* filename, const double fraction, const i const double zratio = myreader.load_block2(ix, fixedBID, iz, blockdata); for (int z=0; z < _BLOCKSIZE_; ++z) for (int x=0; x < _BLOCKSIZE_; ++x) + { + assert(ix*_BLOCKSIZE_+x < m_data.width()); + assert(iz*_BLOCKSIZE_+z < m_data.height()); m_data(ix*_BLOCKSIZE_+x, iz*_BLOCKSIZE_+z) = blockdata[z][BlocalID][x]; + } } } else if (2 == dir) // x-y plane { const int fixed = static_cast<int>(maxDim[2]*fraction); - width = maxDim[0]; - height = maxDim[1]; - m_data.resize(width, height); + m_data.resize(maxDim[0], maxDim[1]); const int fixedBID = fixed/_BLOCKSIZE_; const int BlocalID = fixed % _BLOCKSIZE_; @@ -163,7 +159,11 @@ void Polaroid::load_wavelet(const char* filename, const double fraction, const i const double zratio = myreader.load_block2(ix, iy, fixedBID, blockdata); for (int y=0; y < _BLOCKSIZE_; ++y) for (int x=0; x < _BLOCKSIZE_; ++x) + { + assert(ix*_BLOCKSIZE_+x < m_data.width()); + assert(iy*_BLOCKSIZE_+y < m_data.height()); m_data(ix*_BLOCKSIZE_+x, iy*_BLOCKSIZE_+y) = blockdata[BlocalID][y][x]; + } } } else @@ -177,20 +177,3 @@ void Polaroid::load_wavelet(const char* filename, const double fraction, const i fprintf(stderr, "WARNING: Executable was compiled without wavelet compressor support...\n"); #endif /* _USE_CUBISMZ_ */ } - -void Polaroid::capture(PhotoPaper* const paper) -{ - if (m_loaded) - { - paper->make_new(m_data.width(), m_data.height()); - - // set description - string desc("2D Slice Data"); - paper->set_description(desc.c_str()); - - // put pixel - for (int h=0; h < m_data.height(); ++h) - for (int w=0; w < m_data.width(); ++w) - paper->set_pixel(w, h, m_data(w,h)); - } -}