LuminanceHDR
LuminanceHDR copied to clipboard
Change resizing algorithm to lanczos or at least cubic
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.
The preview quality is still low in 2.5.0.
@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 Thank you for this tip, pushed right now, try it out.
@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 It didn't complain on Qt 5.6, thank you.
- Downscaling test
- Without patch:
- With patch:
- Without patch:
- Upscaling test
- Without patch:
- With patch:
- Without patch:
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:
It looks like no interpolation was used.
Here is a comparison of the LHDR resized image vs ImageMagick's Lanczos:
@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 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 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 Bilinear, Lanczos
@fcomida bottom one is infinitely better!
@Beep6581 It can produce artifacts though, at very low resolutions.
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?
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 our previous code is derived from here: bilinear image scaling with added OpenMP support and block based resampling.
@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.
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.
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.
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 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)?
In my opinion, I think you should stick to bilinear only, to ensure that artifacts don't occur.
@fcomida in the library example image set, I got artifacts along high contrast edges even for small scaling factors.
@Beep6581 @CarVac got it. Goodbye Lancozs....