40 #include "boost/pointer_cast.hpp" 
   41 #include "boost/regex.hpp" 
   73 static 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);
 
  141     return std::make_shared<NearestWarpingKernel>();
 
  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);
 
  163     boost::cmatch matches;
 
  164     static const boost::regex LanczosRE(
"lanczos(\\d+)");
 
  165     if (
name == 
"bilinear") {
 
  167     } 
else if (boost::regex_match(
name.c_str(), matches, LanczosRE)) {
 
  172     } 
else if (
name == 
"nearest") {
 
  180     if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
 
  181         _warpingKernelPtr->computeCache(_cacheSize);
 
  183     return _warpingKernelPtr;
 
  188     setWarpingKernel(*warpingKernelPtr);
 
  192     if (_maskWarpingKernelPtr) {
 
  193         _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
 
  196             std::static_pointer_cast<SeparableKernel>(warpingKernel.
clone()));
 
  197     _warpingKernelPtr = warpingKernelPtr;
 
  201     if (_maskWarpingKernelPtr) {  
 
  202         if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
 
  203             _maskWarpingKernelPtr->computeCache(_cacheSize);
 
  206     return _maskWarpingKernelPtr;
 
  210     if (!maskWarpingKernelName.
empty()) {
 
  212         setMaskWarpingKernel(*maskWarpingKernelPtr);
 
  214         _maskWarpingKernelPtr.reset();
 
  219     _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
 
  220     _maskWarpingKernelPtr = std::static_pointer_cast<SeparableKernel>(maskWarpingKernel.
clone());
 
  223 void WarpingControl::_testWarpingKernels(
SeparableKernel const &warpingKernel,
 
  231     if (!kernelBBox.
contains(maskKernelBBox)) {
 
  233                           "warping kernel is smaller than mask warping kernel");
 
  237 template <
typename DestExposureT, 
typename SrcExposureT>
 
  239                  typename DestExposureT::MaskedImageT::SinglePixel padValue) {
 
  240     if (!destExposure.hasWcs()) {
 
  243     if (!srcExposure.hasWcs()) {
 
  246     typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
 
  247     destExposure.setPhotoCalib(srcExposure.getPhotoCalib());
 
  248     destExposure.setFilter(srcExposure.getFilter());
 
  249     destExposure.getInfo()->setVisitInfo(srcExposure.getInfo()->getVisitInfo());
 
  250     return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), control,
 
  260         geom::SkyWcs 
const &destWcs,         
 
  261         geom::SkyWcs 
const &srcWcs)          
 
  265     return srcWcs.skyToPixel(destWcs.pixelToSky(destPix));
 
  268 inline double computeRelativeArea(
 
  277     return std::abs(dSrcA.getX() * dSrcB.getY() - dSrcA.getY() * dSrcB.getX());
 
  282 template <
typename DestImageT, 
typename SrcImageT>
 
  283 int warpImage(DestImageT &destImage, geom::SkyWcs 
const &destWcs, SrcImageT 
const &srcImage,
 
  285               typename DestImageT::SinglePixel padValue) {
 
  287     return warpImage(destImage, srcImage, *srcToDest, control, padValue);
 
  290 template <
typename DestImageT, 
typename SrcImageT>
 
  291 int warpImage(DestImageT &destImage, SrcImageT 
const &srcImage,
 
  293               typename DestImageT::SinglePixel padValue) {
 
  303         warpingKernelPtr->shrinkBBox(srcImage.getBBox(
image::LOCAL));
 
  305         for (
int y = 0, height = destImage.getHeight(); 
y < height; ++
y) {
 
  306             for (
typename DestImageT::x_iterator destPtr = destImage.row_begin(
y), 
end = destImage.row_end(
y);
 
  307                  destPtr != 
end; ++destPtr) {
 
  316             std::dynamic_pointer_cast<LanczosWarpingKernel>(warpingKernelPtr);
 
  318     int numGoodPixels = 0;
 
  321     auto const parentDestToParentSrc = srcToDest.inverted();
 
  322     std::vector<double> const localDestToParentDestVec = {
static_cast<double>(destImage.getX0()),
 
  323                                                           static_cast<double>(destImage.getY0())};
 
  325     auto const localDestToParentSrc = localDestToParentDest.then(*parentDestToParentSrc);
 
  328     int const srcWidth = srcImage.getWidth();
 
  329     int const srcHeight = srcImage.getHeight();
 
  330     LOGL_DEBUG(
"TRACE2.afw.math.warp", 
"source image width=%d; height=%d", srcWidth, srcHeight);
 
  332     int const destWidth = destImage.getWidth();
 
  333     int const destHeight = destImage.getHeight();
 
  334     LOGL_DEBUG(
"TRACE2.afw.math.warp", 
"remap image width=%d; height=%d", destWidth, destHeight);
 
  337     LOGL_DEBUG(
"TRACE3.afw.math.warp", 
"Remapping masked image");
 
  339     int const maxCol = destWidth - 1;
 
  340     int const maxRow = destHeight - 1;
 
  344     if (interpLength > 0) {
 
  349         int const numColEdges = 2 + ((destWidth - 1) / interpLength);
 
  354         edgeColList.
reserve(numColEdges);
 
  359         invWidthList.
reserve(numColEdges);
 
  364         for (
int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) {
 
  365             int endCol = prevEndCol + interpLength;
 
  366             if (endCol > maxCol) {
 
  370             assert(endCol - prevEndCol > 0);
 
  371             invWidthList.
push_back(1.0 / 
static_cast<double>(endCol - prevEndCol));
 
  373         assert(edgeColList.
back() == maxCol);
 
  388         endColPosList.
reserve(numColEdges);
 
  391         for (
int colBand = 0, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
 
  392             int const endCol = edgeColList[colBand];
 
  395         auto rightSrcPosList = localDestToParentSrc->applyForward(endColPosList);
 
  396         srcPosView[-1] = rightSrcPosList[0];
 
  397         for (
int colBand = 1, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
 
  398             int const prevEndCol = edgeColList[colBand - 1];
 
  399             int const endCol = edgeColList[colBand];
 
  403                     (rightSrcPosList[colBand] - leftSrcPos) * invWidthList[colBand];
 
  405             for (
int col = prevEndCol + 1; 
col <= endCol; ++
col) {
 
  406                 srcPosView[
col] = srcPosView[
col - 1] + xDeltaSrcPos;
 
  411         while (endRow < maxRow) {
 
  414             int prevEndRow = endRow;
 
  415             endRow = prevEndRow + interpLength;
 
  416             if (endRow > maxRow) {
 
  419             assert(endRow - prevEndRow > 0);
 
  420             double interpInvHeight = 1.0 / 
static_cast<double>(endRow - prevEndRow);
 
  425             for (
int colBand = 0, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
 
  426                 int endCol = edgeColList[colBand];
 
  429             auto bottomSrcPosList = localDestToParentSrc->applyForward(destRowPosList);
 
  430             for (
int colBand = 0, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
 
  431                 int endCol = edgeColList[colBand];
 
  432                 yDeltaSrcPosList[colBand] =
 
  433                         (bottomSrcPosList[colBand] - srcPosView[endCol]) * interpInvHeight;
 
  436             for (
int row = prevEndRow + 1; 
row <= endRow; ++
row) {
 
  437                 typename DestImageT::x_iterator destXIter = destImage.row_begin(
row);
 
  438                 srcPosView[-1] += yDeltaSrcPosList[0];
 
  439                 for (
int colBand = 1, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
 
  442                     int const prevEndCol = edgeColList[colBand - 1];
 
  443                     int const endCol = edgeColList[colBand];
 
  452                     for (
int col = prevEndCol + 1; 
col <= endCol; ++
col, ++destXIter) {
 
  455                         double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[
col]);
 
  457                         srcPosView[
col] = srcPos;
 
  460                                     destXIter, srcPos, relativeArea,
 
  475         destPosList.
reserve(1 + destWidth);
 
  476         for (
int col = -1; 
col < destWidth; ++
col) {
 
  479         auto prevSrcPosList = localDestToParentSrc->applyForward(destPosList);
 
  481         for (
int row = 0; 
row < destHeight; ++
row) {
 
  483             for (
int col = -1; 
col < destWidth; ++
col) {
 
  486             auto srcPosList = localDestToParentSrc->applyForward(destPosList);
 
  488             typename DestImageT::x_iterator destXIter = destImage.row_begin(
row);
 
  489             for (
int col = 0; 
col < destWidth; ++
col, ++destXIter) {
 
  491                 auto srcPos = srcPosList[
col + 1];
 
  492                 double relativeArea =
 
  493                         computeRelativeArea(srcPos, prevSrcPosList[
col], prevSrcPosList[
col + 1]);
 
  495                 if (warpAtOnePoint(destXIter, srcPos, relativeArea,
 
  502             swap(srcPosList, prevSrcPosList);
 
  506     return numGoodPixels;
 
  509 template <
typename DestImageT, 
typename SrcImageT>
 
  513                       typename DestImageT::SinglePixel padValue) {
 
  515     if ((destImage.getWidth() != srcImage.getWidth()) || (destImage.getHeight() != srcImage.getHeight()) ||
 
  516         (destImage.getXY0() != srcImage.getXY0())) {
 
  518         errStream << 
"src and dest images must have same size and xy0.";
 
  523     SrcImageT srcImageCopy(srcImage, 
true);
 
  524     srcImageCopy.setXY0(0, 0);
 
  525     destImage.setXY0(0, 0);
 
  537     static float t = 0.0;
 
  538     float t_before = 1.0*clock()/CLOCKS_PER_SEC;
 
  539     int n = 
warpImage(destImage, srcImageCopy, affTran, control, padValue);
 
  540     float t_after = 1.0*clock()/CLOCKS_PER_SEC;
 
  541     float dt = t_after - t_before;
 
  543     std::cout <<srcImage.getWidth()<<
"x"<<srcImage.getHeight()<<
": "<< dt <<
" "<< t <<
std::endl;
 
  545     int n = 
warpImage(destImage, srcImageCopy, *affineTransform22, control, padValue);
 
  549     destImage.setXY0(srcImage.getXY0());
 
  559 #define EXPOSURE(PIXTYPE) image::Exposure<PIXTYPE, image::MaskPixel, image::VariancePixel> 
  560 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel> 
  561 #define IMAGE(PIXTYPE) image::Image<PIXTYPE> 
  564 #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT)                                                         \ 
  565     template int warpCenteredImage(                                                                          \ 
  566             IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage,                       \ 
  567             lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition,   \ 
  568             WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue);                    \ 
  569     NL template int warpCenteredImage(                                                                       \ 
  570             MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage,           \ 
  571             lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition,   \ 
  572             WarpingControl const &control, MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue);              \ 
  573     NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage,     \ 
  574                               geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \ 
  575                               IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue);                                 \ 
  576     NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage,                                      \ 
  577                               MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage,                                   \ 
  578                               geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \ 
  579                               MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue);                           \ 
  580     NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs,               \ 
  581                               IMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs,             \ 
  582                               WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue);  \ 
  583     NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs,         \ 
  584                               MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs,       \ 
  585                               WarpingControl const &control,                                                 \ 
  586                               MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue);                           \ 
  587     NL template int warpExposure(EXPOSURE(DESTIMAGEPIXELT) & destExposure,                                   \ 
  588                                  EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, WarpingControl const &control, \ 
  589                                  EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);