#ifndef Image_h
#define Image_h
#include <vector>
#include <cassert>
#include <cstdlib>
#include <limits>
#include <iostream>
using namespace std;
template <typename _T>
_T random() {
double result = static_cast<double>(rand());
result /= RAND_MAX;
result *= numeric_limits<_T>::max();
return static_cast<_T>(result);
}
template <>
double random<double>() {
double result = static_cast<double>(rand());
result /= RAND_MAX;
return result;
}
template <>
bool random<bool>() {
double result = static_cast<double>(rand());
result /= RAND_MAX;
return (result >= 0.5) ? true : false;
}
template <typename _T>
_T _or(_T _x, _T _y) {
return _x | _y;
}
template <>
double _or<double>(double _x, double _y) {
return (_x >= _y) ? _x : _y;
}
template <>
bool _or<bool>(bool _x, bool _y) {
return _x || _y;
}
template <typename _T>
_T _and(_T _x, _T _y) {
return _x & _y;
}
template <>
double _and<double>(double _x, double _y) {
return (_x + _y);
}
template <>
bool _and<bool>(bool _x, bool _y) {
return _x && _y;
}
template <typename _T>
double fill_factor(_T _data) {
return static_cast<double>(_data);
}
template <>
double fill_factor<bool>(bool _data) {
return (_data) ? 1.0 : 0.0;
}
template <typename _T>
_T _invert(_T _data) {
return ~_data;
}
template <>
double _invert<double>(double _data) {
return 0.5 - _data;
}
template <>
bool _invert<bool>(bool _data) {
return !_data;
}
template <typename _T, typename _SizeT = unsigned int>
class ImageT
{
_SizeT m_width;
_SizeT m_height;
vector<_T> m_data;
public:
typedef enum {
ZeroFill,
RandomFill
} FillType;
ImageT() {
m_width = 0;
m_height = 0;
}
static ImageT* create(_SizeT _width, _SizeT _height, FillType _ftype = ZeroFill) {
assert(_width > 0);
assert(_height > 0);
ImageT* result = new ImageT();
result->m_width = _width;
result->m_height = _height;
result->m_data.resize(_width * _height);
if (_ftype == RandomFill)
result->random_fill();
else
result->zero_fill();
return result;
}
ImageT(const ImageT& _src) {
m_width = _src.width();
m_height = _src.height();
m_data.resize(m_width * m_height);
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x)
m_data[y * m_width + x] = _src(x, y);
}
inline void resize(_SizeT _width, _SizeT _height, FillType _ftype = ZeroFill) {
if ( _width == m_width && _height == m_height)
return;
vector<_T> tmp;
tmp.resize(_width * _height);
for (_SizeT y = 0; y < _height; ++y)
for (_SizeT x = 0; x < _width; ++x)
tmp[y * _width + x] = m_data[y * m_width + x];
m_data.resize(_height * _width);
m_width = _width;
m_height = _height;
if (_ftype == RandomFill)
random_fill();
else
zero_fill();
for (_SizeT y = 0; y < _height; ++y)
for (_SizeT x = 0; x < _width; ++x)
m_data[y * _width + x] = tmp[y * _width + x];
}
void random_fill() {
srand(static_cast<unsigned int>(time(nullptr)));
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x)
set_pixel_data(x, y, random<_T>());
}
void zero_fill() {
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x)
set_pixel_data(x, y, static_cast<_T>(0));
}
inline void set_pixel_data(_SizeT _x, _SizeT _y, _T _data) {
assert(_x >= 0 && _x < m_width);
assert(_y >= 0 && _y < m_height);
m_data[_y * m_width + _x] = _data;
}
inline _T operator () (_SizeT _x, _SizeT _y) const {
assert(_x >= 0 && _x < m_width);
assert(_y >= 0 && _y < m_height);
return m_data[_y * m_width + _x];
}
ImageT& operator *= (_T _val) {
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x) {
_T _data = *this(x, y) * _val;
set_pixel_data(x, y, _data);
}
return *this;
}
ImageT& operator += (_T _val) {
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x) {
_T _data = *this(x, y) + _val;
set_pixel_data(x, y, _data);
}
return *this;
}
inline _SizeT width() const {
return m_width;
}
inline _SizeT height() const {
return m_height;
}
ImageT operator | (const ImageT& _val) const {
_SizeT _w = (m_width > _val.width()) ? m_width : _val.width();
_SizeT _h = (m_height > _val.height()) ? m_height : _val.height();
ImageT result(*this);
result.resize(_w, _h);
for (_SizeT y = 0; y < _val.height(); ++y)
for (_SizeT x = 0; x < _val.width(); ++x)
result.set_pixel_data(x, y, _or<_T>(result(x, y), _val(x, y)));
return result;
}
ImageT operator & (const ImageT& _val) const {
_SizeT _w = (m_width > _val.width()) ? m_width : _val.width();
_SizeT _h = (m_height > _val.height()) ? m_height : _val.height();
ImageT result(*this);
result.resize(_w, _h);
for (_SizeT y = 0; y < _val.height(); ++y)
for (_SizeT x = 0; x < _val.width(); ++x)
result.set_pixel_data(x, y, _and<_T>(result(x, y), _val(x, y)));
return result;
}
template <typename _Q, typename _SizeQ>
ImageT<_T, _SizeT>& operator *= (const ImageT<_Q, _SizeQ>& _val) {
_SizeT _w = (m_width > _val.width()) ? m_width : _val.width();
_SizeT _h = (m_height > _val.height()) ? m_height : _val.height();
resize(_w, _h);
for (_SizeT y = 0; y < _val.height(); ++y)
for (_SizeT x = 0; x < _val.width(); ++x) {
_T _data = (*this)(x, y) * static_cast<_T>(_val(x, y));
set_pixel_data(x, y, _data);
}
return *this;
}
template <typename _Q, typename _SizeQ = unsigned int>
ImageT& operator += (const ImageT<_Q, _SizeQ>& _val) {
_SizeT _w = (m_width > _val.width()) ? m_width : _val.width();
_SizeT _h = (m_height > _val.height()) ? m_height : _val.height();
resize(_w, _h);
for (_SizeT y = 0; y < _val.height(); ++y)
for (_SizeT x = 0; x < _val.width(); ++x) {
_T _data = (*this)(x, y) + static_cast<_T>(_val(x, y));
set_pixel_data(x, y, _data);
}
return *this;
}
ImageT operator ~ () const {
ImageT result(*this);
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x)
result.set_pixel_data(x, y, _invert<_T>((*this)(x, y)));
return result;
}
double fill_factor() const {
double _square = m_width * m_height;
double _sum = 0.;
for (_SizeT y = 0; y < m_height; ++y)
for (_SizeT x = 0; x < m_width; ++x) {
_T _data = ::fill_factor<_T>((*this)(x, y));
_sum += _data;
}
_sum /= _square;
return _sum;
}
};
template <typename _T, typename _SizeT = unsigned int>
ostream& operator << (ostream& os, const ImageT<_T, _SizeT>& image) {
double _max = 0.5;
for (_SizeT y = 0; y < image.height(); ++y) {
for (_SizeT x = 0; x < image.width(); ++x) {
os << (image(x,y) >= _max ? '*' : '.');
}
os << endl;
}
return os;
}
typedef ImageT<double> Image;
typedef ImageT<bool> ImageB;
#endif /* Image_h */
//#include <iostream>
//#include "Image.h"
using namespace std;
int main(int argc, const char * argv[]) {
// insert code here...
cout << "Hello, World!" << endl;
Image* image1 = Image::create(64, 48, Image::RandomFill);
Image* image2 = Image::create(32, 20, Image::RandomFill);
Image image3 = *image1 | *image2;
Image image4 = *image1 & *image2;
ImageB* image5 = ImageB::create(40, 30, ImageB::RandomFill);
ImageB image6 = ~ *image5;
Image image7 = *image1;
image7 += (~ *image5);
cout << "Fill factor 1: " << image1->fill_factor() << endl;
cout << "Fill factor 2: " << image2->fill_factor() << endl;
cout << "Fill factor 3: " << image3.fill_factor() << endl;
cout << "Fill factor 4: " << image4.fill_factor() << endl;
cout << "Fill factor 5: " << image5->fill_factor() << endl;
cout << "Fill factor 6: " << image6.fill_factor() << endl;
cout << "Fill factor 7: " << image7.fill_factor() << endl;
cout << image7;
delete(image5);
delete(image2);
delete(image1);
return 0;
}