73static inline void checkWarpingKernelParameter(
const SeparableKernel *p,
unsigned int ind,
double value) {
76 "bad ind argument in WarpingKernel::setKernelParameter()");
78 int ctr = p->getCtr()[ind];
79 int size = p->getDimensions()[ind];
81 if (ctr == (size - 1) / 2) {
82 if (value < -1e-6 || value > 1 + 1e-6) {
84 "bad coordinate in WarpingKernel::setKernelParameter()");
86 }
else if (ctr == (size + 1) / 2) {
87 if (value < -1 - 1e-6 || value > 1e-6) {
89 "bad coordinate in WarpingKernel::setKernelParameter()");
93 "bad ctr value in WarpingKernel::setKernelParameter()");
104 checkWarpingKernelParameter(
this, ind, value);
125 return 0.5 + (1.0 - (2.0 * fabs(this->
_params[0]))) * (0.5 - fabs(x));
129 checkWarpingKernelParameter(
this, ind, value);
135 os <<
"_BilinearFunction1: ";
136 os << Function1<Kernel::Pixel>::toString(prefix);
146 return static_cast<double>((fabs(this->
_params[0]) < 0.5) == (fabs(x) < 0.5));
150 checkWarpingKernelParameter(
this, ind, value);
156 os <<
"_NearestFunction1: ";
157 os << Function1<Kernel::Pixel>::toString(prefix);
163struct LanczosKernelPersistenceHelper {
167 static LanczosKernelPersistenceHelper
const &get() {
168 static LanczosKernelPersistenceHelper
const instance;
172 LanczosKernelPersistenceHelper(LanczosKernelPersistenceHelper
const &) =
delete;
173 LanczosKernelPersistenceHelper(LanczosKernelPersistenceHelper &&) =
delete;
174 LanczosKernelPersistenceHelper &operator=(LanczosKernelPersistenceHelper
const &) =
delete;
175 LanczosKernelPersistenceHelper &operator=(LanczosKernelPersistenceHelper &&) =
delete;
178 LanczosKernelPersistenceHelper()
179 : schema(), order(schema.addField<int>(
"order",
"order of Lanczos function")) {}
182class :
public table::io::PersistableFactory {
184 table::io::CatalogVector
const &catalogs)
const override {
185 auto const &keys = LanczosKernelPersistenceHelper::get();
194} lanczosFactory(
"LanczosWarpingKernel");
197class DefaultPersistableFactory :
public table::io::PersistableFactory {
198 std::shared_ptr<table::io::Persistable>
read(table::io::InputArchive
const &archive,
199 table::io::CatalogVector
const &catalogs)
const override {
204 using table::io::PersistableFactory::PersistableFactory;
207DefaultPersistableFactory<BilinearWarpingKernel> bilinearFactory(
"BilinearWarpingKernel");
208DefaultPersistableFactory<NearestWarpingKernel> nearestFactory(
"NearestWarpingKernel");
213 auto const &keys = LanczosKernelPersistenceHelper::get();
216 record->set(keys.order,
getOrder());
227 static const std::regex LanczosRE(
"lanczos(\\d+)");
228 if (name ==
"bilinear") {
231 std::string orderStr(matches[1].first, matches[1].second);
234 }
else if (name ==
"nearest") {
237 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"unknown warping kernel name: \"" + name +
"\"");
242 if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
243 _warpingKernelPtr->computeCache(_cacheSize);
245 return _warpingKernelPtr;
254 if (_maskWarpingKernelPtr) {
255 _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
259 _warpingKernelPtr = warpingKernelPtr;
263 if (_maskWarpingKernelPtr) {
264 if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
265 _maskWarpingKernelPtr->computeCache(_cacheSize);
268 return _maskWarpingKernelPtr;
272 if (!maskWarpingKernelName.
empty()) {
276 _maskWarpingKernelPtr.reset();
281 _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
285void WarpingControl::_testWarpingKernels(
SeparableKernel const &warpingKernel,
293 if (!kernelBBox.
contains(maskKernelBBox)) {
295 "warping kernel is smaller than mask warping kernel");
301struct WarpingControlPersistenceHelper {
302 table::Schema schema;
303 table::Key<int> warpingKernelIndex;
304 table::Key<table::Flag> hasMaskKernel;
305 table::Key<int> maskKernelIndex;
306 table::Key<int> cacheSize;
307 table::Key<int> interpLength;
308 table::Key<image::MaskPixel> growFullMask;
310 static WarpingControlPersistenceHelper
const &get() {
311 static WarpingControlPersistenceHelper
const instance;
315 WarpingControlPersistenceHelper(WarpingControlPersistenceHelper
const &) =
delete;
316 WarpingControlPersistenceHelper(WarpingControlPersistenceHelper &&) =
delete;
317 WarpingControlPersistenceHelper &operator=(WarpingControlPersistenceHelper
const &) =
delete;
318 WarpingControlPersistenceHelper &operator=(WarpingControlPersistenceHelper &&) =
delete;
321 WarpingControlPersistenceHelper()
324 schema.addField<int>(
"warpingKernelIndex",
"archive ID of nested warping kernel")),
325 hasMaskKernel(schema.addField<table::Flag>(
"hasMaskKernel",
"whether a mask kernel is stored")),
326 maskKernelIndex(schema.addField<int>(
"maskKernelIndex",
327 "archive ID of nested mask kernel. "
328 "Valid only if hasMaskKernel")),
329 cacheSize(schema.addField<int>(
"cacheSize",
"Cache size for warping kernel(s)")),
330 interpLength(schema.addField<int>(
"interpLength",
331 "Distance over which WCS can be linearly interpolated")),
332 growFullMask(schema.addField<
image::MaskPixel>(
333 "growFullMask",
"bits to grow to full width of image/variance kernel")) {}
336std::string _getWarpingControlPersistenceName() {
return "WarpingControl"; }
338class :
public table::io::PersistableFactory {
339 std::shared_ptr<table::io::Persistable>
read(table::io::InputArchive
const &archive,
340 table::io::CatalogVector
const &catalogs)
const override {
341 auto const &
keys = WarpingControlPersistenceHelper::get();
344 afw::table::BaseRecord
const &record =
catalogs.front().front();
349 record.get(
keys.interpLength),
350 record.get(
keys.growFullMask));
354 control->setWarpingKernel(*archive.get<
SeparableKernel>(record.get(
keys.warpingKernelIndex)));
355 if (record.get(
keys.hasMaskKernel)) {
356 control->setMaskWarpingKernel(*archive.get<
SeparableKernel>(record.get(
keys.maskKernelIndex)));
362} controlFactory(_getWarpingControlPersistenceName());
371 return _warpingKernelPtr->isPersistable() &&
376 auto const &keys = WarpingControlPersistenceHelper::get();
380 record->set(keys.warpingKernelIndex, handle.
put(_warpingKernelPtr));
383 record->set(keys.maskKernelIndex, handle.
put(_maskWarpingKernelPtr));
385 record->set(keys.cacheSize, _cacheSize);
386 record->set(keys.interpLength, _interpLength);
387 record->set(keys.growFullMask, _growFullMask);
392template <
typename DestExposureT,
typename SrcExposureT>
394 typename DestExposureT::MaskedImageT::SinglePixel padValue) {
395 if (!destExposure.hasWcs()) {
396 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"destExposure has no Wcs");
398 if (!srcExposure.hasWcs()) {
399 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"srcExposure has no Wcs");
401 typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
402 if (srcExposure.getInfo()->hasId()) {
403 destExposure.getInfo()->setId(srcExposure.getInfo()->getId());
405 destExposure.setPhotoCalib(srcExposure.getPhotoCalib());
406 destExposure.setFilter(srcExposure.getFilter());
407 destExposure.getInfo()->setVisitInfo(srcExposure.getInfo()->getVisitInfo());
408 return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), control,
418 geom::SkyWcs
const &destWcs,
419 geom::SkyWcs
const &srcWcs)
423 return srcWcs.skyToPixel(destWcs.pixelToSky(destPix));
426inline double computeRelativeArea(
435 return std::abs(dSrcA.getX() * dSrcB.getY() - dSrcA.getY() * dSrcB.getX());
440template <
typename DestImageT,
typename SrcImageT>
441int warpImage(DestImageT &destImage, geom::SkyWcs
const &destWcs, SrcImageT
const &srcImage,
443 typename DestImageT::SinglePixel padValue) {
444 auto srcToDest = geom::makeWcsPairTransform(srcWcs, destWcs);
445 return warpImage(destImage, srcImage, *srcToDest, control, padValue);
441int warpImage(DestImageT &destImage, geom::SkyWcs
const &destWcs, SrcImageT
const &srcImage, {
…}
448template <
typename DestImageT,
typename SrcImageT>
449int warpImage(DestImageT &destImage, SrcImageT
const &srcImage,
450 geom::TransformPoint2ToPoint2
const &srcToDest,
WarpingControl const &control,
451 typename DestImageT::SinglePixel padValue) {
452 if (imagesOverlap(destImage, srcImage)) {
453 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"destImage overlaps srcImage; cannot warp");
461 warpingKernelPtr->shrinkBBox(srcImage.getBBox(
image::LOCAL));
463 for (
int y = 0, height = destImage.getHeight(); y < height; ++y) {
464 for (
typename DestImageT::x_iterator destPtr = destImage.row_begin(y), end = destImage.row_end(y);
465 destPtr != end; ++destPtr) {
476 int numGoodPixels = 0;
479 auto const parentDestToParentSrc = srcToDest.inverted();
480 std::vector<double> const localDestToParentDestVec = {
static_cast<double>(destImage.getX0()),
481 static_cast<double>(destImage.getY0())};
482 auto const localDestToParentDest = geom::TransformPoint2ToPoint2(
ast::ShiftMap(localDestToParentDestVec));
483 auto const localDestToParentSrc = localDestToParentDest.then(*parentDestToParentSrc);
486 int const srcWidth = srcImage.getWidth();
487 int const srcHeight = srcImage.getHeight();
488 LOGL_DEBUG(
"TRACE2.lsst.afw.math.warp",
"source image width=%d; height=%d", srcWidth, srcHeight);
490 int const destWidth = destImage.getWidth();
491 int const destHeight = destImage.getHeight();
492 LOGL_DEBUG(
"TRACE2.lsst.afw.math.warp",
"remap image width=%d; height=%d", destWidth, destHeight);
495 LOGL_DEBUG(
"TRACE3.lsst.afw.math.warp",
"Remapping masked image");
497 int const maxCol = destWidth - 1;
498 int const maxRow = destHeight - 1;
502 if (interpLength > 0) {
507 int const numColEdges = 2 + ((destWidth - 1) / interpLength);
512 edgeColList.
reserve(numColEdges);
517 invWidthList.
reserve(numColEdges);
522 for (
int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) {
523 int endCol = prevEndCol + interpLength;
524 if (endCol > maxCol) {
528 assert(endCol - prevEndCol > 0);
529 invWidthList.
push_back(1.0 /
static_cast<double>(endCol - prevEndCol));
531 assert(edgeColList.
back() == maxCol);
543 std::vector<lsst::geom::Point2D>::iterator
const srcPosView = srcPosList.
begin() + 1;
546 endColPosList.
reserve(numColEdges);
549 for (
int endCol : edgeColList) {
552 auto rightSrcPosList = localDestToParentSrc->applyForward(endColPosList);
553 srcPosView[-1] = rightSrcPosList[0];
554 for (
int colBand = 1, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
555 int const prevEndCol = edgeColList[colBand - 1];
556 int const endCol = edgeColList[colBand];
560 (rightSrcPosList[colBand] - leftSrcPos) * invWidthList[colBand];
562 for (
int col = prevEndCol + 1; col <= endCol; ++col) {
563 srcPosView[col] = srcPosView[col - 1] + xDeltaSrcPos;
568 while (endRow < maxRow) {
571 int prevEndRow = endRow;
572 endRow = prevEndRow + interpLength;
573 if (endRow > maxRow) {
576 assert(endRow - prevEndRow > 0);
577 double interpInvHeight = 1.0 /
static_cast<double>(endRow - prevEndRow);
582 for (
int endCol : edgeColList) {
585 auto bottomSrcPosList = localDestToParentSrc->applyForward(destRowPosList);
586 for (
int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
587 int endCol = edgeColList[colBand];
588 yDeltaSrcPosList[colBand] =
589 (bottomSrcPosList[colBand] - srcPosView[endCol]) * interpInvHeight;
592 for (
int row = prevEndRow + 1; row <= endRow; ++row) {
593 typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
594 srcPosView[-1] += yDeltaSrcPosList[0];
595 for (
int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
598 int const prevEndCol = edgeColList[colBand - 1];
599 int const endCol = edgeColList[colBand];
608 for (
int col = prevEndCol + 1; col <= endCol; ++col, ++destXIter) {
611 double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[col]);
613 srcPosView[col] = srcPos;
616 destXIter, srcPos, relativeArea,
631 destPosList.
reserve(1 + destWidth);
632 for (
int col = -1; col < destWidth; ++col) {
635 auto prevSrcPosList = localDestToParentSrc->applyForward(destPosList);
637 for (
int row = 0; row < destHeight; ++row) {
639 for (
int col = -1; col < destWidth; ++col) {
642 auto srcPosList = localDestToParentSrc->applyForward(destPosList);
644 typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
645 for (
int col = 0; col < destWidth; ++col, ++destXIter) {
647 auto srcPos = srcPosList[col + 1];
648 double relativeArea =
649 computeRelativeArea(srcPos, prevSrcPosList[col], prevSrcPosList[col + 1]);
651 if (warpAtOnePoint(destXIter, srcPos, relativeArea,
658 swap(srcPosList, prevSrcPosList);
662 return numGoodPixels;
449int warpImage(DestImageT &destImage, SrcImageT
const &srcImage, {
…}
665template <
typename DestImageT,
typename SrcImageT>
669 typename DestImageT::SinglePixel padValue) {
671 if ((destImage.getWidth() != srcImage.getWidth()) || (destImage.getHeight() != srcImage.getHeight()) ||
672 (destImage.getXY0() != srcImage.getXY0())) {
674 errStream <<
"src and dest images must have same size and xy0.";
675 throw LSST_EXCEPT(pexExcept::InvalidParameterError, errStream.
str());
679 SrcImageT srcImageCopy(srcImage,
true);
680 srcImageCopy.setXY0(0, 0);
681 destImage.setXY0(0, 0);
693 static float t = 0.0;
694 float t_before = 1.0*clock()/CLOCKS_PER_SEC;
695 int n =
warpImage(destImage, srcImageCopy, affTran, control, padValue);
696 float t_after = 1.0*clock()/CLOCKS_PER_SEC;
697 float dt = t_after - t_before;
699 std::cout <<srcImage.getWidth()<<
"x"<<srcImage.getHeight()<<
": "<< dt <<
" "<< t <<
std::endl;
701 int n =
warpImage(destImage, srcImageCopy, *affineTransform22, control, padValue);
705 destImage.setXY0(srcImage.getXY0());
715#define EXPOSURE(PIXTYPE) image::Exposure<PIXTYPE, image::MaskPixel, image::VariancePixel>
716#define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
717#define IMAGE(PIXTYPE) image::Image<PIXTYPE>
720#define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \
721 template int warpCenteredImage( \
722 IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
723 lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition, \
724 WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
725 NL template int warpCenteredImage( \
726 MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
727 lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition, \
728 WarpingControl const &control, MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
729 NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
730 geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
731 IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
732 NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, \
733 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
734 geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
735 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
736 NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
737 IMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
738 WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
739 NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
740 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
741 WarpingControl const &control, \
742 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
743 NL template int warpExposure(EXPOSURE(DESTIMAGEPIXELT) & destExposure, \
744 EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, WarpingControl const &control, \
745 EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);
#define INSTANTIATE(FROMSYS, TOSYS)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
LSST DM logging module built on log4cxx.
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Implementation of the Photometric Calibration class.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
std::string toString(std::string const &="") const override
Return string representation.
Kernel::Pixel operator()(double x) const override
Solve bilinear equation.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
std::vector< double > _params
lsst::geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
lsst::geom::Point2I getCtr() const
Return index of kernel's center.
int getWidth() const
Return the Kernel's width.
Lanczos warping: accurate but slow and can introduce ringing artifacts.
int getOrder() const
get the order of the kernel
LanczosWarpingKernel(int order)
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Kernel::Pixel operator()(double x) const override
Solve nearest neighbor equation.
std::string toString(std::string const &="") const override
Return string representation.
Nearest neighbor warping: fast; good for undersampled data.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
SeparableKernel()
Construct an empty spatially invariant SeparableKernel of size 0x0.
Parameters to control convolution.
bool hasMaskWarpingKernel() const
return true if there is a mask kernel
void setWarpingKernel(SeparableKernel const &warpingKernel)
set the warping kernel
int getInterpLength() const
get the interpolation length (pixels)
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
void setWarpingKernelName(std::string const &warpingKernelName)
set the warping kernel by name
void setMaskWarpingKernelName(std::string const &maskWarpingKernelName)
set or clear the mask warping kernel by name
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
void setMaskWarpingKernel(SeparableKernel const &maskWarpingKernel)
set the mask warping kernel
std::shared_ptr< SeparableKernel > getWarpingKernel() const
get the warping kernel
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
std::shared_ptr< SeparableKernel > getMaskWarpingKernel() const
get the mask warping kernel
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
A functor that computes one warped pixel.
Base class for all records.
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
Schema getSchema() const
Return the Schema that holds this record's fields and keys.
A class used as a handle to a particular field in a table.
Defines the fields and offsets for a table.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
void saveEmpty()
Indicate that the object being persisted has no state, and hence will never call makeCatalog() or sav...
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
PersistableFactory(std::string const &name)
Constructor for the factory.
io::OutputArchiveHandle OutputArchiveHandle
An integer coordinate rectangle.
bool contains(Point2I const &point) const noexcept
Return true if the box contains the point.
Reports invalid arguments.
T emplace_back(T... args)
double indexToPosition(double ind)
Convert image index to image position.
std::shared_ptr< SeparableKernel > makeWarpingKernel(std::string name)
Return a warping kernel given its name.
int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage, lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an image with a LinearTranform about a specified point.
int warpImage(DestImageT &destImage, geom::SkyWcs const &destWcs, SrcImageT const &srcImage, geom::SkyWcs const &srcWcs, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an Image or MaskedImage to a new Wcs.
int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue=lsst::afw::math::edgePixel< typename DestExposureT::MaskedImageT >(typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT >::image_category()))
Warp (remap) one exposure to another.
CatalogT< BaseRecord > BaseCatalog
Extent< double, 2 > Extent2D
Point< double, 2 > Point2D
Extent< int, 2 > Extent2I
T static_pointer_cast(T... args)
typename ImageT::image_category image_category
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override