LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
Image.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008-2016 AURA/LSST.
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 <cstdint>
30 #include <iostream>
31 #include "boost/mpl/vector.hpp"
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wunused-variable"
34 #pragma clang diagnostic pop
35 #include "boost/format.hpp"
36 #include "boost/filesystem/path.hpp"
37 #include "boost/gil/gil_all.hpp"
38 
39 #include "lsst/pex/exceptions.h"
40 #include "lsst/afw/image/Image.h"
42 #include "lsst/afw/image/Wcs.h"
43 #include "lsst/afw/fits.h"
46 
47 namespace image = lsst::afw::image;
48 namespace geom = lsst::afw::geom;
49 
50 /************************************************************************************************************/
51 template <typename PixelT>
53  geom::Extent2I const & dimensions,
54  Manager::Ptr & manager
55 ) {
56  if (dimensions.getX() < 0 || dimensions.getY() < 0) {
57  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
58  str(boost::format("Both width and height must be non-negative: %d, %d")
59  % dimensions.getX() % dimensions.getY()));
60  }
61  if (dimensions.getX() != 0 && dimensions.getY() > std::numeric_limits<int>::max()/dimensions.getX()) {
62  throw LSST_EXCEPT(pex::exceptions::LengthError,
63  str(boost::format("Image dimensions (%d x %d) too large; int overflow detected.")
64  % dimensions.getX() % dimensions.getY()));
65  }
66  std::pair<Manager::Ptr,PixelT*> r = ndarray::SimpleManager<PixelT>::allocate(
67  dimensions.getX() * dimensions.getY()
68  );
69  manager = r.first;
70  return boost::gil::interleaved_view(
71  dimensions.getX(), dimensions.getY(),
72  (typename _view_t::value_type* )r.second,
73  dimensions.getX()*sizeof(PixelT)
74  );
75 }
76 template <typename PixelT>
78  geom::Extent2I const & dimensions, geom::Extent2I const & offset, const _view_t & view
79 ) {
80  if (offset.getX() < 0 || offset.getY() < 0 ||
81  offset.getX() + dimensions.getX() > view.width() ||
82  offset.getY() + dimensions.getY() > view.height()
83  ) {
84  throw LSST_EXCEPT(
85  lsst::pex::exceptions::LengthError,
86  (boost::format("Box2I(Point2I(%d,%d),Extent2I(%d,%d)) doesn't fit in image %dx%d") %
87  offset.getX() % offset.getY() %
88  dimensions.getX() % dimensions.getY() %
89  view.width() % view.height()
90  ).str()
91  );
92  }
93  return boost::gil::subimage_view(
94  view,
95  offset.getX(), offset.getY(),
96  dimensions.getX(), dimensions.getY()
97  );
98 }
99 
106 template <typename PixelT>
108  geom::Extent2I const & dimensions
109 ) : lsst::daf::base::Citizen(typeid(this)),
110  _origin(0,0), _manager(),
111  _gilView(_allocateView(dimensions, _manager))
112 {}
113 
119 template <typename PixelT>
121  geom::Box2I const & bbox
122 ) : lsst::daf::base::Citizen(typeid(this)),
123  _origin(bbox.getMin()), _manager(),
124  _gilView(_allocateView(bbox.getDimensions(), _manager))
125 {}
126 
133 template<typename PixelT>
135  ImageBase const& rhs,
136  bool const deep
137 ) :
139  lsst::daf::base::Citizen(typeid(this)),
140  _origin(rhs._origin),
141  _manager(rhs._manager),
142  _gilView(rhs._gilView)
143 {
144  if (deep) {
145  ImageBase tmp(getBBox());
146  tmp.assign(*this); // now copy the pixels
147  swap(tmp);
148  }
149 }
150 
159 template<typename PixelT>
161  ImageBase const& rhs,
162  geom::Box2I const& bbox,
163  ImageOrigin const origin,
164  bool const deep
165 ) :
167  lsst::daf::base::Citizen(typeid(this)),
168  _origin((origin==PARENT) ? bbox.getMin(): rhs._origin + geom::Extent2I(bbox.getMin())),
169  _manager(rhs._manager), // reference counted pointer, don't copy pixels
170  _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView))
171 {
172  if (deep) {
173  ImageBase tmp(getBBox());
174  tmp.assign(*this); // now copy the pixels
175  swap(tmp);
176  }
177 }
178 
188 template<typename PixelT>
189 image::ImageBase<PixelT>::ImageBase(Array const & array, bool deep, geom::Point2I const & xy0) :
190  lsst::daf::base::Citizen(typeid(this)),
191  _origin(xy0),
192  _manager(array.getManager()),
193  _gilView(
194  boost::gil::interleaved_view(
195  array.template getSize<1>(), array.template getSize<0>(),
196  (typename _view_t::value_type* )array.getData(),
197  array.template getStride<0>() * sizeof(PixelT)
198  )
199  )
200 {
201  if (deep) {
202  ImageBase tmp(*this, true);
203  swap(tmp);
204  }
205 }
206 
214 template<typename PixelT>
216  ImageBase tmp(rhs);
217  swap(tmp); // See Meyers, Effective C++, Item 11
218 
219  return *this;
220 }
221 
225 template<typename PixelT>
227  assign(rhs);
228 }
229 
241 template<typename PixelT>
242 void image::ImageBase<PixelT>::assign(ImageBase const &rhs, geom::Box2I const &bbox, ImageOrigin origin) {
243  auto lhsDim = bbox.isEmpty() ? getDimensions() : bbox.getDimensions();
244  if (lhsDim != rhs.getDimensions()) {
245  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
246  (boost::format("Dimension mismatch: %dx%d v. %dx%d") %
247  lhsDim.getX() % lhsDim.getY() % rhs.getWidth() % rhs.getHeight()).str());
248  }
249  if (bbox.isEmpty()) {
250  copy_pixels(rhs._gilView, _gilView);
251  } else {
252  auto lhsOff = (origin == PARENT) ? bbox.getMin() - _origin : geom::Extent2I(bbox.getMin());
253  auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
254  copy_pixels(rhs._gilView, lhsGilView);
255  }
256 }
257 
259 template<typename PixelT>
261  return const_cast<typename image::ImageBase<PixelT>::PixelReference>(
262  static_cast<typename image::ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0])
263  );
264 }
265 
267 template<typename PixelT>
269  int x,
270  int y,
271  image::CheckIndices const& check
272  )
273 {
274  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
275  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
276  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") %
277  x % y % (getWidth() - 1) % (getHeight() - 1)).str());
278  }
279 
280  return const_cast<typename image::ImageBase<PixelT>::PixelReference>(
281  static_cast<typename image::ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0])
282  );
283 }
284 
286 template<typename PixelT>
289  return _gilView(x, y)[0];
290 }
291 
293 template<typename PixelT>
296  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
297  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
298  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") %
299  x % y % (this->getWidth() - 1) % (this->getHeight() - 1)).str());
300  }
301 
302  return _gilView(x, y)[0];
303 }
304 
305 template<typename PixelT>
307  using std::swap; // See Meyers, Effective C++, Item 25
308 
309  swap(_manager, rhs._manager); // just swapping the pointers
310  swap(_gilView, rhs._gilView);
311  swap(_origin, rhs._origin);
312 }
313 
314 template<typename PixelT>
316  a.swap(b);
317 }
318 
319 template <typename PixelT>
321  int rowStride = reinterpret_cast<PixelT*>(row_begin(1)) - reinterpret_cast<PixelT*>(row_begin(0));
322  return ndarray::external(
323  reinterpret_cast<PixelT*>(row_begin(0)),
324  ndarray::makeVector(getHeight(), getWidth()),
325  ndarray::makeVector(rowStride, 1),
326  this->_manager
327  );
328 }
329 
330 
331 template <typename PixelT>
333  int rowStride = reinterpret_cast<PixelT*>(row_begin(1)) - reinterpret_cast<PixelT*>(row_begin(0));
334  return ndarray::external(
335  reinterpret_cast<PixelT*>(row_begin(0)),
336  ndarray::makeVector(getHeight(), getWidth()),
337  ndarray::makeVector(rowStride, 1),
338  this->_manager
339  );
340 }
341 //
342 // Iterators
343 //
348 template<typename PixelT>
350  return _gilView.begin();
351 }
352 
354 template<typename PixelT>
356  return _gilView.end();
357 }
358 
360 template<typename PixelT>
362  return _gilView.rbegin();
363 }
364 
366 template<typename PixelT>
368  return _gilView.rend();
369 }
370 
372 template<typename PixelT>
374  return _gilView.at(x, y);
375 }
376 
381 template<typename PixelT>
383  bool contiguous
384 ) const {
385  if (!contiguous) {
386  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
387  "Only contiguous == true makes sense");
388  }
389  if (!this->isContiguous()) {
390  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
391  "Image's pixels are not contiguous");
392  }
393 
394  return row_begin(0);
395 }
396 
401 template<typename PixelT>
403  bool contiguous
404 ) const {
405  if (!contiguous) {
406  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
407  "Only contiguous == true makes sense");
408  }
409  if (!this->isContiguous()) {
410  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
411  "Image's pixels are not contiguous");
412  }
413 
414  return row_end(getHeight()-1);
415 }
416 
417 /************************************************************************************************************/
419 template<typename PixelT>
421  fill_pixels(_gilView, rhs);
422 
423  return *this;
424 }
425 
426 /************************************************************************************************************/
427 //
428 // On to Image itself. ctors, cctors, and operator=
429 //
436 template<typename PixelT>
437 image::Image<PixelT>::Image(unsigned int width,
438  unsigned int height,
439  PixelT initialValue
440  ) :
441  image::ImageBase<PixelT>(geom::ExtentI(width, height))
442 {
443  *this = initialValue;
444 }
445 
452 template<typename PixelT>
454  PixelT initialValue
455  ) :
456  image::ImageBase<PixelT>(dimensions)
457 {
458  *this = initialValue;
459 }
460 
464 template<typename PixelT>
466  PixelT initialValue
467  ) :
468  image::ImageBase<PixelT>(bbox) {
469  *this = initialValue;
470 }
471 
478 template<typename PixelT>
480  bool const deep
481  ) :
483  image::ImageBase<PixelT>(rhs, deep) {}
484 
493 template<typename PixelT>
495  geom::Box2I const& bbox,
496  ImageOrigin const origin,
497  bool const deep
498  ) :
500  image::ImageBase<PixelT>(rhs, bbox, origin, deep) {}
501 
503 template<typename PixelT>
505  this->ImageBase<PixelT>::operator=(rhs);
506 
507  return *this;
508 }
509 
517 template<typename PixelT>
519  this->ImageBase<PixelT>::operator=(rhs);
520 
521  return *this;
522 }
523 
524 /************************************************************************************************************/
525 
526 #ifndef DOXYGEN // doc for this section has been moved to header
527 
528 template<typename PixelT>
530  std::string const & fileName,
531  int hdu,
532  PTR(daf::base::PropertySet) metadata,
533  geom::Box2I const & bbox,
534  ImageOrigin origin
535 ) : image::ImageBase<PixelT>() {
536  fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
537  fitsfile.setHdu(hdu);
538  try {
539  *this = Image(fitsfile, metadata, bbox, origin);
540  } catch(lsst::afw::fits::FitsError &e) {
541  fitsfile.status = 0; // reset so we can read NAXIS
542  if (fitsfile.getImageDim() == 0) { // no pixels to read
543  LSST_EXCEPT_ADD(e, str(boost::format("HDU %d has NAXIS == 0") % hdu));
544  }
545  throw e;
546  }
547 }
548 template<typename PixelT>
550  fits::MemFileManager & manager,
551  int const hdu,
552  PTR(daf::base::PropertySet) metadata,
553  geom::Box2I const& bbox,
554  ImageOrigin const origin
555 ) : image::ImageBase<PixelT>() {
556  fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
557  fitsfile.setHdu(hdu);
558  *this = Image(fitsfile, metadata, bbox, origin);
559 }
560 
561 template<typename PixelT>
563  fits::Fits & fitsfile,
564  PTR(daf::base::PropertySet) metadata,
565  geom::Box2I const& bbox,
566  ImageOrigin const origin
567 ) : image::ImageBase<PixelT>() {
568 
569  typedef boost::mpl::vector<
570  unsigned char,
571  unsigned short,
572  short,
573  int,
574  unsigned int,
575  float,
576  double,
577  std::uint64_t
578  > fits_image_types;
579 
580  if (!metadata) {
581  metadata.reset(new daf::base::PropertyList());
582  }
583 
584  fits_read_image<fits_image_types>(fitsfile, *this, *metadata, bbox, origin);
585 }
586 
587 template<typename PixelT>
589  std::string const & fileName,
591  std::string const & mode
592 ) const {
593  fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
594  writeFits(fitsfile, metadata_i);
595 }
596 
597 template<typename PixelT>
599  fits::MemFileManager & manager,
601  std::string const & mode
602 ) const {
603  fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
604  writeFits(fitsfile, metadata_i);
605 }
606 
607 template<typename PixelT>
609  fits::Fits & fitsfile,
611 ) const {
612  PTR(daf::base::PropertySet) metadata;
613  PTR(daf::base::PropertySet) wcsAMetadata =
615  this->getX0(), this->getY0());
616  if (metadata_i) {
617  metadata = metadata_i->deepCopy();
618  metadata->combine(wcsAMetadata);
619  } else {
620  metadata = wcsAMetadata;
621  }
622  image::fits_write_image(fitsfile, *this, metadata);
623 }
624 
625 #endif // !DOXYGEN
626 
627 /************************************************************************************************************/
628 
629 template<typename PixelT>
631  using std::swap; // See Meyers, Effective C++, Item 25
633  ; // no private variables to swap
634 }
635 
636 template<typename PixelT>
638  a.swap(b);
639 }
640 
641 /************************************************************************************************************/
642 
643 // In-place, per-pixel, sqrt().
644 template<typename PixelT>
646  transform_pixels(_getRawView(), _getRawView(),
647  [](PixelT const& l) -> PixelT { return static_cast<PixelT>(std::sqrt(l)); });
648 }
649 
651 template<typename PixelT>
653  transform_pixels(_getRawView(), _getRawView(),
654  [&rhs](PixelT const& l) -> PixelT { return l + rhs; });
655 }
656 
658 template<typename PixelT>
660  if (this->getDimensions() != rhs.getDimensions()) {
661  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
662  (boost::format("Images are of different size, %dx%d v %dx%d") %
663  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
664  }
665  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
666  [](PixelT const& l, PixelT const& r) -> PixelT { return l + r; });
667 }
668 
672 template<typename PixelT>
674  lsst::afw::math::Function2<double> const& function
675  ) {
676  for (int y = 0; y != this->getHeight(); ++y) {
677  double const yPos = this->indexToPosition(y, image::Y);
678  double xPos = this->indexToPosition(0, image::X);
679  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y);
680  ptr != end; ++ptr, ++xPos) {
681  *ptr += function(xPos, yPos);
682  }
683  }
684 }
685 
687 template<typename PixelT>
688 void image::Image<PixelT>::scaledPlus(double const c, Image<PixelT> const& rhs) {
689  if (this->getDimensions() != rhs.getDimensions()) {
690  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
691  (boost::format("Images are of different size, %dx%d v %dx%d") %
692  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
693  }
694  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
695  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l + static_cast<PixelT>(c*r); });
696 }
697 
699 template<typename PixelT>
701  transform_pixels(_getRawView(), _getRawView(),
702  [&rhs](PixelT const& l) -> PixelT { return l - rhs; });
703 }
704 
706 template<typename PixelT>
708  if (this->getDimensions() != rhs.getDimensions()) {
709  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
710  (boost::format("Images are of different size, %dx%d v %dx%d") %
711  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
712  }
713  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
714  [](PixelT const& l, PixelT const& r) -> PixelT { return l - r; });
715 }
716 
718 template<typename PixelT>
719 void image::Image<PixelT>::scaledMinus(double const c, Image<PixelT> const& rhs) {
720  if (this->getDimensions() != rhs.getDimensions()) {
721  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
722  (boost::format("Images are of different size, %dx%d v %dx%d") %
723  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
724  }
725  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
726  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l - static_cast<PixelT>(c*r); });
727 }
728 
732 template<typename PixelT>
734  lsst::afw::math::Function2<double> const& function
735  ) {
736  for (int y = 0; y != this->getHeight(); ++y) {
737  double const yPos = this->indexToPosition(y, image::Y);
738  double xPos = this->indexToPosition(0, image::X);
739  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y);
740  ptr != end; ++ptr, ++xPos) {
741  *ptr -= function(xPos, yPos);
742  }
743  }
744 }
745 
747 template<typename PixelT>
749  transform_pixels(_getRawView(), _getRawView(),
750  [&rhs](PixelT const& l) -> PixelT { return l*rhs; });
751 }
752 
754 template<typename PixelT>
756  if (this->getDimensions() != rhs.getDimensions()) {
757  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
758  (boost::format("Images are of different size, %dx%d v %dx%d") %
759  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
760  }
761  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
762  [](PixelT const& l, PixelT const& r) -> PixelT { return l*r; });
763 }
764 
766 template<typename PixelT>
767 void image::Image<PixelT>::scaledMultiplies(double const c, Image<PixelT> const& rhs) {
768  if (this->getDimensions() != rhs.getDimensions()) {
769  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
770  (boost::format("Images are of different size, %dx%d v %dx%d") %
771  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
772  }
773  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
774  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l*static_cast<PixelT>(c*r); });
775 }
776 
780 template<typename PixelT>
782  transform_pixels(_getRawView(), _getRawView(),
783  [&rhs](PixelT const& l) -> PixelT { return l/rhs; });
784 }
785 //
786 // Specialize float and double for efficiency
787 //
788 namespace lsst { namespace afw { namespace image {
789 template<>
790 void Image<double>::operator/=(double const rhs) {
791  double const irhs = 1/rhs;
792  *this *= irhs;
793 }
794 
795 template<>
796 void Image<float>::operator/=(float const rhs) {
797  float const irhs = 1/rhs;
798  *this *= irhs;
799 }
800 }}}
801 
803 template<typename PixelT>
805  if (this->getDimensions() != rhs.getDimensions()) {
806  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
807  (boost::format("Images are of different size, %dx%d v %dx%d") %
808  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
809  }
810  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
811  [](PixelT const& l, PixelT const& r) -> PixelT { return l/r; });
812 }
813 
815 template<typename PixelT>
816 void image::Image<PixelT>::scaledDivides(double const c, Image<PixelT> const& rhs) {
817  if (this->getDimensions() != rhs.getDimensions()) {
818  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
819  (boost::format("Images are of different size, %dx%d v %dx%d") %
820  this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str());
821  }
822  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
823  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l/static_cast<PixelT>(c*r); });
824 }
825 
826 /************************************************************************************************************/
827 
828 namespace {
829 /*
830  * Worker routine for manipulating images;
831  */
832 template<typename LhsPixelT, typename RhsPixelT>
833 struct plusEq : 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 template<typename LhsPixelT, typename RhsPixelT>
840 struct minusEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
841  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
842  return static_cast<LhsPixelT>(lhs - rhs);
843  }
844 };
845 
846 template<typename LhsPixelT, typename RhsPixelT>
847 struct timesEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
848  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
849  return static_cast<LhsPixelT>(lhs*rhs);
850  }
851 };
852 
853 template<typename LhsPixelT, typename RhsPixelT>
854 struct divideEq : public lsst::afw::image::pixelOp2<LhsPixelT, RhsPixelT> {
855  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const {
856  return static_cast<LhsPixelT>(lhs/rhs);
857  }
858 };
859 }
860 
863 template<typename LhsPixelT, typename RhsPixelT>
865  image::for_each_pixel(lhs, rhs, plusEq<LhsPixelT, RhsPixelT>());
866 }
867 
870 template<typename LhsPixelT, typename RhsPixelT>
872  image::for_each_pixel(lhs, rhs, minusEq<LhsPixelT, RhsPixelT>());
873 }
874 
877 template<typename LhsPixelT, typename RhsPixelT>
879  image::for_each_pixel(lhs, rhs, timesEq<LhsPixelT, RhsPixelT>());
880 }
881 
884 template<typename LhsPixelT, typename RhsPixelT>
886  image::for_each_pixel(lhs, rhs, divideEq<LhsPixelT, RhsPixelT>());
887 }
888 
889 /************************************************************************************************************/
890 //
891 // Explicit instantiations
892 //
894 #define INSTANTIATE_OPERATOR(OP_EQ, T) \
895  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<std::uint16_t> const& rhs); \
896  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<int> const& rhs); \
897  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<float> const& rhs); \
898  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<double> const& rhs); \
899  template void image::operator OP_EQ(image::Image<T>& lhs, image::Image<std::uint64_t> const& rhs);
900 
901 #define INSTANTIATE(T) \
902  template class image::ImageBase<T>; \
903  template class image::Image<T>; \
904  INSTANTIATE_OPERATOR(+=, T); \
905  INSTANTIATE_OPERATOR(-=, T); \
906  INSTANTIATE_OPERATOR(*=, T); \
907  INSTANTIATE_OPERATOR(/=, T)
908 
909 INSTANTIATE(std::uint16_t);
910 INSTANTIATE(int);
911 INSTANTIATE(float);
912 INSTANTIATE(double);
913 INSTANTIATE(std::uint64_t);
int y
iterator at(int x, int y) const
Return an STL compliant iterator at the point (x, y)
Definition: Image.cc:373
void scaledDivides(double const c, Image< PixelT >const &rhs)
Divide lhs by Image c*rhs (i.e. pixel-by-pixel division)
Definition: Image.cc:816
iterator end() const
Return an STL compliant iterator to the end of the image.
Definition: Image.cc:355
Extent2I const getDimensions() const
Definition: Box.h:153
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:367
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
boost::shared_ptr< lsst::daf::base::PropertyList > createTrivialWcsAsPropertySet(std::string const &wcsName, int const x0, int const y0)
Definition: Wcs.cc:1190
void operator/=(PixelT const rhs)
Definition: Image.cc:781
geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Definition: Image.h:379
static _view_t _makeSubView(geom::Extent2I const &dimensions, geom::Extent2I const &offset, const _view_t &view)
Definition: Image.cc:77
void for_each_pixel(Image< LhsT > &lhs, pixelOp0< LhsT > const &func)
void swap(Mask< PixelT > &a, Mask< PixelT > &b)
Definition: Mask.cc:524
lsst::daf::base::PropertyList PropertyList
Definition: Wcs.cc:60
#define CONST_PTR(...)
Definition: base.h:47
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:201
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition: Image.h:115
Extent< int, 2 > Extent2I
Definition: Extent.h:358
void operator*=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:878
#define INSTANTIATE(T)
An integer coordinate rectangle.
Definition: Box.h:53
void operator<<=(const ImageBase &rhs)
Definition: Image.cc:226
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:688
lsst::daf::base::PropertySet PropertySet
Definition: Wcs.cc:59
_view_t::iterator iterator
An STL compliant iterator.
Definition: Image.h:143
geom::Point2I _origin
Definition: Image.h:386
afw::table::PointKey< int > dimensions
Definition: GaussianPsf.cc:42
Image & operator=(const PixelT rhs)
Set the image&#39;s pixels to rhs.
Definition: Image.cc:504
void operator*=(PixelT const rhs)
Multiply lhs by scalar rhs.
Definition: Image.cc:748
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:300
void assign(ImageBase const &rsh, geom::Box2I const &bbox=geom::Box2I(), ImageOrigin origin=PARENT)
Definition: Image.cc:242
_view_t _getRawView() const
Definition: Image.h:403
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:241
double x
void operator+=(PixelT const rhs)
Add scalar rhs to lhs.
Definition: Image.cc:652
bool isEmpty() const
Return true if the box contains no points.
Definition: Box.h:166
void swap(ImageBase &rhs)
Definition: Image.cc:306
void operator-=(PixelT const rhs)
Subtract scalar rhs from lhs.
Definition: Image.cc:700
Support for functors over Image&#39;s pixels.
Extent< int, 2 > ExtentI
Definition: Extent.h:355
ndarray::Array< PixelT const, 2, 1 > ConstArray
An immutable ndarray representation of the image.
Definition: Image.h:168
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
Manager::Ptr _manager
Definition: Image.h:387
static _view_t _allocateView(geom::Extent2I const &dimensions, Manager::Ptr &manager)
Definition: Image.cc:52
void scaledMinus(double const c, Image< PixelT >const &rhs)
Subtract Image c*rhs from lhs.
Definition: Image.cc:719
Class for storing generic metadata.
Definition: PropertySet.h:82
void operator/=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:885
#define PTR(...)
Definition: base.h:41
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:767
void operator-=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:871
ImageOrigin _origin
Definition: fits_io_mpl.h:81
iterator begin() const
Definition: Image.cc:349
reverse_iterator rbegin() const
Return an STL compliant reverse iterator to the start of the image.
Definition: Image.cc:361
Include files required for standard LSST Exception handling.
Point2I const getMin() const
Definition: Box.h:123
friend class Image
Definition: Image.h:433
int getWidth() const
Return the number of columns in the image.
Definition: Image.h:239
#define LSST_EXCEPT_ADD(e, m)
Definition: Exception.h:51
ndarray::Array< PixelT, 2, 1 > Array
A mutable ndarray representation of the image.
Definition: Image.h:166
void swap(Image &rhs)
Definition: Image.cc:630
A class to represent a 2-dimensional array of pixels.
Definition: PSF.h:43
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
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.
ImageBase & operator=(const ImageBase &rhs)
Definition: Image.cc:215
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y)
Definition: Image.cc:260
void operator+=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Definition: Image.cc:864