LSSTApplications  19.0.0-14-gb0260a2+72efe9b372,20.0.0+7927753e06,20.0.0+8829bf0056,20.0.0+995114c5d2,20.0.0+b6f4b2abd1,20.0.0+bddc4f4cbe,20.0.0-1-g253301a+8829bf0056,20.0.0-1-g2b7511a+0d71a2d77f,20.0.0-1-g5b95a8c+7461dd0434,20.0.0-12-g321c96ea+23efe4bbff,20.0.0-16-gfab17e72e+fdf35455f6,20.0.0-2-g0070d88+ba3ffc8f0b,20.0.0-2-g4dae9ad+ee58a624b3,20.0.0-2-g61b8584+5d3db074ba,20.0.0-2-gb780d76+d529cf1a41,20.0.0-2-ged6426c+226a441f5f,20.0.0-2-gf072044+8829bf0056,20.0.0-2-gf1f7952+ee58a624b3,20.0.0-20-geae50cf+e37fec0aee,20.0.0-25-g3dcad98+544a109665,20.0.0-25-g5eafb0f+ee58a624b3,20.0.0-27-g64178ef+f1f297b00a,20.0.0-3-g4cc78c6+e0676b0dc8,20.0.0-3-g8f21e14+4fd2c12c9a,20.0.0-3-gbd60e8c+187b78b4b8,20.0.0-3-gbecbe05+48431fa087,20.0.0-38-ge4adf513+a12e1f8e37,20.0.0-4-g97dc21a+544a109665,20.0.0-4-gb4befbc+087873070b,20.0.0-4-gf910f65+5d3db074ba,20.0.0-5-gdfe0fee+199202a608,20.0.0-5-gfbfe500+d529cf1a41,20.0.0-6-g64f541c+d529cf1a41,20.0.0-6-g9a5b7a1+a1cd37312e,20.0.0-68-ga3f3dda+5fca18c6a4,20.0.0-9-g4aef684+e18322736b,w.2020.45
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 
25 /*
26  * Implementation for ImageBase and Image
27  */
28 #include <cstdint>
29 #include <iostream>
30 #include <functional>
31 #include <type_traits>
32 #include "boost/mpl/vector.hpp"
33 #pragma clang diagnostic push
34 #pragma clang diagnostic ignored "-Wunused-variable"
35 #pragma clang diagnostic pop
36 #include "boost/format.hpp"
37 #include "boost/filesystem/path.hpp"
38 
39 #include "boost/version.hpp"
40 #if BOOST_VERSION < 106900
41 #include "boost/gil/gil_all.hpp"
42 #else
43 #include "boost/gil.hpp"
44 #endif
45 
46 #include "lsst/pex/exceptions.h"
47 #include "lsst/afw/geom/wcsUtils.h"
48 #include "lsst/afw/image/Image.h"
50 #include "lsst/afw/fits.h"
52 
53 namespace lsst {
54 namespace afw {
55 namespace image {
56 
57 template <typename PixelT>
58 typename ImageBase<PixelT>::_view_t ImageBase<PixelT>::_allocateView(lsst::geom::Extent2I const& dimensions,
59  Manager::Ptr& manager) {
60  if (dimensions.getX() < 0 || dimensions.getY() < 0) {
62  str(boost::format("Both width and height must be non-negative: %d, %d") %
63  dimensions.getX() % dimensions.getY()));
64  }
65  if (dimensions.getX() != 0 && dimensions.getY() > std::numeric_limits<int>::max() / dimensions.getX()) {
67  str(boost::format("Image dimensions (%d x %d) too large; int overflow detected.") %
68  dimensions.getX() % dimensions.getY()));
69  }
71  ndarray::SimpleManager<PixelT>::allocate(dimensions.getX() * dimensions.getY());
72  manager = r.first;
73  return boost::gil::interleaved_view(dimensions.getX(), dimensions.getY(),
74  (typename _view_t::value_type*)r.second,
75  dimensions.getX() * sizeof(PixelT));
76 }
77 template <typename PixelT>
78 typename ImageBase<PixelT>::_view_t ImageBase<PixelT>::_makeSubView(lsst::geom::Extent2I const& dimensions,
79  lsst::geom::Extent2I const& offset,
80  const _view_t& view) {
81  if (offset.getX() < 0 || offset.getY() < 0 || offset.getX() + dimensions.getX() > view.width() ||
82  offset.getY() + dimensions.getY() > view.height()) {
83  throw LSST_EXCEPT(
86  "Box2I(Point2I(%d,%d),lsst::geom::Extent2I(%d,%d)) doesn't fit in image %dx%d") %
87  offset.getX() % offset.getY() % dimensions.getX() % dimensions.getY() % view.width() %
88  view.height())
89  .str());
90  }
91  return boost::gil::subimage_view(view, offset.getX(), offset.getY(), dimensions.getX(),
92  dimensions.getY());
93 }
94 
95 template <typename PixelT>
97  : _origin(0, 0), _manager(), _gilView(_allocateView(dimensions, _manager)) {}
98 
99 template <typename PixelT>
101  : _origin(bbox.getMin()), _manager(), _gilView(_allocateView(bbox.getDimensions(), _manager)) {}
102 
103 template <typename PixelT>
104 ImageBase<PixelT>::ImageBase(ImageBase const& rhs, bool const deep
105 
106  )
107  : _origin(rhs._origin), _manager(rhs._manager), _gilView(rhs._gilView) {
108  if (deep) {
109  ImageBase tmp(getBBox());
110  tmp.assign(*this); // now copy the pixels
111  swap(tmp);
112  }
113 }
114 // Delegate to copy-constructor for backwards compatibility
115 template <typename PixelT>
117 
118 template <typename PixelT>
120  bool const deep
121 
122  )
123  : _origin((origin == PARENT) ? bbox.getMin() : rhs._origin + lsst::geom::Extent2I(bbox.getMin())),
124  _manager(rhs._manager), // reference counted pointer, don't copy pixels
125  _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
126  if (deep) {
128  tmp.assign(*this); // now copy the pixels
129  swap(tmp);
130  }
131 }
132 
133 template <typename PixelT>
134 ImageBase<PixelT>::ImageBase(Array const& array, bool deep, lsst::geom::Point2I const& xy0)
135  : _origin(xy0),
136  _manager(array.getManager()),
137  _gilView(boost::gil::interleaved_view(array.template getSize<1>(), array.template getSize<0>(),
138  (typename _view_t::value_type*)array.getData(),
139  array.template getStride<0>() * sizeof(PixelT))) {
140  if (deep) {
141  ImageBase tmp(*this, true);
142  swap(tmp);
143  }
144 }
145 
146 template <typename PixelT>
148  ImageBase tmp(rhs);
149  swap(tmp); // See Meyers, Effective C++, Item 11
150 
151  return *this;
152 }
153 // Delegate to copy-assignment for backwards compatibility
154 template <typename PixelT>
156  return *this = rhs;
157 }
158 
159 template <typename PixelT>
161  auto lhsDim = bbox.isEmpty() ? getDimensions() : bbox.getDimensions();
162  if (lhsDim != rhs.getDimensions()) {
164  (boost::format("Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
165  lhsDim.getY() % rhs.getWidth() % rhs.getHeight())
166  .str());
167  }
168  if (bbox.isEmpty()) {
169  copy_pixels(rhs._gilView, _gilView);
170  } else {
171  auto lhsOff = (origin == PARENT) ? bbox.getMin() - _origin : lsst::geom::Extent2I(bbox.getMin());
172  auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
173  copy_pixels(rhs._gilView, lhsGilView);
174  }
175 }
176 
177 template <typename PixelT>
179  return const_cast<typename ImageBase<PixelT>::PixelReference>(
180  static_cast<typename ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0]));
181 }
182 
183 template <typename PixelT>
185  CheckIndices const& check) {
186  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
188  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
189  (getWidth() - 1) % (getHeight() - 1))
190  .str());
191  }
192 
193  return const_cast<typename ImageBase<PixelT>::PixelReference>(
194  static_cast<typename ImageBase<PixelT>::PixelConstReference>(_gilView(x, y)[0]));
195 }
196 
197 template <typename PixelT>
199  return _gilView(x, y)[0];
200 }
201 
202 template <typename PixelT>
204  int x, int y, CheckIndices const& check) const {
205  if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
207  (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
208  (this->getWidth() - 1) % (this->getHeight() - 1))
209  .str());
210  }
211 
212  return _gilView(x, y)[0];
213 }
214 
215 template <typename PixelT>
217  ImageOrigin origin) {
218  int x = index.getX();
219  int y = index.getY();
220  if (origin == PARENT) {
221  x -= getX0();
222  y -= getY0();
223  }
224  return _gilView(x, y)[0];
225 }
226 
227 template <typename PixelT>
229  ImageOrigin origin) const {
230  int x = index.getX();
231  int y = index.getY();
232  if (origin == PARENT) {
233  x -= getX0();
234  y -= getY0();
235  }
236  return _gilView(x, y)[0];
237 }
238 
239 template <typename PixelT>
241  using std::swap; // See Meyers, Effective C++, Item 25
242 
243  swap(_manager, rhs._manager); // just swapping the pointers
244  swap(_gilView, rhs._gilView);
245  swap(_origin, rhs._origin);
246 }
247 
248 template <typename PixelT>
250  a.swap(b);
251 }
252 
253 //
254 // Iterators
255 //
256 template <typename PixelT>
258  return _gilView.begin();
259 }
260 
261 template <typename PixelT>
263  return _gilView.end();
264 }
265 
266 template <typename PixelT>
268  return _gilView.rbegin();
269 }
270 
271 template <typename PixelT>
273  return _gilView.rend();
274 }
275 
276 template <typename PixelT>
278  return _gilView.at(x, y);
279 }
280 
281 template <typename PixelT>
283  if (!contiguous) {
284  throw LSST_EXCEPT(pex::exceptions::RuntimeError, "Only contiguous == true makes sense");
285  }
286  if (!this->isContiguous()) {
287  throw LSST_EXCEPT(pex::exceptions::RuntimeError, "Image's pixels are not contiguous");
288  }
289 
290  return row_begin(0);
291 }
292 
293 template <typename PixelT>
295  if (!contiguous) {
296  throw LSST_EXCEPT(pex::exceptions::RuntimeError, "Only contiguous == true makes sense");
297  }
298  if (!this->isContiguous()) {
299  throw LSST_EXCEPT(pex::exceptions::RuntimeError, "Image's pixels are not contiguous");
300  }
301 
302  return row_end(getHeight() - 1);
303 }
304 
305 template <typename PixelT>
307  fill_pixels(_gilView, rhs);
308 
309  return *this;
310 }
311 
312 //
313 // On to Image itself. ctors, cctors, and operator=
314 //
315 template <typename PixelT>
316 Image<PixelT>::Image(unsigned int width, unsigned int height, PixelT initialValue)
317  : ImageBase<PixelT>(lsst::geom::ExtentI(width, height)) {
318  *this = initialValue;
319 }
320 
321 template <typename PixelT>
324  *this = initialValue;
325 }
326 
327 template <typename PixelT>
329  *this = initialValue;
330 }
331 
332 template <typename PixelT>
333 Image<PixelT>::Image(Image const& rhs, bool const deep) : ImageBase<PixelT>(rhs, deep) {}
334 // Delegate to copy-constructor for backwards compatibility
335 template <typename PixelT>
336 Image<PixelT>::Image(Image&& rhs) : Image(rhs, false) {}
337 
338 template <typename PixelT>
340  bool const deep)
341  : ImageBase<PixelT>(rhs, bbox, origin, deep) {}
342 
343 template <typename PixelT>
346 
347  return *this;
348 }
349 
350 template <typename PixelT>
352  this->ImageBase<PixelT>::operator=(rhs);
353 
354  return *this;
355 }
356 // Delegate to copy-assignment for backwards compatibility
357 template <typename PixelT>
359  return *this = rhs;
360 }
361 
362 #ifndef DOXYGEN // doc for this section has been moved to header
363 
364 template <typename PixelT>
366  lsst::geom::Box2I const& bbox, ImageOrigin origin, bool allowUnsafe) {
367  ImageFitsReader reader(fileName, hdu);
368  *this = reader.read<PixelT>(bbox, origin, allowUnsafe);
369  if (metadata) {
370  metadata->combine(reader.readMetadata());
371  }
372 }
373 
374 template <typename PixelT>
377  ImageOrigin const origin, bool allowUnsafe) {
378  ImageFitsReader reader(manager, hdu);
379  *this = reader.read<PixelT>(bbox, origin, allowUnsafe);
380  if (metadata) {
381  metadata->combine(reader.readMetadata());
382  }
383 }
384 
385 template <typename PixelT>
387  lsst::geom::Box2I const& bbox, ImageOrigin const origin, bool allowUnsafe) {
388  ImageFitsReader reader(&fitsFile);
389  *this = reader.read<PixelT>(bbox, origin, allowUnsafe);
390  if (metadata) {
391  metadata->combine(reader.readMetadata());
392  }
393 }
394 
395 template <typename PixelT>
396 void Image<PixelT>::writeFits(std::string const& fileName,
398  std::string const& mode) const {
399  fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
400  writeFits(fitsfile, metadata_i);
401 }
402 
403 template <typename PixelT>
404 void Image<PixelT>::writeFits(fits::MemFileManager& manager,
406  std::string const& mode) const {
407  fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
408  writeFits(fitsfile, metadata_i);
409 }
410 
411 template <typename PixelT>
412 void Image<PixelT>::writeFits(fits::Fits& fitsfile,
414  fitsfile.writeImage(*this, fits::ImageWriteOptions(*this), metadata);
415 }
416 
417 template <typename PixelT>
418 void Image<PixelT>::writeFits(std::string const& filename, fits::ImageWriteOptions const& options,
420  std::shared_ptr<Mask<MaskPixel> const> mask) const {
421  fits::Fits fitsfile(filename, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
422  writeFits(fitsfile, options, header, mask);
423 }
424 
425 template <typename PixelT>
426 void Image<PixelT>::writeFits(fits::MemFileManager& manager, fits::ImageWriteOptions const& options,
428  std::shared_ptr<Mask<MaskPixel> const> mask) const {
429  fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
430  writeFits(fitsfile, options, header, mask);
431 }
432 
433 template <typename PixelT>
434 void Image<PixelT>::writeFits(fits::Fits& fitsfile, fits::ImageWriteOptions const& options,
436  std::shared_ptr<Mask<MaskPixel> const> mask) const {
437  fitsfile.writeImage(*this, options, header, mask);
438 }
439 
440 #endif // !DOXYGEN
441 
442 template <typename PixelT>
444  using std::swap; // See Meyers, Effective C++, Item 25
446  ; // no private variables to swap
447 }
448 
449 template <typename PixelT>
451  a.swap(b);
452 }
453 
454 // In-place, per-pixel, sqrt().
455 template <typename PixelT>
457  transform_pixels(_getRawView(), _getRawView(),
458  [](PixelT const& l) -> PixelT { return static_cast<PixelT>(std::sqrt(l)); });
459 }
460 
461 template <typename PixelT>
463  transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT const& l) -> PixelT { return l + rhs; });
464  return *this;
465 }
466 
467 template <typename PixelT>
469  if (this->getDimensions() != rhs.getDimensions()) {
471  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
472  this->getHeight() % rhs.getWidth() % rhs.getHeight())
473  .str());
474  }
475  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
476  [](PixelT const& l, PixelT const& r) -> PixelT { return l + r; });
477  return *this;
478 }
479 
480 template <typename PixelT>
482  for (int y = 0; y != this->getHeight(); ++y) {
483  double const yPos = this->indexToPosition(y, Y);
484  double xPos = this->indexToPosition(0, X);
485  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y); ptr != end;
486  ++ptr, ++xPos) {
487  *ptr += function(xPos, yPos);
488  }
489  }
490  return *this;
491 }
492 
493 template <typename PixelT>
494 void Image<PixelT>::scaledPlus(double const c, Image<PixelT> const& rhs) {
495  if (this->getDimensions() != rhs.getDimensions()) {
497  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
498  this->getHeight() % rhs.getWidth() % rhs.getHeight())
499  .str());
500  }
501  transform_pixels(
502  _getRawView(), rhs._getRawView(), _getRawView(),
503  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l + static_cast<PixelT>(c * r); });
504 }
505 
506 template <typename PixelT>
508  transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT const& l) -> PixelT { return l - rhs; });
509  return *this;
510 }
511 
512 template <typename PixelT>
514  if (this->getDimensions() != rhs.getDimensions()) {
516  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
517  this->getHeight() % rhs.getWidth() % rhs.getHeight())
518  .str());
519  }
520  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
521  [](PixelT const& l, PixelT const& r) -> PixelT { return l - r; });
522  return *this;
523 }
524 
525 template <typename PixelT>
526 void Image<PixelT>::scaledMinus(double const c, Image<PixelT> const& rhs) {
527  if (this->getDimensions() != rhs.getDimensions()) {
529  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
530  this->getHeight() % rhs.getWidth() % rhs.getHeight())
531  .str());
532  }
533  transform_pixels(
534  _getRawView(), rhs._getRawView(), _getRawView(),
535  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l - static_cast<PixelT>(c * r); });
536 }
537 
538 template <typename PixelT>
540  for (int y = 0; y != this->getHeight(); ++y) {
541  double const yPos = this->indexToPosition(y, Y);
542  double xPos = this->indexToPosition(0, X);
543  for (typename Image<PixelT>::x_iterator ptr = this->row_begin(y), end = this->row_end(y); ptr != end;
544  ++ptr, ++xPos) {
545  *ptr -= function(xPos, yPos);
546  }
547  }
548  return *this;
549 }
550 
551 template <typename PixelT>
553  transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT const& l) -> PixelT { return l * rhs; });
554  return *this;
555 }
556 
557 template <typename PixelT>
559  if (this->getDimensions() != rhs.getDimensions()) {
561  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
562  this->getHeight() % rhs.getWidth() % rhs.getHeight())
563  .str());
564  }
565  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
566  [](PixelT const& l, PixelT const& r) -> PixelT { return l * r; });
567  return *this;
568 }
569 
570 template <typename PixelT>
571 void Image<PixelT>::scaledMultiplies(double const c, Image<PixelT> const& rhs) {
572  if (this->getDimensions() != rhs.getDimensions()) {
574  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
575  this->getHeight() % rhs.getWidth() % rhs.getHeight())
576  .str());
577  }
578  transform_pixels(
579  _getRawView(), rhs._getRawView(), _getRawView(),
580  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l * static_cast<PixelT>(c * r); });
581 }
582 
583 template <typename PixelT>
585  transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT const& l) -> PixelT { return l / rhs; });
586  return *this;
587 }
588 //
589 // Specialize float and double for efficiency
590 //
591 template <>
593  double const irhs = 1 / rhs;
594  *this *= irhs;
595  return *this;
596 }
597 
598 template <>
600  float const irhs = 1 / rhs;
601  *this *= irhs;
602  return *this;
603 }
604 
605 template <typename PixelT>
607  if (this->getDimensions() != rhs.getDimensions()) {
609  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
610  this->getHeight() % rhs.getWidth() % rhs.getHeight())
611  .str());
612  }
613  transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(),
614  [](PixelT const& l, PixelT const& r) -> PixelT { return l / r; });
615  return *this;
616 }
617 
618 template <typename PixelT>
619 void Image<PixelT>::scaledDivides(double const c, Image<PixelT> const& rhs) {
620  if (this->getDimensions() != rhs.getDimensions()) {
622  (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() %
623  this->getHeight() % rhs.getWidth() % rhs.getHeight())
624  .str());
625  }
626  transform_pixels(
627  _getRawView(), rhs._getRawView(), _getRawView(),
628  [&c](PixelT const& l, PixelT const& r) -> PixelT { return l / static_cast<PixelT>(c * r); });
629 }
630 
631 namespace {
632 /*
633  * Worker routine for manipulating images;
634  */
635 template <typename LhsPixelT, typename RhsPixelT>
636 struct plusEq : public pixelOp2<LhsPixelT, RhsPixelT> {
637  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const override {
638  return static_cast<LhsPixelT>(lhs + rhs);
639  }
640 };
641 
642 template <typename LhsPixelT, typename RhsPixelT>
643 struct minusEq : public pixelOp2<LhsPixelT, RhsPixelT> {
644  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const override {
645  return static_cast<LhsPixelT>(lhs - rhs);
646  }
647 };
648 
649 template <typename LhsPixelT, typename RhsPixelT>
650 struct timesEq : public pixelOp2<LhsPixelT, RhsPixelT> {
651  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const override {
652  return static_cast<LhsPixelT>(lhs * rhs);
653  }
654 };
655 
656 template <typename LhsPixelT, typename RhsPixelT>
657 struct divideEq : public pixelOp2<LhsPixelT, RhsPixelT> {
658  LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const override {
659  return static_cast<LhsPixelT>(lhs / rhs);
660  }
661 };
662 } // namespace
663 
664 template <typename LhsPixelT, typename RhsPixelT>
666  for_each_pixel(lhs, rhs, plusEq<LhsPixelT, RhsPixelT>());
667  return lhs;
668 }
669 
670 template <typename LhsPixelT, typename RhsPixelT>
672  for_each_pixel(lhs, rhs, minusEq<LhsPixelT, RhsPixelT>());
673  return lhs;
674 }
675 
676 template <typename LhsPixelT, typename RhsPixelT>
678  for_each_pixel(lhs, rhs, timesEq<LhsPixelT, RhsPixelT>());
679  return lhs;
680 }
681 
682 template <typename LhsPixelT, typename RhsPixelT>
684  for_each_pixel(lhs, rhs, divideEq<LhsPixelT, RhsPixelT>());
685  return lhs;
686 }
687 
690  if (metadata.exists("ZNAXIS1") && metadata.exists("ZNAXIS2")) {
691  dims = lsst::geom::Extent2I(metadata.getAsInt("ZNAXIS1"), metadata.getAsInt("ZNAXIS2"));
692  } else {
693  dims = lsst::geom::Extent2I(metadata.getAsInt("NAXIS1"), metadata.getAsInt("NAXIS2"));
694  }
696  return lsst::geom::Box2I(xy0, dims);
697 }
698 
699 template <typename T1, typename T2>
700 bool imagesOverlap(ImageBase<T1> const& image1, ImageBase<T2> const& image2) {
701  auto arr1 = image1.getArray();
702  // get the address of the first and one-past-the-last element of arr1 using ndarray iterators;
703  // this works because the iterators for contiguous 1-d ndarray Arrays are just pointers
704  auto beg1Addr = arr1.front().begin();
705  auto end1Addr = arr1.back().end();
706 
707  auto arr2 = image2.getArray();
708  auto beg2Addr = arr2.front().begin();
709  auto end2Addr = arr2.back().end();
710 
711  auto ptrLess = std::less<void const* const>();
712  return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
713 }
714 
715 //
716 // Explicit instantiations
717 //
719 #define INSTANTIATE_OPERATOR(OP_EQ, T) \
720  template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint16_t> const& rhs); \
721  template Image<T>& operator OP_EQ(Image<T>& lhs, Image<int> const& rhs); \
722  template Image<T>& operator OP_EQ(Image<T>& lhs, Image<float> const& rhs); \
723  template Image<T>& operator OP_EQ(Image<T>& lhs, Image<double> const& rhs); \
724  template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint64_t> const& rhs);
725 
726 #define INSTANTIATE(T) \
727  template class ImageBase<T>; \
728  template class Image<T>; \
729  INSTANTIATE_OPERATOR(+=, T); \
730  INSTANTIATE_OPERATOR(-=, T); \
731  INSTANTIATE_OPERATOR(*=, T); \
732  INSTANTIATE_OPERATOR(/=, T)
733 
734 #define INSTANTIATE2(T1, T2) template bool imagesOverlap<T1, T2>(ImageBase<T1> const&, ImageBase<T2> const&);
735 
737 INSTANTIATE(int);
738 INSTANTIATE(float);
739 INSTANTIATE(double);
741 
745 INSTANTIATE2(std::uint16_t, double);
747 
749 INSTANTIATE2(int, int);
750 INSTANTIATE2(int, float);
751 INSTANTIATE2(int, double);
753 
755 INSTANTIATE2(float, int);
756 INSTANTIATE2(float, float);
757 INSTANTIATE2(float, double);
759 
760 INSTANTIATE2(double, std::uint16_t);
761 INSTANTIATE2(double, int);
762 INSTANTIATE2(double, float);
763 INSTANTIATE2(double, double);
764 INSTANTIATE2(double, std::uint64_t);
765 
769 INSTANTIATE2(std::uint64_t, double);
771 
773 } // namespace image
774 } // namespace afw
775 } // namespace lsst
y
int y
Definition: SpanSet.cc:49
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
lsst::afw::image::ImageBase::_allocateView
static _view_t _allocateView(lsst::geom::Extent2I const &dimensions, Manager::Ptr &manager)
Definition: Image.cc:58
lsst::daf::base::PropertySet::getAsInt
int getAsInt(std::string const &name) const
Get the last value for a bool/char/short/int property name (possibly hierarchical).
lsst::afw::image::ImageBase::Array
ndarray::Array< PixelT, 2, 1 > Array
A mutable ndarray representation of the image.
Definition: ImageBase.h:149
lsst::afw::image::ImageBase::assign
void assign(ImageBase const &rhs, lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT)
Copy pixels from another image to a specified subregion of this image.
Definition: Image.cc:160
lsst::afw::image::ImageFitsReader::read
Image< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the Image.
Definition: ImageFitsReader.cc:27
std::string
STL class.
std::shared_ptr
STL class.
lsst::afw::image::ImageBase::rbegin
reverse_iterator rbegin() const
Return an STL compliant reverse iterator to the start of the image.
Definition: Image.cc:267
lsst::afw::math::scaledPlus
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
Compute the scaled sum of two images.
Definition: ConvolveImage.cc:162
std::pair
lsst::afw::fits::Fits
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:297
ImageAlgorithm.h
lsst::afw::image::ImageBase::rend
reverse_iterator rend() const
Return an STL compliant reverse iterator to the end of the image.
Definition: Image.cc:272
lsst::afw::image::ImageBase::at
iterator at(int x, int y) const
Return an STL compliant iterator at the point (x, y)
Definition: Image.cc:277
lsst::afw::image::ImageBase::end
iterator end() const
Return an STL compliant iterator to the end of the image.
Definition: Image.cc:262
fits.h
lsst::ip::diffim::detail::PixelT
float PixelT
Definition: AssessSpatialKernelVisitor.cc:208
lsst::afw
Definition: imageAlgorithm.dox:1
lsst::afw::image::ImageBase::reverse_iterator
_view_t::reverse_iterator reverse_iterator
An STL compliant reverse iterator.
Definition: ImageBase.h:129
lsst::afw::image::ImageBase::_getRawView
_view_t _getRawView() const
Definition: ImageBase.h:463
lsst::daf::base::PropertySet::exists
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
boost
Definition: Polygon.cc:25
wcsUtils.h
lsst::afw::image::indexToPosition
double indexToPosition(double ind)
Convert image index to image position.
Definition: ImageUtils.h:55
lsst.pex.config.history.format
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
lsst::afw::image::ImageBase::operator=
ImageBase & operator=(const ImageBase &rhs)
Shallow assignment operator.
Definition: Image.cc:147
INSTANTIATE
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:484
lsst::afw::fits::MemFileManager
Lifetime-management for memory that goes into FITS memory files.
Definition: fits.h:121
lsst::afw::image::X
@ X
Definition: ImageUtils.h:36
mask
afw::table::Key< afw::table::Array< MaskPixelT > > mask
Definition: HeavyFootprint.cc:217
std::less
lsst::afw::image::ImageBase::getHeight
int getHeight() const
Return the number of rows in the image.
Definition: ImageBase.h:296
Image.h
std::sqrt
T sqrt(T... args)
lsst::afw::image::ImageFitsReader
A FITS reader class for regular Images.
Definition: ImageFitsReader.h:39
end
int end
Definition: BoundedField.cc:105
lsst::afw::image::ImageBase::operator()
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y) in LOCAL coordinates.
Definition: Image.cc:178
lsst::afw::image::operator*=
Image< LhsPixelT > & operator*=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Multiply lhs by Image rhs (i.e. pixel-by-pixel multiplication) where types are different.
Definition: Image.cc:677
lsst::afw::image::ImageBase::begin
iterator begin() const
Return an STL compliant iterator to the start of the image.
Definition: Image.cc:257
lsst::afw::image::ImageBase::PixelReference
Reference< PixelT >::type PixelReference
A Reference to a PixelT.
Definition: ImageBase.h:117
x
double x
Definition: ChebyshevBoundedField.cc:277
lsst.pex::exceptions::LengthError
Reports attempts to exceed implementation-defined length limits for some classes.
Definition: Runtime.h:76
lsst::afw::image::Image::Image
friend class Image
Definition: Image.h:72
lsst::afw::image::ImageBase::_makeSubView
static _view_t _makeSubView(lsst::geom::Extent2I const &dimensions, lsst::geom::Extent2I const &offset, const _view_t &view)
Definition: Image.cc:78
lsst::afw::image::Y
@ Y
Definition: ImageUtils.h:36
lsst::afw::image::ImageBase::getArray
Array getArray()
Definition: ImageBase.h:474
ptr
uint64_t * ptr
Definition: RangeSet.cc:88
std::uint16_t
dimensions
afw::table::PointKey< int > dimensions
Definition: GaussianPsf.cc:49
lsst::afw::image::CheckIndices
A class used to request that array accesses be checked.
Definition: ImageBase.h:74
lsst::afw::typehandling::PolymorphicValue::swap
void swap(PolymorphicValue &lhs, PolymorphicValue &rhs) noexcept
Swap specialization for PolymorphicValue.
Definition: PolymorphicValue.h:152
lsst::afw::image::operator-=
Image< LhsPixelT > & operator-=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Subtract lhs from Image rhs (i.e. pixel-by-pixel subtraction) where types are different.
Definition: Image.cc:671
lsst::afw::image::ImageBase::x_iterator
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
Definition: ImageBase.h:133
b
table::Key< int > b
Definition: TransmissionCurve.cc:467
ImageFitsReader.h
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
lsst::afw::image::detail::wcsNameForXY0
std::string const wcsNameForXY0
Definition: ImageBase.h:70
LSST_EXCEPT
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::swap
T swap(T... args)
lsst::afw::image::for_each_pixel
void for_each_pixel(Image< LhsT > &lhs, pixelOp0< LhsT > const &func)
Set each pixel in an Image<LhsT> to func()
Definition: ImageAlgorithm.h:97
lsst::geom
Definition: AffineTransform.h:36
lsst::afw::image::bboxFromMetadata
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
Definition: Image.cc:688
lsst::afw::math::Function2< double >
lsst::afw::image::pixelOp2::operator()
virtual LhsT operator()(LhsT lhs, RhsT rhs) const =0
lsst::geom::ExtentI
Extent< int, 2 > ExtentI
Definition: Extent.h:396
lsst::afw::image::ImageBase::getDimensions
lsst::geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
Definition: ImageBase.h:354
lsst::afw::image::ImageBase::fast_iterator
x_iterator fast_iterator
A fast STL compliant iterator for contiguous images N.b.
Definition: ImageBase.h:137
a
table::Key< int > a
Definition: TransmissionCurve.cc:466
lsst::afw::image::ImageBaseFitsReader::readMetadata
std::shared_ptr< daf::base::PropertyList > readMetadata()
Read the image's FITS header.
Definition: ImageBaseFitsReader.cc:105
lsst::geom::Extent2I
Extent< int, 2 > Extent2I
Definition: Extent.h:397
lsst::afw::image::operator/=
Image< LhsPixelT > & operator/=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Divide lhs by Image rhs (i.e. pixel-by-pixel division) where types are different.
Definition: Image.cc:683
lsst::geom::Point< int, 2 >
lsst::afw::image::ImageBase::iterator
_view_t::iterator iterator
An STL compliant iterator.
Definition: ImageBase.h:125
lsst::afw::cameraGeom::swap
void swap(CameraSys &a, CameraSys &b)
Definition: CameraSys.h:157
lsst::afw::image::pixelOp2
A functor class equivalent to std::function<LhsT (LhsT, RhsT)>, but with a virtual operator()
Definition: ImageAlgorithm.h:79
lsst::daf::base::PropertySet
Class for storing generic metadata.
Definition: PropertySet.h:67
lsst::geom::Box2I
An integer coordinate rectangle.
Definition: Box.h:55
lsst::afw::geom::getImageXY0FromMetadata
lsst::geom::Point2I getImageXY0FromMetadata(daf::base::PropertySet &metadata, std::string const &wcsName, bool strip=false)
Definition: wcsUtils.cc:98
lsst::afw::image::PARENT
@ PARENT
Definition: ImageBase.h:94
lsst::afw::image::swap
void swap(Image< PixelT > &a, Image< PixelT > &b)
Definition: Image.cc:450
INSTANTIATE2
#define INSTANTIATE2(ImagePixelT1, ImagePixelT2)
Definition: MaskedImage.cc:674
lsst::afw::image::operator+=
Image< LhsPixelT > & operator+=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Add lhs to Image rhs (i.e. pixel-by-pixel addition) where types are different.
Definition: Image.cc:665
lsst::afw::image::ImageOrigin
ImageOrigin
Definition: ImageBase.h:94
lsst::afw::image::imagesOverlap
bool imagesOverlap(ImageBase< T1 > const &image1, ImageBase< T2 > const &image2)
Return true if the pixels for two images or masks overlap in memory.
Definition: Image.cc:700
lsst::afw::image::ImageBase::getBBox
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Definition: ImageBase.h:443
lsst::afw::image::Image
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:58
lsst::afw::image::ImageBase::swap
void swap(ImageBase &rhs)
Definition: Image.cc:240
lsst::afw::image::ImageBase::PixelConstReference
ConstReference< PixelT >::type PixelConstReference
A ConstReference to a PixelT.
Definition: ImageBase.h:119
lsst::afw::image::ImageBase
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition: ImageBase.h:102
lsst::geom::Extent< int, 2 >
std::numeric_limits
lsst::afw::image::ImageBase::get
PixelReference get(lsst::geom::Point2I const &index, ImageOrigin origin)
Return a reference to a single pixel (with no bounds check).
Definition: Image.cc:216
lsst::afw::image::ImageBase::ImageBase
friend class ImageBase
Definition: ImageBase.h:154
lsst.pipe.drivers.constructCalibs.getSize
def getSize(dimList)
Definition: constructCalibs.py:176
lsst::afw::image::ImageBase::getWidth
int getWidth() const
Return the number of columns in the image.
Definition: ImageBase.h:294
bbox
AmpInfoBoxKey bbox
Definition: Amplifier.cc:117
lsst.pex::exceptions::RuntimeError
Reports errors that are due to events beyond the control of the program.
Definition: Runtime.h:104
exceptions.h