LuminanceHDR icon indicating copy to clipboard operation
LuminanceHDR copied to clipboard

Change resizing algorithm to lanczos or at least cubic

Open Beep6581 opened this issue 9 years ago • 23 comments

The resizing algorithm used for the preview results in a jagged image (probably nearest neighbor aliasing). Please change it to Lanczos or at least (bi)cubic for a higher quality preview.

Beep6581 avatar Jun 11 '15 18:06 Beep6581

The preview quality is still low in 2.5.0.

imgur-2017_04_19-14 41 10 imgur-2017_04_19-14 41 00

Beep6581 avatar Apr 19 '17 12:04 Beep6581

@fcomida looks like the Qt way of doing this is by enabling the "Aliasing" render hint. http://doc.qt.io/qt-5/qpainter.html#RenderHint-enum This could also help: http://stackoverflow.com/questions/17734290/antialiasing-not-working-in-qgraphicsview

Beep6581 avatar Apr 29 '17 16:04 Beep6581

@Beep6581 Thank you for this tip, pushed right now, try it out.

fcomida avatar Apr 29 '17 17:04 fcomida

@fcomida great! While it's compiling, I wanted to point out that:

QPainter::HighQualityAntialiasing 0x08 This value is obsolete and will be ignored, use the Antialiasing render hint instead.

Beep6581 avatar Apr 29 '17 17:04 Beep6581

@Beep6581 It didn't complain on Qt 5.6, thank you.

fcomida avatar Apr 29 '17 17:04 fcomida

  • Downscaling test
    • Without patch: imgur-2017_04_29-20 02 16
    • With patch: imgur-2017_04_29-20 02 11
  • Upscaling test
    • Without patch: imgur-2017_04_29-20 00 14
    • With patch: imgur-2017_04_29-20 00 19

The results are consistent with expectations: the preview is smoother. Great!

But now it's clear that there is a second area in need of improvement - the resizing algorithm. Not the one which resizes the preview, but the one which resizes the actual image.

I set the result size to 512x343: imgur-2017_04_29-20 10 00 It looks like no interpolation was used. Here is a comparison of the LHDR resized image vs ImageMagick's Lanczos: compare

@fcomida could you take a look at that too? It's very important as it severely affects every image not saved at its original full size.

Beep6581 avatar Apr 29 '17 18:04 Beep6581

@Beep6581 I will, indeed those Qt settings are only for displaying the images, for saving and for the cropping/resizing features an interpolation algorithm must be implemented. I was asked to implement dithering too, was he you?

fcomida avatar Apr 29 '17 19:04 fcomida

@fcomida no, I did not ask for dithering. Maybe when whoever asked for dithering sees good interpolation they won't want it anymore.

RawTherapee code is very fast and the resizing is great, if you'd like to copypasta: https://github.com/Beep6581/RawTherapee/blob/dev/rtengine/ipresize.cc

Beep6581 avatar Apr 29 '17 19:04 Beep6581

screenshot_20170430_025930 screenshot_20170430_030020 @Beep6581 Bilinear, Lanczos

fcomida avatar Apr 30 '17 01:04 fcomida

@fcomida bottom one is infinitely better!

Beep6581 avatar Apr 30 '17 08:04 Beep6581

screenshot_20170430_131219 screenshot_20170430_131333 @Beep6581 It can produce artifacts though, at very low resolutions.

fcomida avatar Apr 30 '17 11:04 fcomida

The image resizing quality before this patch was unusably bad. The overall improvement is terrific, but those artifacts are a problem. I reproduced them using 078314eb816c29450cc7185ceb5051799554a16d at any resolution, along very high contrast edges. Some kind of overshoot in the calculation when a low value lies directly adjacent a very high value?

What color space is the LHDR image in when its resized?

Beep6581 avatar Apr 30 '17 15:04 Beep6581

imgur-2017_04_30-17 33 59

Beep6581 avatar Apr 30 '17 15:04 Beep6581

I had a chat with a person who knows things (@CarVac, the author of Filmulator), and the summary is that:

  • Downscaling performed on HDR images needs non-negative kernels
  • Lanczos shouldn't be used on HDR files, it is inherently unsuitable for them. LHDR should use bilinear with box sampling for that:

bilinear is only useful for things between 0.5x and 1x for downsampling, so you need to do box sampling first, to do integer scaling, and then you do bilinear

Code here: https://github.com/CarVac/filmulator-gui/blob/master/filmulator-gui/core/scale.cpp

Beep6581 avatar Apr 30 '17 15:04 Beep6581

@Beep6581 our previous code is derived from here: bilinear image scaling with added OpenMP support and block based resampling.

fcomida avatar Apr 30 '17 16:04 fcomida

@fcomida Did you implement the "Caveat" in that article?

Bilinear scaling performs best when the desired output dimension is no more than double or half its original size. If that is the case however, it might be good to implement additional technique called Mip Mapping on top of the existing algorithm.

You may be properly implementing bilinear scaling, but first you have to get it within a factor of two of the desired size using integer scaling.

CarVac avatar Apr 30 '17 17:04 CarVac

If this is the function in question:

https://github.com/LuminanceHDR/LuminanceHDR/blob/master/src/Libpfs/manip/resize.hxx#L214

It looks like it doesn't perform any of the necessary integer scaling.

CarVac avatar Apr 30 '17 18:04 CarVac

The function is that one, it was implemented by Davide time ago. So no Lanczos at all? In my limited tests it performs well except for large scaling factors.

fcomida avatar Apr 30 '17 18:04 fcomida

Lanczos is fine if you do resizing after tonemapping, which is not what you care about since you want to do the tonemapping on a lower resolution so it can run faster.

Lanczos has problems with ringing when the initial contrast is too high. For HDR content like this, since the highlights are tremendously brighter than their surroundings, that can result in the very visible halos that @Beep6581 showed in his latest screenshot.

The bilinear algorithm looks correct, but it's currently bilinearly interpolating between only the four neighbors nearest next to each destination pixel, not far off from plain nearest-neighbor. It needs to be integer downsampled to a size between 1X and 2X the end result size before you run the bilinear filter.

CarVac avatar Apr 30 '17 18:04 CarVac

@CarVac Yes, It was actually me that pointed out those artifacts. I'm gonna improve bilinear then. At small scaling factors Lanczos doesn't seem to produce artifacts though, have I been lucky with my testing? Can we switch among the two (Lanczos for small scaling factor an then bilinear)?

fcomida avatar Apr 30 '17 18:04 fcomida

In my opinion, I think you should stick to bilinear only, to ensure that artifacts don't occur.

CarVac avatar Apr 30 '17 19:04 CarVac

@fcomida in the library example image set, I got artifacts along high contrast edges even for small scaling factors.

Beep6581 avatar Apr 30 '17 19:04 Beep6581

@Beep6581 @CarVac got it. Goodbye Lancozs....

fcomida avatar Apr 30 '17 19:04 fcomida