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>
413 ConstIterator
begin()
const;
424 ConstIterator
end()
const;
437 ConstXIterator
rowBegin(
int y)
const;
451 ConstXIterator
rowEnd(
int y)
const;
465 ConstYIterator
colBegin(
int x)
const;
479 ConstYIterator
colEnd(
int x)
const;
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;
632 SPL::copy_n(data, n, std::back_inserter(data_));
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>());
827 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
828 ptr_->data_.begin(), std::bind2nd(std::plus<T>(), value));
836 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
837 ptr_->data_.begin(), std::bind2nd(std::minus<T>(), value));
845 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
846 ptr_->data_.begin(), std::bind2nd(std::multiplies<T>(), value));
854 std::transform(ptr_->data_.begin(), ptr_->data_.end(),
855 ptr_->data_.begin(), std::bind2nd(std::divides<T>(), value));
872 return ptr_->height_;
878 assert(ptr_->width_ * ptr_->height_ == ptr_->data_.size());
879 return ptr_->data_.size();
885 return ptr_->getRefCount() > 1;
891 return ptr_ == a.ptr_;
901 assert(x >= 0 && x < getWidth() && y >= 0 && y < getHeight());
903 return ptr_->data_[y * getWidth() + x];
909 assert(x >= 0 && x < getWidth() && y >= 0 && y < getHeight());
910 return ptr_->data_[y * getWidth() + x];
916 assert(getWidth() == 1 || getHeight() == 1);
917 assert(i >= 0 && i < getSize());
919 return ptr_->data_[i];
925 assert(getWidth() == 1 || getHeight() == 1);
926 assert(i >= 0 && i < getSize());
927 return ptr_->data_[i];
937 return ptr_->data_.begin();
944 return ptr_->data_.begin();
950 return ptr_->data_.end();
957 return ptr_->data_.end();
963 assert(y >= 0 && y < getHeight());
964 return begin() + (y * getWidth());
970 assert(y >= 0 && y < getHeight());
972 return begin() + (y * getWidth());
978 assert(y >= 0 && y < getHeight());
979 return begin() + ((y + 1) * getWidth());
985 assert(y >= 0 && y < getHeight());
987 return begin() + ((y + 1) * getWidth());
993 assert(x >= 0 && x < getWidth());
994 return ConstYIterator(getWidth(), &(*(begin() + x)));
1000 assert(x >= 0 && x < getWidth());
1002 return YIterator(getWidth(), &(*(begin() + x)));
1008 assert(x >= 0 && x < getWidth());
1009 return ConstYIterator(getWidth(), &(*(begin() + (getSize() + x))));
1015 assert(x >= 0 && x < getWidth());
1017 return YIterator(getWidth(), &(*(begin() + (getSize() + x))));
1027 assert(width >= 0 && height >= 0);
1028 if (getWidth() != width || getHeight() != height) {
1030 ptr_ =
new Rep(width, height);
1035 template <
class InputIterator>
1038 assert(width >= 0 && height >= 0);
1039 if (getWidth() == width && getHeight() == height && ptr_->getRefCount() == 1) {
1040 SPL::copy_n(data, getSize(), begin());
1043 ptr_ =
new Rep(width, height, data);
1054 assert(getSize() > 0);
1055 return *std::max_element(begin(), end());
1061 assert(getSize() > 0);
1062 return *std::min_element(begin(), end());
1068 return std::accumulate(begin(), end(), T(0));
1078 out << getWidth() <<
" " << getHeight() <<
"\n";
1079 for (
int j = 0; j < getHeight(); ++j) {
1080 for (
int i = 0; i < getWidth(); ++i) {
1081 T val = operator()(i, j);
1082 std::stringstream str;
1083 str << std::setw(fieldWidth) << val;
1084 std::string buf = str.str();
1085 if (buf.size() > fieldWidth) {
1086 buf = buf.substr(0, fieldWidth);
1090 if (i < getWidth() - 1) {
1102 std::ifstream in(fileName);
1113 std::ofstream out(fileName);
1126 std::ostream& operator<<(std::ostream& out, const Array2<T>& a)
1129 for (
int y = 0; y < a.
getHeight(); ++y) {
1131 for (
int x = 0; x < a.
getWidth(); ++x) {
1150 if (!(in >> width)) {
1154 if (!(in >> height)) {
1157 if (width < 0 || height < 0) {
1158 in.setstate(std::ios::failbit);
1163 for (
int y = 0; y < a.
getHeight(); ++y) {
1165 for (
int x = 0; x < a.
getWidth(); ++x) {
1167 if (!(in >> value)) {
1188 std::swap(ptr_, a.ptr_);
1196 std::fill(begin(), end(), value);
1203 for (
int k = 0; k < getHeight() / 2; ++k) {
1204 XIterator i = rowBegin(k);
1205 XIterator j = rowBegin(getHeight() - 1 - k);
1206 for (
int n = getWidth(); n > 0; --n) {
1219 for (
int y = 0; y < getHeight(); ++y) {
1220 XIterator i = rowBegin(y);
1221 XIterator j = i + (getWidth() - 1);
1222 for (
int n = getWidth() / 2; n > 0; --n) {
1240 for (
int y = 0; y < width; ++y) {
1241 for (
int x = 0; x < height; ++x) {
1242 result(x, y) = a(y, x);
1257 for (
int y = 0; y < a.
getHeight(); ++y) {
1260 for (
int x = 0; x < a.
getWidth(); ++x) {
1292 out <<
"Array2<T> " <<
this <<
" ";
1304 #if defined(SPL_ARRAY2_DEBUG)
1305 std::cerr <<
"Array2<T>::copyOnWrite() " <<
this <<
"\n";
1309 assert(ptr_->getRefCount() > 1);
1312 this->ptr_ = ptr_->clone();
1318 if (ptr_->getRefCount() > 1) {
1344 typedef typename Array::XIterator ArrayIter;
1346 PnmPutData() : comps_(0)
1350 void initialize(
typename std::vector<Array>& comps)
1353 assert(comps.size() >= 0);
1354 dataIters_.reserve(3);
1355 y_ = (*comps_)[0].getHeight() - 1;
1356 remaining_ = (*comps_)[0].getWidth();
1357 for (
typename std::vector<Array>::iterator i = comps_->begin();
1358 i != comps_->end(); ++i) {
1359 assert(!i->isShared());
1360 dataIters_.push_back(i->rowBegin(y_));
1365 void operator()(
int value)
1368 ArrayIter& iter = dataIters_[comp_];
1374 if (comp_ >= comps_->size()) {
1377 if (remaining_ <= 0) {
1378 remaining_ = (*comps_)[0].getWidth();
1381 typename std::vector<Array>::iterator comp =
1383 for (
typename std::vector<ArrayIter>::iterator i =
1384 dataIters_.begin(); i != dataIters_.end(); ++i) {
1385 *i = comp->rowBegin(y_);
1393 std::vector<Array>* comps_;
1394 typename std::vector<ArrayIter> dataIters_;
1404 typedef PnmPutData<T> PutData;
1405 void operator()(
int width,
int height,
int numComps,
int maxVal,
1406 bool sgnd, PutData& putData) {
1408 for (
int i = 0; i < numComps; ++i) {
1409 comps_.push_back(Array2<T>(width, height));
1411 putData.initialize(comps_);
1415 typename std::vector<Array2<T> > comps_;
1425 typedef Array2<T> Array;
1426 typedef typename Array::ConstXIterator ConstArrayIter;
1428 PnmGetData(
const typename std::vector<Array>& comps,
int maxVal,
1429 bool sgnd) : comps_(comps)
1431 assert(comps.size() >= 0);
1432 dataIters_.reserve(3);
1433 int width = comps[0].getWidth();
1434 int height = comps[0].getHeight();
1437 for (
typename std::vector<Array>::const_iterator i = comps.begin();
1438 i != comps.end(); ++i) {
1439 dataIters_.push_back(i->rowBegin(y_));
1447 ConstArrayIter& iter = dataIters_[comp_];
1452 if (comp_ >= comps_.size()) {
1455 if (remaining_ <= 0) {
1456 remaining_ = comps_[0].getWidth();
1459 typename std::vector<Array>::const_iterator comp =
1461 for (
typename std::vector<ConstArrayIter>::iterator i =
1462 dataIters_.begin(); i != dataIters_.end(); ++i) {
1463 *i = comp->rowBegin(y_);
1474 const std::vector<Array>& comps_;
1475 typename std::vector<ConstArrayIter> dataIters_;
1500 int maxVal,
bool sgnd,
bool binaryFormat =
true)
1502 PnmGetData<T> getData(comps, maxVal, sgnd);
1503 return pnmEncode(outStream, comps[0].getWidth(), comps[0].getHeight(),
1504 comps.size(), maxVal, sgnd, getData, binaryFormat);
1539 bool sgnd,
bool binaryFormat =
true)
1542 sgnd, binaryFormat);
1562 bool binaryFormat =
true)
1564 std::vector<Array2<T> > comps;
1565 comps.push_back(red);
1566 comps.push_back(green);
1567 comps.push_back(blue);
1568 return encodePnm(outStream, comps, maxVal, sgnd, binaryFormat);
1587 int& maxVal,
bool& sgnd)
1589 PnmInitialize<T> initialize;
1591 if ((ret = pnmDecode(inStream, initialize))) {
1594 comps = initialize.comps_;
1595 maxVal = initialize.maxVal_;
1596 sgnd = initialize.sgnd_;
1618 std::vector<Array2<T> > comps;
1619 if ((ret =
decodePnm(inStream, comps, maxVal, sgnd))) {
1622 assert(maxVal == 1);
1645 std::vector<Array2<T> > comps;
1646 if ((ret =
decodePnm(inStream, comps, maxVal, sgnd))) {
1669 Array2<T>& blue,
int& maxVal,
bool& sgnd)
1672 std::vector<Array2<T> > comps;
1673 if ((ret =
decodePnm(inStream, comps, maxVal, sgnd))) {
void resize(int width, int height)
Change the size of the array.
Definition: Array2.hpp:1025
ConstXIterator rowEnd(int y) const
Get a const iterator for one past the end in the specified row of the array.
Definition: Array2.hpp:976
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:1147
T min() const
Get the minimum of the elements in the array.
Definition: Array2.hpp:1059
T & operator()(int x, int y)
Get a mutable reference to the (x,y)-th element in the array.
Definition: Array2.hpp:899
Array2< T > transpose(const Array2< T > &a)
Get the transpose of the array.
Definition: Array2.hpp:1235
T sum() const
Get the sum of the elements in the array.
Definition: Array2.hpp:1066
Definition: Arcball.hpp:48
Array2 & operator*=(const Array2 &a)
Multiply another array (elementwise) by this array.
Definition: Array2.hpp:804
void unshare() const
Force the underlying data to be copied if the data is shared.
Definition: Array2.hpp:1316
Array2< double > RealArray2
A two-dimensional array with real elements.
Definition: Array2.hpp:1696
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:1499
T ElemType
The type of the elements in the array.
Definition: Array2.hpp:166
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:1613
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:1200
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:1538
bool isSharedWith(const Array2 &a) const
Is the data for this array shared with the specified array?
Definition: Array2.hpp:889
bool isShared() const
Is the data for this array shared with another array?
Definition: Array2.hpp:883
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:1642
ConstYIterator colEnd(int x) const
Get a const iterator for one past the end in the specified column of the array.
Definition: Array2.hpp:1006
void dump(std::ostream &out) const
Output information about an array to a stream for debugging.
Definition: Array2.hpp:1290
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:1668
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
ConstXIterator rowBegin(int y) const
Get a const iterator for the first element in the specified row of the array.
Definition: Array2.hpp:961
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:1519
void fill(const T &value=T(0))
Set all elements in the array to the specified value.
Definition: Array2.hpp:1193
void swap(Array2 &a)
Swap the array data with the data of the specified array.
Definition: Array2.hpp:1182
A two-dimensional array class with lazy copying and reference counting.
Definition: Array2.hpp:83
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:1076
Array2 & operator/=(const Array2 &a)
Divide this array (elementwise) by another array.
Definition: Array2.hpp:814
ConstYIterator colBegin(int x) const
Get a const iterator for the first element in the specified column of the array.
Definition: Array2.hpp:991
T max() const
Get the maximum of the elements in the array.
Definition: Array2.hpp:1052
int load(const char *fileName)
Load an array from the file with the specified name.
Definition: Array2.hpp:1100
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
int getHeight() const
Get the height of the array.
Definition: Array2.hpp:870
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:1699
ConstIterator begin() const
Get a const iterator for the first element in the array.
Definition: Array2.hpp:935
int save(const char *fileName) const
Save an array to the file with the specified name.
Definition: Array2.hpp:1111
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:1586
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:1560
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:1280
ConstIterator end() const
Get a const iterator for one past the last element in the array.
Definition: Array2.hpp:948
bool operator==(const Array2< T > &a, const Array2< T > &b)
Test two arrays for equality.
Definition: Array2.hpp:1252
Array2 & fliplr()
Flip the array left to right.
Definition: Array2.hpp:1216
Array2 & operator-=(const Array2 &a)
Subtract another array (elementwise) from this array.
Definition: Array2.hpp:794
int getSize() const
Get the number of elements in the array.
Definition: Array2.hpp:876
int getWidth() const
Get the width of the array.
Definition: Array2.hpp:864