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) {
62 str(
boost::format(
"Both width and height must be non-negative: %d, %d") %
67 str(
boost::format(
"Image dimensions (%d x %d) too large; int overflow detected.") %
74 (
typename _view_t::value_type*)r.second,
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") %
92 && view.width() == 0 && view.height() == 0) {
96 return boost::gil::subimage_view(view, offset.getX(), offset.getY(),
dimensions.getX(),
101 template <
typename PixelT>
103 : _origin(0, 0), _manager(), _gilView(_allocateView(
dimensions, _manager)) {}
105 template <
typename PixelT>
107 : _origin(
bbox.getMin()), _manager(), _gilView(_allocateView(
bbox.getDimensions(), _manager)) {}
109 template <
typename PixelT>
113 : _origin(rhs._origin), _manager(rhs._manager), _gilView(rhs._gilView) {
121 template <
typename PixelT>
124 template <
typename PixelT>
130 _manager(rhs._manager),
131 _gilView(_makeSubView(
bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
139 template <
typename PixelT>
142 _manager(array.getManager()),
143 _gilView(
boost::gil::interleaved_view(array.template
getSize<1>(), array.template
getSize<0>(),
144 (typename _view_t::value_type*)array.getData(),
145 array.template getStride<0>() * sizeof(
PixelT))) {
152 template <
typename PixelT>
160 template <
typename PixelT>
165 template <
typename PixelT>
167 auto lhsDim =
bbox.isEmpty() ? getDimensions() :
bbox.getDimensions();
170 (
boost::format(
"Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
174 if (
bbox.isEmpty()) {
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);
254 template <
typename PixelT>
262 template <
typename PixelT>
264 return _gilView.begin();
267 template <
typename PixelT>
269 return _gilView.end();
272 template <
typename PixelT>
274 return _gilView.rbegin();
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>
370 template <
typename PixelT>
376 metadata->combine(reader.readMetadata());
380 template <
typename PixelT>
391 template <
typename PixelT>
394 ImageFitsReader reader(&fitsFile);
397 metadata->combine(reader.readMetadata());
401 template <
typename PixelT>
409 template <
typename PixelT>
417 template <
typename PixelT>
420 fitsfile.writeImage(*
this, fits::ImageWriteOptions(*
this), metadata);
423 template <
typename PixelT>
431 template <
typename PixelT>
439 template <
typename PixelT>
443 fitsfile.writeImage(*
this, options, header,
mask);
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>
716 auto beg1Addr = arr1.front().begin();
717 auto end1Addr = arr1.back().end();
720 auto beg2Addr = arr2.front().begin();
721 auto end2Addr = arr2.back().end();
724 return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
731 #define INSTANTIATE_OPERATOR(OP_EQ, T) \
732 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint16_t> const& rhs); \
733 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<int> const& rhs); \
734 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<float> const& rhs); \
735 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<double> const& rhs); \
736 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint64_t> const& rhs);
738 #define INSTANTIATE(T) \
739 template class ImageBase<T>; \
740 template class Image<T>; \
741 INSTANTIATE_OPERATOR(+=, T); \
742 INSTANTIATE_OPERATOR(-=, T); \
743 INSTANTIATE_OPERATOR(*=, T); \
744 INSTANTIATE_OPERATOR(/=, T)
746 #define INSTANTIATE2(T1, T2) template bool imagesOverlap<T1, T2>(ImageBase<T1> const&, ImageBase<T2> const&);
#define INSTANTIATE(FROMSYS, TOSYS)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
afw::table::PointKey< int > dimensions
#define INSTANTIATE2(ImagePixelT1, ImagePixelT2)
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Lifetime-management for memory that goes into FITS memory files.
A class used to request that array accesses be checked.
std::shared_ptr< daf::base::PropertyList > readMetadata()
Read the image's FITS header.
The base class for all image classed (Image, Mask, MaskedImage, ...)
iterator end() const
Return an STL compliant iterator to the end of the image.
iterator begin() const
Return an STL compliant iterator to the start of the image.
static _view_t _allocateView(lsst::geom::Extent2I const &dimensions, Manager::Ptr &manager)
Reference< PixelT >::type PixelReference
A Reference to a PixelT.
PixelReference operator()(int x, int y)
Return a reference to the pixel (x, y) in LOCAL coordinates.
static _view_t _makeSubView(lsst::geom::Extent2I const &dimensions, lsst::geom::Extent2I const &offset, const _view_t &view)
int getWidth() const
Return the number of columns in the image.
_view_t::reverse_iterator reverse_iterator
An STL compliant reverse iterator.
x_iterator fast_iterator
A fast STL compliant iterator for contiguous images N.b.
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
ndarray::Array< PixelT, 2, 1 > Array
A mutable ndarray representation of the image.
int getArea() const
Return the area of the image.
lsst::geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
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.
int getHeight() const
Return the number of rows in the image.
_view_t::iterator iterator
An STL compliant iterator.
ImageBase & operator=(const ImageBase &rhs)
Shallow assignment operator.
iterator at(int x, int y) const
Return an STL compliant iterator at the point (x, y)
ConstReference< PixelT >::type PixelConstReference
A ConstReference to a PixelT.
reverse_iterator rbegin() const
Return an STL compliant reverse iterator to the start of the image.
_view_t _getRawView() const
PixelReference get(lsst::geom::Point2I const &index, ImageOrigin origin)
Return a reference to a single pixel (with no bounds check).
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
void swap(ImageBase &rhs)
reverse_iterator rend() const
Return an STL compliant reverse iterator to the end of the image.
A FITS reader class for regular Images.
Image< PixelT > read(lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT, bool allowUnsafe=false)
Read the Image.
A class to represent a 2-dimensional array of pixels.
void scaledPlus(double const c, Image< PixelT > const &rhs)
Add Image c*rhs to lhs.
Image & operator*=(PixelT const rhs)
Multiply lhs by scalar rhs.
void scaledMinus(double const c, Image< PixelT > const &rhs)
Subtract Image c*rhs from lhs.
Image & operator-=(PixelT const rhs)
Subtract scalar rhs from lhs.
Image & operator=(const PixelT rhs)
Set the image's pixels to rhs.
void scaledMultiplies(double const c, Image< PixelT > const &rhs)
Multiply lhs by Image c*rhs (i.e. pixel-by-pixel multiplication)
Image & operator+=(PixelT const rhs)
Add scalar rhs to lhs.
Image & operator/=(PixelT const rhs)
Divide lhs by scalar rhs.
void writeFits(std::string const &fileName, std::shared_ptr< lsst::daf::base::PropertySet const > metadata=std::shared_ptr< lsst::daf::base::PropertySet const >(), std::string const &mode="w") const
Write an image to a regular FITS file.
void scaledDivides(double const c, Image< PixelT > const &rhs)
Divide lhs by Image c*rhs (i.e. pixel-by-pixel division)
A Function taking two arguments.
Class for storing generic metadata.
int getAsInt(std::string const &name) const
Get the last value for a bool/char/short/int property name (possibly hierarchical).
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
An integer coordinate rectangle.
Reports attempts to exceed implementation-defined length limits for some classes.
Reports errors that are due to events beyond the control of the program.
void swap(CameraSys &a, CameraSys &b)
lsst::geom::Point2I getImageXY0FromMetadata(daf::base::PropertySet &metadata, std::string const &wcsName, bool strip=false)
std::string const wcsNameForXY0
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
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.
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.
void for_each_pixel(Image< LhsT > &lhs, pixelOp0< LhsT > const &func)
Set each pixel in an Image<LhsT> to func()
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)
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.
double indexToPosition(double ind)
Convert image index to image position.
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.
bool imagesOverlap(ImageBase< T1 > const &image1, ImageBase< T2 > const &image2)
Return true if the pixels for two images or masks overlap in memory.
void swap(Image< PixelT > &a, Image< PixelT > &b)
Extent< int, 2 > Extent2I
def writeFits(filename, stamp_ims, metadata, type_name, write_mask, write_variance)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
A base class for image defects.
A functor class equivalent to std::function<LhsT (LhsT, RhsT)>, but with a virtual operator()