From f792af5803d613f42e7480f5e637c38125c99dfd Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Thu, 17 Nov 2011 23:51:43 +0100 Subject: [PATCH] using new output mechanism, and using boost program options --- Attractor.hpp | 3 - AwesomeAttract0r.xcodeproj/project.pbxproj | 66 ++++--- Canvas.cpp | 3 - Canvas.hpp | 209 +++++++++++++++++++-- Image.hpp | 15 ++ ImageFormatBMP.hpp | 159 ++++++++++++++++ ImageFormatPNG.hpp | 103 ++++++++++ Logger.hpp | 139 ++++++++++++++ Projector.hpp | 29 +-- Tonemapper.hpp | 69 +++++++ array.hpp | 23 +++ batch.sh | 2 +- canvae/PNG.hpp | 168 ----------------- canvae/Raw.cpp | 65 ------- canvae/Raw.hpp | 28 --- canvae/bmp.hpp | 88 --------- canvae/libpng.hpp | 88 --------- main.cpp | 191 ++++++++----------- 18 files changed, 826 insertions(+), 622 deletions(-) delete mode 100644 Canvas.cpp create mode 100644 Image.hpp create mode 100644 ImageFormatBMP.hpp create mode 100644 ImageFormatPNG.hpp create mode 100644 Tonemapper.hpp create mode 100644 array.hpp delete mode 100644 canvae/PNG.hpp delete mode 100644 canvae/Raw.cpp delete mode 100644 canvae/Raw.hpp delete mode 100644 canvae/bmp.hpp delete mode 100644 canvae/libpng.hpp diff --git a/Attractor.hpp b/Attractor.hpp index 73ef7ae..a7efd83 100644 --- a/Attractor.hpp +++ b/Attractor.hpp @@ -49,9 +49,6 @@ public: void iterate() { (*kernel)(); - } - - void plot() { projector->plot(kernel->vector()); } diff --git a/AwesomeAttract0r.xcodeproj/project.pbxproj b/AwesomeAttract0r.xcodeproj/project.pbxproj index 6af455c..b37f340 100644 --- a/AwesomeAttract0r.xcodeproj/project.pbxproj +++ b/AwesomeAttract0r.xcodeproj/project.pbxproj @@ -8,14 +8,13 @@ /* Begin PBXBuildFile section */ 01C5701213B63AF0009D151B /* Projector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5700713B63AF0009D151B /* Projector.cpp */; }; - 01C5701313B63AF0009D151B /* Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5700D13B63AF0009D151B /* Canvas.cpp */; }; 01C5701413B63AF0009D151B /* AttractorKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5700F13B63AF0009D151B /* AttractorKernel.cpp */; }; 01C5701513B63AF0009D151B /* Attractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5701113B63AF0009D151B /* Attractor.cpp */; }; - 01C5702913B63B56009D151B /* Raw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5702813B63B56009D151B /* Raw.cpp */; }; 01C5703213B63B78009D151B /* stf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5703113B63B78009D151B /* stf.cpp */; }; 01C5704313B63BBE009D151B /* Projection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5704013B63BBE009D151B /* Projection.cpp */; }; 01C5704413B63BBE009D151B /* Normalizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C5704213B63BBE009D151B /* Normalizer.cpp */; }; 01C5707E13B63CF9009D151B /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 01C5707D13B63CF9009D151B /* libpng.a */; }; + 427057AE147571FC00CBE978 /* libboost_program_options.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 427057AD147571FC00CBE978 /* libboost_program_options.a */; }; 8DD76F650486A84900D96B5E /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.cpp */; settings = {ATTRIBUTES = (); }; }; /* End PBXBuildFile section */ @@ -39,16 +38,11 @@ 01C5700913B63AF0009D151B /* myMath.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = myMath.hpp; sourceTree = ""; }; 01C5700A13B63AF0009D151B /* Logger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Logger.hpp; sourceTree = ""; }; 01C5700B13B63AF0009D151B /* defines.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = defines.hpp; sourceTree = ""; }; - 01C5700C13B63AF0009D151B /* Canvas.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Canvas.hpp; sourceTree = ""; }; - 01C5700D13B63AF0009D151B /* Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Canvas.cpp; sourceTree = ""; }; 01C5700E13B63AF0009D151B /* AwesomeAttractorConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AwesomeAttractorConfig.h; sourceTree = ""; }; 01C5700F13B63AF0009D151B /* AttractorKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttractorKernel.cpp; sourceTree = ""; }; 01C5701013B63AF0009D151B /* Attractor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Attractor.hpp; sourceTree = ""; }; 01C5701113B63AF0009D151B /* Attractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Attractor.cpp; sourceTree = ""; }; 01C5701613B63AF0009D151B /* AwesomeAttract0r */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = AwesomeAttract0r; sourceTree = BUILT_PRODUCTS_DIR; }; - 01C5702613B63B56009D151B /* PNG.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = PNG.hpp; path = canvae/PNG.hpp; sourceTree = ""; }; - 01C5702713B63B56009D151B /* Raw.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Raw.hpp; path = canvae/Raw.hpp; sourceTree = ""; }; - 01C5702813B63B56009D151B /* Raw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Raw.cpp; path = canvae/Raw.cpp; sourceTree = ""; }; 01C5703013B63B78009D151B /* stf.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = stf.hpp; path = stfu/stf.hpp; sourceTree = ""; }; 01C5703113B63B78009D151B /* stf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stf.cpp; path = stfu/stf.cpp; sourceTree = ""; }; 01C5703913B63BA3009D151B /* Unravel3D.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Unravel3D.hpp; path = kernels/Unravel3D.hpp; sourceTree = ""; }; @@ -63,8 +57,13 @@ 01C5704213B63BBE009D151B /* Normalizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Normalizer.cpp; path = projectors/Normalizer.cpp; sourceTree = ""; }; 01C5707D13B63CF9009D151B /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = /usr/local/lib/libpng.a; sourceTree = ""; }; 08FB7796FE84155DC02AAC07 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; - 420486591455B11C0025CC53 /* libpng.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = libpng.hpp; path = canvae/libpng.hpp; sourceTree = ""; }; - 42D2E10F1455D88C00FBC16A /* bmp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = bmp.hpp; path = canvae/bmp.hpp; sourceTree = ""; }; + 427057A61475637B00CBE978 /* Canvas.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Canvas.hpp; sourceTree = ""; }; + 427057A71475637B00CBE978 /* Image.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Image.hpp; sourceTree = ""; }; + 427057A81475637B00CBE978 /* ImageFormatBMP.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ImageFormatBMP.hpp; sourceTree = ""; }; + 427057A91475637B00CBE978 /* ImageFormatPNG.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ImageFormatPNG.hpp; sourceTree = ""; }; + 427057AB1475637B00CBE978 /* Tonemapper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Tonemapper.hpp; sourceTree = ""; }; + 427057AC1475654E00CBE978 /* array.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = array.hpp; sourceTree = ""; }; + 427057AD147571FC00CBE978 /* libboost_program_options.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libboost_program_options.a; path = ../../../../../usr/local/lib/libboost_program_options.a; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,6 +72,7 @@ buildActionMask = 2147483647; files = ( 01C5707E13B63CF9009D151B /* libpng.a in Frameworks */, + 427057AE147571FC00CBE978 /* libboost_program_options.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -88,7 +88,7 @@ name = stf; sourceTree = ""; }; - 01C5709D13B63E3A009D151B /* Attractors */ = { + 01C5709D13B63E3A009D151B /* Kernels */ = { isa = PBXGroup; children = ( 01C5700513B63AF0009D151B /* AttractorKernel.hpp */, @@ -100,21 +100,17 @@ 01C5703D13B63BA3009D151B /* Logistic.hpp */, 01C5703E13B63BA3009D151B /* Ikeda3D.hpp */, ); - name = Attractors; + name = Kernels; sourceTree = ""; }; 08FB7794FE84155DC02AAC07 /* AwesomeAttract0r */ = { isa = PBXGroup; children = ( - 420486591455B11C0025CC53 /* libpng.hpp */, - 01C5703F13B63BBE009D151B /* Projection.hpp */, - 01C5704013B63BBE009D151B /* Projection.cpp */, - 01C5704113B63BBE009D151B /* Normalizer.hpp */, - 01C5704213B63BBE009D151B /* Normalizer.cpp */, 08FB7795FE84155DC02AAC07 /* Source */, C6859E8C029090F304C91782 /* Documentation */, 1AB674ADFE9D54B511CA2CBB /* Products */, 01C5707D13B63CF9009D151B /* libpng.a */, + 427057AD147571FC00CBE978 /* libboost_program_options.a */, ); name = AwesomeAttract0r; sourceTree = ""; @@ -122,20 +118,19 @@ 08FB7795FE84155DC02AAC07 /* Source */ = { isa = PBXGroup; children = ( - 01C5709D13B63E3A009D151B /* Attractors */, + 427057AC1475654E00CBE978 /* array.hpp */, + 427057A61475637B00CBE978 /* Canvas.hpp */, + 427057A71475637B00CBE978 /* Image.hpp */, + 427057A81475637B00CBE978 /* ImageFormatBMP.hpp */, + 427057A91475637B00CBE978 /* ImageFormatPNG.hpp */, + 427057AB1475637B00CBE978 /* Tonemapper.hpp */, + 427057A5147562DB00CBE978 /* Projectors */, + 01C5709D13B63E3A009D151B /* Kernels */, 01C5709C13B63E2F009D151B /* stf */, - 01C5702613B63B56009D151B /* PNG.hpp */, - 42D2E10F1455D88C00FBC16A /* bmp.hpp */, - 01C5702713B63B56009D151B /* Raw.hpp */, - 01C5702813B63B56009D151B /* Raw.cpp */, - 01C5700613B63AF0009D151B /* Projector.hpp */, - 01C5700713B63AF0009D151B /* Projector.cpp */, 01C5700813B63AF0009D151B /* ostream_helpers.h */, 01C5700913B63AF0009D151B /* myMath.hpp */, 01C5700A13B63AF0009D151B /* Logger.hpp */, 01C5700B13B63AF0009D151B /* defines.hpp */, - 01C5700C13B63AF0009D151B /* Canvas.hpp */, - 01C5700D13B63AF0009D151B /* Canvas.cpp */, 01C5700E13B63AF0009D151B /* AwesomeAttractorConfig.h */, 01C5701013B63AF0009D151B /* Attractor.hpp */, 01C5701113B63AF0009D151B /* Attractor.cpp */, @@ -152,6 +147,19 @@ name = Products; sourceTree = ""; }; + 427057A5147562DB00CBE978 /* Projectors */ = { + isa = PBXGroup; + children = ( + 01C5700613B63AF0009D151B /* Projector.hpp */, + 01C5700713B63AF0009D151B /* Projector.cpp */, + 01C5703F13B63BBE009D151B /* Projection.hpp */, + 01C5704013B63BBE009D151B /* Projection.cpp */, + 01C5704113B63BBE009D151B /* Normalizer.hpp */, + 01C5704213B63BBE009D151B /* Normalizer.cpp */, + ); + name = Projectors; + sourceTree = ""; + }; C6859E8C029090F304C91782 /* Documentation */ = { isa = PBXGroup; children = ( @@ -211,10 +219,8 @@ files = ( 8DD76F650486A84900D96B5E /* main.cpp in Sources */, 01C5701213B63AF0009D151B /* Projector.cpp in Sources */, - 01C5701313B63AF0009D151B /* Canvas.cpp in Sources */, 01C5701413B63AF0009D151B /* AttractorKernel.cpp in Sources */, 01C5701513B63AF0009D151B /* Attractor.cpp in Sources */, - 01C5702913B63B56009D151B /* Raw.cpp in Sources */, 01C5703213B63B78009D151B /* stf.cpp in Sources */, 01C5704313B63BBE009D151B /* Projection.cpp in Sources */, 01C5704413B63BBE009D151B /* Normalizer.cpp in Sources */, @@ -233,7 +239,7 @@ GCC_DEBUGGING_SYMBOLS = full; GCC_FAST_MATH = YES; GCC_OPTIMIZATION_LEVEL = 3; - HEADER_SEARCH_PATHS = "/usr/local/include//**"; + HEADER_SEARCH_PATHS = /usr/local/include; LIBRARY_SEARCH_PATHS = "/usr/local/lib//**"; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; @@ -241,7 +247,6 @@ WARNING_CFLAGS = ( "-Wall", "-Wextra", - "-Weffc++", ); }; name = "Release with Symbols"; @@ -280,7 +285,7 @@ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; - HEADER_SEARCH_PATHS = "/usr/local/include//**"; + HEADER_SEARCH_PATHS = /usr/local/include; LIBRARY_SEARCH_PATHS = "/usr/local/lib//**"; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; @@ -288,7 +293,6 @@ WARNING_CFLAGS = ( "-Wall", "-Wextra", - "-Weffc++", ); }; name = Debug; diff --git a/Canvas.cpp b/Canvas.cpp deleted file mode 100644 index cf5f742..0000000 --- a/Canvas.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "Canvas.hpp" - -// lol diff --git a/Canvas.hpp b/Canvas.hpp index c854006..8fa16e8 100644 --- a/Canvas.hpp +++ b/Canvas.hpp @@ -1,22 +1,201 @@ -#ifndef CANVAS_HPP -#define CANVAS_HPP +// +// Canvas.hpp +// AwesomeAttractorND +// +// Created by Joshua Moerman on 10/28/11. +// Copyright 2011 Vadovas. All rights reserved. +// +/* + Interface (or Concept) Canvas: + Canvas canvas(width, height, ...); Constructs a Canvas with given dimensions + canvas[x][y]...[z] Returns a (const) reference to an element + canvas.plot(position) Plots on the canvas (where position is normalized, ie in the unit-cube) + canvas.size() gives width/size for the given dimension N. + canvas.begin() .end() gives iterators to the elements (directly) + */ -class Canvas { -protected: +#ifndef AwesomeAttractorND_Canvas_hpp +#define AwesomeAttractorND_Canvas_hpp - unsigned int dimension; - Canvas(const unsigned int dimension) : dimension(dimension) {}; +#include +#include +#include "array.hpp" -public: - - unsigned int getDimension() const { return dimension; }; +class Canvas2D { + typedef unsigned int value_type; + typedef std::vector Row; + typedef std::vector Storage; - virtual ~Canvas() {}; - - virtual void clear() = 0; - virtual void plot(const double* normalizedPosition, const double* normalizedColor) = 0; - virtual void output_file(cstd::string const & filename) const = 0; +public: + Canvas2D(size_t width, size_t height) + : storage(width, Storage::value_type(height, 0)) + {} + + Row & operator[](size_t r){ + return storage[r]; + } + + Row const & operator[](size_t r) const { + return storage[r]; + } + + void plot(double const * const position){ + const size_t width = size<0>(); + const size_t height = size<1>(); + + const size_t c = 0.5*position[0]*width + width*.5; + const size_t r = 0.5*position[1]*width + height*.5; + + if(c < width && r < height) { + storage[r][c]++; + } + } + + size_t size() const { + return size<0>() * size<1>(); + } + + template + size_t size() const { + if ( N == 0 ) return storage.size(); + if ( N == 1 ) return storage.front().size(); + return 0; + } + + struct iterator; + iterator begin(){ + return iterator(this); + } + iterator end(){ + return iterator(this, 0, size<1>()); + }; + + struct const_iterator; + const_iterator begin() const { + return const_iterator(this); + } + + const_iterator end() const { + return const_iterator(this, 0, size<1>()); + } + + const_iterator cbegin() const { + return const_iterator(this); + } + + const_iterator cend() const { + return const_iterator(this, 0, size<1>()); + } + + struct iterator : public std::iterator { + iterator(iterator const & rh) + : canvas(rh.canvas) + , c(rh.c) + , r(rh.r) + {} + + iterator & operator++(){ + ++c; + if (c >= canvas->size<0>()) { + c = 0; + ++r; + } + return *this; + } + + iterator operator++(int){ + iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(iterator const & rh) const { + return canvas == rh.canvas && c == rh.c && r == rh.r; + } + + bool operator!=(iterator const & rh) const { + return canvas != rh.canvas || c != rh.c || r != rh.r; + } + + value_type & operator*(){ + return (*canvas)[r][c]; + } + + value_type & operator->(){ + return (*canvas)[r][c]; + } + + private: + friend class Canvas2D; + iterator(Canvas2D * canvas, size_t c = 0, size_t r = 0) + : canvas(canvas) + , c(c) + , r(r) + {} + + iterator(); + + Canvas2D * canvas; + size_t c; + size_t r; + }; + + struct const_iterator : public std::iterator { + const_iterator(const_iterator const & rh) + : canvas(rh.canvas) + , c(rh.c) + , r(rh.r) + {} + + const_iterator & operator++(){ + ++c; + if (c >= canvas->size<0>()) { + c = 0; + ++r; + } + return *this; + } + + const_iterator operator++(int){ + const_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const_iterator const & rh) const { + return canvas == rh.canvas && c == rh.c && r == rh.r; + } + + bool operator!=(const_iterator const & rh) const { + return canvas != rh.canvas || c != rh.c || r != rh.r; + } + + value_type const & operator*() const { + return (*canvas)[r][c]; + } + + value_type const & operator->() const { + return (*canvas)[r][c]; + } + + private: + friend class Canvas2D; + const_iterator(Canvas2D const * canvas, size_t c = 0, size_t r = 0) + : canvas(canvas) + , c(c) + , r(r) + {} + + const_iterator(); + + Canvas2D const * canvas; + size_t c; + size_t r; + }; + +private: + Storage storage; }; -#endif // CANVAS_HPP +#endif diff --git a/Image.hpp b/Image.hpp new file mode 100644 index 0000000..e837571 --- /dev/null +++ b/Image.hpp @@ -0,0 +1,15 @@ +// +// Image.hpp +// AwesomeAttractorND +// +// Created by Joshua Moerman on 11/2/11. +// Copyright 2011 Vadovas. All rights reserved. +// + +#ifndef AwesomeAttractorND_Image_hpp +#define AwesomeAttractorND_Image_hpp + +#include "ImageFormatBMP.hpp" +#include "ImageFormatPNG.hpp" + +#endif diff --git a/ImageFormatBMP.hpp b/ImageFormatBMP.hpp new file mode 100644 index 0000000..7df45c7 --- /dev/null +++ b/ImageFormatBMP.hpp @@ -0,0 +1,159 @@ +// +// ImageFormatBMP.hpp +// AwesomeAttractorND +// +// Created by Joshua Moerman on 11/12/11. +// Copyright 2011 Vadovas. All rights reserved. +// + +#ifndef AwesomeAttractorND_ImageFormatBMP_hpp +#define AwesomeAttractorND_ImageFormatBMP_hpp + +#include +#include +#include +#include + +namespace ImageFormats { + namespace bmp { + struct pixelBGR{ + pixelBGR(double red, double green, double blue) + : blue(clamp(255*blue)) + , green(clamp(255*green)) + , red(clamp(255*red)) + {} + + pixelBGR(int red, int green, int blue) + : blue(clamp(blue)) + , green(clamp(green)) + , red(clamp(red)) + {} + + void swapRB(){ + std::swap(red, blue); + } + + private: + uint8_t clamp(int n){ + return std::min(255, std::max(0, n)); + } + + uint8_t blue; + uint8_t green; + uint8_t red; + }; + + struct bitmap_file_header { + uint32_t filesize; + uint16_t creator1; + uint16_t creator2; + uint32_t bmp_offset; + + template + bitmap_file_header(DIBT dib_header): + filesize(dib_header.bytes() + dib_header.header_sz + 12 + 2), + creator1(0), + creator2(0), + bmp_offset(dib_header.header_sz + 12 + 2){} + + void write(std::ostream& out) const { + out << "BM"; + out.write(reinterpret_cast(this), 12); + } + }; + + struct bitmapcoreheader { + uint32_t header_sz; + uint16_t width; + uint16_t height; + uint16_t nplanes; + uint16_t bitspp; + + bitmapcoreheader(uint16_t width, uint16_t height, uint16_t bitspp = 24): + header_sz(sizeof(bitmapcoreheader)), + width(width), + height(height), + nplanes(1), + bitspp(bitspp){} + + void write(std::ostream& out) const { + out.write(reinterpret_cast(this), header_sz); + } + + uint32_t bytes(){ + return width*height*bitspp/8; + } + }; + + template + struct bitmap { + typedef P pixel; + + bitmap(uint16_t width, uint16_t height) + : dib_header(width, height, sizeof(pixel)*8) + , header(dib_header) + , data(0) {} + + void write(std::string const & filename){ + std::ofstream file(filename.c_str()); + write(file); + } + + void write(std::ostream& out){ + header.write(out); + dib_header.write(out); + //std::copy_n((char const *)data, dib_header.bytes(), std::ostream_iterator(out)); + std::copy((char const *)data, (char const *)data + dib_header.bytes(), std::ostream_iterator(out)); + } + + private: + DIBT dib_header; + bitmap_file_header header; + P const * data; + }; + + template + struct bitmap_stream { + typedef P pixel; + + bitmap_stream(uint16_t width, uint16_t height, std::string filename) + : dib_header(width, height, sizeof(pixel)*8) + , header(dib_header) + , file(filename.c_str()) + , x(0) + , y(0) + { + if(!file) + throw std::runtime_error("bitmap file could not be opened."); + header.write(file); + dib_header.write(file); + } + + bitmap_stream& operator<<(pixel const & p){ + if (y >= dib_header.height){ + throw std::out_of_range("Writing BMP image out of bounds."); + } + + pixel p2(p); + p2.swapRB(); + file.write((char const *)&p2, sizeof(pixel)); + ++x; + if (x >= dib_header.width){ + x = 0; + ++y; + } + return *this; + } + + private: + DIBT dib_header; + bitmap_file_header header; + std::ofstream file; + + uint16_t x; + uint16_t y; + }; + } +} + +#endif diff --git a/ImageFormatPNG.hpp b/ImageFormatPNG.hpp new file mode 100644 index 0000000..1e06487 --- /dev/null +++ b/ImageFormatPNG.hpp @@ -0,0 +1,103 @@ +// +// ImageFormatPNG.hpp +// AwesomeAttractorND +// +// Created by Joshua Moerman on 11/12/11. +// Copyright 2011 Vadovas. All rights reserved. +// + +#ifndef AwesomeAttractorND_ImageFormatPNG_hpp +#define AwesomeAttractorND_ImageFormatPNG_hpp + +#include +#include +#include + +namespace ImageFormats { + namespace png{ + struct pixelRGB { + pixelRGB() + : red(0) + , green(0) + , blue(0) + {} + + pixelRGB(double red, double green, double blue) + : red(clamp(255*red)) + , green(clamp(255*green)) + , blue(clamp(255*blue)) + {} + + pixelRGB(int red, int green, int blue) + : red(clamp(red)) + , green(clamp(green)) + , blue(clamp(blue)) + {} + + private: + uint8_t clamp(int n){ + return std::min(255, std::max(0, n)); + } + + uint8_t red; + uint8_t green; + uint8_t blue; + }; + + struct png_stream{ + typedef pixelRGB pixel; + + png_stream(uint32_t width, uint32_t height, std::string filename) + : fp(0) + , png_ptr(0) + , info_ptr(0) + , row(width) + , x(0) + { + fp = fopen(filename.c_str(), "wb"); + if(!fp) throw std::runtime_error("Could not open file"); + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if(!png_ptr) throw std::runtime_error("PNG structure could not be allocated"); + + info_ptr = png_create_info_struct(png_ptr); + if(!info_ptr) throw std::runtime_error("PNG information structure could not be allocated"); + + png_init_io(png_ptr, fp); + + png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_set_compression_level(png_ptr, 9); + + png_write_info(png_ptr, info_ptr); + } + + ~png_stream(){ + png_write_end(png_ptr, info_ptr); + png_destroy_info_struct(png_ptr, &info_ptr); + fclose(fp); + } + + png_stream& operator<<(pixel const & p){ + row[x] = p; + ++x; + if(x >= row.size()){ + png_write_row(png_ptr, reinterpret_cast(row.data())); + x = 0; + } + + return *this; + } + + private: + FILE* fp; + png_structp png_ptr; + png_infop info_ptr; + + std::vector row; + uint32_t x; + }; + } +} + +#endif diff --git a/Logger.hpp b/Logger.hpp index d2cf192..4f9d4da 100644 --- a/Logger.hpp +++ b/Logger.hpp @@ -2,6 +2,11 @@ #define LOGGER_HPP_INCLUDED #include +#include +#include +#include +#include +#include extern int verbose; @@ -17,6 +22,140 @@ extern int verbose; #define LogError(s, ...) \ if ( verbose >= 0 ) { printf("%s, %s(), %d: ", __FILE__, __func__, __LINE__); printf(s, ##__VA_ARGS__); } +/* + Imported from Astrant: + Questions/Suggestions mail nick@astrant.net + */ + +struct Logger { + Logger(std::ostream& logging_stream_, std::string prefix_ = std::string("")) + : logging_stream(&logging_stream_) + , prefix(prefix_) + {} + + void log(std::string what){ + *logging_stream << get_prefix() << "(" << what << ") took place at (" << boost::posix_time::microsec_clock::local_time() << std::endl; + } + + void start(std::string what){ + Event e; + e.start = boost::posix_time::microsec_clock::local_time(); + e.name = what; + + EventMap::iterator it = event_map.find(what); + if(it != event_map.end()){ + *logging_stream << get_prefix() << "WARNING: Overwriting event(" << e.name << "), did you forget to call stop()?"; + } else { + event_name_stack.push(what); + } + + event_map.insert(it, std::make_pair(what, e)); + } + + void stop() { + assert(!event_name_stack.empty()); + stop(event_name_stack.top()); + } + +private: + void stop(std::string what){ + EventMap::iterator it = event_map.find(what); + if(it == event_map.end()){ + *logging_stream << get_prefix() << "WARNING: No such, or already stopped, event(" << what << "), did you forget to call start()?"; + } else { + it->second.end = boost::posix_time::microsec_clock::local_time(); + log_event(it->second); + event_map.erase(it); + } + + event_name_stack.pop(); + } + + struct Event { + boost::posix_time::ptime start; + boost::posix_time::ptime end; + std::string name; + }; + + // A map containing strings -> Event, used by start() and stop() + typedef std::map EventMap; + EventMap event_map; + + // A stack used by 0-parameter stop() to stop the last start()ed event. + std::stack event_name_stack; + + std::ostream* logging_stream; + + std::string prefix; + + void log_event(Event const& e){ + *logging_stream << get_prefix() << "Event(" << e.name << ") started at (" << e.start << ") ended at (" << e.end << ") duration (" << e.end - e.start << " ms) " << std::endl; + } + + std::string get_prefix() const { + if(prefix == std::string("")){ + return prefix; + } else { + return prefix + ": "; + } + } +}; + +/* + My progressbar class (as seen on github) + */ + +struct Progressbar { + Progressbar(std::ostream & out, std::string prefix = "", std::string begin = "", std::string end = "") + : out(out) + , begin(begin) + , prefix(prefix) + , end(end) + { + if (begin != "") { + out << begin << std::endl; + } + + show(0, 1, ' '); + } + + ~Progressbar(){ + show(1, 1, '='); + + if (end != "") { + out << "\n" << end << std::endl; + } else { + out << std::endl; + } + } + + template + void show(T const & progress, T const & max, char delim = '>'){ + out << "\r"; + + size_t width = 80; // default terminal size :D + width -= prefix.size(); + width -= 3; // [, > and ] + + if (prefix != "") { + width -= 1; + out << prefix << ' '; + } + + double ratio = (double) progress / (double) max; + size_t length = width * ratio; + + std::string fill(length, '='); + std::string empty(width - length, ' '); + out << '[' << fill << delim << empty << ']' << std::flush; + } + +private: + std::ostream & out; + std::string begin; + std::string prefix; + std::string end; +}; #endif // LOGGER_HPP_INCLUDED diff --git a/Projector.hpp b/Projector.hpp index 4af3693..c8daebf 100644 --- a/Projector.hpp +++ b/Projector.hpp @@ -9,13 +9,13 @@ class Projector { public: - // SHOULD NOT BE HERE - Canvas* canvas; - - Projector(unsigned int inputDimension, unsigned int outputDimension) : - canvas(0), projector(0), projectedPoint(0), projectedColor(0), - inputDimension(inputDimension), outputDimension(outputDimension), - ready(true) { + Projector(unsigned int inputDimension, unsigned int outputDimension) + : projectedPoint(0) + , projectedColor(0) + , inputDimension(inputDimension) + , outputDimension(outputDimension) + , ready(true) + { try { allocate(); } catch(std::exception& e) { @@ -32,26 +32,15 @@ public: void plot(const double* point) { project(point); - - if(ready) { - if(canvas != NULL) { - canvas->plot(projectedPoint, projectedColor); - } - - /*if(projector != NULL) { - projector->plot(projectedPoint, projectedColor); - }*/ - } } static Projector* createProjector(stfu::node& projector, unsigned int input_dimension); -protected: - Projector* projector; - +public: double* projectedPoint; double* projectedColor; +protected: unsigned int inputDimension; unsigned int outputDimension; diff --git a/Tonemapper.hpp b/Tonemapper.hpp new file mode 100644 index 0000000..5dcde94 --- /dev/null +++ b/Tonemapper.hpp @@ -0,0 +1,69 @@ +// +// Tonemapper.hpp +// AwesomeAttractorND +// +// Created by Joshua Moerman on 10/28/11. +// Copyright 2011 Vadovas. All rights reserved. +// + +#ifndef AwesomeAttractorND_Tonemapper_hpp +#define AwesomeAttractorND_Tonemapper_hpp + +#include +#include +#include + +namespace Tonemappers { + + struct Normalizer { + Normalizer() + : max(0) + {} + + template + void analyse(C const & canvas){ + max = *std::max_element(canvas.begin(), canvas.end()); + } + + template + void process(C const & canvas, I & image){ + for (typename C::const_iterator it = canvas.begin(); it != canvas.end(); ++it) { + const double grayscale = get_value(*it); + image << typename I::pixel(grayscale, grayscale, grayscale); + } + } + + protected: + double get_value(unsigned int n){ + return (double) n / (double) max; + } + unsigned int max; + }; + + struct GammaCorrector : public Normalizer { + template + void analyse(C const & canvas){ + Normalizer::analyse(canvas); + const unsigned int sum = std::accumulate(canvas.begin(), canvas.end(), 0); + const double average = sum / (double) canvas.size(); + power = -2.5/std::log(average/max); + } + + template + void process(C const & canvas, I & image){ + for (typename C::const_iterator it = canvas.begin(); it != canvas.end(); ++it) { + const double grayscale = get_value(*it); + image << typename I::pixel(grayscale, grayscale, grayscale); + } + } + + protected: + double get_value(unsigned int n){ + return std::pow(Normalizer::get_value(n), power); + } + double power; + }; + +} + +#endif diff --git a/array.hpp b/array.hpp new file mode 100644 index 0000000..98ec13e --- /dev/null +++ b/array.hpp @@ -0,0 +1,23 @@ +// +// array.hpp +// AwesomeAttractorND +// +// Created by Joshua Moerman on 11/2/11. +// Copyright 2011 Vadovas. All rights reserved. +// + +#ifndef AwesomeAttractorND_array_hpp +#define AwesomeAttractorND_array_hpp + +// workaround to easily work in xcode :D + +#ifndef __APPLE__ +#include +#else +#include +namespace std { + using tr1::array; +} +#endif + +#endif diff --git a/batch.sh b/batch.sh index dff384b..fe6c7bf 100755 --- a/batch.sh +++ b/batch.sh @@ -1,2 +1,2 @@ #!/bin/bash -while true; do ~/Library/Developer/Xcode/DerivedData/AwesomeAttract0r-akxvgtneyociakezlpkfgaywuvoo/Build/Products/Debug/AwesomeAttract0r -P /Users/joshua/Documents/Code/AwesomeAttractor/render/ -R -I 20 -W 640 -H 640 -v attractors/emptyUnravel3D.stf; done +while true; do ./build/Debug/AwesomeAttract0r -P /Users/joshua/Documents/Code/AwesomeAttractor/render/ -R -I 20 -W 640 -H 640 -v -f attractors/emptyUnravel3D.stf; done diff --git a/canvae/PNG.hpp b/canvae/PNG.hpp deleted file mode 100644 index 4634c8b..0000000 --- a/canvae/PNG.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef PNG_HPP -#define PNG_HPP - -#include -#include -#include -#include - -#ifndef __APPLE__ - #include -#else - #include - namespace std { - using tr1::array; - } -#endif - -#include "libpng.hpp" - -#include "../Canvas.hpp" - -class PNG : public Canvas { - unsigned int width; - unsigned int height; - unsigned int num_colors; - - unsigned int* int_array; - //std::shared_ptr> int_array; - -public: - - double v; - - PNG(unsigned int width, unsigned int height, unsigned int num_colors = 1) - : Canvas(2) - , width(width) - , height(height) - , num_colors(num_colors) - , int_array(0) - , v(2.0) { - - //int_array = std::make_shared>(width*height*num_colors); - int_array = new unsigned int[width*height*num_colors]; - LogInfo("PNG::PNG(): width: %d, height: %d, colors: %d\n", width, height, num_colors); - - assert(int_array != 0); - - clear(); - - LogDebug("New Canvas\n"); - } - - virtual void clear() { - std::fill_n(int_array, width*height*num_colors, 0); - } - - virtual void plot(const double* normalizedPosition, const double* normalizedColor) { - const double& x = normalizedPosition[0]; - const double& y = normalizedPosition[1]; - - const unsigned int x_int = x*width + width*.5; - const unsigned int y_int = y*width + height*.5; - const unsigned int index = x_int + width * y_int; - - if(x_int < width && y_int < height) { - if(normalizedColor[0] > 0.0){ - int_array[index]++; - } else { - int_array[index + width*height]++; - } - } - } - - virtual void output_file(std::string const & filename_in) const { - std::string filename = filename_in; - filename += ".png"; - unsigned int* max_int = new unsigned int[num_colors]; - double* power = new double[num_colors]; - - for(unsigned int i = 0; i < num_colors; ++i) { - max_int[i] = 0; - double cumulative = 0; - unsigned int n = 0; - - for(unsigned int j = 0; j < width*height; j++) { - if(max_int[i] < int_array[j+i*width*height]) { - max_int[i] = int_array[j+i*width*height]; - } - if(int_array[j+i* width* height] != 0) { - cumulative += int_array[j+i*width*height]; - n++; - } - } - - - const double average = cumulative / (double)(width*height); - power[i] = -2.5/std::log(average/(double)max_int[i]); - if(power[i] < 0) { - power[i] = 1; - LogError("negative power\n"); - } - - if(n < width) { - LogInfo("not enough data in dimension %d\n", i); - return; - } - } - - const double vibrancy = v; - - // TODO: find a way to set these things: - // pngFile->setcompressionlevel(9); - // pngFile->settext("Attractor", "Joshua Moerman", "A awesome attractor", "AwesomeAttractor"); - - png::image< png::rgb_pixel > image(width, height); - std::array power_matrix = {{ - 1.0, 1.5, - 2.0, 2.5, - 3.0, 1.5 - }}; - std::array output_matrix = {{ - 2.0, 2.0, - 2.0, 1.5, - 2.0, 2.0 - }}; - - for(unsigned int x = 0; x < width; x++) { - for(unsigned int y = 0; y < height; y++) { - double r = 0.0; - double g = 0.0; - double b = 0.0; - double average_norm_value = 0.0; - for(unsigned int c = 0; c < num_colors; ++c){ - average_norm_value += (double)int_array[x + y*width + c*width*height]/max_int[c]; - } - average_norm_value /= (double) num_colors; - for(unsigned int c = 0; c < num_colors; c++) { - double norm_value = (double)int_array[x + y*width + c*width*height]/max_int[c]; - norm_value = vibrancy*norm_value + (1.0 - vibrancy) * average_norm_value; - norm_value = std::max(0.0, norm_value); - r += (std::pow(norm_value, power[c]*power_matrix[c+0]))*output_matrix[c+0]; - g += (std::pow(norm_value, power[c]*power_matrix[c+2]))*output_matrix[c+2]; - b += (std::pow(norm_value, power[c]*power_matrix[c+4]))*output_matrix[c+4]; - } - - r = std::max(0.0, std::min(1.0, r)); - b = std::max(0.0, std::min(1.0, b)); - g = std::max(0.0, std::min(1.0, g)); - image[y][x] = png::rgb_pixel(r*255, g*255, b*255); - } - } - - delete[] max_int; - delete[] power; - - LogInfo("Writing %s\n", filename.c_str()); - image.write(filename); - - LogMoreInfo("File written"); - } - -private: - PNG(PNG const &); - PNG & operator=(PNG const &); -}; - -#endif // PNG_HPP - diff --git a/canvae/Raw.cpp b/canvae/Raw.cpp deleted file mode 100644 index 999ac5d..0000000 --- a/canvae/Raw.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "../Logger.hpp" -#include -#include -#include -#include -#include -#include -#include - -#include "Raw.hpp" - - -Raw::Raw(const unsigned int dimension, const unsigned int* sizes_) - : Canvas(dimension) - , sizes(0) - , sizesMultiplied(0) - , pixelArray(0) - , arraySize(1) - { - - sizes = new unsigned int[dimension]; - assert(sizes != NULL); - std::copy(sizes_, sizes_ + dimension, sizes); - - sizesMultiplied = new unsigned int[dimension]; - assert(sizesMultiplied != NULL); - sizesMultiplied[0] = 1; - for(unsigned int i = 1; i < dimension; ++i) { - sizesMultiplied[i] = sizesMultiplied[i-1]*sizes[i-1]; - } - - for(unsigned int i = 0; i < dimension; ++i) { - arraySize *= sizes[i]; - } - pixelArray = new unsigned int[arraySize]; - assert(pixelArray != NULL); - - clear(); - - LogDebug("New RawCanvas of dimension %d\n", dimension); -} - -void Raw::clear() { - std::fill_n(pixelArray, arraySize, 0); -} - -void Raw::plot(const double* position) { - unsigned int index = 0; - for(unsigned int i = 0; i < dimension; ++i) { - index += (unsigned int)(position[i]*sizes[i] + 0.5*sizes[i])*sizesMultiplied[i]; - } - - if(index < arraySize) { - pixelArray[index]++; - } -} - -/* - I/O functions -*/ - -void Raw::output_file(const char* filename) const { - std::ofstream outfile(filename, std::ofstream::binary); - outfile.write(reinterpret_cast(pixelArray), sizeof(unsigned int)*arraySize); -} diff --git a/canvae/Raw.hpp b/canvae/Raw.hpp deleted file mode 100644 index ed2b4bf..0000000 --- a/canvae/Raw.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RAW_HPP -#define RAW_HPP - -#include "../Canvas.hpp" - -class Raw : public Canvas { - unsigned int* sizes; - unsigned int* sizesMultiplied; - unsigned int* pixelArray; - unsigned int arraySize; - -public: - - Raw(const unsigned int dimension, const unsigned int* sizes); - - virtual void clear(); - virtual void plot(const double* normalizedPosition); - virtual void output_file(const char* filename) const; - -private: - Raw(Raw const &); - Raw & operator=(Raw const &); -}; - - - -#endif // RAW_HPP - diff --git a/canvae/bmp.hpp b/canvae/bmp.hpp deleted file mode 100644 index a4a4615..0000000 --- a/canvae/bmp.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// bmp.hpp -// AwesomeAttract0r -// -// Created by Joshua Moerman on 10/24/11. -// Copyright 2011 Vadovas. All rights reserved. -// - -#ifndef AwesomeAttract0r_bmp_hpp -#define AwesomeAttract0r_bmp_hpp - -#include -#include -#include -#include - -namespace bmp { - - struct bitmap_file_header { - uint32_t filesize; - uint16_t creator1; - uint16_t creator2; - uint32_t bmp_offset; - - template - bitmap_file_header(DIBT dib_header): - filesize(dib_header.bytes() + dib_header.header_sz + 12 + 2), - creator1(0), - creator2(0), - bmp_offset(dib_header.header_sz + 12 + 2){} - - void write(std::ostream& out) const { - out << "BM"; - out.write(reinterpret_cast(this), 12); - } - }; - - struct bitmapcoreheader { - uint32_t header_sz; - uint16_t width; - uint16_t height; - uint16_t nplanes; - uint16_t bitspp; - - bitmapcoreheader(int width, int height): - header_sz(sizeof(bitmapcoreheader)), - width(width), - height(height), - nplanes(1), - bitspp(24){} - - void write(std::ostream& out) const { - out.write(reinterpret_cast(this), header_sz); - } - - unsigned int bytes(){ - return width*height*bitspp/8; - } - }; - - template - struct bitmap { - DIBT dib_header; - bitmap_file_header header; - T const * data; - - bitmap(int width, int height) - : dib_header(width, height) - , header(dib_header) - , data(0) {} - - void write(std::string const & filename){ - std::ofstream file(filename.c_str()); - write(file); - } - - void write(std::ostream& out){ - header.write(out); - dib_header.write(out); - //std::copy_n((char const *)data, dib_header.bytes(), std::ostream_iterator(out)); - std::copy((char const *)data, (char const *)data + dib_header.bytes(), std::ostream_iterator(out)); - } - - }; - -} - -#endif diff --git a/canvae/libpng.hpp b/canvae/libpng.hpp deleted file mode 100644 index 9be96cc..0000000 --- a/canvae/libpng.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// libpng.hpp -// AwesomeAttract0r -// -// Created by Joshua Moerman on 10/24/11. -// Copyright 2011 Vadovas. All rights reserved. -// - -#ifndef AwesomeAttract0r_libpng_hpp -#define AwesomeAttract0r_libpng_hpp - -#ifndef __APPLE__ -#include -#else -#warning PNG++ is not yet supported (will save as bmp) -#include "bmp.hpp" -namespace png { - struct rgb_pixel{ - char* data; - char red, green, blue; - - rgb_pixel(char* d) - : data(d) - , red(0) - , green(0) - , blue(0) - {} - - rgb_pixel(unsigned int r, unsigned int g, unsigned int b) - : data(0) - , red(r) - , green(g) - , blue(b) - {} - - void operator=(rgb_pixel const & rh){ - data[0] = rh.blue; - data[1] = rh.green; - data[2] = rh.red; - } - }; - - struct row{ - char * data; - - row(char* d) - : data(d) - {} - - rgb_pixel operator[](unsigned int c){return rgb_pixel(data + c*3);} - }; - - template - struct image{ - bmp::bitmap bitmap; - char * data; - - unsigned int width; - unsigned int height; - - image(unsigned int w, unsigned int h) - : bitmap(w, h) - , data(0) - , width(w) - , height(h) - { - data = new char[width*height*3]; - bitmap.data = data; - } - - ~image(){ - delete[] data; - } - - row operator[](unsigned int r){return row(data + r*height*3);} - - void write(std::string const & filename){ - bitmap.write(filename); - } - - private: - image(image const &); - image & operator=(image const &); - }; -} -#endif - -#endif diff --git a/main.cpp b/main.cpp index d9d502d..513fa56 100644 --- a/main.cpp +++ b/main.cpp @@ -1,39 +1,23 @@ -#include "Logger.hpp" #include #include #include #include #include -#include "Attractor.hpp" -#include "Canvas.hpp" -#include "Projector.hpp" - -#include "canvae/PNG.hpp" - +#include "Logger.hpp" #include "ostream_helpers.h" #include "defines.hpp" #include "AwesomeAttractorConfig.h" +#include "Attractor.hpp" +#include "Canvas.hpp" +#include "Image.hpp" +#include "Tonemapper.hpp" -int verbose; +#include +namespace po = boost::program_options; -void showHelpText() { - std::cout << - "Awesome Attractor, version " __DATE__ "\n" - "Usage: AwesomeAttractor [OPTION]* [FILE]\n" - "Optons:\n" - " -h, --help Shows this help\n" - " -q quiet mode\n" - " -v verbose mode\n" - " -V loud mode\n" - " -W N Sets width of output image (1024)\n" - " -H N Sets height of output image (1024)\n" - " -I N Sets number of milions of iterations (100)\n" - " -R Random attractor (no file will be read)\n" - << std::endl; - exit(0); -} +int verbose = 3; std::string generate_filename(){ char filename[64]; @@ -44,112 +28,95 @@ std::string generate_filename(){ return std::string(filename); } -void render(Attractor & myAttractor, unsigned int iterations){ - clock_t start = clock(); - +void render(Attractor & myAttractor, Canvas2D & canvas, unsigned int iterations){ + Progressbar progress(std::cout, "rendering"); for(unsigned int j = 1; j <= iterations; ++j) { for(unsigned int i = 0; i < 1000000; ++i) { myAttractor.iterate(); - myAttractor.plot(); - } - if(verbose >= 0) { - std::cout << "\r" << j << " out of " << iterations << " done." << std::flush; + canvas.plot(myAttractor.projector->projectedPoint); } + progress.show(j, iterations); } - - clock_t end = clock(); - - double totalIterations = 1000000.0*iterations; - double totalTime = ((double)(end-start)/(double)(CLOCKS_PER_SEC)); - LogInfo("\nTotal clock time: %f\n", totalTime); - LogMoreInfo("Average iterations per second: %f\n\n", totalIterations/totalTime); } int main(int argc, char* argv[]) { + LogInfo("Awesome Attractor, version %s\n", __DATE__); + verbose = 0; - std::string attractorFile = ""; - std::string output_path = "render/"; + std::string attractorFile; + std::string output_path; bool generate_random = false; - unsigned int iterations = DEFAULT_ITERATIONS; - unsigned int width = DEFAULT_WIDTH; - unsigned int height = DEFAULT_HEIGHT; + unsigned int iterations, width, height; srand(time(0)); - - if(argc <= 1) { - showHelpText(); - } - - for(int i = 1; i < argc; ++i) { - if(strcmp(argv[i], "-v") == 0) { - verbose = 1; - } else if(strcmp(argv[i], "-V") == 0) { - verbose = 3; - } else if(strcmp(argv[i], "-q") == 0) { - verbose = -1; - } else if(strcmp(argv[i], "--help") == 0) { - showHelpText(); - } else if(strcmp(argv[i], "-h") == 0) { - showHelpText(); - } else if(strcmp(argv[i], "-W") == 0) { - width = atoi(argv[++i]); - } else if(strcmp(argv[i], "-H") == 0) { - height = atoi(argv[++i]); - } else if(strcmp(argv[i], "-I") == 0) { - iterations = atoi(argv[++i]); - } else if(strcmp(argv[i], "-P") == 0) { - output_path = argv[++i]; - } else if(strcmp(argv[i], "-R") == 0) { - generate_random = true; - } else { - attractorFile = argv[i]; - } - } - - LogInfo("Awesome Attractor, version %s\n", __DATE__); - - Attractor* my_attractor_ptr = 0; - if(attractorFile != "") - my_attractor_ptr = new Attractor(attractorFile); - else if(generate_random) - my_attractor_ptr = new Attractor(); - - if(my_attractor_ptr == 0){ - LogError("Nothing todo\n"); - exit(0); + + po::options_description desc("Usage"); + desc.add_options() + ("help,h", "produce help message") + ("iterations,I", po::value(&iterations)->default_value(DEFAULT_ITERATIONS), "set number of iterations (in milions)") + ("width,W", po::value(&width)->default_value(DEFAULT_WIDTH), "width of output image") + ("height,H", po::value(&height)->default_value(DEFAULT_HEIGHT), "height of output image") + ("input-file,f", po::value(&attractorFile)->default_value(""), "attractor file to read") + ("output-path,P", po::value(&output_path)->default_value("render/"), "path to output image") + ("random,R", "use random parameters") + ; + + po::variables_map vm; + try { + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + } catch(std::exception & e) { + std::cout << "Failed to read commandline: " << e.what() << std::endl; + std::cout << desc << std::endl; + return 1; } - - Attractor& myAttractor = *my_attractor_ptr; - PNG* output = new PNG(width, height, 2); - myAttractor.projector->canvas = output; - myAttractor.init_range(); - - LogInfo("\nRendering\n"); - render(myAttractor, iterations); - - // saving image - std::string filename = generate_filename(); - for(int vibrancy = 2; vibrancy <= 2; ++vibrancy){ - clock_t start = clock(); - myAttractor.projector->canvas->output_file(output_path+filename); - clock_t end = clock(); - - double totalTime = ((double)(end-start)/(double)(CLOCKS_PER_SEC)); - - LogInfo("Total clock time for writing png: %f\n", totalTime); + + if (vm.count("help") || argc <= 1) { + std::cout << desc << std::endl; + return 1; } - // saving stf + if(vm.count("random")) generate_random = true; + + std::string filename = output_path + generate_filename(); + + Logger logger(std::cout); + Canvas2D canvas(width, height); { - std::string path(filename); - path += ".stf"; + Attractor* my_attractor_ptr = 0; + if(attractorFile != "") + my_attractor_ptr = new Attractor(attractorFile); + else if(generate_random) + my_attractor_ptr = new Attractor(); - std::ofstream file(path.c_str()); - file << myAttractor.stf_output() << std::endl; - } + if(my_attractor_ptr == 0){ + LogError("Nothing todo\n"); + exit(0); + } + my_attractor_ptr->init_range(); + + logger.start("rendering"); + render(*my_attractor_ptr, canvas, iterations); + logger.stop(); + + { + std::string path(filename + ".stf"); + std::ofstream file(path.c_str()); + file << my_attractor_ptr->stf_output() << std::endl; + } + + delete my_attractor_ptr; + } - delete my_attractor_ptr; - return 0; + { + Tonemappers::GammaCorrector tonemapper; + tonemapper.analyse(canvas); + + logger.start("saving image"); + ImageFormats::png::png_stream image(canvas.size<0>(), canvas.size<1>(), filename + ".png"); + tonemapper.process(canvas, image); + logger.stop(); + } }