Bilinear Resampling

Blitz3D Forums/Blitz3D Programming/Bilinear Resampling

Krischan(Posted 2009) [#1]
For my current project I need a bilinear resampling function which is NOT based on Tformfilter and Resizeimage. The goal is to stretch a 64x64 bank to a 256x256 or higher dimensioned bank with bilinear interpolated values. I've setup a quick test with a 4x4 "data image" but there is an error I cant identify. The target size is shown in the green rectangle and you'll notice that the blob is distorted a little bit (it will get even worse if you increase the s# scale variable)

Where is the error? I added some kind of debug logging and the correct results should be:

0, 32, 96,128,128, 96, 32, 0
32, 64,128,160,160,128, 64, 32
96,128,191,223,223,191,128, 96
128,160,223,255,255,223,160,128
128,160,223,255,255,223,160,128
96,128,191,223,223,191,128, 96
32, 64,128,160,160,128, 64, 32
0, 32, 96,128,128, 96, 32, 0

but they are

0, 32, 64, 64, 64, 32, 0, 0
32, 96,160,160,160, 96, 32, 16
64,160,255,255,255,160, 64, 32
64,160,255,255,255,160, 64, 32
64,160,255,255,255,160, 64, 32
32, 96,160,160,160, 96, 32, 16
0, 32, 64, 64, 64, 32, 0, 0
0, 16, 32, 32, 32, 16, 0, 0

Please help, I'm stuck there :-/




Subirenihil(Posted 2009) [#2]
First off, your target values are a little off (on the edges, how can {0,64,64,0} expand into {0,32,96,128,128,96,32,0} - linear interpolation is about {0,32,64,64,64,64,32,0} while spline interpolation is about {0,36,64,80,80,64,36,0}).

What it looks like you are trying to do is expand the image from
0.0 _ 1.0 _ 2.0 _ 3.0
to
0.0 _ 0.4 _ 0.9 _ 1.3 _ 1.7 _ 2.1 _ 2.6 _ 3.0
but you are coding it to expand to
0.0 _ 0.5 _ 1.0 _ 1.5 _ 2.0 _ 2.5 _ 3.0 _ 3.5
which shifts it off center.

The following is what you (inadvertently) are doing (the xx's are the interpolated values, the numbers are what you have in your array):
 00  xx  64  xx  64  xx  00  xx (00)
 XX  xx  XX  xx  XX  xx  XX  xx (00)
 64  xx 255  xx 255  xx  64  xx (00)
 XX  xx  XX  xx  XX  xx  XX  xx (00)
 64  xx 255  xx 255  xx  64  xx (00)
 XX  xx  XX  xx  XX  xx  XX  xx (00)
 00  xx  64  xx  64  xx  00  xx (00)
 XX  xx  XX  xx  XX  xx  XX  xx (00)
(00)(00)(00)(00)(00)(00)(00)(00)(00)

The parentheses are around array values that you didn't think you were accessing (they are also the pixels that are beyond the edge of the image).

I have modified your code 2 ways; the first is scaling the same amount you were scaling it but centered, the second scales it so that the corners are still in the corners.

Version 1 gives:
-0.25 _ 0.25 _ 0.75 _ 1.25 _ 1.75 _ 2.25 _ 2.75 _ 3.25
Version 2 gives:
0.0 _ 0.4 _ 0.9 _ 1.3 _ 1.7 _ 2.1 _ 2.6 _ 3.0

Version 1:


Version 2:


I'm not going to try to make a spline interpolation function right now, its a bit more complex and it's getting late for me. Hope one of these works for ya (I personally prefer version 1, but that's just me)


Krischan(Posted 2009) [#3]
Thank you! For my test data I compared the debug entries with the results I got in Photoshop, dunno which bilinear filter they use. But after hours of testing I found that your second solution is brilliant for my needs. I am now able to "resize" a 64x64 heightmap part to 512x512, blend it with a fractal image and get 8 times higher resolution with it and maintaining the basic heightmap structure (in just 200ms). And it is still tileable after that!


Subirenihil(Posted 2009) [#4]
Ah, Photoshop likely (don't know if you changed any setting when you resized your test image) used a fancier function to enlarge it.

My code could probably be optimized to be more efficient, but glad to have helped.

Now...which version goes in the code archives....?