support wrapped bilinear scaling
to get rid of seams in repeating patterns. https://github.com/mapbox/mapbox-gl-styles/issues/50#issuecomment-86159351
This commit is contained in:
committed by
Konstantin Käfer
parent
9080f25d31
commit
14e8b4bb09
@@ -165,7 +165,7 @@ void SpriteAtlas::copy(const Rect<dimension>& dst, const SpritePosition& src, co
|
||||
static_cast<uint32_t>(dst.originalW * pixelRatio),
|
||||
static_cast<uint32_t>(dst.originalH * pixelRatio) };
|
||||
|
||||
util::bilinearScale(srcData, srcSize, srcPos, dstData, dstSize, dstPos);
|
||||
util::bilinearScale(srcData, srcSize, srcPos, dstData, dstSize, dstPos, wrap);
|
||||
|
||||
// Add borders around the copied image if required.
|
||||
if (wrap) {
|
||||
|
||||
@@ -49,38 +49,39 @@ namespace util {
|
||||
|
||||
void bilinearScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize,
|
||||
const Rect<uint32_t>& srcPos, uint32_t* dstData, const vec2<uint32_t>& dstSize,
|
||||
const Rect<uint32_t>& dstPos) {
|
||||
const Rect<uint32_t>& dstPos, bool wrap) {
|
||||
const auto factor = getFactor(srcPos, dstPos);
|
||||
const auto bounds = getBounds(srcSize, srcPos, dstSize, dstPos, factor);
|
||||
|
||||
double fractSrcY = srcPos.y;
|
||||
double fractSrcX;
|
||||
uint32_t x, y;
|
||||
size_t i = dstSize.x * dstPos.y + dstPos.x;
|
||||
for (y = 0; y < bounds.y; y++) {
|
||||
fractSrcX = srcPos.x;
|
||||
const uint32_t srcY0 = fractSrcY;
|
||||
const uint32_t srcY1 = std::min(srcY0 + 1, srcSize.y - 1);
|
||||
const double fractY = y * factor.y;
|
||||
const uint32_t Y0 = fractY;
|
||||
const uint32_t Y1 = wrap ? (Y0 + 1) % srcPos.h : (Y0 + 1);
|
||||
const uint32_t srcY0 = srcPos.y + Y0;
|
||||
const uint32_t srcY1 = std::min(srcPos.y + Y1, srcSize.y - 1);
|
||||
for (x = 0; x < bounds.x; x++) {
|
||||
const uint32_t srcX0 = fractSrcX;
|
||||
const uint32_t srcX1 = std::min(srcX0 + 1, srcSize.x - 1);
|
||||
const double fractX = x * factor.x;
|
||||
const uint32_t X0 = fractX;
|
||||
const uint32_t X1 = wrap ? (X0 + 1) % srcPos.w : (X0 + 1);
|
||||
const uint32_t srcX0 = srcPos.x + X0;
|
||||
const uint32_t srcX1 = std::min(srcPos.x + X1, srcSize.x - 1);
|
||||
|
||||
const uint32_t tl = srcData[srcSize.x * srcY0 + srcX0];
|
||||
const uint32_t tr = srcData[srcSize.x * srcY0 + srcX1];
|
||||
const uint32_t bl = srcData[srcSize.x * srcY1 + srcX0];
|
||||
const uint32_t br = srcData[srcSize.x * srcY1 + srcX1];
|
||||
|
||||
const double dx = fractSrcX - srcX0;
|
||||
const double dy = fractSrcY - srcY0;
|
||||
const double dx = fractX - X0;
|
||||
const double dy = fractY - Y0;
|
||||
uint32_t& dst = dstData[i + x];
|
||||
b<0>(dst) = bilinearInterpolate(b<0>(tl), b<0>(tr), b<0>(bl), b<0>(br), dx, dy);
|
||||
b<1>(dst) = bilinearInterpolate(b<1>(tl), b<1>(tr), b<1>(bl), b<1>(br), dx, dy);
|
||||
b<2>(dst) = bilinearInterpolate(b<2>(tl), b<2>(tr), b<2>(bl), b<2>(br), dx, dy);
|
||||
b<3>(dst) = bilinearInterpolate(b<3>(tl), b<3>(tr), b<3>(bl), b<3>(br), dx, dy);
|
||||
fractSrcX += factor.x;
|
||||
}
|
||||
i += dstSize.x;
|
||||
fractSrcY += factor.y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,4 +109,4 @@ void nearestNeighborScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace util {
|
||||
|
||||
void bilinearScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize,
|
||||
const Rect<uint32_t>& srcPos, uint32_t* dstData, const vec2<uint32_t>& dstSize,
|
||||
const Rect<uint32_t>& dstPos);
|
||||
const Rect<uint32_t>& dstPos, bool wrap);
|
||||
|
||||
void nearestNeighborScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize,
|
||||
const Rect<uint32_t>& srcPos, uint32_t* dstData,
|
||||
|
||||
Reference in New Issue
Block a user