LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
LSSTDataManagementBasePackage
Image.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
29 #include <iostream>
30 #include "boost/mpl/vector.hpp"
31 #pragma clang diagnostic push
32 #pragma clang diagnostic ignored "-Wunused-variable"
33 #include "boost/lambda/lambda.hpp"
34 #pragma clang diagnostic pop
35 #include "boost/bind/bind.hpp"
36 #include "boost/format.hpp"
37 #include "boost/filesystem/path.hpp"
38 #include "boost/gil/gil_all.hpp"
39 
40 #include "lsst/pex/exceptions.h"
41 #include "lsst/afw/image/Image.h"
43 #include "lsst/afw/image/Wcs.h"
44 #include "lsst/afw/fits.h"
47 
48 namespace image = lsst::afw::image;
49 namespace geom = lsst::afw::geom;
50 
51 /************************************************************************************************************/
52 template <typename PixelT>
54  geom::Extent2I const & dimensions,
55  Manager::Ptr & manager
56 ) {
57  if (dimensions.getX() < 0 || dimensions.getY() < 0) {
58  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
59  str(boost::format("Both width and height must be non-negative: %d, %d")
60  % dimensions.getX() % dimensions.getY()));
61  }
62 
63  std::pair<Manager::Ptr,PixelT*> r = ndarray::SimpleManager<PixelT>::allocate(
64  dimensions.getX() * dimensions.getY()
65  );
66  manager = r.first;
67  return boost::gil::interleaved_view(
68  dimensions.getX(), dimensions.getY(),
69  (typename _view_t::value_type* )r.second,
70  dimensions.getX()*sizeof(PixelT)
71  );
72 }
73 template <typename PixelT>
75  geom::Extent2I const & dimensions, geom::Extent2I const & offset, const _view_t & view
76 ) {
77  if (offset.getX() < 0 || offset.getY() < 0 ||
78  offset.getX() + dimensions.getX() > view.width() ||
79  offset.getY() + dimensions.getY() > view.height()
80  ) {
81  throw LSST_EXCEPT(
82  lsst::pex::exceptions::LengthError,
83  (boost::format("Box2I(Point2I(%d,%d),Extent2I(%d,%d)) doesn't fit in image %dx%d") %
84  offset.getX() % offset.getY() %
85  dimensions.getX() % dimensions.getY() %
86  view.width() % view.height()
87  ).str()
88  );
89  }
90  return boost::gil::subimage_view(
91  view,
92  offset.getX(), offset.getY(),
93  dimensions.getX(), dimensions.getY()
94  );
95 }
96 
103 template <typename PixelT>
105  geom::Extent2I const & dimensions
106 ) : lsst::daf::base::Citizen(typeid(this)),
107  _origin(0,0), _manager(),
108  _gilView(_allocateView(dimensions, _manager))
109 {}
110 
116 template <typename PixelT>
118  geom::Box2I const & bbox
119 ) : lsst::daf::base::Citizen(typeid(this)),
120  _origin(bbox.getMin()), _manager(),
121  _gilView(_allocateView(bbox.getDimensions(), _manager))
122 {}
123 
130 template<typename PixelT>
132  ImageBase const& rhs,
133  bool const deep
134 ) :
136  lsst::daf::base::Citizen(typeid(this)),
137  _origin(rhs._origin),
138  _manager(rhs._manager),
139  _gilView(rhs._gilView)
140 {
141  if (deep) {
142  ImageBase tmp(getBBox());
143  tmp <<= *this; // now copy the pixels
144  swap(tmp);
145  }
146 }
147 
156 template<typename PixelT>
158  ImageBase const& rhs,
159  geom::Box2I const& bbox,
160  ImageOrigin const origin,
161  bool const deep
162 ) :
164  lsst::daf::base::Citizen(typeid(this)),
165  _origin((origin==PARENT) ? bbox.getMin(): rhs._origin + geom::Extent2I(bbox.getMin())),
166  _manager(rhs._manager), // reference counted pointer, don't copy pixels
167  _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView))
168 {
169  if (deep) {
170  ImageBase tmp(getBBox());
171  tmp <<= *this; // now copy the pixels
172  swap(tmp);
173  }
174 }
175 
185 template<typename PixelT>
186 image::ImageBase<PixelT>::ImageBase(Array const & array, bool deep, geom::Point2I const & xy0) :
187  lsst::daf::base::Citizen(typeid(this)),
188  _origin(xy0),
189  _manager(array.getManager()),
190  _gilView(
191  boost::gil::interleaved_view(
192  array.template getSize<1>(), array.template getSize<0>(),
193  (typename _view_t::value_type* )array.getData(),
194  array.template getStride<0>() * sizeof(PixelT)
195  )
196  )
197 {
198  if (deep) {
199  ImageBase tmp(*this, true);
200  swap(tmp);
201  }
202 }
203 
211 template<typename PixelT>
213  ImageBase tmp(rhs);
214  swap(tmp); // See Meyers, Effective C++, Item 11
215 
216  return *this;
217 }
218 
220 template<typename PixelT>
222  if (getDimensions() != rhs.getDimensions()) {
223  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
224  (boost::format("Dimension mismatch: %dx%d v. %dx%d") %
225  getWidth() % getHeight() % rhs.getWidth() % rhs.getHeight()).str());
226  }
227  copy_pixels(rhs._gilView, _gilView);
228 }
229 
231 template<typename PixelT>
233  return const_cast<typename image::ImageBase<PixelT>::PixelReference>(
234  static_cast<typename image::ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0])
235  );
236 }
237 
239 template<typename PixelT>
241  int x,
242  int y,
243  image::CheckIndices const& check
244  )
245 {
246  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
247  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
248  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") %
249  x % y % (getWidth() - 1) % (getHeight() - 1)).str());
250  }
251 
252  return const_cast<typename image::ImageBase<PixelT>::PixelReference>(
253  static_cast<typename image::ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0])
254  );
255 }
256 
258 template<typename PixelT>
261  return _gilView(x, y)[0];
262 }
263 
265 template<typename PixelT>
268  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
269  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
270  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") %
271  x % y % (this->getWidth() - 1) % (this->getHeight() - 1)).str());
272  }
273 
274  return _gilView(x, y)[0];
275 }
276 
277 template<typename PixelT>
279  using std::swap; // See Meyers, Effective C++, Item 25
280 
281  swap(_manager, rhs._manager); // just swapping the pointers
282  swap(_gilView, rhs._gilView);
283  swap(_origin, rhs._origin);
284 }
285 
286 template<typename PixelT>
288  a.swap(b);
289 }
290 
291 template <typename PixelT>
293  int rowStride = reinterpret_cast<PixelT*>(row_begin(1)) - reinterpret_cast<PixelT*>(row_begin(0));
294  return ndarray::external(
295  reinterpret_cast<PixelT*>(row_begin(0)),
296  ndarray::makeVector(getHeight(), getWidth()),
297  ndarray::makeVector(rowStride, 1),
298  this->_manager
299  );
300 }
301 
302 
303 template <typename PixelT>
305  int rowStride = reinterpret_cast<PixelT*>(row_begin(1)) - reinterpret_cast<PixelT*>(row_begin(0));
306  return ndarray::external(
307  reinterpret_cast<PixelT*>(row_begin(0)),
308  ndarray::makeVector(getHeight(), getWidth()),
309  ndarray::makeVector(rowStride, 1),
310  this->_manager
311  );
312 }
313 //
314 // Iterators
315 //
320 template<typename PixelT>
322  return _gilView.begin();
323 }
324 
326 template<typename PixelT>
328  return _gilView.end();
329 }
330 
332 template<typename PixelT>
334  return _gilView.rbegin();
335 }
336 
338 template<typename PixelT>
340  return _gilView.rend();
341 }
342 
344 template<typename PixelT>
346  return _gilView.at(x, y);
347 }
348 
353 template<typename PixelT>
355  bool contiguous
356 ) const {
357  if (!contiguous) {
358  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
359  "Only contiguous == true makes sense");
360  }
361  if (!this->isContiguous()) {
362  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
363  "Image's pixels are not contiguous");
364  }
365 
366  return row_begin(0);
367 }
368 
373 template<typename PixelT>
375  bool contiguous
376 ) const {
377  if (!contiguous) {
378  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
379  "Only contiguous == true makes sense");
380  }
381  if (!this->isContiguous()) {
382  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
383  "Image's pixels are not contiguous");
384  }
385 
386  return row_end(getHeight()-1);
387 }
388 
389 /************************************************************************************************************/
391 template<typename PixelT>
393  fill_pixels(_gilView, rhs);
394 
395  return *this;
396 }
397 
398 /************************************************************************************************************/
399 //
400 // On to Image itself. ctors, cctors, and operator=
401 //
408 template<typename PixelT>
409 image::Image<PixelT>::Image(unsigned int width,
410  unsigned int height,
411  PixelT initialValue
412  ) :
413  image::ImageBase<PixelT>(geom::ExtentI(width, height))
414 {
415  *this = initialValue;
416 }
417 
424 template<typename PixelT>
426  PixelT initialValue
427  ) :
428  image::ImageBase<PixelT>(dimensions)
429 {
430  *this = initialValue;
431 }
432 
436 template<typename PixelT>
438  PixelT initialValue
439  ) :
440  image::ImageBase<PixelT>(bbox) {
441  *this = initialValue;
442 }
443 
450 template<typename PixelT>
452  bool const deep
453  ) :
455  image::ImageBase<PixelT>(rhs, deep) {}
456 
465 template<typename PixelT>
467  geom::Box2I const& bbox,
468  ImageOrigin const origin,
469  bool const deep
470  ) :
472  image::ImageBase<PixelT>(rhs, bbox, origin, deep) {}
473 
475 template<typename PixelT>
477  this->ImageBase<PixelT>::operator=(rhs);
478 
479  return *this;
480 }
481 
489 template<typename PixelT>
491  this->ImageBase<PixelT>::operator=(rhs);
492 
493  return *this;
494 }
495 
496 /************************************************************************************************************/
497 
498 #ifndef DOXYGEN // doc for this section has been moved to header
499 
500 template<typename PixelT>
502  std::string const & fileName,
503  int hdu,
504  PTR(daf::base::PropertySet) metadata,
505  geom::Box2I const & bbox,
506  ImageOrigin origin
507 ) : image::ImageBase<PixelT>() {
508  fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
509  fitsfile.setHdu(hdu);
510  try {
511  *this = Image(fitsfile, metadata, bbox, origin);
512  } catch(lsst::afw::fits::FitsError &e) {
513  fitsfile.status = 0; // reset so we can read NAXIS
514  if (fitsfile.getImageDim() == 0) { // no pixels to read
515  LSST_EXCEPT_ADD(e, str(boost::format("HDU %d has NAXIS == 0") % hdu));
516  }
517  throw e;
518  }
519 }
520 template<typename PixelT>
522  fits::MemFileManager & manager,
523  int const hdu,
524  PTR(daf::base::PropertySet) metadata,
525  geom::Box2I const& bbox,
526  ImageOrigin const origin
527 ) : image::ImageBase<PixelT>() {
528  fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
529  fitsfile.setHdu(hdu);
530  *this = Image(fitsfile, metadata, bbox, origin);
531 }
532 
533 template<typename PixelT>
535  fits::Fits & fitsfile,
536  PTR(daf::base::PropertySet) metadata,
537  geom::Box2I const& bbox,
538  ImageOrigin const origin
539 ) : image::ImageBase<PixelT>() {
540 
541  typedef boost::mpl::vector<
542  unsigned char,
543  unsigned short,
544  short,
545  int,
546  unsigned int,
547  float,
548  double,
549  boost::uint64_t
550  > fits_image_types;
551 
552  if (!metadata) {
553  metadata.reset(new daf::base::PropertyList());
554  }
555 
556  fits_read_image<fits_image_types>(fitsfile, *this, *metadata, bbox, origin);
557 }
558 
559 template<typename PixelT>
561  std::string const & fileName,
563  std::string const & mode
564 ) const {
565  fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
566  writeFits(fitsfile, metadata_i);
567 }
568 
569 template<typename PixelT>
571  fits::MemFileManager & manager,
573  std::string const & mode
574 ) const {
575  fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
576  writeFits(fitsfile, metadata_i);
577 }
578 
579 template<typename PixelT>
581  fits::Fits & fitsfile,
583 ) const {
584  PTR(daf::base::PropertySet) metadata;
585  PTR(daf::base::PropertySet) wcsAMetadata =
587  this->getX0(), this->getY0());
588  if (metadata_i) {
589  metadata = metadata_i->deepCopy();
590  metadata->combine(wcsAMetadata);
591  } else {
592  metadata = wcsAMetadata;
593  }
594  image::fits_write_image(fitsfile, *this, metadata);
595 }
596 
597 #endif // !DOXYGEN
598 
599 /************************************************************************************************************/
600 
601 template<typename PixelT>
603  using std::swap; // See Meyers, Effective C++, Item 25
605  ; // no private variables to swap
606 }
607 
608 template<typename PixelT>
610  a.swap(b);
611 }
612 
613 /************************************************************************************************************/
614 //
615 // N.b. We could use the STL, but I find boost::lambda clearer, and more easily extended
616 // to e.g. setting random numbers
617 // transform_pixels(_gilView, _gilView, lambda::ret<PixelT>(lambda::_1 + rhs));
618 // is equivalent to
619 // transform_pixels(_gilView, _gilView, std::bind2nd(std::plus<PixelT>(), rhs));
620 //
621 namespace bl = boost::lambda;
622 
623 // dstn: being a bear of little brain when it comes to templated lambdas, I found it easier to
624 // write out this sqrt function which does the casts explicitly.
625 template<typename PixelT>
626 static PixelT mysqrt(PixelT x) {
627  return static_cast<PixelT>(std::sqrt(x));
628 }
629 
630 // In-place, per-pixel, sqrt().
631 template<typename PixelT>
633  transform_pixels(_getRawView(), _getRawView(),
634  boost::bind(mysqrt<PixelT>, bl::_1));
635 }
636 
638 template<typename PixelT>
640  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 + rhs));
641 }
642 
644 template<typename PixelT>
646  if (this->getDimensions() != rhs.getDimensions()) {
647  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
648  (boost::format("Images are of different size, %dx%d v %dx%d") %
649  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
650  }
651  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 + bl::_2));
652 }
653 
657 template<typename PixelT>
659  lsst::afw::math::Function2<double> const& function
660  ) {
661  for (int y = 0; y != this->getHeight(); ++y) {
662  double const yPos = this->indexToPosition(y, image::Y);
663  double xPos = this->indexToPosition(0, image::X);
664  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y);
665  ptr != end; ++ptr, ++xPos) {
666  *ptr += function(xPos, yPos);
667  }
668  }
669 }
670 
672 template<typename PixelT>
673 void image::Image<PixelT>::scaledPlus(double const c, Image<PixelT> const& rhs) {
674  if (this->getDimensions() != rhs.getDimensions()) {
675  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
676  (boost::format("Images are of different size, %dx%d v %dx%d") %
677  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
678  }
679  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
680  bl::ret<PixelT>(bl::_1 + bl::ret<PixelT>(c*bl::_2)));
681 }
682 
684 template<typename PixelT>
686  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 - rhs));
687 }
688 
690 template<typename PixelT>
692  if (this->getDimensions() != rhs.getDimensions()) {
693  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
694  (boost::format("Images are of different size, %dx%d v %dx%d") %
695  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
696  }
697  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 - bl::_2));
698 }
699 
701 template<typename PixelT>
702 void image::Image<PixelT>::scaledMinus(double const c, Image<PixelT> const& rhs) {
703  if (this->getDimensions() != rhs.getDimensions()) {
704  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
705  (boost::format("Images are of different size, %dx%d v %dx%d") %
706  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
707  }
708  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
709  bl::ret<PixelT>(bl::_1 - bl::ret<PixelT>(c*bl::_2)));
710 }
711 
715 template<typename PixelT>
717  lsst::afw::math::Function2<double> const& function
718  ) {
719  for (int y = 0; y != this->getHeight(); ++y) {
720  double const yPos = this->indexToPosition(y, image::Y);
721  double xPos = this->indexToPosition(0, image::X);
722  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y);
723  ptr != end; ++ptr, ++xPos) {
724  *ptr -= function(xPos, yPos);
725  }
726  }
727 }
728 
730 template<typename PixelT>
732  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 * rhs));
733 }
734 
736 template<typename PixelT>
738  if (this->getDimensions() != rhs.getDimensions()) {
739  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
740  (boost::format("Images are of different size, %dx%d v %dx%d") %
741  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
742  }
743  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 * bl::_2));
744 }
745 
747 template<typename PixelT>
748 void image::Image<PixelT>::scaledMultiplies(double const c, Image<PixelT> const& rhs) {
749  if (this->getDimensions() != rhs.getDimensions()) {
750  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
751  (boost::format("Images are of different size, %dx%d v %dx%d") %
752  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
753  }
754  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
755  bl::ret<PixelT>(bl::_1 * bl::ret<PixelT>(c*bl::_2)));
756 }
757 
761 template<typename PixelT>
763  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 / rhs));
764 }
765 //
766 // Specialize float and double for efficiency
767 //
768 namespace lsst { namespace afw { namespace image {
769 template<>
770 void Image<double>::operator/=(double const rhs) {
771  double const irhs = 1/rhs;
772  *this *= irhs;
773 }
774 
775 template<>
776 void Image<float>::operator/=(float const rhs) {
777  float const irhs = 1/rhs;
778  *this *= irhs;
779 }
780 }}}
781 
783 template<typename PixelT>
785  if (this->getDimensions() != rhs.getDimensions()) {
786  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
787  (boost::format("Images are of different size, %dx%d v %dx%d") %
788  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
789  }
790  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 / bl::_2));
791 }
792 
794 template<typename PixelT>
795 void image::Image<PixelT>::scaledDivides(double const c, Image<PixelT> const& rhs) {
796  if (this->getDimensions() != rhs.getDimensions()) {
797  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
798  (boost::format("Images are of different size, %dx%d v %dx%d") %
799  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
800  }
801  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
802  bl::ret<PixelT>(bl::_1 / bl::ret<PixelT>(c*bl::_2)));
803 }
804 
805 /************************************************************************************************************/
806 
807 namespace {
808 /*
809  * Worker routine for manipulating images;
810  */
811 template<typename LhsPixelT, typename RhsPixelT>
812 struct plusEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
813  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
814  return static_cast<LhsPixelT>(lhs + rhs);
815  }
816 };
817 
818 template<typename LhsPixelT, typename RhsPixelT>
819 struct minusEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
820  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
821  return static_cast<LhsPixelT>(lhs - rhs);
822  }
823 };
824 
825 template<typename LhsPixelT, typename RhsPixelT>
826 struct timesEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
827  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
828  return static_cast<LhsPixelT>(lhs*rhs);
829  }
830 };
831 
832 template<typename LhsPixelT, typename RhsPixelT>
833 struct divideEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
834  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
835  return static_cast<LhsPixelT>(lhs/rhs);
836  }
837 };
838 }
839 
842 template<typename LhsPixelT, typename RhsPixelT>
844  image::for_each_pixel(lhs, rhs, plusEq<LhsPixelT, RhsPixelT>());
845 }
846 
849 template<typename LhsPixelT, typename RhsPixelT>
851  image::for_each_pixel(lhs, rhs, minusEq<LhsPixelT, RhsPixelT>());
852 }
853 
856 template<typename LhsPixelT, typename RhsPixelT>
858  image::for_each_pixel(lhs, rhs, timesEq<LhsPixelT, RhsPixelT>());
859 }
860 
863 template<typename LhsPixelT, typename RhsPixelT>
865  image::for_each_pixel(lhs, rhs, divideEq<LhsPixelT, RhsPixelT>());
866 }
867 
868 /************************************************************************************************************/
869 //
870 // Explicit instantiations
871 //
873 #define INSTANTIATE_OPERATOR(OP_EQ, T) \
874  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<boost::uint16_t> const& rhs); \
875  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<int> const& rhs); \
876  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<float> const& rhs); \
877  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<double> const& rhs); \
878  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<boost::uint64_t> const& rhs);
879 
880 #define INSTANTIATE(T) \
881  template class image::ImageBase<T>; \
882  template class image::Image<T>; \
883  INSTANTIATE_OPERATOR(+=, T); \
884  INSTANTIATE_OPERATOR(-=, T); \
885  INSTANTIATE_OPERATOR(*=, T); \
886  INSTANTIATE_OPERATOR(/=, T)
887 
888 INSTANTIATE(boost::uint16_t);
889 INSTANTIATE(int);
890 INSTANTIATE(float);
891 INSTANTIATE(double);
892 INSTANTIATE(boost::uint64_t);
iterator at(int x, int y) const
Return an STL compliant iterator at the point (x, y)
Definition: Image.cc:345
void scaledDivides(double const c, Image< PixelT >const &rhs)
Divide lhs by Image c*rhs (i.e. pixel-by-pixel division)
Definition: Image.cc:795
iterator end() const
Return an STL compliant iterator to the end of the image.
Definition: Image.cc:327
View< boost::fusion::vector1< index::Full > > view()
Start a view definition that includes the entire first dimension.
Definition: views.h:131
x_iterator fast_iterator
Definition: Image.h:154
#define PTR(...)
Definition: base.h:41
reverse_iterator rend() const
Return an STL compliant reverse iterator to the end of the image.
Definition: Image.cc:339
ConstReference< PixelT >::type PixelConstReference
A ConstReference to a PixelT.
Definition: Image.h:137
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:54
_view_t::reverse_iterator reverse_iterator
An STL compliant reverse iterator.
Definition: Image.h:147
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
Definition: Image.cc:287
int y
afw::table::Key< afw::table::Point< int > > dimensions
detail::ExternalInitializer< T, N, Owner > external(T *data, Vector< int, N > const &shape, Vector< int, N > const &strides, Owner const &owner)
Create an expression that initializes an Array with externally allocated memory.
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
Definition: Image.h:151
void operator/=(PixelT const rhs)
Definition: Image.cc:762
geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Definition: Image.h:377
static _view_t _makeSubView(geom::Extent2I const &dimensions, geom::Extent2I const &offset, const _view_t &view)
Definition: Image.cc:74
void for_each_pixel(Image< LhsT > &lhs, pixelOp0< LhsT > const &func)
lsst::daf::base::PropertyList PropertyList
Definition: Wcs.cc:58
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:194
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition: Image.h:115
Extent< int, 2 > Extent2I
Definition: Extent.h:350
void operator*=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:857
void writeFits(std::string const &fileName, boost::shared_ptr< lsst::daf::base::PropertySet const > metadata=boost::shared_ptr< lsst::daf::base::PropertySet const >(), std::string const &mode="w") const
Write an image to a regular FITS file.
An integer coordinate rectangle.
Definition: Box.h:53
void operator<<=(const ImageBase &rhs)
Set the lhs&#39;s pixel values to equal the rhs&#39;s.
Definition: Image.cc:221
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
void scaledPlus(double const c, Image< PixelT >const &rhs)
Add Image c*rhs to lhs.
Definition: Image.cc:673
lsst::daf::base::PropertySet PropertySet
Definition: Wcs.cc:57
_view_t::iterator iterator
An STL compliant iterator.
Definition: Image.h:143
geom::Point2I _origin
Definition: Image.h:384
boost::intrusive_ptr< Manager > Ptr
Definition: Manager.h:42
Image & operator=(const PixelT rhs)
Set the image&#39;s pixels to rhs.
Definition: Image.cc:476
Include files required for standard LSST Exception handling.
void operator*=(PixelT const rhs)
Multiply lhs by scalar rhs.
Definition: Image.cc:731
lsst::afw::image::detail::types_traits< PixelT >::view_t _view_t
Definition: Image.h:118
geom::Extent2I getDimensions() const
Return the image&#39;s size; useful for passing to constructors.
Definition: Image.h:298
int x
_view_t _getRawView() const
Definition: Image.h:401
Vector< T, N > makeVector(T v1, T v2,..., T vN)
Variadic constructor for Vector.
friend class ImageBase
Definition: Image.h:170
Support for 2-D images.
A class used to request that array accesses be checked.
Definition: Image.h:87
int getHeight() const
Return the number of rows in the image.
Definition: Image.h:239
boost::shared_ptr< lsst::daf::base::PropertyList > createTrivialWcsAsPropertySet(std::string const &wcsName, int const x0=0, int const y0=0)
Definition: Wcs.cc:1228
void operator+=(PixelT const rhs)
Add scalar rhs to lhs.
Definition: Image.cc:639
void swap(ImageBase &rhs)
Definition: Image.cc:278
#define CONST_PTR(...)
Definition: base.h:47
void operator-=(PixelT const rhs)
Subtract scalar rhs from lhs.
Definition: Image.cc:685
Support for functors over Image&#39;s pixels.
Extent< int, 2 > ExtentI
Definition: Extent.h:347
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
A multidimensional strided array.
Definition: Array.h:47
Manager::Ptr _manager
Definition: Image.h:385
static _view_t _allocateView(geom::Extent2I const &dimensions, Manager::Ptr &manager)
Definition: Image.cc:53
void scaledMinus(double const c, Image< PixelT >const &rhs)
Subtract Image c*rhs from lhs.
Definition: Image.cc:702
#define INSTANTIATE(T)
Class for storing generic metadata.
Definition: PropertySet.h:82
void operator/=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:864
Reference< PixelT >::type PixelReference
A Reference to a PixelT.
Definition: Image.h:135
afw::table::Key< double > b
void scaledMultiplies(double const c, Image< PixelT >const &rhs)
Multiply lhs by Image c*rhs (i.e. pixel-by-pixel multiplication)
Definition: Image.cc:748
void operator-=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:850
iterator begin() const
Definition: Image.cc:321
reverse_iterator rbegin() const
Return an STL compliant reverse iterator to the start of the image.
Definition: Image.cc:333
friend class Image
Definition: Image.h:431
static std::pair< Manager::Ptr, T * > allocate(int size)
Definition: Manager.h:71
int getWidth() const
Return the number of columns in the image.
Definition: Image.h:237
#define LSST_EXCEPT_ADD(e, m)
Definition: Exception.h:51
void swap(Image &rhs)
Definition: Image.cc:602
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
void fits_write_image(fits::Fits &fitsfile, const ImageT &image, boost::shared_ptr< daf::base::PropertySet const > metadata=boost::shared_ptr< daf::base::PropertySet const >())
Definition: fits_io.h:104
std::string const wcsNameForXY0
Definition: Image.h:82
ImageBase & operator=(const ImageBase &rhs)
Definition: Image.cc:212
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y)
Definition: Image.cc:232
Eigen::Vector3d _origin
Definition: attributes.cc:152
void operator+=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:843