Add pull push filter with bilinear filtering.

pull/216/head
castano 16 years ago
parent b4f17b968a
commit 9bda107603

@ -11,6 +11,27 @@
using namespace nv;
float BitMap::sampleLinearClamp(float x, float y) const
{
const float fracX = x - floor(x);
const float fracY = y - floor(y);
const uint ix0 = ::clamp(uint(floor(x)), 0U, m_width-1);
const uint iy0 = ::clamp(uint(floor(y)), 0U, m_height-1);
const uint ix1 = ::clamp(uint(floor(x))+1, 0U, m_width-1);
const uint iy1 = ::clamp(uint(floor(y))+1, 0U, m_height-1);
float f1 = bitAt(ix0, iy0);
float f2 = bitAt(ix1, iy0);
float f3 = bitAt(ix0, iy1);
float f4 = bitAt(ix1, iy1);
float i1 = lerp(f1, f2, fracX);
float i2 = lerp(f3, f4, fracX);
return lerp(i1, i2, fracY);
}
// This is a variation of Sapiro's inpainting method.
void nv::fillExtrapolate(int passCount, FloatImage * img, BitMap * bmap)
@ -26,6 +47,7 @@ void nv::fillExtrapolate(int passCount, FloatImage * img, BitMap * bmap)
nvCheck(bmap->height() == uint(h));
AutoPtr<BitMap> newbmap(new BitMap(w, h));
newbmap->clearAll();
for(int p = 0; p < passCount; p++)
{
@ -210,11 +232,13 @@ void nv::fillVoronoi(FloatImage * img, const BitMap * bmap)
for( x = 0; x < w; x++ ) {
const int sx = edm[y * w + x].x;
const int sy = edm[y * w + x].y;
nvDebugCheck(sx < w && sy < h);
if( sx != x || sy != y ) {
for(int c = 0; c < count; c++ ) {
img->setPixel(img->pixel(sx, sy, c), x, y, c);
if (sx < w && sy < h)
{
if (sx != x || sy != y) {
for(int c = 0; c < count; c++ ) {
img->setPixel(img->pixel(sx, sy, c), x, y, c);
}
}
}
}
@ -247,7 +271,9 @@ static bool downsample(const FloatImage * src, const BitMap * srcMask, const Flo
FloatImage * dst = new FloatImage();
dst->allocate(count, nw, nh);
BitMap * dstMask = new BitMap(nw, nh);
dstMask->clearAll();
for(uint c = 0; c < count; c++) {
for(uint y = 0; y < nh; y++) {
@ -358,6 +384,80 @@ void nv::fillPullPush(FloatImage * img, const BitMap * bmap)
deleteAll(mipmapMasks);
}
// It looks much cooler with trilinear filtering
void nv::fillPullPushLinear(FloatImage * img, const BitMap * bmap)
{
nvCheck(img != NULL);
const uint count = img->componentNum();
const uint w = img->width();
const uint h = img->height();
const uint num = log2(max(w,h));
// Build mipmap chain.
Array<const FloatImage *> mipmaps(num);
Array<const BitMap *> mipmapMasks(num);
mipmaps.append(img);
mipmapMasks.append(bmap);
const FloatImage * current;
const BitMap * currentMask;
// Compute mipmap chain.
while(downsample(mipmaps.back(), mipmapMasks.back(), &current, &currentMask))
{
mipmaps.append(current);
mipmapMasks.append(currentMask);
}
// Sample mipmaps until non-hole is found.
for(uint y = 0; y < h; y++) {
for(uint x = 0; x < w; x++) {
float sx = x;
float sy = y;
float coverageSum = 0.0f;
const uint levelCount = mipmaps.count();
for (uint l = 0; l < levelCount; l++)
{
const float fx = sx / mipmaps[l]->width();
const float fy = sy / mipmaps[l]->height();
float coverage = mipmapMasks[l]->sampleLinearClamp(sx, sy);
if (coverage > 0.0f)
{
// Sample mipmaps[l](sx, sy) and copy to img(x, y)
for(uint c = 0; c < count; c++) {
img->addPixel((1 - coverageSum) * mipmaps[l]->sampleLinearClamp(fx, fy, c), x, y, c);
}
coverageSum += coverage;
if (coverageSum >= 1.0f)
{
break;
}
}
sx /= 2;
sy /= 2;
}
}
}
// Don't delete the original image and mask.
mipmaps[0] = NULL;
mipmapMasks[0] = NULL;
// Delete the mipmaps.
deleteAll(mipmaps);
deleteAll(mipmapMasks);
}
/*
@ -654,6 +754,7 @@ void nv::fillQuadraticExtrapolate(int passCount, FloatImage * img, BitMap * bmap
nvCheck(bmap->height() == uint(h));
AutoPtr<BitMap> newbmap( new BitMap(w, h) );
newbmap->clearAll();
float * coverageChannel = NULL;
if (coverageIndex != -1)

@ -22,6 +22,8 @@ namespace nv
uint width() const { return m_width; }
uint height() const { return m_height; }
float sampleLinearClamp(float x, float y) const;
bool bitAt(uint x, uint y) const
{
nvDebugCheck(x < m_width && y < m_height);
@ -86,6 +88,7 @@ namespace nv
NVIMAGE_API void fillVoronoi(FloatImage * img, const BitMap * bmap);
NVIMAGE_API void fillPullPush(FloatImage * img, const BitMap * bmap);
NVIMAGE_API void fillPullPushLinear(FloatImage * img, const BitMap * bmap);
NVIMAGE_API void fillExtrapolate(int passCount, FloatImage * img, BitMap * bmap);
NVIMAGE_API void fillQuadraticExtrapolate(int passCount, FloatImage * img, BitMap * bmap, int coverageIndex = -1);

Loading…
Cancel
Save