LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
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  if (dimensions.getX() != 0 && dimensions.getY() > std::numeric_limits<int>::max()/dimensions.getX()) {
63  throw LSST_EXCEPT(pex::exceptions::LengthError,
64  str(boost::format("Image dimensions (%d x %d) too large; int overflow detected.")
65  % dimensions.getX() % dimensions.getY()));
66  }
67  std::pair<Manager::Ptr,PixelT*> r = ndarray::SimpleManager<PixelT>::allocate(
68  dimensions.getX() * dimensions.getY()
69  );
70  manager = r.first;
71  return boost::gil::interleaved_view(
72  dimensions.getX(), dimensions.getY(),
73  (typename _view_t::value_type* )r.second,
74  dimensions.getX()*sizeof(PixelT)
75  );
76 }
77 template <typename PixelT>
79  geom::Extent2I const & dimensions, geom::Extent2I const & offset, const _view_t & view
80 ) {
81  if (offset.getX() < 0 || offset.getY() < 0 ||
82  offset.getX() + dimensions.getX() > view.width() ||
83  offset.getY() + dimensions.getY() > view.height()
84  ) {
85  throw LSST_EXCEPT(
86  lsst::pex::exceptions::LengthError,
87  (boost::format("Box2I(Point2I(%d,%d),Extent2I(%d,%d)) doesn't fit in image %dx%d") %
88  offset.getX() % offset.getY() %
89  dimensions.getX() % dimensions.getY() %
90  view.width() % view.height()
91  ).str()
92  );
93  }
94  return boost::gil::subimage_view(
95  view,
96  offset.getX(), offset.getY(),
97  dimensions.getX(), dimensions.getY()
98  );
99 }
100 
107 template <typename PixelT>
109  geom::Extent2I const & dimensions
110 ) : lsst::daf::base::Citizen(typeid(this)),
111  _origin(0,0), _manager(),
112  _gilView(_allocateView(dimensions, _manager))
113 {}
114 
120 template <typename PixelT>
122  geom::Box2I const & bbox
123 ) : lsst::daf::base::Citizen(typeid(this)),
124  _origin(bbox.getMin()), _manager(),
125  _gilView(_allocateView(bbox.getDimensions(), _manager))
126 {}
127 
134 template<typename PixelT>
136  ImageBase const& rhs,
137  bool const deep
138 ) :
140  lsst::daf::base::Citizen(typeid(this)),
141  _origin(rhs._origin),
142  _manager(rhs._manager),
143  _gilView(rhs._gilView)
144 {
145  if (deep) {
146  ImageBase tmp(getBBox());
147  tmp <<= *this; // now copy the pixels
148  swap(tmp);
149  }
150 }
151 
160 template<typename PixelT>
162  ImageBase const& rhs,
163  geom::Box2I const& bbox,
164  ImageOrigin const origin,
165  bool const deep
166 ) :
168  lsst::daf::base::Citizen(typeid(this)),
169  _origin((origin==PARENT) ? bbox.getMin(): rhs._origin + geom::Extent2I(bbox.getMin())),
170  _manager(rhs._manager), // reference counted pointer, don't copy pixels
171  _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView))
172 {
173  if (deep) {
174  ImageBase tmp(getBBox());
175  tmp <<= *this; // now copy the pixels
176  swap(tmp);
177  }
178 }
179 
189 template<typename PixelT>
190 image::ImageBase<PixelT>::ImageBase(Array const & array, bool deep, geom::Point2I const & xy0) :
191  lsst::daf::base::Citizen(typeid(this)),
192  _origin(xy0),
193  _manager(array.getManager()),
194  _gilView(
195  boost::gil::interleaved_view(
196  array.template getSize<1>(), array.template getSize<0>(),
197  (typename _view_t::value_type* )array.getData(),
198  array.template getStride<0>() * sizeof(PixelT)
199  )
200  )
201 {
202  if (deep) {
203  ImageBase tmp(*this, true);
204  swap(tmp);
205  }
206 }
207 
215 template<typename PixelT>
217  ImageBase tmp(rhs);
218  swap(tmp); // See Meyers, Effective C++, Item 11
219 
220  return *this;
221 }
222 
224 template<typename PixelT>
226  if (getDimensions() != rhs.getDimensions()) {
227  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
228  (boost::format("Dimension mismatch: %dx%d v. %dx%d") %
229  getWidth() % getHeight() % rhs.getWidth() % rhs.getHeight()).str());
230  }
231  copy_pixels(rhs._gilView, _gilView);
232 }
233 
235 template<typename PixelT>
237  return const_cast<typename image::ImageBase<PixelT>::PixelReference>(
238  static_cast<typename image::ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0])
239  );
240 }
241 
243 template<typename PixelT>
245  int x,
246  int y,
247  image::CheckIndices const& check
248  )
249 {
250  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
251  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
252  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") %
253  x % y % (getWidth() - 1) % (getHeight() - 1)).str());
254  }
255 
256  return const_cast<typename image::ImageBase<PixelT>::PixelReference>(
257  static_cast<typename image::ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0])
258  );
259 }
260 
262 template<typename PixelT>
265  return _gilView(x, y)[0];
266 }
267 
269 template<typename PixelT>
272  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
273  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
274  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") %
275  x % y % (this->getWidth() - 1) % (this->getHeight() - 1)).str());
276  }
277 
278  return _gilView(x, y)[0];
279 }
280 
281 template<typename PixelT>
283  using std::swap; // See Meyers, Effective C++, Item 25
284 
285  swap(_manager, rhs._manager); // just swapping the pointers
286  swap(_gilView, rhs._gilView);
287  swap(_origin, rhs._origin);
288 }
289 
290 template<typename PixelT>
292  a.swap(b);
293 }
294 
295 template <typename PixelT>
297  int rowStride = reinterpret_cast<PixelT*>(row_begin(1)) - reinterpret_cast<PixelT*>(row_begin(0));
298  return ndarray::external(
299  reinterpret_cast<PixelT*>(row_begin(0)),
300  ndarray::makeVector(getHeight(), getWidth()),
301  ndarray::makeVector(rowStride, 1),
302  this->_manager
303  );
304 }
305 
306 
307 template <typename PixelT>
309  int rowStride = reinterpret_cast<PixelT*>(row_begin(1)) - reinterpret_cast<PixelT*>(row_begin(0));
310  return ndarray::external(
311  reinterpret_cast<PixelT*>(row_begin(0)),
312  ndarray::makeVector(getHeight(), getWidth()),
313  ndarray::makeVector(rowStride, 1),
314  this->_manager
315  );
316 }
317 //
318 // Iterators
319 //
324 template<typename PixelT>
326  return _gilView.begin();
327 }
328 
330 template<typename PixelT>
332  return _gilView.end();
333 }
334 
336 template<typename PixelT>
338  return _gilView.rbegin();
339 }
340 
342 template<typename PixelT>
344  return _gilView.rend();
345 }
346 
348 template<typename PixelT>
350  return _gilView.at(x, y);
351 }
352 
357 template<typename PixelT>
359  bool contiguous
360 ) const {
361  if (!contiguous) {
362  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
363  "Only contiguous == true makes sense");
364  }
365  if (!this->isContiguous()) {
366  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
367  "Image's pixels are not contiguous");
368  }
369 
370  return row_begin(0);
371 }
372 
377 template<typename PixelT>
379  bool contiguous
380 ) const {
381  if (!contiguous) {
382  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
383  "Only contiguous == true makes sense");
384  }
385  if (!this->isContiguous()) {
386  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
387  "Image's pixels are not contiguous");
388  }
389 
390  return row_end(getHeight()-1);
391 }
392 
393 /************************************************************************************************************/
395 template<typename PixelT>
397  fill_pixels(_gilView, rhs);
398 
399  return *this;
400 }
401 
402 /************************************************************************************************************/
403 //
404 // On to Image itself. ctors, cctors, and operator=
405 //
412 template<typename PixelT>
414  unsigned int height,
415  PixelT initialValue
416  ) :
417  image::ImageBase<PixelT>(geom::ExtentI(width, height))
418 {
419  *this = initialValue;
420 }
421 
428 template<typename PixelT>
430  PixelT initialValue
431  ) :
432  image::ImageBase<PixelT>(dimensions)
433 {
434  *this = initialValue;
435 }
436 
440 template<typename PixelT>
442  PixelT initialValue
443  ) :
444  image::ImageBase<PixelT>(bbox) {
445  *this = initialValue;
446 }
447 
454 template<typename PixelT>
456  bool const deep
457  ) :
459  image::ImageBase<PixelT>(rhs, deep) {}
460 
469 template<typename PixelT>
471  geom::Box2I const& bbox,
472  ImageOrigin const origin,
473  bool const deep
474  ) :
476  image::ImageBase<PixelT>(rhs, bbox, origin, deep) {}
477 
479 template<typename PixelT>
481  this->ImageBase<PixelT>::operator=(rhs);
482 
483  return *this;
484 }
485 
493 template<typename PixelT>
495  this->ImageBase<PixelT>::operator=(rhs);
496 
497  return *this;
498 }
499 
500 /************************************************************************************************************/
501 
502 #ifndef DOXYGEN // doc for this section has been moved to header
503 
504 template<typename PixelT>
506  std::string const & fileName,
507  int hdu,
508  PTR(daf::base::PropertySet) metadata,
509  geom::Box2I const & bbox,
510  ImageOrigin origin
511 ) : image::ImageBase<PixelT>() {
512  fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
513  fitsfile.setHdu(hdu);
514  try {
515  *this = Image(fitsfile, metadata, bbox, origin);
516  } catch(lsst::afw::fits::FitsError &e) {
517  fitsfile.status = 0; // reset so we can read NAXIS
518  if (fitsfile.getImageDim() == 0) { // no pixels to read
519  LSST_EXCEPT_ADD(e, str(boost::format("HDU %d has NAXIS == 0") % hdu));
520  }
521  throw e;
522  }
523 }
524 template<typename PixelT>
526  fits::MemFileManager & manager,
527  int const hdu,
528  PTR(daf::base::PropertySet) metadata,
529  geom::Box2I const& bbox,
530  ImageOrigin const origin
531 ) : image::ImageBase<PixelT>() {
532  fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
533  fitsfile.setHdu(hdu);
534  *this = Image(fitsfile, metadata, bbox, origin);
535 }
536 
537 template<typename PixelT>
539  fits::Fits & fitsfile,
540  PTR(daf::base::PropertySet) metadata,
541  geom::Box2I const& bbox,
542  ImageOrigin const origin
543 ) : image::ImageBase<PixelT>() {
544 
545  typedef boost::mpl::vector<
546  unsigned char,
547  unsigned short,
548  short,
549  int,
550  unsigned int,
551  float,
552  double,
553  boost::uint64_t
554  > fits_image_types;
555 
556  if (!metadata) {
557  metadata.reset(new daf::base::PropertyList());
558  }
559 
560  fits_read_image<fits_image_types>(fitsfile, *this, *metadata, bbox, origin);
561 }
562 
563 template<typename PixelT>
565  std::string const & fileName,
567  std::string const & mode
568 ) const {
569  fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
570  writeFits(fitsfile, metadata_i);
571 }
572 
573 template<typename PixelT>
575  fits::MemFileManager & manager,
577  std::string const & mode
578 ) const {
579  fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
580  writeFits(fitsfile, metadata_i);
581 }
582 
583 template<typename PixelT>
585  fits::Fits & fitsfile,
587 ) const {
588  PTR(daf::base::PropertySet) metadata;
589  PTR(daf::base::PropertySet) wcsAMetadata =
591  this->getX0(), this->getY0());
592  if (metadata_i) {
593  metadata = metadata_i->deepCopy();
594  metadata->combine(wcsAMetadata);
595  } else {
596  metadata = wcsAMetadata;
597  }
598  image::fits_write_image(fitsfile, *this, metadata);
599 }
600 
601 #endif // !DOXYGEN
602 
603 /************************************************************************************************************/
604 
605 template<typename PixelT>
607  using std::swap; // See Meyers, Effective C++, Item 25
609  ; // no private variables to swap
610 }
611 
612 template<typename PixelT>
614  a.swap(b);
615 }
616 
617 /************************************************************************************************************/
618 //
619 // N.b. We could use the STL, but I find boost::lambda clearer, and more easily extended
620 // to e.g. setting random numbers
621 // transform_pixels(_gilView, _gilView, lambda::ret<PixelT>(lambda::_1 + rhs));
622 // is equivalent to
623 // transform_pixels(_gilView, _gilView, std::bind2nd(std::plus<PixelT>(), rhs));
624 //
625 namespace bl = boost::lambda;
626 
627 // dstn: being a bear of little brain when it comes to templated lambdas, I found it easier to
628 // write out this sqrt function which does the casts explicitly.
629 template<typename PixelT>
630 static PixelT mysqrt(PixelT x) {
631  return static_cast<PixelT>(std::sqrt(x));
632 }
633 
634 // In-place, per-pixel, sqrt().
635 template<typename PixelT>
637  transform_pixels(_getRawView(), _getRawView(),
638  boost::bind(mysqrt<PixelT>, bl::_1));
639 }
640 
642 template<typename PixelT>
644  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 + rhs));
645 }
646 
648 template<typename PixelT>
650  if (this->getDimensions() != rhs.getDimensions()) {
651  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
652  (boost::format("Images are of different size, %dx%d v %dx%d") %
653  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
654  }
655  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 + bl::_2));
656 }
657 
661 template<typename PixelT>
663  lsst::afw::math::Function2<double> const& function
664  ) {
665  for (int y = 0; y != this->getHeight(); ++y) {
666  double const yPos = this->indexToPosition(y, image::Y);
667  double xPos = this->indexToPosition(0, image::X);
668  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y);
669  ptr != end; ++ptr, ++xPos) {
670  *ptr += function(xPos, yPos);
671  }
672  }
673 }
674 
676 template<typename PixelT>
677 void image::Image<PixelT>::scaledPlus(double const c, Image<PixelT> const& rhs) {
678  if (this->getDimensions() != rhs.getDimensions()) {
679  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
680  (boost::format("Images are of different size, %dx%d v %dx%d") %
681  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
682  }
683  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
684  bl::ret<PixelT>(bl::_1 + bl::ret<PixelT>(c*bl::_2)));
685 }
686 
688 template<typename PixelT>
690  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 - rhs));
691 }
692 
694 template<typename PixelT>
696  if (this->getDimensions() != rhs.getDimensions()) {
697  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
698  (boost::format("Images are of different size, %dx%d v %dx%d") %
699  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
700  }
701  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 - bl::_2));
702 }
703 
705 template<typename PixelT>
706 void image::Image<PixelT>::scaledMinus(double const c, Image<PixelT> const& rhs) {
707  if (this->getDimensions() != rhs.getDimensions()) {
708  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
709  (boost::format("Images are of different size, %dx%d v %dx%d") %
710  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
711  }
712  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
713  bl::ret<PixelT>(bl::_1 - bl::ret<PixelT>(c*bl::_2)));
714 }
715 
719 template<typename PixelT>
721  lsst::afw::math::Function2<double> const& function
722  ) {
723  for (int y = 0; y != this->getHeight(); ++y) {
724  double const yPos = this->indexToPosition(y, image::Y);
725  double xPos = this->indexToPosition(0, image::X);
726  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y);
727  ptr != end; ++ptr, ++xPos) {
728  *ptr -= function(xPos, yPos);
729  }
730  }
731 }
732 
734 template<typename PixelT>
736  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 * rhs));
737 }
738 
740 template<typename PixelT>
742  if (this->getDimensions() != rhs.getDimensions()) {
743  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
744  (boost::format("Images are of different size, %dx%d v %dx%d") %
745  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
746  }
747  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 * bl::_2));
748 }
749 
751 template<typename PixelT>
752 void image::Image<PixelT>::scaledMultiplies(double const c, Image<PixelT> const& rhs) {
753  if (this->getDimensions() != rhs.getDimensions()) {
754  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
755  (boost::format("Images are of different size, %dx%d v %dx%d") %
756  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
757  }
758  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
759  bl::ret<PixelT>(bl::_1 * bl::ret<PixelT>(c*bl::_2)));
760 }
761 
765 template<typename PixelT>
767  transform_pixels(_getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 / rhs));
768 }
769 //
770 // Specialize float and double for efficiency
771 //
772 namespace lsst { namespace afw { namespace image {
773 template<>
774 void Image<double>::operator/=(double const rhs) {
775  double const irhs = 1/rhs;
776  *this *= irhs;
777 }
778 
779 template<>
780 void Image<float>::operator/=(float const rhs) {
781  float const irhs = 1/rhs;
782  *this *= irhs;
783 }
784 }}}
785 
787 template<typename PixelT>
789  if (this->getDimensions() != rhs.getDimensions()) {
790  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
791  (boost::format("Images are of different size, %dx%d v %dx%d") %
792  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
793  }
794  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret<PixelT>(bl::_1 / bl::_2));
795 }
796 
798 template<typename PixelT>
799 void image::Image<PixelT>::scaledDivides(double const c, Image<PixelT> const& rhs) {
800  if (this->getDimensions() != rhs.getDimensions()) {
801  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
802  (boost::format("Images are of different size, %dx%d v %dx%d") %
803  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
804  }
805  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
806  bl::ret<PixelT>(bl::_1 / bl::ret<PixelT>(c*bl::_2)));
807 }
808 
809 /************************************************************************************************************/
810 
811 namespace {
812 /*
813  * Worker routine for manipulating images;
814  */
815 template<typename LhsPixelT, typename RhsPixelT>
816 struct plusEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
817  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
818  return static_cast<LhsPixelT>(lhs + rhs);
819  }
820 };
821 
822 template<typename LhsPixelT, typename RhsPixelT>
823 struct minusEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
824  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
825  return static_cast<LhsPixelT>(lhs - rhs);
826  }
827 };
828 
829 template<typename LhsPixelT, typename RhsPixelT>
830 struct timesEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
831  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
832  return static_cast<LhsPixelT>(lhs*rhs);
833  }
834 };
835 
836 template<typename LhsPixelT, typename RhsPixelT>
837 struct divideEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
838  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
839  return static_cast<LhsPixelT>(lhs/rhs);
840  }
841 };
842 }
843 
846 template<typename LhsPixelT, typename RhsPixelT>
848  image::for_each_pixel(lhs, rhs, plusEq<LhsPixelT, RhsPixelT>());
849 }
850 
853 template<typename LhsPixelT, typename RhsPixelT>
855  image::for_each_pixel(lhs, rhs, minusEq<LhsPixelT, RhsPixelT>());
856 }
857 
860 template<typename LhsPixelT, typename RhsPixelT>
862  image::for_each_pixel(lhs, rhs, timesEq<LhsPixelT, RhsPixelT>());
863 }
864 
867 template<typename LhsPixelT, typename RhsPixelT>
869  image::for_each_pixel(lhs, rhs, divideEq<LhsPixelT, RhsPixelT>());
870 }
871 
872 /************************************************************************************************************/
873 //
874 // Explicit instantiations
875 //
877 #define INSTANTIATE_OPERATOR(OP_EQ, T) \
878  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<boost::uint16_t> const& rhs); \
879  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<int> const& rhs); \
880  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<float> const& rhs); \
881  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<double> const& rhs); \
882  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<boost::uint64_t> const& rhs);
883 
884 #define INSTANTIATE(T) \
885  template class image::ImageBase<T>; \
886  template class image::Image<T>; \
887  INSTANTIATE_OPERATOR(+=, T); \
888  INSTANTIATE_OPERATOR(-=, T); \
889  INSTANTIATE_OPERATOR(*=, T); \
890  INSTANTIATE_OPERATOR(/=, T)
891 
892 INSTANTIATE(boost::uint16_t);
893 INSTANTIATE(int);
894 INSTANTIATE(float);
895 INSTANTIATE(double);
896 INSTANTIATE(boost::uint64_t);
int y
iterator at(int x, int y) const
Return an STL compliant iterator at the point (x, y)
Definition: Image.cc:349
void scaledDivides(double const c, Image< PixelT >const &rhs)
Divide lhs by Image c*rhs (i.e. pixel-by-pixel division)
Definition: Image.cc:799
iterator end() const
Return an STL compliant iterator to the end of the image.
Definition: Image.cc:331
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
reverse_iterator rend() const
Return an STL compliant reverse iterator to the end of the image.
Definition: Image.cc:343
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:291
Include files required for standard LSST Exception handling.
#define INSTANTIATE(MATCH)
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
#define PTR(...)
Definition: base.h:41
void operator/=(PixelT const rhs)
Definition: Image.cc:766
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:78
void for_each_pixel(Image< LhsT > &lhs, pixelOp0< LhsT > const &func)
lsst::daf::base::PropertyList PropertyList
Definition: Wcs.cc:59
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:355
void operator*=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:861
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:225
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:677
lsst::daf::base::PropertySet PropertySet
Definition: Wcs.cc:58
_view_t::iterator iterator
An STL compliant iterator.
Definition: Image.h:143
geom::Point2I _origin
Definition: Image.h:384
afw::table::PointKey< int > dimensions
Definition: GaussianPsf.cc:42
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:480
void operator*=(PixelT const rhs)
Multiply lhs by scalar rhs.
Definition: Image.cc:735
void ImageT ImageT int float saturatedPixelValue int const width
Definition: saturated.cc:44
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
_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.
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
Definition: saturated.cc:47
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:1187
double x
void operator+=(PixelT const rhs)
Add scalar rhs to lhs.
Definition: Image.cc:643
void swap(ImageBase &rhs)
Definition: Image.cc:282
void operator-=(PixelT const rhs)
Subtract scalar rhs from lhs.
Definition: Image.cc:689
Support for functors over Image&#39;s pixels.
void ImageT ImageT int float saturatedPixelValue int const height
Definition: saturated.cc:44
Extent< int, 2 > ExtentI
Definition: Extent.h:352
#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:706
Class for storing generic metadata.
Definition: PropertySet.h:82
void operator/=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:868
Reference< PixelT >::type PixelReference
A Reference to a PixelT.
Definition: Image.h:135
#define CONST_PTR(...)
Definition: base.h:47
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:752
void operator-=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:854
ImageOrigin _origin
Definition: fits_io_mpl.h:81
iterator begin() const
Definition: Image.cc:325
reverse_iterator rbegin() const
Return an STL compliant reverse iterator to the start of the image.
Definition: Image.cc:337
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:606
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:216
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y)
Definition: Image.cc:236
void operator+=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:847