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) {
62 str(
boost::format(
"Both width and height must be non-negative: %d, %d") %
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 : _origin(0, 0), _manager(), _gilView(_allocateView(dimensions, _manager)) {}
99 template <
typename PixelT>
101 : _origin(bbox.getMin()), _manager(), _gilView(_allocateView(bbox.getDimensions(), _manager)) {}
103 template <
typename PixelT>
107 : _origin(rhs._origin), _manager(rhs._manager), _gilView(rhs._gilView) {
115 template <
typename PixelT>
118 template <
typename PixelT>
124 _manager(rhs._manager),
125 _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
133 template <
typename PixelT>
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))) {
146 template <
typename PixelT>
154 template <
typename PixelT>
159 template <
typename PixelT>
165 template <
typename PixelT>
170 (
boost::format(
"Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
175 copy_pixels(rhs._gilView, _gilView);
178 auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
179 copy_pixels(rhs._gilView, lhsGilView);
183 template <
typename PixelT>
189 template <
typename PixelT>
192 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
194 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
195 (getWidth() - 1) % (getHeight() - 1))
203 template <
typename PixelT>
205 return _gilView(x, y)[0];
208 template <
typename PixelT>
211 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
213 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y %
214 (this->getWidth() - 1) % (this->getHeight() - 1))
218 return _gilView(x, y)[0];
221 template <
typename PixelT>
224 int x = index.getX();
225 int y = index.getY();
230 return _gilView(x, y)[0];
233 template <
typename PixelT>
236 int x = index.getX();
237 int y = index.getY();
242 return _gilView(x, y)[0];
245 template <
typename PixelT>
249 swap(_manager, rhs._manager);
250 swap(_gilView, rhs._gilView);
251 swap(_origin, rhs._origin);
254 template <
typename PixelT>
262 template <
typename PixelT>
264 return _gilView.
begin();
267 template <
typename PixelT>
269 return _gilView.end();
272 template <
typename PixelT>
277 template <
typename PixelT>
279 return _gilView.
rend();
282 template <
typename PixelT>
284 return _gilView.
at(x, y);
287 template <
typename PixelT>
292 if (!this->isContiguous()) {
299 template <
typename PixelT>
304 if (!this->isContiguous()) {
308 return row_end(getHeight() - 1);
311 template <
typename PixelT>
313 fill_pixels(_gilView, rhs);
321 template <
typename PixelT>
324 *
this = initialValue;
327 template <
typename PixelT>
330 *
this = initialValue;
333 template <
typename PixelT>
335 *
this = initialValue;
338 template <
typename PixelT>
341 template <
typename PixelT>
344 template <
typename PixelT>
349 template <
typename PixelT>
356 template <
typename PixelT>
363 template <
typename PixelT>
368 #ifndef DOXYGEN // doc for this section has been moved to header 370 template <
typename PixelT>
380 template <
typename PixelT>
391 template <
typename PixelT>
401 template <
typename PixelT>
405 fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
406 writeFits(fitsfile, metadata_i);
409 template <
typename PixelT>
413 fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
414 writeFits(fitsfile, metadata_i);
417 template <
typename PixelT>
423 template <
typename PixelT>
427 fits::Fits fitsfile(filename, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
428 writeFits(fitsfile, options, header,
mask);
431 template <
typename PixelT>
435 fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
436 writeFits(fitsfile, options, header,
mask);
439 template <
typename PixelT>
448 template <
typename PixelT>
455 template <
typename PixelT>
461 template <
typename PixelT>
463 transform_pixels(_getRawView(), _getRawView(),
467 template <
typename PixelT>
469 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l + rhs; });
473 template <
typename PixelT>
477 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
481 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
486 template <
typename PixelT>
488 for (
int y = 0;
y != this->getHeight(); ++
y) {
493 *
ptr +=
function(xPos, yPos);
499 template <
typename PixelT>
503 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
512 template <
typename PixelT>
514 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l - rhs; });
518 template <
typename PixelT>
522 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
526 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
531 template <
typename PixelT>
535 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
544 template <
typename PixelT>
546 for (
int y = 0;
y != this->getHeight(); ++
y) {
551 *
ptr -=
function(xPos, yPos);
557 template <
typename PixelT>
559 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l * rhs; });
563 template <
typename PixelT>
567 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
571 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
576 template <
typename PixelT>
580 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
589 template <
typename PixelT>
591 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l / rhs; });
599 double const irhs = 1 / rhs;
606 float const irhs = 1 / rhs;
611 template <
typename PixelT>
615 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
619 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
624 template <
typename PixelT>
628 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
641 template <
typename LhsPixelT,
typename RhsPixelT>
642 struct plusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
643 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
644 return static_cast<LhsPixelT
>(lhs + rhs);
648 template <
typename LhsPixelT,
typename RhsPixelT>
649 struct minusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
650 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
651 return static_cast<LhsPixelT
>(lhs - rhs);
655 template <
typename LhsPixelT,
typename RhsPixelT>
656 struct timesEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
657 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
658 return static_cast<LhsPixelT
>(lhs * rhs);
662 template <
typename LhsPixelT,
typename RhsPixelT>
663 struct divideEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
664 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
665 return static_cast<LhsPixelT
>(lhs / rhs);
670 template <
typename LhsPixelT,
typename RhsPixelT>
676 template <
typename LhsPixelT,
typename RhsPixelT>
682 template <
typename LhsPixelT,
typename RhsPixelT>
688 template <
typename LhsPixelT,
typename RhsPixelT>
696 if (metadata.
exists(
"ZNAXIS1") && metadata.
exists(
"ZNAXIS2")) {
705 template <
typename T1,
typename T2>
710 auto beg1Addr = arr1.front().begin();
711 auto end1Addr = arr1.back().end();
714 auto beg2Addr = arr2.front().begin();
715 auto end2Addr = arr2.back().end();
718 return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
725 #define INSTANTIATE_OPERATOR(OP_EQ, T) \ 726 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint16_t> const& rhs); \ 727 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<int> const& rhs); \ 728 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<float> const& rhs); \ 729 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<double> const& rhs); \ 730 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint64_t> const& rhs); 732 #define INSTANTIATE(T) \ 733 template class ImageBase<T>; \ 734 template class Image<T>; \ 735 INSTANTIATE_OPERATOR(+=, T); \ 736 INSTANTIATE_OPERATOR(-=, T); \ 737 INSTANTIATE_OPERATOR(*=, T); \ 738 INSTANTIATE_OPERATOR(/=, T) 740 #define INSTANTIATE2(T1, T2) template bool imagesOverlap<T1, T2>(ImageBase<T1> const&, ImageBase<T2> const&);
Extent2I const getDimensions() const noexcept
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
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.
afw::table::PointKey< int > dimensions
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.
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.
#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.
void swap(CameraSys &a, CameraSys &b)
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)