30#include "boost/format.hpp"
31#include "boost/gil.hpp"
44template <
typename PixelT>
46 Manager::Ptr& manager) {
49 str(boost::format(
"Both width and height must be non-negative: %d, %d") %
54 str(boost::format(
"Image dimensions (%d x %d) too large; int overflow detected.") %
61 (
typename _view_t::value_type*)r.second,
64template <
typename PixelT>
67 const _view_t& view) {
68 if (offset.getX() < 0 || offset.getY() < 0 || offset.getX() +
dimensions.getX() > view.width() ||
69 offset.getY() +
dimensions.getY() > view.height()) {
73 "Box2I(Point2I(%d,%d),lsst::geom::Extent2I(%d,%d)) doesn't fit in image %dx%d") %
79 && view.width() == 0 && view.height() == 0) {
83 return boost::gil::subimage_view(view, offset.getX(), offset.getY(),
dimensions.getX(),
88template <
typename PixelT>
90 : _origin(0, 0), _manager(), _gilView(_allocateView(
dimensions, _manager)) {}
92template <
typename PixelT>
94 : _origin(
bbox.getMin()), _manager(), _gilView(_allocateView(
bbox.getDimensions(), _manager)) {}
96template <
typename PixelT>
100 : _origin(rhs._origin), _manager(rhs._manager), _gilView(rhs._gilView) {
108template <
typename PixelT>
111template <
typename PixelT>
117 _manager(rhs._manager),
118 _gilView(_makeSubView(
bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
126template <
typename PixelT>
129 _manager(array.getManager()),
130 _gilView(
boost::gil::interleaved_view(array.template getSize<1>(), array.template getSize<0>(),
131 (typename _view_t::value_type*)array.getData(),
132 array.template getStride<0>() * sizeof(PixelT))) {
139template <
typename PixelT>
147template <
typename PixelT>
152template <
typename PixelT>
154 auto lhsDim =
bbox.isEmpty() ? getDimensions() :
bbox.getDimensions();
157 (boost::format(
"Dimension mismatch: %dx%d v. %dx%d") % lhsDim.getX() %
161 if (
bbox.isEmpty()) {
162 copy_pixels(rhs._gilView, _gilView);
165 auto lhsGilView = _makeSubView(lhsDim, lhsOff, _gilView);
166 copy_pixels(rhs._gilView, lhsGilView);
170template <
typename PixelT>
176template <
typename PixelT>
179 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
181 (boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") %
x %
y %
182 (getWidth() - 1) % (getHeight() - 1))
190template <
typename PixelT>
192 return _gilView(
x,
y)[0];
195template <
typename PixelT>
198 if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
200 (boost::format(
"Index (%d, %d) is out of range [0--%d], [0--%d]") %
x %
y %
201 (this->getWidth() - 1) % (this->getHeight() - 1))
205 return _gilView(
x,
y)[0];
208template <
typename PixelT>
211 int x = index.getX();
212 int y = index.getY();
217 return _gilView(
x,
y)[0];
220template <
typename PixelT>
223 int x = index.getX();
224 int y = index.getY();
229 return _gilView(
x,
y)[0];
232template <
typename PixelT>
236 swap(_manager, rhs._manager);
237 swap(_gilView, rhs._gilView);
238 swap(_origin, rhs._origin);
241template <
typename PixelT>
249template <
typename PixelT>
251 return _gilView.begin();
254template <
typename PixelT>
256 return _gilView.end();
259template <
typename PixelT>
261 return _gilView.rbegin();
264template <
typename PixelT>
266 return _gilView.rend();
269template <
typename PixelT>
271 return _gilView.at(
x,
y);
274template <
typename PixelT>
279 if (!this->isContiguous()) {
286template <
typename PixelT>
291 if (!this->isContiguous()) {
295 return row_end(getHeight() - 1);
298template <
typename PixelT>
300 fill_pixels(_gilView, rhs);
308template <
typename PixelT>
311 *
this = initialValue;
314template <
typename PixelT>
317 *
this = initialValue;
320template <
typename PixelT>
322 *
this = initialValue;
325template <
typename PixelT>
328template <
typename PixelT>
331template <
typename PixelT>
336template <
typename PixelT>
343template <
typename PixelT>
350template <
typename PixelT>
357template <
typename PixelT>
361 *
this = reader.
read<PixelT>(
bbox, origin, allowUnsafe);
367template <
typename PixelT>
372 *
this = reader.
read<PixelT>(
bbox, origin, allowUnsafe);
378template <
typename PixelT>
382 *
this = reader.
read<PixelT>(
bbox, origin, allowUnsafe);
388template <
typename PixelT>
393 writeFits(fitsfile, metadata_i);
396template <
typename PixelT>
400 writeFits(fileName, metadata_i.
get(), mode);
403template <
typename PixelT>
408 writeFits(fitsfile, metadata_i);
411template <
typename PixelT>
415 writeFits(manager, metadata_i.
get(), mode);
418template <
typename PixelT>
424template <
typename PixelT>
427 writeFits(fitsfile, metadata.
get());
430template <
typename PixelT>
432 std::string const& mode, daf::base::PropertySet
const * header,
433 Mask<MaskPixel>
const * mask)
const {
435 writeFits(fitsfile, options, header, mask);
438template <
typename PixelT>
445template <
typename PixelT>
447 std::string const& mode, daf::base::PropertySet
const * header,
448 Mask<MaskPixel>
const * mask)
const {
450 writeFits(fitsfile, options, header, mask);
453template <
typename PixelT>
460template <
typename PixelT>
467template <
typename PixelT>
471 writeFits(fitsfile, options, header.
get(),
mask.get());
476template <
typename PixelT>
482template <
typename PixelT>
488template <
typename PixelT>
490 transform_pixels(_getRawView(), _getRawView(),
491 [](PixelT
const& l) -> PixelT {
return static_cast<PixelT
>(
std::sqrt(l)); });
494template <
typename PixelT>
496 transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT
const& l) -> PixelT {
return l + rhs; });
500template <
typename PixelT>
504 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
508 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
509 [](PixelT
const& l, PixelT
const& r) -> PixelT {
return l + r; });
513template <
typename PixelT>
515 for (
int y = 0;
y != this->getHeight(); ++
y) {
520 *
ptr += function(xPos, yPos);
526template <
typename PixelT>
530 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
536 [&c](PixelT
const& l, PixelT
const& r) -> PixelT {
return l + (c * r); });
539template <
typename PixelT>
541 transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT
const& l) -> PixelT {
return l - rhs; });
545template <
typename PixelT>
549 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
553 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
554 [](PixelT
const& l, PixelT
const& r) -> PixelT {
return l - r; });
558template <
typename PixelT>
562 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
568 [&c](PixelT
const& l, PixelT
const& r) -> PixelT {
return l - (c * r); });
571template <
typename PixelT>
573 for (
int y = 0;
y != this->getHeight(); ++
y) {
578 *
ptr -= function(xPos, yPos);
584template <
typename PixelT>
586 transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT
const& l) -> PixelT {
return l * rhs; });
590template <
typename PixelT>
594 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
598 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
599 [](PixelT
const& l, PixelT
const& r) -> PixelT {
return l * r; });
603template <
typename PixelT>
607 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
613 [&c](PixelT
const& l, PixelT
const& r) -> PixelT {
return l * (c * r); });
616template <
typename PixelT>
618 transform_pixels(_getRawView(), _getRawView(), [&rhs](PixelT
const& l) -> PixelT {
return l / rhs; });
626 double const irhs = 1 / rhs;
633 float const irhs = 1 / rhs;
638template <
typename PixelT>
642 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
646 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
647 [](PixelT
const& l, PixelT
const& r) -> PixelT {
return l / r; });
651template <
typename PixelT>
655 (boost::format(
"Images are of different size, %dx%d v %dx%d") % this->getWidth() %
661 [&c](PixelT
const& l, PixelT
const& r) -> PixelT {
return l / (c * r); });
668template <
typename LhsPixelT,
typename RhsPixelT>
669struct plusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
670 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
671 return static_cast<LhsPixelT
>(lhs + rhs);
675template <
typename LhsPixelT,
typename RhsPixelT>
676struct minusEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
677 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
678 return static_cast<LhsPixelT
>(lhs - rhs);
682template <
typename LhsPixelT,
typename RhsPixelT>
683struct timesEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
684 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
685 return static_cast<LhsPixelT
>(lhs * rhs);
689template <
typename LhsPixelT,
typename RhsPixelT>
690struct divideEq :
public pixelOp2<LhsPixelT, RhsPixelT> {
691 LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs)
const override {
692 return static_cast<LhsPixelT
>(lhs / rhs);
697template <
typename LhsPixelT,
typename RhsPixelT>
703template <
typename LhsPixelT,
typename RhsPixelT>
709template <
typename LhsPixelT,
typename RhsPixelT>
715template <
typename LhsPixelT,
typename RhsPixelT>
723 if (metadata.
exists(
"ZNAXIS1") && metadata.
exists(
"ZNAXIS2")) {
732template <
typename T1,
typename T2>
743 auto beg1Addr = arr1.front().begin();
744 auto end1Addr = arr1.back().end();
747 auto beg2Addr = arr2.front().begin();
748 auto end2Addr = arr2.back().end();
751 return ptrLess(beg1Addr, end2Addr) && ptrLess(beg2Addr, end1Addr);
758#define INSTANTIATE_OPERATOR(OP_EQ, T) \
759 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint16_t> const& rhs); \
760 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<int> const& rhs); \
761 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<float> const& rhs); \
762 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<double> const& rhs); \
763 template Image<T>& operator OP_EQ(Image<T>& lhs, Image<std::uint64_t> const& rhs);
765#define INSTANTIATE(T) \
766 template class ImageBase<T>; \
767 template class Image<T>; \
768 INSTANTIATE_OPERATOR(+=, T); \
769 INSTANTIATE_OPERATOR(-=, T); \
770 INSTANTIATE_OPERATOR(*=, T); \
771 INSTANTIATE_OPERATOR(/=, T)
773#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.
Image & operator*=(PixelT const rhs)
Multiply lhs by scalar rhs.
Image & operator-=(PixelT const rhs)
Subtract scalar rhs from lhs.
void scaledPlus(PixelT const c, Image< PixelT > const &rhs)
Add Image c*rhs to lhs.
Image & operator=(const PixelT rhs)
Set the image's pixels to rhs.
Image & operator+=(PixelT const rhs)
Add scalar rhs to lhs.
void scaledMinus(PixelT const c, Image< PixelT > const &rhs)
Subtract Image c*rhs from lhs.
Image & operator/=(PixelT const rhs)
Divide lhs by scalar rhs.
void writeFits(std::string const &fileName, daf::base::PropertySet const *metadata=nullptr, std::string const &mode="w") const
Write an image to a regular FITS file.
void scaledDivides(PixelT const c, Image< PixelT > const &rhs)
Divide lhs by Image c*rhs (i.e. pixel-by-pixel division)
void scaledMultiplies(PixelT const c, Image< PixelT > const &rhs)
Multiply lhs by Image c*rhs (i.e. pixel-by-pixel multiplication)
Represent a 2-dimensional array of bitmask pixels.
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.
std::string const wcsNameForXY0
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.
Extent< int, 2 > Extent2I
def writeFits(filename, stamps, metadata, type_name, write_mask, write_variance, write_archive=False)
Options for writing an image to FITS.
A functor class equivalent to std::function<LhsT (LhsT, RhsT)>, but with a virtual operator()