Opened 9 years ago

Last modified 3 years ago

#7500 assigned enhancement

Image scaling < 1.0 (downsampling) shows aliasing

Reported by: aldeck Owned by: nobody
Priority: normal Milestone: R1
Component: Servers/app_server Version: R1/Development
Keywords: image scaling downsampling aliasing Cc: stippi
Blocked By: Blocking:
Platform: All

Description (last modified by aldeck)

Image scaling < 1.0 (downsampling) shows aliasing

Can be reproduced with ImageViewer or desktop background with this high resolution test image (any highres image with sharp contrasted lines will do)

Change History (5)

comment:1 by aldeck, 9 years ago

Cc: stippi added
Description: modified (diff)
Keywords: aliasing added; moire artifacts removed
Summary: Image scaling (downsampling) shows moire artifactsImage scaling < 1.0 (downsampling) shows aliasing

I haven't had enough time to test what i wanted, though all i can affirm a that point is that the generic agg implementation of DrawBitmap (Painter.cpp) has the problem. Note that i haven't analyzed the algorithms themselves and don't know if they actually support high quality downscaling. Will possibly look further when i make more time.

cc'ing stippi as i'm sure he has a clue

comment:2 by stippi, 9 years ago

Type: bugenhancement

The bilinear scaling which happens when downscaling images is not the ideal algorithm. AGG also supports "resampling", which is much better suited and would produce perfect results. However, the AGG filter also supports arbitrary transformations and is much more computationally expensive. If you look closely to other operating systems and/or imaging applications, you will see that only few of them perform resampling and most do the simple bilinear scaling that is being used now. One can consume even more computing resources by doing a color space gamma correction before performing the scaling operation. That is to convert the image to 16 bit per channel linear RGB color space, downscale using resampling and converting the result back to non-linear 8 bit per channel RGB (sRGB) for on-screen display. Most applications however need the fast image scaling instead of the correct one, so this ticket points out a possible enhancement. The DrawBitmap() method in BView takes a new flags parameter in Haiku, and it would be possible to specify the kind of filtering one wants (correct versus fast, or even the exact filtering method).

comment:3 by aldeck, 9 years ago

Thanks for the detailed explanation. I wasn't sure if it ever worked before and thus if it was a bug or missing feature (maybe when scaling was done by ShowImage internally instead of native BBitmap scaled drawing?). The reason i worry is that the aliasing is really degrading the image (even for the inexperienced eye) for what is getting a common use case nowadays (watching photos with a really higher res that the screen). I haven't tried other OS'es than Ubuntu recently but at least the image viewer and Chromium browser do it right. I probably won't be able to look into it soon, though at least there's a ticket now :)

comment:4 by stippi, 9 years ago

If you want to play with it, and if I don't overlook something important, it should be possible to implement the resampler based on doing bilinear scaling iteratively. For each iteration step, you would scale the image down by a factor of 0.5, until you finally arrive at the factor you wanted. For example, a scaling factor of 0.25 could be achieved by doing a bilinear downscale with factor 0.5 two times. Since it definitely takes the AGG resampling filter more than two times the time it takes the bilinear filter, this should be much faster. And it could be even faster by implementing a special version of the filter for the factor 0.5. (No filter weights need to be calculated and the inner loop can be much simpler). The general purpose implementation would be used for the last step which would be between 0.5 and 1.0 most likely.

Some background: When resampling an image, you look at each pixel in the source image to compute the target pixels (an arbitrary area of pixels collapses into one pixel). When doing bilinear scaling, you don't ever look at more than four times the pixels of the target image in the source image. Basically, you can imagine it as computing a floating point coordinate of the target pixel in the source image, and then you compute the target pixel by weighting the four pixels around that location. That makes it clear why this algorithm produces bad artifacts when the image scale falls below 0.5 -- you start ommiting source pixels. For a scale between 0.5 and 1.0, resampling and bilinear scaling should be equivalent. When you use the existing, optimized bilinear scaling functions and do multiple passes to arrive at the target scale, you could perhaps create a much faster resampling implementation than what AGG provides. (It also does not provide all the features, but only those that we need.)

comment:5 by axeld, 3 years ago

Owner: changed from axeld to nobody
Status: newassigned
Note: See TracTickets for help on using tickets.