in cpp/spectrum/core/proc/legacy/SeparableFiltersResampler.cpp [164:246]
std::size_t SeparableFiltersResampler::prepareContributorLists() {
// count number of rows that need to be buffered to allow y resizing
std::size_t nRowsBuffered = 0;
// for each direction
for (int d = 1; d >= 0; --d) {
const std::uint32_t& dst = (d ? mDstWidth : mDstHeight);
const std::uint32_t& src = (d ? mSrcWidth : mSrcHeight);
const double scale = static_cast<double>(dst) / src;
const double filterHalfWidth = ((MK_SUPPORT * 0.5f) / scale);
// for each dst coordinate, identify the src coordinates which contribute
// to it
for (std::uint32_t c = 0; c < dst; ++c) {
vector<Contrib>& contrib = (d ? mXContributors[c] : mYContributors[c]);
// convert from discrete to continuous coordinates, scale, then
// convert back to discrete.
float center = ((static_cast<float>(c) + 0.5f) / scale) - 0.5f;
int left = static_cast<int>(floor(center - filterHalfWidth));
int right = static_cast<int>(ceil(center + filterHalfWidth));
// calculate index and weight for each contributor
float totalWeight = 0.0f;
float maxWeight = -INFINITY;
std::size_t maxWeightIndex = 0;
for (int j = left; j <= right; ++j) {
// get the weight associated with this index
float weight = magicKernelWeight((center - j) * scale);
if (weight == 0.0f) {
continue;
}
totalWeight += weight;
// ensure index is valid (clamp if necessary)
int index = j;
if (index < 0) {
index = 0;
} else if (index >= (int)src) {
index = src - 1;
}
// record this contributor
contrib.push_back(Contrib(index, weight));
if (weight > maxWeight) {
maxWeight = weight;
maxWeightIndex = contrib.size() - 1;
}
}
// normalize
const double norm = (1.0f / totalWeight);
totalWeight = 0.0f;
for (std::size_t j = 0; j < contrib.size(); ++j) {
contrib[j].weight *= norm;
contrib[j].wQ = FltToFixQ11(contrib[j].weight);
totalWeight += contrib[j].weight;
}
// ensure filtered values add up to 1
if (totalWeight != 1.0f) {
contrib[maxWeightIndex].weight += (1.0f - totalWeight);
contrib[maxWeightIndex].wQ =
FltToFixQ11(contrib[maxWeightIndex].weight);
}
// buffered rows logic
if (d == 0) {
nRowsBuffered = std::max(nRowsBuffered, contrib.size());
}
}
}
// for each src row, count how many times it contributes to dst
for (std::uint32_t r = 0; r < mDstHeight; ++r) {
for (std::size_t k = 0; k < mYContributors[r].size(); ++k) {
SPECTRUM_ENFORCE_IF(mYContributors[r][k].index < 0);
SPECTRUM_ENFORCE_IF(mYContributors[r][k].index >= (int)mSrcHeight);
mSrcRowInfo[mYContributors[r][k].index].second++;
}
}
return nRowsBuffered;
}