Bilinear Interpolation bad for down sizing images

Started by
13 comments, last by Winograd 17 years, 8 months ago
Use box area sampling for minification filter: great quality! Here is link to different filters, the last image is box area sampler minification to extremely small size, followed by bicubic magnification:

http://www.liimatta.org/fusion/filter/filter.html

The sourcecode is also available, currently compiles and works on Linux (various, tested lately on IA32/x86 and AMD64 variants), IRIX 6.5, Windows (32 and 64 bit) and MacOS X (only tested on Intel macs lately, tested on Power Macs previously but cannot guarantee it works out-of-the-zip :).

Codewise, it would look like this:

(sorry don't know the tags, so I just write plain inline here)

// --- test.cpp ---
#include <fusion/core/surface.hpp>
using namespace fusion::core;

int main()
{
// initialize the fusion::core component
core::init();

// create surface object, overload the pixelformat (*1)
surface* so = surface::create("test.jpg",pixelformat::argb8888);

// invoke the appropriate filters ;)
so->resize(10,10);
so->resize(400,300);
so->save("snap.jpg");

// cya surface object
so->release();
}

// --- end ---

Note above:

(*1) The pixelformat is very flexible, this one is just one built-in static pixelformat (a few common formats are pre-built into the library). Besides the most typical formats, floating-point is fully supported, compressed surfaces is supported (so you can store DXT compressed surfaces etc.), decompression of surfaces is naturally supported, mipmaps, cubemaps and so on are supported through the same interface. :)

Example:

surface* so = surface::create("koolstuff.dds"); // <-- note: no overload used

At this point we check if your IDirectSuperDevice20000 or OpenGL ICD supports compressed textures, if not, we decompress and dump the data with some rgb format that suits our purposes. If it does, we dump the contents of the surface as-is and go on our merry way with compressed textures. \:D/

Useful for other stuff aswell, example, filesystem:

stream* s = filesystem::create("test.bla");

Or,

stream* s = filesystem::create("foo/bar.zip/test.bla"); // !!!

Or,

surface* so = surface::create("foo/bar.zip/test.png"); // !!!

Because the filesystem is plugin based and modular, and the codec manager is also plugin based and modular, it's possible to mix and match the different plugins to do things like above. Since we can read jpg's, png's, whatever and can access zip files like folders, it automatically follows that we can read jpg off a zip file among other things. ;)

About image resizing, the resize filters implemented are reasonably high quality, worth a minute or two to check out.
Advertisement
Quote:Original post by Agony
But a downsampled pixel is not a point, it is an area. And thus anything that falls within that area from the image before downsampling should get equal weight. If something is entirely within the area, there is no concept of closer to the area or farther away from the area. The center of the area is irrelevant.


No, i'm afraid you're wrong. Downsampled pixel is a point. It is a sample of a bandlimited continuous image, just like the samples of the original image were. The downsampled pixel can, however, be estimated from the given area of the original image.

But, what makes you think that the 3x3 area contains all the information needed in order to recover the actual sample (i.e., pixel) of downsampled image? Perhaps one would need 7x7? Or NxN? But how about weighting? What I am trying to say is, that while your reasoning seems intuitive, it is flawed and over simplified. This is not to say that the method would not work well visually (although, this is subjective). In fact, simple averaging is probably more than adequate when considering its low computational complexity.

Quote:Original post by Agony
Based off of a quick check of their website, it looks like this sharpness has nothing to do with their method of downsampling, but their improved method of capturing all colors at every pixel.


I would hardly call aliased image an improvement. Then again, this is subjective.
Wow, this has turned into a very interesting discussion. My original intent was to simply sample a texture that tiled across a quad for painting purposes. I found that if the texture needed to be tiled, lets say 8 times, across the quad, if I used bilinear filtering to sample the texture at each point on the quad, the results had too much contrast between neighboring pixels.

But I just used simple averaging of the four neighboring pixels and it looks just fine. I did a comparison between simple averaging and the way OpenGL downsamples textures and the results are identical.
Author Freeworld3Dhttp://www.freeworld3d.org
lol i still dont get how bilinear interpolation can reduce images... my implementation of it is you basically map a point in the large image to a point in the small image. then you take 4 of it's nearest neighbors and do a bilinear interpolation on it (z = Axy + Bx + Cy + D). so if you were to say resample a really large image down to a really small one, each pixel in the small image is only sampling from 4 pixels... where if u use pixel averaging it will average many pixels. so that is probably why your bilinear interp is looking like crap... not enough sample points for larger images.
Y-Go
I suggest everyone interested in the topic to view this comparison:

Comparison of different down sampling methods


It is interesting to see how theoretically same kernel results in drastically different results depending on the implementation. To my knowledge, triangle kernel of ImageMagick should be equal to bilinear of Photoshop (compare the results).

Especially compare the results for ImageMagick at the bottom of the page. Note that box antialiased image (that is, image filtered with averaging filter) is second worst of all tested. Only nearest neighbour was even worse. Although, one must remember that the exact implementation of those filters are not known (well the source code is available, but I'm lazy).

It is also worth noting that sinc and lanczos (the theoretically good filters) don't in fact remove aliasing as effectively as bicubic (or cubic). This is surprising, but it may be explained by low order kernel (in theory sinc kernel extends to infinity). This is understandable as some aliasing may please the eye. That is, we perceive aliased image slightly sharper than correctly antialiased image. However, one would expect kernel named 'sinc' to outperform at least bicubic in terms of reduced aliasing.

EDIT: The tests in the given web site were made with 20% resampling. This is much more demanding task than for example 50% or 25%. I did few tests of my own with the same test image and 50% resampling. Results were consistent with the ones given at the website.


@anonymous poster:

Bilinear is only good to 50% resize and it is questionable even then. Usually when resizing images, it is done in steps with simple kernels. Something like Emmanuel Deloget explained. For example, resizing to 25% could be done as two 50% down samplings. In this scheme lower order kernel is sufficient (such as bilinear).

This topic is closed to new replies.

Advertisement