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" 39 #include "boost/version.hpp" 40 #if BOOST_VERSION < 106900 41 #include "boost/gil/gil_all.hpp" 43 #include "boost/gil.hpp" 57 template <
typename PixelT>
59 Manager::Ptr& manager) {
60 if (dimensions.getX() < 0 || dimensions.getY() < 0) {
63 dimensions.getX() % dimensions.getY()));
67 str(
boost::format(
"Image dimensions (%d x %d) too large; int overflow detected.") %
68 dimensions.getX() % dimensions.getY()));
71 ndarray::SimpleManager<PixelT>::allocate(dimensions.getX() * dimensions.getY());
73 return boost::gil::interleaved_view(dimensions.getX(), dimensions.getY(),
74 (
typename _view_t::value_type*)r.second,
75 dimensions.getX() *
sizeof(
PixelT));
77 template <
typename PixelT>
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()) {
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() %
91 return boost::gil::subimage_view(view, offset.getX(), offset.getY(), dimensions.getX(),
95 template <
typename PixelT>
97 : daf::
base::Citizen(typeid(this)),
100 _gilView(_allocateView(dimensions, _manager)) {}
102 template <
typename PixelT>
104 : daf::
base::Citizen(typeid(this)),
105 _origin(bbox.getMin()),
107 _gilView(_allocateView(bbox.getDimensions(), _manager)) {}
109 template <
typename PixelT>
113 : daf::
base::Citizen(typeid(this)),
114 _origin(rhs._origin),
115 _manager(rhs._manager),
116 _gilView(rhs._gilView) {
124 template <
typename PixelT>
127 template <
typename PixelT>
132 : daf::
base::Citizen(typeid(this)),
133 _origin((origin ==
PARENT) ? bbox.getMin() : rhs._origin +
lsst::geom::
Extent2I(bbox.getMin())),
134 _manager(rhs._manager),
135 _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
143 template <
typename PixelT>
145 : daf::
base::Citizen(typeid(this)),
147 _manager(array.getManager()),
148 _gilView(
boost::gil::interleaved_view(array.template
getSize<1>(), array.template
getSize<0>(),
149 (typename _view_t::value_type*)array.getData(),
150 array.template getStride<0>() * sizeof(
PixelT))) {
157 template <
typename PixelT>
165 template <
typename PixelT>
170 template <
typename PixelT>
176 template <
typename PixelT>
181 (
boost::format(
"Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
186 copy_pixels(rhs._gilView, _gilView);
189 auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
190 copy_pixels(rhs._gilView, lhsGilView);
194 template <
typename PixelT>
200 template <
typename PixelT>
203 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
205 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
206 (getWidth() - 1) % (getHeight() - 1))
214 template <
typename PixelT>
216 return _gilView(x, y)[0];
219 template <
typename PixelT>
222 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
224 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
225 (this->getWidth() - 1) % (this->getHeight() - 1))
229 return _gilView(x, y)[0];
232 template <
typename PixelT>
235 int x = index.getX();
236 int y = index.getY();
241 return _gilView(x, y)[0];
244 template <
typename PixelT>
247 int x = index.getX();
248 int y = index.getY();
253 return _gilView(x, y)[0];
257 template <
typename PixelT>
261 swap(_manager, rhs._manager);
262 swap(_gilView, rhs._gilView);
263 swap(_origin, rhs._origin);
266 template <
typename PixelT>
274 template <
typename PixelT>
276 return _gilView.
begin();
279 template <
typename PixelT>
281 return _gilView.end();
284 template <
typename PixelT>
289 template <
typename PixelT>
291 return _gilView.
rend();
294 template <
typename PixelT>
296 return _gilView.
at(x, y);
299 template <
typename PixelT>
304 if (!this->isContiguous()) {
311 template <
typename PixelT>
316 if (!this->isContiguous()) {
320 return row_end(getHeight() - 1);
323 template <
typename PixelT>
325 fill_pixels(_gilView, rhs);
333 template <
typename PixelT>
336 *
this = initialValue;
339 template <
typename PixelT>
342 *
this = initialValue;
345 template <
typename PixelT>
347 *
this = initialValue;
350 template <
typename PixelT>
353 template <
typename PixelT>
356 template <
typename PixelT>
361 template <
typename PixelT>
368 template <
typename PixelT>
375 template <
typename PixelT>
380 #ifndef DOXYGEN // doc for this section has been moved to header 382 template <
typename PixelT>
393 template <
typename PixelT>
405 template <
typename PixelT>
416 template <
typename PixelT>
420 fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
421 writeFits(fitsfile, metadata_i);
424 template <
typename PixelT>
428 fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
429 writeFits(fitsfile, metadata_i);
432 template <
typename PixelT>
438 template <
typename PixelT>
442 fits::Fits fitsfile(filename, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
443 writeFits(fitsfile, options, header,
mask);
446 template <
typename PixelT>
450 fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
451 writeFits(fitsfile, options, header,
mask);
454 template <
typename PixelT>
463 template <
typename PixelT>
470 template <
typename PixelT>
476 template <
typename PixelT>
478 transform_pixels(_getRawView(), _getRawView(),
482 template <
typename PixelT>
484 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l + rhs; });
488 template <
typename PixelT>
492 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
496 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
501 template <
typename PixelT>
503 for (
int y = 0;
y != this->getHeight(); ++
y) {
508 *
ptr +=
function(xPos, yPos);
514 template <
typename PixelT>
518 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
527 template <
typename PixelT>
529 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l - rhs; });
533 template <
typename PixelT>
537 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
541 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
546 template <
typename PixelT>
550 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
559 template <
typename PixelT>
561 for (
int y = 0;
y != this->getHeight(); ++
y) {
566 *
ptr -=
function(xPos, yPos);
572 template <
typename PixelT>
574 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l * rhs; });
578 template <
typename PixelT>
582 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
586 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
591 template <
typename PixelT>
595 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
604 template <
typename PixelT>
606 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l / rhs; });
614 double const irhs = 1 / rhs;
621 float const irhs = 1 / rhs;
626 template <
typename PixelT>
630 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
634 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
639 template <
typename PixelT>
643 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
656 template <
typename LhsPixelT,
typename RhsPixelT>
657 struct plusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
658 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
659 return static_cast<LhsPixelT
>(lhs + rhs);
663 template <
typename LhsPixelT,
typename RhsPixelT>
664 struct minusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
665 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
666 return static_cast<LhsPixelT
>(lhs - rhs);
670 template <
typename LhsPixelT,
typename RhsPixelT>
671 struct timesEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
672 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
673 return static_cast<LhsPixelT
>(lhs * rhs);
677 template <
typename LhsPixelT,
typename RhsPixelT>
678 struct divideEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
679 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
680 return static_cast<LhsPixelT
>(lhs / rhs);
685 template <
typename LhsPixelT,
typename RhsPixelT>
691 template <
typename LhsPixelT,
typename RhsPixelT>
697 template <
typename LhsPixelT,
typename RhsPixelT>
703 template <
typename LhsPixelT,
typename RhsPixelT>
711 if (metadata.
exists(
"ZNAXIS1") && metadata.
exists(
"ZNAXIS2")) {
720 template <
typename T1,
typename T2>
725 auto beg1Addr = arr1.front().begin();
726 auto end1Addr = arr1.back().end();
729 auto beg2Addr = arr2.front().begin();
730 auto end2Addr = arr2.back().end();
733 return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
740 #define INSTANTIATE_OPERATOR(OP_EQ, T) \ 741 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint16_t> const& rhs); \ 742 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<int> const& rhs); \ 743 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<float> const& rhs); \ 744 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<double> const& rhs); \ 745 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint64_t> const& rhs); 747 #define INSTANTIATE(T) \ 748 template class ImageBase<T>; \ 749 template class Image<T>; \ 750 INSTANTIATE_OPERATOR(+=, T); \ 751 INSTANTIATE_OPERATOR(-=, T); \ 752 INSTANTIATE_OPERATOR(*=, T); \ 753 INSTANTIATE_OPERATOR(/=, T) 755 #define INSTANTIATE2(T1, T2) template bool imagesOverlap<T1, T2>(ImageBase<T1> const&, ImageBase<T2> const&); Extent2I const getDimensions() const noexcept
afw::table::PointKey< int > dimensions
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
Compute the scaled sum of two images.
A functor class equivalent to std::function<LhsT (LhsT, RhsT)>, but with a virtual operator() ...
x_iterator fast_iterator
A fast STL compliant iterator for contiguous images N.b.
std::shared_ptr< daf::base::PropertyList > readMetadata()
Read the image's FITS header.
ConstReference< PixelT >::type PixelConstReference
A ConstReference to a PixelT.
double indexToPosition(double ind)
Convert image index to image position.
_view_t::reverse_iterator reverse_iterator
An STL compliant reverse iterator.
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.
int getHeight() const
Return the number of rows in the image.
bool isEmpty() const noexcept
Return true if the box contains no points.
Reports attempts to exceed implementation-defined length limits for some classes. ...
Options for writing an image to FITS.
int getAsInt(std::string const &name) const
Get the last value for a bool/char/short/int property name (possibly hierarchical).
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
A FITS reader class for regular Images.
void for_each_pixel(Image< LhsT > &lhs, pixelOp0< LhsT > const &func)
Set each pixel in an Image<LhsT> to func()
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
The base class for all image classed (Image, Mask, MaskedImage, ...)
A Function taking two arguments.
Point2I const getMin() const noexcept
_view_t::iterator iterator
An STL compliant iterator.
A base class for image defects.
Represent a 2-dimensional array of bitmask pixels.
Lifetime-management for memory that goes into FITS memory files.
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.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
bool imagesOverlap(ImageBase< T1 > const &image1, ImageBase< T2 > const &image2)
Return true if the pixels for two images or masks overlap in memory.
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
A class used to request that array accesses be checked.
void swap(ImageBase &rhs)
Image< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the Image.
void swap(Image< PixelT > &a, Image< PixelT > &b)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Extent< int, 2 > Extent2I
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.
reverse_iterator rend() const
Return an STL compliant reverse iterator to the end of the image.
lsst::geom::Point2I getImageXY0FromMetadata(daf::base::PropertySet &metadata, std::string const &wcsName, bool strip=false)
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.
Class for storing generic metadata.
int getWidth() const
Return the number of columns in the image.
Reference< PixelT >::type PixelReference
A Reference to a PixelT.
reverse_iterator rbegin() const
Return an STL compliant reverse iterator to the start of the image.
iterator begin() const
Return an STL compliant iterator to the start of the image.
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. ...
iterator at(int x, int y) const
Return an STL compliant iterator at the point (x, y)
lsst::geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
void writeImage(ndarray::Array< T const, N, C > const &array)
Write an ndarray::Array to a FITS image HDU.
_view_t _getRawView() const
static _view_t _allocateView(lsst::geom::Extent2I const &dimensions, Manager::Ptr &manager)
ndarray::Array< MaskPixelT, 2, 1 > Array
A mutable ndarray representation of the image.
An integer coordinate rectangle.
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
A class to represent a 2-dimensional array of pixels.
#define INSTANTIATE2(ImagePixelT1, ImagePixelT2)
std::string const wcsNameForXY0
#define INSTANTIATE(FROMSYS, TOSYS)
Reports errors that are due to events beyond the control of the program.
static _view_t _makeSubView(lsst::geom::Extent2I const &dimensions, lsst::geom::Extent2I const &offset, const _view_t &view)