32 #ifndef SPL_Array2_hpp 33 #define SPL_Array2_hpp 42 #if defined(SPL_ARRAY2_DEBUG) 43 #define SPL_ARRAY2_INLINE 46 #define SPL_ARRAY2_INLINE inline 54 #include <SPL/config.hpp> 63 #include <boost/iterator/iterator_facade.hpp> 95 template <
class>
friend class Array2;
97 ArrayRep2(
int width,
int height);
99 ArrayRep2(
int width,
int height,
const T& value);
101 template <
class InputIterator>
102 ArrayRep2(
int width,
int height, InputIterator data);
108 ArrayRep2(
const ArrayRep2&);
112 ArrayRep2& operator=(
const ArrayRep2&);
115 ArrayRep2* clone()
const;
120 int getRefCount()
const;
134 void dump(std::ostream& out)
const;
143 std::vector<T> data_;
172 template <
class Value>
173 class YIter :
public boost::iterator_facade<YIter<Value>, Value,
174 std::random_access_iterator_tag>
177 YIter() : step_(0), ptr_(0)
180 explicit YIter(
int step, Value* ptr) : step_(step), ptr_(ptr)
183 template <
class OtherValue>
184 YIter(
const YIter<OtherValue>& other) : step_(other.step_),
189 friend class boost::iterator_core_access;
190 template <
class>
friend class YIter;
191 template <
class OtherValue>
192 bool equal(
const YIter<OtherValue>& other)
const 194 return ptr_ == other.ptr_;
208 template <
class OtherValue>
209 int distance_to(
const YIter<OtherValue>& other)
const 211 return (other.ptr_ - ptr_) / step_;
213 Value& dereference()
const {
222 typedef typename std::vector<T>::iterator
Iterator;
251 Array2(
int width,
int height);
257 Array2(
int width,
int height,
const T& value);
263 template <
class InputIter>
264 Array2(
int width,
int height, InputIter data);
280 template <
class OtherType>
296 template <
class OtherType>
500 void resize(
int width,
int height);
506 template <
class InputIterator>
507 void resize(
int width,
int height, InputIterator data);
540 std::ostream&
output(std::ostream& out,
int fieldWidth)
const;
545 int load(
const char* fileName);
550 int save(
const char* fileName)
const;
559 void fill(
const T& value = T(0));
579 void dump(std::ostream& out)
const;
588 template <
class>
friend class Array2;
591 typedef ArrayRep2<T> Rep;
597 void copyOnWrite()
const;
611 width_(width), height_(height), data_(width * height), refCount_(1)
613 assert(width >= 0 && height >= 0);
618 const T& value) : width_(width), height_(height),
619 data_(width * height, value), refCount_(1)
621 assert(width >= 0 && height >= 0);
625 template <
class InputIterator>
627 InputIterator data) : width_(width), height_(height), data_(), refCount_(1)
629 assert(width >= 0 && height >= 0);
630 int n = width * height;
646 return new ArrayRep2(width_, height_, data_.begin());
658 if (--refCount_ == 0) {
670 void ArrayRep2<T>::dump(
typename std::ostream& out)
const 674 << width_ <<
" " << height_ <<
" " 675 << (&*data_.begin()) <<
" " 688 ptr_ =
new Rep(0, 0);
694 assert(width >= 0 && height >= 0);
695 ptr_ =
new Rep(width, height);
701 #if defined(SPL_ARRAY2_DEBUG) 702 std::cerr <<
"Array2<T>::Array2(const Array2<T>&) " 703 <<
this <<
" " << (&a) <<
"\n";
712 assert(width >= 0 && height >= 0);
713 ptr_ =
new Rep(width, height, value);
717 template <
class InputIterator>
720 assert(width >= 0 && height >= 0);
721 ptr_ =
new Rep(width, height, data);
727 #if defined(SPL_ARRAY2_DEBUG) 728 std::cerr <<
"Array2<T>::~Array2() " <<
this <<
" " << ptr_ <<
"\n";
734 template <
class OtherType>
737 #if defined(SPL_ARRAY2_DEBUG) 738 std::cerr <<
"Array2::pseudo_copy_ctor " <<
this <<
" " << ptr_ <<
"\n";
750 #if defined(SPL_ARRAY2_DEBUG) 751 std::cerr <<
"Array2<T>& Array2<T>::operator=(const Array2<T>&) " 752 <<
this <<
" " << (&a) <<
"\n";
764 template <
class OtherType>
767 #if defined(SPL_ARRAY2_DEBUG) 768 std::cerr <<
"Array2::operator= special\n";
770 if (reinterpret_cast<void*>(
this) != reinterpret_cast<const void*>(&a)) {
773 std::copy(a.ptr_->data_.begin(), a.ptr_->data_.end(),
774 ptr_->data_.begin());
788 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
789 a.ptr_->data_.begin(), ptr_->data_.begin(), std::plus<T>());
798 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
799 a.ptr_->data_.begin(), ptr_->data_.begin(), std::minus<T>());
808 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
809 a.ptr_->data_.begin(), ptr_->data_.begin(), std::multiplies<T>());
818 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
819 a.ptr_->data_.begin(), ptr_->data_.begin(), std::divides<T>());
828 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
829 ptr_->data_.begin(), std::bind2nd(std::plus<T>(), value));
831 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
832 ptr_->data_.begin(), [=](
auto x){
return x + value;});
842 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
843 ptr_->data_.begin(), std::bind2nd(std::minus<T>(), value));
845 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
846 ptr_->data_.begin(), [=](
auto x){
return x - value;});
856 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
857 ptr_->data_.begin(), std::bind2nd(std::multiplies<T>(), value));
859 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
860 ptr_->data_.begin(), [=](
auto x){
return x * value;});
870 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
871 ptr_->data_.begin(), std::bind2nd(std::divides<T>(), value));
873 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
874 ptr_->data_.begin(), [=](
auto x){
return x / value;});
892 return ptr_->height_;
898 assert(ptr_->width_ * ptr_->height_ == ptr_->data_.size());
899 return ptr_->data_.size();
905 return ptr_->getRefCount() > 1;
911 return ptr_ == a.ptr_;
921 assert(x >= 0 && x < getWidth() && y >= 0 && y < getHeight());
923 return ptr_->data_[y * getWidth() + x];
929 assert(x >= 0 && x < getWidth() && y >= 0 && y < getHeight());
930 return ptr_->data_[y * getWidth() + x];
936 assert(getWidth() == 1 || getHeight() == 1);
937 assert(i >= 0 && i < getSize());
939 return ptr_->data_[i];
945 assert(getWidth() == 1 || getHeight() == 1);
946 assert(i >= 0 && i < getSize());
947 return ptr_->data_[i];
957 return ptr_->data_.begin();
964 return ptr_->data_.begin();
970 return ptr_->data_.end();
977 return ptr_->data_.end();
983 assert(y >= 0 && y < getHeight());
984 return begin() + (y * getWidth());
990 assert(y >= 0 && y < getHeight());
992 return begin() + (y * getWidth());
998 assert(y >= 0 && y < getHeight());
999 return begin() + ((y + 1) * getWidth());
1005 assert(y >= 0 && y < getHeight());
1007 return begin() + ((y + 1) * getWidth());
1013 assert(x >= 0 && x < getWidth());
1020 assert(x >= 0 && x < getWidth());
1022 return YIterator(getWidth(), &(*(begin() + x)));
1028 assert(x >= 0 && x < getWidth());
1029 return ConstYIterator(getWidth(), &(*(begin() + (getSize() + x))));
1035 assert(x >= 0 && x < getWidth());
1037 return YIterator(getWidth(), &(*(begin() + (getSize() + x))));
1047 assert(width >= 0 && height >= 0);
1048 if (getWidth() != width || getHeight() != height) {
1050 ptr_ =
new Rep(width, height);
1055 template <
class InputIterator>
1058 assert(width >= 0 && height >= 0);
1059 if (getWidth() == width && getHeight() == height && ptr_->getRefCount() == 1) {
1063 ptr_ =
new Rep(width, height, data);
1074 assert(getSize() > 0);
1075 return *std::max_element(begin(), end());
1081 assert(getSize() > 0);
1082 return *std::min_element(begin(), end());
1088 return std::accumulate(begin(), end(), T(0));
1098 out << getWidth() <<
" " << getHeight() <<
"\n";
1099 for (
int j = 0; j < getHeight(); ++j) {
1100 for (
int i = 0; i < getWidth(); ++i) {
1101 T val = operator()(i, j);
1102 std::stringstream str;
1103 str << std::setw(fieldWidth) << val;
1104 std::string buf = str.str();
1105 if (buf.size() > fieldWidth) {
1106 buf = buf.substr(0, fieldWidth);
1110 if (i < getWidth() - 1) {
1122 std::ifstream in(fileName);
1133 std::ofstream out(fileName);
1146 std::ostream& operator<<(std::ostream& out, const Array2<T>& a)
1149 for (
int y = 0; y < a.
getHeight(); ++y) {
1151 for (
int x = 0; x < a.
getWidth(); ++x) {
1170 if (!(in >> width)) {
1174 if (!(in >> height)) {
1177 if (width < 0 || height < 0) {
1178 in.setstate(std::ios::failbit);
1183 for (
int y = 0; y < a.
getHeight(); ++y) {
1185 for (
int x = 0; x < a.
getWidth(); ++x) {
1187 if (!(in >> value)) {
1208 std::swap(ptr_, a.ptr_);
1216 std::fill(begin(), end(), value);
1223 for (
int k = 0; k < getHeight() / 2; ++k) {
1225 XIterator j = rowBegin(getHeight() - 1 - k);
1226 for (
int n = getWidth(); n > 0; --n) {
1239 for (
int y = 0; y < getHeight(); ++y) {
1242 for (
int n = getWidth() / 2; n > 0; --n) {
1260 for (
int y = 0; y < width; ++y) {
1261 for (
int x = 0; x < height; ++x) {
1262 result(x, y) = a(y, x);
1277 for (
int y = 0; y < a.
getHeight(); ++y) {
1280 for (
int x = 0; x < a.
getWidth(); ++x) {
1312 out <<
"Array2<T> " <<
this <<
" ";
1324 #if defined(SPL_ARRAY2_DEBUG) 1325 std::cerr <<
"Array2<T>::copyOnWrite() " <<
this <<
"\n";
1329 assert(ptr_->getRefCount() > 1);
1332 this->ptr_ = ptr_->clone();
1338 if (ptr_->getRefCount() > 1) {
1364 typedef typename Array::XIterator ArrayIter;
1366 PnmPutData() : comps_(0)
1370 void initialize(
typename std::vector<Array>& comps)
1373 assert(comps.size() >= 0);
1374 dataIters_.reserve(3);
1375 y_ = (*comps_)[0].getHeight() - 1;
1376 remaining_ = (*comps_)[0].getWidth();
1377 for (
typename std::vector<Array>::iterator i = comps_->begin();
1378 i != comps_->end(); ++i) {
1379 assert(!i->isShared());
1380 dataIters_.push_back(i->rowBegin(y_));
1385 void operator()(
int value)
1388 ArrayIter& iter = dataIters_[comp_];
1394 if (comp_ >= comps_->size()) {
1397 if (remaining_ <= 0) {
1398 remaining_ = (*comps_)[0].getWidth();
1401 typename std::vector<Array>::iterator comp =
1403 for (
typename std::vector<ArrayIter>::iterator i =
1404 dataIters_.begin(); i != dataIters_.end(); ++i) {
1405 *i = comp->rowBegin(y_);
1413 std::vector<Array>* comps_;
1414 typename std::vector<ArrayIter> dataIters_;
1424 typedef PnmPutData<T> PutData;
1425 void operator()(
int width,
int height,
int numComps,
int maxVal,
1426 bool sgnd, PutData& putData) {
1428 for (
int i = 0; i < numComps; ++i) {
1429 comps_.push_back(Array2<T>(width, height));
1435 typename std::vector<Array2<T> > comps_;
1445 typedef Array2<T> Array;
1446 typedef typename Array::ConstXIterator ConstArrayIter;
1448 PnmGetData(
const typename std::vector<Array>& comps,
int maxVal,
1449 bool sgnd) : comps_(comps)
1451 assert(comps.size() >= 0);
1452 dataIters_.reserve(3);
1453 int width = comps[0].getWidth();
1454 int height = comps[0].getHeight();
1457 for (
typename std::vector<Array>::const_iterator i = comps.begin();
1458 i != comps.end(); ++i) {
1459 dataIters_.push_back(i->rowBegin(y_));
1467 ConstArrayIter& iter = dataIters_[comp_];
1472 if (comp_ >= comps_.size()) {
1475 if (remaining_ <= 0) {
1476 remaining_ = comps_[0].getWidth();
1479 typename std::vector<Array>::const_iterator comp =
1481 for (
typename std::vector<ConstArrayIter>::iterator i =
1482 dataIters_.begin(); i != dataIters_.end(); ++i) {
1483 *i = comp->rowBegin(y_);
1494 const std::vector<Array>& comps_;
1495 typename std::vector<ConstArrayIter> dataIters_;
1520 int maxVal,
bool sgnd,
bool binaryFormat =
true)
1522 PnmGetData<T>
getData(comps, maxVal, sgnd);
1523 return pnmEncode(outStream, comps[0].getWidth(), comps[0].getHeight(),
1524 comps.size(), maxVal, sgnd,
getData, binaryFormat);
1559 bool sgnd,
bool binaryFormat =
true)
1562 sgnd, binaryFormat);
1582 bool binaryFormat =
true)
1584 std::vector<Array2<T> > comps;
1585 comps.push_back(red);
1586 comps.push_back(green);
1587 comps.push_back(blue);
1588 return encodePnm(outStream, comps, maxVal, sgnd, binaryFormat);
1607 int& maxVal,
bool& sgnd)
1609 PnmInitialize<T> initialize;
1611 if ((ret =
pnmDecode(inStream, initialize))) {
1614 comps = initialize.comps_;
1615 maxVal = initialize.maxVal_;
1616 sgnd = initialize.sgnd_;
1638 std::vector<Array2<T> > comps;
1639 if ((ret =
decodePnm(inStream, comps, maxVal, sgnd))) {
1642 assert(maxVal == 1);
1665 std::vector<Array2<T> > comps;
1666 if ((ret =
decodePnm(inStream, comps, maxVal, sgnd))) {
1689 Array2<T>& blue,
int& maxVal,
bool& sgnd)
1692 std::vector<Array2<T> > comps;
1693 if ((ret =
decodePnm(inStream, comps, maxVal, sgnd))) {
void resize(int width, int height)
Change the size of the array.
Definition: Array2.hpp:1045
ConstYIterator colEnd(int x) const
Get a const iterator for one past the end in the specified column of the array.
Definition: Array2.hpp:1026
ConstXIterator rowEnd(int y) const
Get a const iterator for one past the end in the specified row of the array.
Definition: Array2.hpp:996
bool isShared() const
Is the data for this array shared with another array?
Definition: Array2.hpp:903
This file contains miscellaneous code.
Array2 & operator=(const Array2 &a)
The assignment operator.
Definition: Array2.hpp:748
std::istream & operator>>(std::istream &in, Array2< T > &a)
Input an array from the specified stream.
Definition: Array2.hpp:1167
T & operator()(int x, int y)
Get a mutable reference to the (x,y)-th element in the array.
Definition: Array2.hpp:919
Array2< T > transpose(const Array2< T > &a)
Get the transpose of the array.
Definition: Array2.hpp:1255
Definition: Arcball.hpp:48
int getWidth() const
Get the width of the array.
Definition: Array2.hpp:884
Array2 & operator*=(const Array2 &a)
Multiply another array (elementwise) by this array.
Definition: Array2.hpp:804
std::ostream & output(std::ostream &out, int fieldWidth) const
Output an array to a stream using the specified field width for each array element.
Definition: Array2.hpp:1096
ConstIterator begin() const
Get a const iterator for the first element in the array.
Definition: Array2.hpp:955
Array2< double > RealArray2
A two-dimensional array with real elements.
Definition: Array2.hpp:1716
int encodePnm(std::ostream &outStream, const std::vector< Array2< T > > &comps, int maxVal, bool sgnd, bool binaryFormat=true)
Output the array as an image in the PNM format.
Definition: Array2.hpp:1519
T ElemType
The type of the elements in the array.
Definition: Array2.hpp:166
ConstXIterator rowBegin(int y) const
Get a const iterator for the first element in the specified row of the array.
Definition: Array2.hpp:981
OutputIterator copy_n(InputIterator first, Size count, OutputIterator result)
This template function is equivalent to std::copy_n in the new C++ 0x standard.
Definition: misc.hpp:56
Array2()
Create an empty array.
Definition: Array2.hpp:686
#define SPL_ARRAY2_INLINE
Defining this symbol will enable extra code for debugging.
Definition: Array2.hpp:47
int decodePbm(std::istream &inStream, Array2< T > &bits)
Input an array as an image in the PNM format.
Definition: Array2.hpp:1633
std::vector< T >::const_iterator ConstXIterator
A constant iterator for elements of a row in the array.
Definition: Array2.hpp:231
Array2 & flipud()
Flip the array upside down.
Definition: Array2.hpp:1220
int encodePgm(std::ostream &outStream, const Array2< T > &gray, int maxVal, bool sgnd, bool binaryFormat=true)
Output the array as an image in the PNM format (PGM type).
Definition: Array2.hpp:1558
int putData(std::ostream &out, PnmHeader &header, GetData &getData)
Write the actual image data to a stream.
Definition: pnmCodec.hpp:228
ConstIterator end() const
Get a const iterator for one past the last element in the array.
Definition: Array2.hpp:968
int decodePgm(std::istream &inStream, Array2< T > &gray, int &maxVal, bool &sgnd)
Input an array as an image in the PNM format.
Definition: Array2.hpp:1662
T min() const
Get the minimum of the elements in the array.
Definition: Array2.hpp:1079
T sum() const
Get the sum of the elements in the array.
Definition: Array2.hpp:1086
void dump(std::ostream &out) const
Output information about an array to a stream for debugging.
Definition: Array2.hpp:1310
int decodePpm(std::istream &inStream, Array2< T > &red, Array2< T > &green, Array2< T > &blue, int &maxVal, bool &sgnd)
Input an array as an image in the PNM format.
Definition: Array2.hpp:1688
std::vector< T >::iterator Iterator
A mutable iterator for all elements in the array.
Definition: Array2.hpp:222
~Array2()
The destructor.
Definition: Array2.hpp:725
YIter< T > YIterator
A mutable iterator for elements of a column in the array.
Definition: Array2.hpp:234
int encodePbm(std::ostream &outStream, const Array2< T > &bits, bool binaryFormat=true)
Output the array as an image in the PNM format (PBM type).
Definition: Array2.hpp:1539
void fill(const T &value=T(0))
Set all elements in the array to the specified value.
Definition: Array2.hpp:1213
void swap(Array2 &a)
Swap the array data with the data of the specified array.
Definition: Array2.hpp:1202
void unshare() const
Force the underlying data to be copied if the data is shared.
Definition: Array2.hpp:1336
A two-dimensional array class with lazy copying and reference counting.
Definition: Array2.hpp:83
Array2 & operator/=(const Array2 &a)
Divide this array (elementwise) by another array.
Definition: Array2.hpp:814
int load(const char *fileName)
Load an array from the file with the specified name.
Definition: Array2.hpp:1120
This file contains a PNM codec.
YIter< const T > ConstYIterator
A constant iterator for elements of a column in the array.
Definition: Array2.hpp:237
ConstYIterator colBegin(int x) const
Get a const iterator for the first element in the specified column of the array.
Definition: Array2.hpp:1011
int save(const char *fileName) const
Save an array to the file with the specified name.
Definition: Array2.hpp:1131
int getData(std::istream &in, PnmHeader &header, PutData &putData)
Read the actual image data from the specified stream.
Definition: pnmCodec.hpp:337
int pnmDecode(std::istream &inStream, Initialize &initialize)
Read data encoded in the PNM format from the specified stream.
Definition: pnmCodec.hpp:309
Array2 & operator+=(const Array2 &a)
Add another array (elementwise) to this array.
Definition: Array2.hpp:784
Array2< int > IntArray2
A two-dimensional array with integer elements.
Definition: Array2.hpp:1719
int decodePnm(std::istream &inStream, std::vector< Array2< T > > &comps, int &maxVal, bool &sgnd)
Input an array as an image in the PNM format.
Definition: Array2.hpp:1606
Iterator XIterator
A mutable iterator for elements of a row in the array.
Definition: Array2.hpp:228
int encodePpm(std::ostream &outStream, const Array2< T > &red, const Array2< T > &green, const Array2< T > &blue, int maxVal, bool sgnd, bool binaryFormat=true)
Output the array as an image in the PNM format (PPM type).
Definition: Array2.hpp:1580
int getSize() const
Get the number of elements in the array.
Definition: Array2.hpp:896
int getHeight() const
Get the height of the array.
Definition: Array2.hpp:890
std::vector< T >::const_iterator ConstIterator
A constant iterator for all elements in the array.
Definition: Array2.hpp:225
bool operator!=(const Array2< T > &a, const Array2< T > &b)
Test two arrays for inequality.
Definition: Array2.hpp:1300
bool isSharedWith(const Array2 &a) const
Is the data for this array shared with the specified array?
Definition: Array2.hpp:909
T max() const
Get the maximum of the elements in the array.
Definition: Array2.hpp:1072
bool operator==(const Array2< T > &a, const Array2< T > &b)
Test two arrays for equality.
Definition: Array2.hpp:1272
Array2 & fliplr()
Flip the array left to right.
Definition: Array2.hpp:1236
Array2 & operator-=(const Array2 &a)
Subtract another array (elementwise) from this array.
Definition: Array2.hpp:794
int pnmEncode(std::ostream &outStream, int width, int height, int numComps, int maxVal, bool sgnd, GetData &getData, bool binaryFormat)
Write data encoded in the PNM format to the specified stream.
Definition: pnmCodec.hpp:195