31 #include "boost/format.hpp"
32 #include "boost/gil.hpp"
45 template <
typename PixelT>
47 Manager::Ptr& manager) {
50 str(
boost::format(
"Both width and height must be non-negative: %d, %d") %
55 str(
boost::format(
"Image dimensions (%d x %d) too large; int overflow detected.") %
62 (
typename _view_t::value_type*)r.second,
65 template <
typename PixelT>
68 const _view_t& view) {
69 if (offset.getX() < 0 || offset.getY() < 0 || offset.getX() +
dimensions.getX() > view.width() ||
70 offset.getY() +
dimensions.getY() > view.height()) {
74 "Box2I(Point2I(%d,%d),lsst::geom::Extent2I(%d,%d)) doesn't fit in image %dx%d") %
80 && view.width() == 0 && view.height() == 0) {
84 return boost::gil::subimage_view(view, offset.getX(), offset.getY(),
dimensions.getX(),
89 template <
typename PixelT>
91 : _origin(0, 0), _manager(), _gilView(_allocateView(
dimensions, _manager)) {}
93 template <
typename PixelT>
95 : _origin(
bbox.getMin()), _manager(), _gilView(_allocateView(
bbox.getDimensions(), _manager)) {}
97 template <
typename PixelT>
101 : _origin(rhs._origin), _manager(rhs._manager), _gilView(rhs._gilView) {
109 template <
typename PixelT>
112 template <
typename PixelT>
118 _manager(rhs._manager),
119 _gilView(_makeSubView(
bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
127 template <
typename PixelT>
130 _manager(array.getManager()),
131 _gilView(
boost::gil::interleaved_view(array.template
getSize<1>(), array.template
getSize<0>(),
132 (typename _view_t::value_type*)array.getData(),
133 array.template getStride<0>() * sizeof(
PixelT))) {
140 template <
typename PixelT>
148 template <
typename PixelT>
153 template <
typename PixelT>
155 auto lhsDim =
bbox.isEmpty() ? getDimensions() :
bbox.getDimensions();
158 (
boost::format(
"Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
162 if (
bbox.isEmpty()) {
163 copy_pixels(rhs._gilView, _gilView);
166 auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
167 copy_pixels(rhs._gilView, lhsGilView);
171 template <
typename PixelT>
177 template <
typename PixelT>
180 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
182 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") %
x %
y %
183 (getWidth() - 1) % (getHeight() - 1))
191 template <
typename PixelT>
193 return _gilView(
x,
y)[0];
196 template <
typename PixelT>
199 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
201 (
boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") %
x %
y %
202 (this->getWidth() - 1) % (this->getHeight() - 1))
206 return _gilView(
x,
y)[0];
209 template <
typename PixelT>
212 int x = index.getX();
213 int y = index.getY();
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>
237 swap(_manager, rhs._manager);
238 swap(_gilView, rhs._gilView);
242 template <
typename PixelT>
250 template <
typename PixelT>
252 return _gilView.begin();
255 template <
typename PixelT>
257 return _gilView.end();
260 template <
typename PixelT>
262 return _gilView.rbegin();
265 template <
typename PixelT>
267 return _gilView.rend();
270 template <
typename PixelT>
272 return _gilView.at(
x,
y);
275 template <
typename PixelT>
280 if (!this->isContiguous()) {
287 template <
typename PixelT>
292 if (!this->isContiguous()) {
296 return row_end(getHeight() - 1);
299 template <
typename PixelT>
301 fill_pixels(_gilView, rhs);
309 template <
typename PixelT>
312 *
this = initialValue;
315 template <
typename PixelT>
318 *
this = initialValue;
321 template <
typename PixelT>
323 *
this = initialValue;
326 template <
typename PixelT>
329 template <
typename PixelT>
332 template <
typename PixelT>
337 template <
typename PixelT>
344 template <
typename PixelT>
351 template <
typename PixelT>
358 template <
typename PixelT>
368 template <
typename PixelT>
379 template <
typename PixelT>
389 template <
typename PixelT>
397 template <
typename PixelT>
405 template <
typename PixelT>
411 template <
typename PixelT>
419 template <
typename PixelT>
427 template <
typename PixelT>
431 fitsfile.writeImage(*
this, options, header,
mask);
436 template <
typename PixelT>
443 template <
typename PixelT>
449 template <
typename PixelT>
451 transform_pixels(_getRawView(), _getRawView(),
455 template <
typename PixelT>
457 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l + rhs; });
461 template <
typename PixelT>
465 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
469 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
474 template <
typename PixelT>
476 for (
int y = 0;
y != this->getHeight(); ++
y) {
481 *
ptr +=
function(xPos, yPos);
487 template <
typename PixelT>
491 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
500 template <
typename PixelT>
502 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l - rhs; });
506 template <
typename PixelT>
510 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
514 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
519 template <
typename PixelT>
523 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
532 template <
typename PixelT>
534 for (
int y = 0;
y != this->getHeight(); ++
y) {
539 *
ptr -=
function(xPos, yPos);
545 template <
typename PixelT>
547 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l * rhs; });
551 template <
typename PixelT>
555 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
559 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
564 template <
typename PixelT>
568 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
577 template <
typename PixelT>
579 transform_pixels(_getRawView(), _getRawView(), [&rhs](
PixelT const& l) ->
PixelT {
return l / rhs; });
587 double const irhs = 1 / rhs;
594 float const irhs = 1 / rhs;
599 template <
typename PixelT>
603 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
607 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
612 template <
typename PixelT>
616 (
boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
629 template <
typename LhsPixelT,
typename RhsPixelT>
630 struct plusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
631 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
632 return static_cast<LhsPixelT
>(lhs + rhs);
636 template <
typename LhsPixelT,
typename RhsPixelT>
637 struct minusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
638 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
639 return static_cast<LhsPixelT
>(lhs - rhs);
643 template <
typename LhsPixelT,
typename RhsPixelT>
644 struct timesEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
645 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
646 return static_cast<LhsPixelT
>(lhs * rhs);
650 template <
typename LhsPixelT,
typename RhsPixelT>
651 struct divideEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
652 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
653 return static_cast<LhsPixelT
>(lhs / rhs);
658 template <
typename LhsPixelT,
typename RhsPixelT>
664 template <
typename LhsPixelT,
typename RhsPixelT>
670 template <
typename LhsPixelT,
typename RhsPixelT>
676 template <
typename LhsPixelT,
typename RhsPixelT>
684 if (metadata.
exists(
"ZNAXIS1") && metadata.
exists(
"ZNAXIS2")) {
693 template <
typename T1,
typename T2>
704 auto beg1Addr = arr1.front().begin();
705 auto end1Addr = arr1.back().end();
708 auto beg2Addr = arr2.front().begin();
709 auto end2Addr = arr2.back().end();
712 return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
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);
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)
734 #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...
void writeImage(ndarray::Array< T const, N, C > const &array)
Write an ndarray::Array to a FITS image HDU.
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)
typename Reference< PixelT >::type PixelReference
A Reference to a PixelT.
typename _view_t::iterator iterator
An STL compliant iterator.
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.
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
int getArea() const
Return the area of the image.
lsst::geom::Extent2I getDimensions() const
Return the image's size; useful for passing to constructors.
typename ndarray::Array< PixelT, 2, 1 > Array
A mutable ndarray representation of the image.
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.
x_iterator fast_iterator
A fast STL compliant iterator for contiguous images N.b.
typename _view_t::reverse_iterator reverse_iterator
An STL compliant reverse iterator.
int getHeight() const
Return the number of rows in the image.
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)
typename _view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
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).
void swap(ImageBase &rhs)
typename ConstReference< PixelT >::type PixelConstReference
A ConstReference to a PixelT.
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.
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, stamps, metadata, type_name, write_mask, write_variance, write_archive=False)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
A base class for image defects.
Options for writing an image to FITS.
A functor class equivalent to std::function<LhsT (LhsT, RhsT)>, but with a virtual operator()