Joshua Moerman
13 years ago
6 changed files with 472 additions and 4 deletions
@ -0,0 +1,37 @@ |
|||||
|
//
|
||||
|
// Canvas.hpp
|
||||
|
// AwesomeAttractorND
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 10/28/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
#ifndef AwesomeAttractorND_Canvas_hpp |
||||
|
#define AwesomeAttractorND_Canvas_hpp |
||||
|
|
||||
|
#include "nd_array.hpp" |
||||
|
|
||||
|
class Canvas2D : public nd_array<unsigned int, 2>{ |
||||
|
typedef Canvas2D self; |
||||
|
typedef nd_array<unsigned int, 2> super; |
||||
|
|
||||
|
public: |
||||
|
Canvas2D(size_t width, size_t height) |
||||
|
: super(width, height) |
||||
|
{} |
||||
|
|
||||
|
void plot(double const * const position){ |
||||
|
const size_t width = get_size(0); |
||||
|
const size_t height = get_size(1); |
||||
|
|
||||
|
const size_t x = position[0]*width + width*.5; |
||||
|
const size_t y = position[1]*width + height*.5; |
||||
|
|
||||
|
if(x < width && y < height) { |
||||
|
(*this)[x][y]++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif |
@ -0,0 +1,147 @@ |
|||||
|
//
|
||||
|
// 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 <ostream> |
||||
|
#include <fstream> |
||||
|
#include <stdexcept> |
||||
|
#include <tr1/memory> |
||||
|
|
||||
|
struct pixel { |
||||
|
friend class Image; |
||||
|
|
||||
|
pixel(double red, double green, double blue) |
||||
|
: red(clamp(255*red)) |
||||
|
, green(clamp(255*green)) |
||||
|
, blue(clamp(255*blue)) |
||||
|
{} |
||||
|
|
||||
|
pixel(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; |
||||
|
}; |
||||
|
|
||||
|
namespace ImageFormats { |
||||
|
namespace bmp { |
||||
|
struct bitmap_file_header { |
||||
|
uint32_t filesize; |
||||
|
uint16_t creator1; |
||||
|
uint16_t creator2; |
||||
|
uint32_t bmp_offset; |
||||
|
|
||||
|
template <typename DIBT> |
||||
|
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<const char*>(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, int bitspp = 24): |
||||
|
header_sz(sizeof(bitmapcoreheader)), |
||||
|
width(width), |
||||
|
height(height), |
||||
|
nplanes(1), |
||||
|
bitspp(bitspp){} |
||||
|
|
||||
|
void write(std::ostream& out) const { |
||||
|
out.write(reinterpret_cast<const char*>(this), header_sz); |
||||
|
} |
||||
|
|
||||
|
unsigned int bytes(){ |
||||
|
return width*height*bitspp/8; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template <typename P = pixel, typename DIBT = bitmapcoreheader> |
||||
|
struct bitmap { |
||||
|
bitmap(int width, int height) |
||||
|
: dib_header(width, height, sizeof(P)*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<char>(out));
|
||||
|
std::copy((char const *)data, (char const *)data + dib_header.bytes(), std::ostream_iterator<char>(out)); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
DIBT dib_header; |
||||
|
bitmap_file_header header; |
||||
|
P const * data; |
||||
|
}; |
||||
|
|
||||
|
template <typename DIBT = bitmapcoreheader> |
||||
|
struct bitmap_stream { |
||||
|
typedef pixel pixel; |
||||
|
|
||||
|
bitmap_stream(int width, int height, std::string filename) |
||||
|
: dib_header(width, height) |
||||
|
, header(dib_header) |
||||
|
, file(filename.c_str()) |
||||
|
{ |
||||
|
header.write(file); |
||||
|
dib_header.write(file); |
||||
|
} |
||||
|
|
||||
|
bitmap_stream& operator<<(pixel const & p){ |
||||
|
file.write(&p, 3); |
||||
|
++x; |
||||
|
if (x >= dib_header.width){ |
||||
|
x = 0; |
||||
|
++y; |
||||
|
} |
||||
|
if (y >= dib_header.height){ |
||||
|
throw std::out_of_range("Writing BMP image out of bounds."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
DIBT dib_header; |
||||
|
bitmap_file_header header; |
||||
|
std::ofstream file; |
||||
|
|
||||
|
uint16_t x; |
||||
|
uint16_t y; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,37 @@ |
|||||
|
//
|
||||
|
// 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 <algorithm> |
||||
|
|
||||
|
namespace Tonemappers { |
||||
|
|
||||
|
class Normalizer2D { |
||||
|
unsigned int max; |
||||
|
|
||||
|
template <typename C> |
||||
|
void analyse(C const & canvas){ |
||||
|
max = *std::max_element(canvas.cbegin(), canvas.cend()); |
||||
|
} |
||||
|
|
||||
|
template <typename C, typename I> |
||||
|
void process(C const & canvas, I & image){ |
||||
|
for (size_t x = 0; x < canvas.get_size(0); ++x) { |
||||
|
for (size_t y = 0; y < canvas.get_size(1); ++y) { |
||||
|
const double grayscale = (double) canvas[x][y] / (double) max; |
||||
|
image << I::pixel(grayscale, grayscale, grayscale); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#endif |
@ -0,0 +1,152 @@ |
|||||
|
//
|
||||
|
// nd_array.hpp
|
||||
|
// AwesomeAttractorND
|
||||
|
//
|
||||
|
// Created by Joshua Moerman on 10/25/11.
|
||||
|
// Copyright 2011 Vadovas. All rights reserved.
|
||||
|
//
|
||||
|
|
||||
|
/*
|
||||
|
Dynamic multi-dimensional array. |
||||
|
With the usual c-syntax: v[x][y][z]. |
||||
|
Memory is allocated as one big block, instead of multiple smaller blocks (which is the case with std::vector<std::vector<...>>). |
||||
|
Showed no difference in speed compared to std::array<std::array<...>> (in release build). |
||||
|
|
||||
|
it is not yet standard compliant. |
||||
|
*/ |
||||
|
|
||||
|
#ifndef AwesomeAttractorND_nd_array_hpp |
||||
|
#define AwesomeAttractorND_nd_array_hpp |
||||
|
|
||||
|
#include <stdexcept> |
||||
|
#include <numeric> |
||||
|
#include <iterator> |
||||
|
#include <tr1/array> |
||||
|
|
||||
|
template <typename T, size_t dimension> |
||||
|
class nd_array{ |
||||
|
public: |
||||
|
typedef T & reference; |
||||
|
typedef T const & const_reference; |
||||
|
typedef T * iterator; |
||||
|
typedef T const * const_iterator; |
||||
|
typedef size_t size_type; |
||||
|
typedef ptrdiff_t difference_type; |
||||
|
typedef T value_type; |
||||
|
typedef T * pointer; |
||||
|
typedef T const * const_pointer; |
||||
|
typedef std::reverse_iterator<iterator> reverse_iterator; |
||||
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
||||
|
|
||||
|
template <size_type N> |
||||
|
struct proxy { |
||||
|
nd_array * const data; |
||||
|
size_t const offset; |
||||
|
|
||||
|
proxy(nd_array * const c, size_t o) |
||||
|
: data(c) |
||||
|
, offset(o) |
||||
|
{} |
||||
|
|
||||
|
proxy<N-1> operator[](size_t y){ |
||||
|
if (N == 0) throw std::logic_error("called operator[] on a value"); |
||||
|
return proxy<N-1>(data, data->sizes[dimension - N]*offset + y); |
||||
|
} |
||||
|
|
||||
|
operator reference(){ |
||||
|
if (N != 0) throw std::logic_error("using a non-value"); |
||||
|
return *(data->data + offset); |
||||
|
} |
||||
|
|
||||
|
reference operator=(T const & n){ |
||||
|
if (N != 0) throw std::logic_error("assignment to a non-value"); |
||||
|
return *(data->data + offset) = n; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template <size_type N> |
||||
|
struct const_proxy { |
||||
|
nd_array const * const data; |
||||
|
size_t const offset; |
||||
|
|
||||
|
const_proxy(nd_array const * const c, size_t o) |
||||
|
: data(c) |
||||
|
, offset(o) |
||||
|
{} |
||||
|
|
||||
|
const_proxy<N-1> operator[](size_t y) const { |
||||
|
if (N == 0) throw std::logic_error("called operator[] on a value"); |
||||
|
return proxy<N-1>(data, data->sizes[dimension - N]*offset + y); |
||||
|
} |
||||
|
|
||||
|
operator const_reference() const { |
||||
|
if (N != 0) throw std::logic_error("using a non-value"); |
||||
|
return *(data->data + offset); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
nd_array(size_type width, size_type height) |
||||
|
: data(0) |
||||
|
, sizes() |
||||
|
{ |
||||
|
if (dimension != 2) throw std::logic_error("wrong constructor"); |
||||
|
sizes[0] = width; |
||||
|
sizes[1] = height; |
||||
|
data = new T[width*height]; |
||||
|
} |
||||
|
|
||||
|
nd_array(size_type width, size_type height, size_type depth) |
||||
|
: data(0) |
||||
|
, sizes() |
||||
|
{ |
||||
|
if (dimension != 3) throw std::logic_error("wrong constructor"); |
||||
|
sizes[0] = width; |
||||
|
sizes[1] = height; |
||||
|
sizes[2] = depth; |
||||
|
data = new T[width*height*depth]; |
||||
|
} |
||||
|
|
||||
|
~nd_array(){ |
||||
|
delete[] data; |
||||
|
} |
||||
|
|
||||
|
size_type get_size(size_type d) const { |
||||
|
return sizes[d]; |
||||
|
} |
||||
|
|
||||
|
size_type size() const { |
||||
|
return std::accumulate(sizes.begin(), sizes.end(), 0, std::multiplies<size_type>()); |
||||
|
} |
||||
|
|
||||
|
proxy<dimension-1> operator[](size_t x){ |
||||
|
return proxy<dimension-1>(this, x); |
||||
|
} |
||||
|
|
||||
|
const_proxy<dimension-1> operator[](size_t x) const { |
||||
|
return proxy<dimension-1>(this, x); |
||||
|
} |
||||
|
|
||||
|
iterator begin(){ |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
iterator end(){ |
||||
|
size_type length = size(); |
||||
|
return data + length; |
||||
|
} |
||||
|
|
||||
|
const_iterator cbegin() const { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
const_iterator cend() const { |
||||
|
size_type length = size(); |
||||
|
return data + length; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
T * data; |
||||
|
std::tr1::array<size_type, dimension> sizes; |
||||
|
}; |
||||
|
|
||||
|
#endif |
Reference in new issue