54 template <
typename OutImageT, 
typename InImageT>
 
   55 void assertDimensionsOK(OutImageT 
const& convolvedImage, InImageT 
const& inImage,
 
   57     if (convolvedImage.getDimensions() != inImage.getDimensions()) {
 
   59         os << 
"convolvedImage dimensions = ( " << convolvedImage.getWidth() << 
", " 
   60            << convolvedImage.getHeight() << 
") != (" << inImage.getWidth() << 
", " << inImage.getHeight()
 
   61            << 
") = inImage dimensions";
 
   64     if (inImage.getWidth() < kernel.
getWidth() || inImage.getHeight() < kernel.
getHeight()) {
 
   66         os << 
"inImage dimensions = ( " << inImage.getWidth() << 
", " << inImage.getHeight()
 
   68            << 
") = kernel dimensions in width and/or height";
 
   74            << 
") smaller than (1, 1) in width and/or height";
 
  119 template <
typename OutPixelT, 
typename ImageIterT, 
typename KernelIterT, 
typename KernelPixelT>
 
  120 inline OutPixelT kernelDotProduct(
 
  121         ImageIterT imageIter,    
 
  122         KernelIterT kernelIter,  
 
  125     OutPixelT outPixel(0);
 
  126     for (
int x = 0; 
x < kWidth; ++
x, ++imageIter, ++kernelIter) {
 
  127         KernelPixelT kVal = *kernelIter;
 
  129             outPixel += 
static_cast<OutPixelT
>((*imageIter) * kVal);
 
  141 template <
typename OutImageT, 
typename InImageT>
 
  148         LOGL_DEBUG(
"TRACE3.afw.math.convolve.basicConvolve",
 
  149                    "generic basicConvolve: dispatch to DeltaFunctionKernel basicConvolve");
 
  154         LOGL_DEBUG(
"TRACE3.afw.math.convolve.basicConvolve",
 
  155                    "generic basicConvolve: dispatch to SeparableKernel basicConvolve");
 
  161                 "TRACE3.afw.math.convolve.basicConvolve",
 
  162                 "generic basicConvolve: dispatch to spatially varying LinearCombinationKernel basicConvolve");
 
  170         LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve",
 
  171                    "generic basicConvolve: using linear interpolation");
 
  176         LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve", 
"generic basicConvolve: using brute force");
 
  181 template <
typename OutImageT, 
typename InImageT>
 
  186     assertDimensionsOK(convolvedImage, inImage, kernel);
 
  188     int const mImageWidth = inImage.getWidth();  
 
  189     int const mImageHeight = inImage.getHeight();
 
  190     int const cnvWidth = mImageWidth + 1 - kernel.
getWidth();
 
  191     int const cnvHeight = mImageHeight + 1 - kernel.
getHeight();
 
  192     int const cnvStartX = kernel.
getCtr().getX();
 
  193     int const cnvStartY = kernel.
getCtr().getY();
 
  194     int const inStartX = kernel.
getPixel().getX();
 
  195     int const inStartY = kernel.
getPixel().getY();
 
  197     LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve", 
"DeltaFunctionKernel basicConvolve");
 
  199     for (
int i = 0; i < cnvHeight; ++i) {
 
  200         typename InImageT::x_iterator inPtr = inImage.x_at(inStartX, i + inStartY);
 
  201         for (
typename OutImageT::x_iterator cnvPtr = convolvedImage.x_at(cnvStartX, i + cnvStartY),
 
  202                                             cnvEnd = cnvPtr + cnvWidth;
 
  203              cnvPtr != cnvEnd; ++cnvPtr, ++inPtr) {
 
  209 template <
typename OutImageT, 
typename InImageT>
 
  215         LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve",
 
  216                    "basicConvolve for LinearCombinationKernel: spatially invariant; using brute force");
 
  226                 refKernelPtr = kernel.
clone();
 
  230             refKernelPtr = kernel.
clone();
 
  233             LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve",
 
  234                        "basicConvolve for LinearCombinationKernel: using interpolation");
 
  237             LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve",
 
  238                        "basicConvolve for LinearCombinationKernel: maxInterpolationError < 0; using brute " 
  246 template <
typename OutImageT, 
typename InImageT>
 
  251     typedef KernelVector::const_iterator KernelIterator;
 
  252     typedef typename InImageT::const_x_iterator InXIterator;
 
  253     typedef typename InImageT::const_xy_locator InXYLocator;
 
  254     typedef typename OutImageT::x_iterator OutXIterator;
 
  255     typedef typename OutImageT::y_iterator OutYIterator;
 
  256     typedef typename OutImageT::SinglePixel OutPixel;
 
  258     assertDimensionsOK(convolvedImage, inImage, kernel);
 
  263     KernelVector kernelXVec(kernel.
getWidth());
 
  264     KernelVector kernelYVec(kernel.
getHeight());
 
  267         LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve",
 
  268                    "SeparableKernel basicConvolve: kernel is spatially varying");
 
  270         for (
int cnvY = goodBBox.
getMinY(); cnvY <= goodBBox.
getMaxY(); ++cnvY) {
 
  271             double const rowPos = inImage.indexToPosition(cnvY, 
image::Y);
 
  273             InXYLocator inImLoc = inImage.xy_at(0, cnvY - goodBBox.
getMinY());
 
  274             OutXIterator cnvXIter = convolvedImage.row_begin(cnvY) + goodBBox.
getMinX();
 
  276                  ++cnvX, ++inImLoc.x(), ++cnvXIter) {
 
  277                 double const colPos = inImage.indexToPosition(cnvX, 
image::X);
 
  283                 *cnvXIter = math::convolveAtAPoint<OutImageT, InImageT>(inImLoc, kernelXVec, kernelYVec);
 
  285                     *cnvXIter = *cnvXIter / kSum;
 
  299         LOGL_DEBUG(
"TRACE2.afw.math.convolve.basicConvolve",
 
  300                    "SeparableKernel basicConvolve: kernel is spatially invariant");
 
  303         KernelIterator 
const kernelXVecBegin = kernelXVec.begin();
 
  304         KernelIterator 
const kernelYVecBegin = kernelYVec.begin();
 
  311         int const yPrefillEnd = buffer.getHeight() - 1;
 
  312         for (; yInd < yPrefillEnd; ++yInd) {
 
  313             OutXIterator bufXIter = buffer.x_at(0, yInd);
 
  314             OutXIterator 
const bufXEnd = buffer.x_at(goodBBox.
getWidth(), yInd);
 
  315             InXIterator inXIter = inImage.x_at(0, yInd);
 
  316             for (; bufXIter != bufXEnd; ++bufXIter, ++inXIter) {
 
  317                 *bufXIter = kernelDotProduct<OutPixel, InXIterator, KernelIterator, KernelPixel>(
 
  318                         inXIter, kernelXVecBegin, kernel.
getWidth());
 
  323         int inY = yPrefillEnd;
 
  324         int bufY = yPrefillEnd;
 
  328             InXIterator inXIter = inImage.x_at(0, inY);
 
  329             OutXIterator bufXIter = buffer.x_at(0, bufY);
 
  330             OutXIterator cnvXIter = convolvedImage.x_at(goodBBox.
getMinX(), cnvY);
 
  331             for (
int bufX = 0; bufX < goodBBox.
getWidth(); ++bufX, ++cnvXIter, ++bufXIter, ++inXIter) {
 
  334                 *bufXIter = kernelDotProduct<OutPixel, InXIterator, KernelIterator, KernelPixel>(
 
  335                         inXIter, kernelXVecBegin, kernel.
getWidth());
 
  337                 OutYIterator bufYIter = buffer.y_at(bufX, 0);
 
  338                 *cnvXIter = kernelDotProduct<OutPixel, OutYIterator, KernelIterator, KernelPixel>(
 
  339                         bufYIter, kernelYVecBegin, kernel.
getHeight());
 
  344             if (cnvY >= goodBBox.
getMaxY()) 
break;
 
  350             std::rotate(kernelYVec.begin(), kernelYVec.end() - 1, kernelYVec.end());
 
  355 template <
typename OutImageT, 
typename InImageT>
 
  363     typedef typename KernelImage::const_x_iterator KernelXIterator;
 
  364     typedef typename KernelImage::const_xy_locator KernelXYLocator;
 
  365     typedef typename InImageT::const_x_iterator InXIterator;
 
  366     typedef typename InImageT::const_xy_locator InXYLocator;
 
  367     typedef typename OutImageT::x_iterator OutXIterator;
 
  368     typedef typename OutImageT::SinglePixel OutPixel;
 
  370     assertDimensionsOK(convolvedImage, inImage, kernel);
 
  372     int const inImageWidth = inImage.getWidth();
 
  373     int const inImageHeight = inImage.getHeight();
 
  374     int const kWidth = kernel.
getWidth();
 
  376     int const cnvWidth = inImageWidth + 1 - kernel.
getWidth();
 
  377     int const cnvHeight = inImageHeight + 1 - kernel.
getHeight();
 
  378     int const cnvStartX = kernel.
getCtr().getX();
 
  379     int const cnvStartY = kernel.
getCtr().getY();
 
  380     int const cnvEndX = cnvStartX + cnvWidth;   
 
  381     int const cnvEndY = cnvStartY + cnvHeight;  
 
  384     KernelXYLocator 
const kernelLoc = kernelImage.xy_at(0, 0);
 
  387         LOGL_DEBUG(
"TRACE4.afw.math.convolve.convolveWithBruteForce",
 
  388                    "convolveWithBruteForce: kernel is spatially varying");
 
  390         for (
int cnvY = cnvStartY; cnvY != cnvEndY; ++cnvY) {
 
  391             double const rowPos = inImage.indexToPosition(cnvY, 
image::Y);
 
  393             InXYLocator inImLoc = inImage.xy_at(0, cnvY - cnvStartY);
 
  394             OutXIterator cnvXIter = convolvedImage.x_at(cnvStartX, cnvY);
 
  395             for (
int cnvX = cnvStartX; cnvX != cnvEndX; ++cnvX, ++inImLoc.x(), ++cnvXIter) {
 
  396                 double const colPos = inImage.indexToPosition(cnvX, 
image::X);
 
  398                 KernelPixel kSum = kernel.
computeImage(kernelImage, 
false, colPos, rowPos);
 
  399                 *cnvXIter = math::convolveAtAPoint<OutImageT, InImageT>(inImLoc, kernelLoc, kWidth, kHeight);
 
  401                     *cnvXIter = *cnvXIter / kSum;
 
  406         LOGL_DEBUG(
"TRACE4.afw.math.convolve.convolveWithBruteForce",
 
  407                    "convolveWithBruteForce: kernel is spatially invariant");
 
  411         for (
int inStartY = 0, cnvY = cnvStartY; inStartY < cnvHeight; ++inStartY, ++cnvY) {
 
  412             KernelXIterator kernelXIter = kernelImage.x_at(0, 0);
 
  413             InXIterator inXIter = inImage.x_at(0, inStartY);
 
  414             OutXIterator cnvXIter = convolvedImage.x_at(cnvStartX, cnvY);
 
  415             for (
int x = 0; 
x < cnvWidth; ++
x, ++cnvXIter, ++inXIter) {
 
  416                 *cnvXIter = kernelDotProduct<OutPixel, InXIterator, KernelXIterator, KernelPixel>(
 
  417                         inXIter, kernelXIter, kWidth);
 
  419             for (
int kernelY = 1, inY = inStartY + 1; kernelY < kHeight; ++inY, ++kernelY) {
 
  420                 KernelXIterator kernelXIter = kernelImage.x_at(0, kernelY);
 
  421                 InXIterator inXIter = inImage.x_at(0, inY);
 
  422                 OutXIterator cnvXIter = convolvedImage.x_at(cnvStartX, cnvY);
 
  423                 for (
int x = 0; 
x < cnvWidth; ++
x, ++cnvXIter, ++inXIter) {
 
  424                     *cnvXIter += kernelDotProduct<OutPixel, InXIterator, KernelXIterator, KernelPixel>(
 
  425                             inXIter, kernelXIter, kWidth);
 
  436 #define IMAGE(PIXTYPE) image::Image<PIXTYPE> 
  437 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel> 
  440 #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE)                                              \ 
  441     template void basicConvolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &, math::Kernel const&,   \ 
  442                                 math::ConvolutionControl const&);                                          \ 
  443     NL template void basicConvolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &,                     \ 
  444                                    math::DeltaFunctionKernel const&, math::ConvolutionControl const&);     \ 
  445     NL template void basicConvolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &,                     \ 
  446                                    math::LinearCombinationKernel const&, math::ConvolutionControl const&); \ 
  447     NL template void basicConvolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &,                     \ 
  448                                    math::SeparableKernel const&, math::ConvolutionControl const&);         \ 
  449     NL template void convolveWithBruteForce(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &,            \ 
  450                                             math::Kernel const&, math::ConvolutionControl const&); 
  452 #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE)             \ 
  453     INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \ 
  454     INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE)