Project Nayuki


Sinc-based image resampler

Sinc function

Nayuki’s sinc-based image resampler (SincImageResample) is a high-quality, flexible image resampler implemented in Java. It preserves detail while minimizing aliasing and ringing. It supports arbitrary upsampling and downsampling ratios in the horizontal and vertical dimensions, and has a configurable filter length.

Longer filter lengths preserve more detail and reduce aliasing but increase ringing, while shorter filters do exactly the opposite. The default filter length is 4.0 for upsampling and (old dimension ÷ new dimension) × 4.0 for downsampling. (Filter length 4.0 is appropriate for generating little ringing on sharp computer-generated graphics; length 6.0 is better for natural photographs in preserving detail.)

The code can be used in two ways: It can be run as a command-line program for resampling a single image. It also provides two reusable functions to allow scripted operations within Java: resampleFile() takes an input and an output file name; resampleImage() takes a BufferedImage object and returns a new one. License: GNU General Public License v3.0+.

Source code

There are two implementations of this sinc resampler concept – one for clarity and one for speed. They compute essentially the same result, except for a very slight discrepancy in rounding. The code has no dependencies besides the Java standard library.

Command-line usage: java SincImageResample InFile.{png,bmp} OutWidth OutHeight OutFile.{png,bmp} [HorzFilterLen [VertFilterLen]] (the filter lengths are optional)
Example: java SincImageResample input.bmp 640 480 output.png

SincImageResample.java

Use this version of the code if you are studying or customizing the image-processing algorithm. This is considered the reference algorithm.

FastSincImageResample.java

Use this version of the code if you are simply running it and want to get results quickly. The command-line parameters are the same as for SincImageResample.

The speedup is approximately 10× to 30× depending on the input and output dimensions, but not depending much on the number of threads. This speedup is achieved at the cost of code duplication, awkward but cache-friendly data arrangement in arrays, manual loop-unrolling, and thread management – which makes the code significantly less clear and elegant than the reference version. This implementation is rigorously tested to match SincImageResample to within ±1 value for each color channel.

Simple API usage:

  • void resampleFile(File inFile, int outWidth, int outHeight, File outFile): Reads the given input image file, resamples the image in memory, and writes to the given output file. See the Javadoc comment in the code for complete details.

  • BufferedImage resampleImage(BufferedImage image, int outWidth, int outHeight): Takes the given BufferedImage and returns a new one that has been resampled. See the Javadoc comment in the code for complete details.