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 #include "boost/gil/gil_all.hpp" 51 template <
typename PixelT>
53 Manager::Ptr& manager) {
54 if (dimensions.getX() < 0 || dimensions.getY() < 0) {
57 dimensions.getX() % dimensions.getY()));
61 str(
boost::format(
"Image dimensions (%d x %d) too large; int overflow detected.") %
62 dimensions.getX() % dimensions.getY()));
65 ndarray::SimpleManager<PixelT>::allocate(dimensions.getX() * dimensions.getY());
67 return boost::gil::interleaved_view(dimensions.getX(), dimensions.getY(),
68 (
typename _view_t::value_type*)r.second,
69 dimensions.getX() *
sizeof(
PixelT));
71 template <
typename PixelT>
74 const _view_t& view) {
75 if (offset.getX() < 0 || offset.getY() < 0 || offset.getX() + dimensions.getX() > view.width() ||
76 offset.getY() + dimensions.getY() > view.height()) {
80 "Box2I(Point2I(%d,%d),lsst::geom::Extent2I(%d,%d)) doesn't fit in image %dx%d") %
81 offset.getX() % offset.getY() % dimensions.getX() % dimensions.getY() % view.width() %
85 return boost::gil::subimage_view(view, offset.getX(), offset.getY(), dimensions.getX(),
89 template <
typename PixelT>
91 : daf::
base::Citizen(typeid(this)),
94 _gilView(_allocateView(dimensions, _manager)) {}
96 template <
typename PixelT>
98 : daf::
base::Citizen(typeid(this)),
99 _origin(bbox.getMin()),
101 _gilView(_allocateView(bbox.getDimensions(), _manager)) {}
103 template <
typename PixelT>
107 : daf::
base::Citizen(typeid(this)),
108 _origin(rhs._origin),
109 _manager(rhs._manager),
110 _gilView(rhs._gilView) {
118 template <
typename PixelT>
121 template <
typename PixelT>
126 : daf::
base::Citizen(typeid(this)),
127 _origin((origin ==
PARENT) ? bbox.getMin() : rhs._origin +
lsst::geom::
Extent2I(bbox.getMin())),
128 _manager(rhs._manager),
129 _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
137 template <
typename PixelT>
139 : daf::
base::Citizen(typeid(this)),
141 _manager(array.getManager()),
142 _gilView(
boost::gil::interleaved_view(array.template
getSize<1>(), array.template
getSize<0>(),
143 (typename _view_t::value_type*)array.getData(),
144 array.template getStride<0>() * sizeof(
PixelT))) {
151 template <
typename PixelT>
159 template <
typename PixelT>
164 template <
typename PixelT>
170 template <
typename PixelT>
175 (
boost::format(
"Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
180 copy_pixels(rhs._gilView, _gilView);
183 auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
184 copy_pixels(rhs._gilView, lhsGilView);
188 template <
typename PixelT>
194 template <
typename PixelT>
197 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
199 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
200 (getWidth() - 1) % (getHeight() - 1))
208 template <
typename PixelT>
210 return _gilView(x, y)[0];
213 template <
typename PixelT>
216 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
218 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
219 (this->getWidth() - 1) % (this->getHeight() - 1))
223 return _gilView(x, y)[0];
226 template <
typename PixelT>
229 int x = index.getX();
230 int y = index.getY();
235 return _gilView(x, y)[0];
238 template <
typename PixelT>
241 int x = index.getX();
242 int y = index.getY();
247 return _gilView(x, y)[0];
251 template <
typename PixelT>
255 swap(_manager, rhs._manager);
256 swap(_gilView, rhs._gilView);
257 swap(_origin, rhs._origin);
260 template <
typename PixelT>
268 template <
typename PixelT>
270 return _gilView.
begin();
273 template <
typename PixelT>
275 return _gilView.end();
278 template <
typename PixelT>
283 template <
typename PixelT>
285 return _gilView.
rend();
288 template <
typename PixelT>
290 return _gilView.
at(x, y);
293 template <
typename PixelT>
298 if (!this->isContiguous()) {
305 template <
typename PixelT>
310 if (!this->isContiguous()) {
314 return row_end(getHeight() - 1);
317 template <
typename PixelT>
319 fill_pixels(_gilView, rhs);
327 template <
typename PixelT>
330 *
this = initialValue;
333 template <
typename PixelT>
336 *
this = initialValue;
339 template <
typename PixelT>
341 *
this = initialValue;
344 template <
typename PixelT>
347 template <
typename PixelT>
350 template <
typename PixelT>
355 template <
typename PixelT>
362 template <
typename PixelT>
369 template <
typename PixelT>
374 #ifndef DOXYGEN // doc for this section has been moved to header 376 template <
typename PixelT>
387 template <
typename PixelT>
399 template <
typename PixelT>
410 template <
typename PixelT>
414 fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
415 writeFits(fitsfile, metadata_i);
418 template <
typename PixelT>
422 fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
423 writeFits(fitsfile, metadata_i);
426 template <
typename PixelT>
432 template <
typename PixelT>
436 fits::Fits fitsfile(filename, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
437 writeFits(fitsfile, options, header,
mask);
440 template <
typename PixelT>
444 fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
445 writeFits(fitsfile, options, header,
mask);
448 template <
typename PixelT>
457 template <
typename PixelT>
464 template <
typename PixelT>
470 template <
typename PixelT>
472 transform_pixels(_getRawView(), _getRawView(),
476 template <
typename PixelT>
478 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l + rhs; });
482 template <
typename PixelT>
486 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
490 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
495 template <
typename PixelT>
497 for (
int y = 0;
y != this->getHeight(); ++
y) {
502 *
ptr +=
function(xPos, yPos);
508 template <
typename PixelT>
512 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
521 template <
typename PixelT>
523 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l - rhs; });
527 template <
typename PixelT>
531 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
535 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
540 template <
typename PixelT>
544 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
553 template <
typename PixelT>
555 for (
int y = 0;
y != this->getHeight(); ++
y) {
560 *
ptr -=
function(xPos, yPos);
566 template <
typename PixelT>
568 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l * rhs; });
572 template <
typename PixelT>
576 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
580 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
585 template <
typename PixelT>
589 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
598 template <
typename PixelT>
600 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l / rhs; });
608 double const irhs = 1 / rhs;
615 float const irhs = 1 / rhs;
620 template <
typename PixelT>
624 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
628 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
633 template <
typename PixelT>
637 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
650 template <
typename LhsPixelT,
typename RhsPixelT>
651 struct plusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
652 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
653 return static_cast<LhsPixelT
>(lhs + rhs);
657 template <
typename LhsPixelT,
typename RhsPixelT>
658 struct minusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
659 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
660 return static_cast<LhsPixelT
>(lhs - rhs);
664 template <
typename LhsPixelT,
typename RhsPixelT>
665 struct timesEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
666 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
667 return static_cast<LhsPixelT
>(lhs * rhs);
671 template <
typename LhsPixelT,
typename RhsPixelT>
672 struct divideEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
673 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
674 return static_cast<LhsPixelT
>(lhs / rhs);
679 template <
typename LhsPixelT,
typename RhsPixelT>
685 template <
typename LhsPixelT,
typename RhsPixelT>
691 template <
typename LhsPixelT,
typename RhsPixelT>
697 template <
typename LhsPixelT,
typename RhsPixelT>
705 if (metadata.
exists(
"ZNAXIS1") && metadata.
exists(
"ZNAXIS2")) {
714 template <
typename T1,
typename T2>
719 auto beg1Addr = arr1.front().begin();
720 auto end1Addr = arr1.back().end();
723 auto beg2Addr = arr2.front().begin();
724 auto end2Addr = arr2.back().end();
727 return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
734 #define INSTANTIATE_OPERATOR(OP_EQ, T) \ 735 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint16_t> const& rhs); \ 736 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<int> const& rhs); \ 737 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<float> const& rhs); \ 738 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<double> const& rhs); \ 739 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint64_t> const& rhs); 741 #define INSTANTIATE(T) \ 742 template class ImageBase<T>; \ 743 template class Image<T>; \ 744 INSTANTIATE_OPERATOR(+=, T); \ 745 INSTANTIATE_OPERATOR(-=, T); \ 746 INSTANTIATE_OPERATOR(*=, T); \ 747 INSTANTIATE_OPERATOR(/=, T) 749 #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.
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)