Community
Participate
Working Groups
Currently, ImageData.scaledTo() does not interpolate pixels, it instead uses nearest-neighbor sampling. This does not give good results when scaling common images in user interfaces such as icons. A better algorithm to use in this case would be linear interpolation, as it provides a reasonable speed-quality tradeoff for user interface graphics.
I agree, my application used scaledTo to scale photos, and the results were atrocious. Drawing an image onto a smaller image produces results that are acceptable. Why has nothing been done with this bug since 2005?
DPIUtil#autoScaleImageData(..) also uses ImageData#scaledTo(..), which e.g. makes toolbar buttons look bad when scaled to 1.5.
Created attachment 259133 [details] SnippetScaling.java Here's a snippet (paste to the org.eclipse.swt.snippets project) that tests various icons with different ways of scaling them to 0.5, 1, 1.25, 1.5, and 2x I don't see a big difference between the different ways to set up the GC for GC#drawImage(..) with GC#setAntialias(..) and GC#setTransform(..). Any of those approaches can be used to improve ImageData#scaledTo(..).
For integer scaling factors, we should give users a way to choose between pixel-doubling and anti-aliasing. At 200%, it's largely a matter of preference. Both strategies are suboptimal, depending on the concrete icons. Abstract forms like Minimize, Maximize, Menu, Resume, Suspend, Terminate look better with pixel-doubling. Other icons may look better with a little blur. E.g. enable anti-aliasing with: -Dorg.eclipse.swt.scaled.images=antialias
New Gerrit change created: https://git.eclipse.org/r/70415
May be we can use gdk_pixbuf_scale_simple api for scaling on gtk and stretchBlt api for windows. I used gdk_pixbuf_scale_simple with GDK_INTERP_BILENEAR. the image quality is pretty good. For more information on GTK https://developer.gnome.org/gdk-pixbuf/unstable/gdk-pixbuf-Scaling.html#gdk-pixbuf-scale-simple In case of cairo we can use cairo_scale to scale the image
(In reply to Sravan Kumar Lakkimsetti from comment #6) Sounds good, and it's effectively what the GC#drawImage(..) in my hack does. How does your proposal work with transparency in the image? If the implementation needs to reuse large parts of the existing implementation, then please extract the reusable parts and avoid code duplication. For non-integer scale factors, the current implementation of ImageData#scaledTo(..) is unusable, and I have no problem with replacing that with a better method. However, I think we need to keep at least an option to use the pixel-doubling method for integer multiples of the original size. Blurring images when scaling *2 or *3 could be considered a breaking change for existing API clients.
(In reply to Markus Keller from comment #7) > (In reply to Sravan Kumar Lakkimsetti from comment #6) > Sounds good, and it's effectively what the GC#drawImage(..) in my hack does. > > How does your proposal work with transparency in the image? If the > implementation needs to reuse large parts of the existing implementation, > then please extract the reusable parts and avoid code duplication. > > For non-integer scale factors, the current implementation of > ImageData#scaledTo(..) is unusable, and I have no problem with replacing > that with a better method. However, I think we need to keep at least an > option to use the pixel-doubling method for integer multiples of the > original size. Blurring images when scaling *2 or *3 could be considered a > breaking change for existing API clients. I haven't tried using the transparency yet. I believe it will work. I will try it.
Markus, I have dynamic scaling bug to be fixed. I may not be able to focus on this in M7. I would like to work on it later. I am thinking of SR1. will that be ok?
Targeting to 4.7 as it is difficult to complete in 4.6 and we will back port to 4.6 post neon release
I don't think we should change ImageData.scaledTo(). The API has always implemented nearest-neighbor scaling, and it's quite possible that there are clients that rely on this behavior. We even have an invocation in SWT's JPEGFileFormat. I've created https://git.eclipse.org/r/#/c/70415/5 , which implements smoother scaling for HiDPI in DPIUtil#autoScaleImageData(..). The scaling method can be chosen explicitly with the command line parameter -Dswt.autoScale.method=nearest or -Dswt.autoScale.method=smooth On GTK, this works fine, and the smooth scaling that is used by default for fractional scale factors looks much better. But on Windows, I ran into huge trouble, see the FIXME in DPIUtil. Drawing of PNGs and GIFs seems to work differently, and both don't work as they should. I didn't find any solution to make GC#drawImage(..) properly draw onto a transparent base image. => We can't fix auto-scaling of images without a solution for this problem on Windows. Any help would be appreciated. I'm out of ideas.
(In reply to Markus Keller from comment #11) > I don't think we should change ImageData.scaledTo(). The API has always > implemented nearest-neighbor scaling, and it's quite possible that there are > clients that rely on this behavior. We even have an invocation in SWT's > JPEGFileFormat. > > I've created https://git.eclipse.org/r/#/c/70415/5 , which implements > smoother scaling for HiDPI in DPIUtil#autoScaleImageData(..). > > The scaling method can be chosen explicitly with the command line parameter > -Dswt.autoScale.method=nearest > or > -Dswt.autoScale.method=smooth > > On GTK, this works fine, and the smooth scaling that is used by default for > fractional scale factors looks much better. > > But on Windows, I ran into huge trouble, see the FIXME in DPIUtil. > > Drawing of PNGs and GIFs seems to work differently, and both don't work as > they should. I didn't find any solution to make GC#drawImage(..) properly > draw onto a transparent base image. > > => We can't fix auto-scaling of images without a solution for this problem > on Windows. Any help would be appreciated. I'm out of ideas. This looks much better on gtk. I haven't tested the windows yet.
Back to inbox. The autoScale stuff has been moved to a new bug 493462. Let's keep this bug for its original intended purpose: Offer an API to scale images with a better interpolation method. It should not be ImageData#scaledTo(..), but a new method.
Hi Conrad, Any idea on this issue ?
(In reply to Markus Keller from comment #11) > I don't think we should change ImageData.scaledTo(). The API has always > implemented nearest-neighbor scaling, and it's quite possible that there are > clients that rely on this behavior. We even have an invocation in SWT's > JPEGFileFormat. > > I've created https://git.eclipse.org/r/#/c/70415/5 , which implements > smoother scaling for HiDPI in DPIUtil#autoScaleImageData(..). > > The scaling method can be chosen explicitly with the command line parameter > -Dswt.autoScale.method=nearest > or > -Dswt.autoScale.method=smooth > > On GTK, this works fine, and the smooth scaling that is used by default for > fractional scale factors looks much better. > > But on Windows, I ran into huge trouble, see the FIXME in DPIUtil. > > Drawing of PNGs and GIFs seems to work differently, and both don't work as > they should. I didn't find any solution to make GC#drawImage(..) properly > draw onto a transparent base image. > > => We can't fix auto-scaling of images without a solution for this problem > on Windows. Any help would be appreciated. I'm out of ideas. Summarizing this issue Part1: - Markus had already initiated the work for the SMOOTH autoScale algorithm and bulk of the changes are already in the master via bug 493462. - SMOOTH autoScale algorithm doesn't give expected result on Windows and the specific limitations are mentioned in below gerrit patch, see the FIXME part: https://git.eclipse.org/r/#/c/70415/5/bundles/org.eclipse.swt/Eclipse+SWT/common/org/eclipse/swt/internal/DPIUtil.java Part2 of the issue, is regarding API change: Once we have sorted the issues with SMOOTH autoScale algorithm.. we can take a call on how to expose it as an API in SWT. [Note: ImageData.scaledTo() method is dedicated to nearest-neighbor scaling, so we will have to figure out a new API]
(In reply to Niraj Modi from comment #15) > Summarizing this issue Part1: > - Markus had already initiated the work for the SMOOTH autoScale algorithm > and bulk of the changes are already in the master via bug 493462. > - SMOOTH autoScale algorithm doesn't give expected result on Windows and the > specific limitations are mentioned in below gerrit patch, see the FIXME part: > https://git.eclipse.org/r/#/c/70415/5/bundles/org.eclipse.swt/Eclipse+SWT/common/org/eclipse/swt/internal/DPIUtil.java > Adding to Niraj's points: The SMOOTH scaling works on Linux/GTK. We need the SMOOTH scaling to work on Windows as well to provide a better scaling of Images at fractional scale factors such as 125% and 150%. Currently, SWT by default rounds-off all scale factors < 175% to 100%.
I don't have a clue on this bug, but I investigated bug 493455, which is the cause for the SMOOTH case in the DPIUtil not working for Windows. I found two problems, but only a solution for one.
(In reply to Conrad Groth from comment #17) > I don't have a clue on this bug, but I investigated bug 493455, which is the > cause for the SMOOTH case in the DPIUtil not working for Windows. I found > two problems, but only a solution for one. Thanks Conrad!
(In reply to Sravan Kumar Lakkimsetti from comment #6) > May be we can use gdk_pixbuf_scale_simple api for scaling on gtk and > stretchBlt api for windows. I used gdk_pixbuf_scale_simple with > GDK_INTERP_BILENEAR. the image quality is pretty good. > ... The windows StretchBlt function is already used in SWT for scaling. Unfortunately this function uses nearest-neighbor scaling.
Created attachment 272986 [details] The output of the SnippedScaling.java together with some AWT experiments
I tried to scale the images by AWT, as AWT offers biliniar and bicubic scaling. The output can be see in the attachment 272986 [details] together with the output of the original SnippetScaling.java (attachment 259133 [details]). I used the conversion methods provided by Snippet156 to convert SWT images to AWT images and vice versa. The first problem is that the transparency gets lost. Also the scaled images look very similar to the antialiased ones from SWT. I will not continue working on this issue. I just wanted to present my results.
Created attachment 272988 [details] The SnippetScaling enhanced by AWT scaling
Created attachment 284302 [details] Icon scaling demo java -jar icons-demo.jar IconsDemo.java source included in the JAR.
Created attachment 284303 [details] Icons demo at 125% screen
Created attachment 284304 [details] Icons demo at 150% screen
Created attachment 284305 [details] Icons demo at 200% screen
I see two distinct issues to this: 1. Icon scaling strategy Given there's a higher resolution variant available, it is always better to downscale from it to the target resolution. Try icons-demo.jar (attachment #284302 [details]) and compare some results: - 125% (attachment #284303 [details]) - 150% (attachment #284304 [details]) - 200% (attachment #284305 [details]) 2. General image (up)scaling Have you considered pixel-art scaling algorithms [1]? These usually have the constraint of scaling only to an integral factor but then I think using a smooth downscaling algorithm with a sharp pixel-art upscaled image produces quite satisfying results. So far I've found xBRZ [2] superior to others for its general results and for its alpha transparency handling. I've made a Java port [3] of it but I don't know if its licensing is suitable for direct use in Eclipse. Maybe if one could produce a formal specificaion of the algorithm it would alow for a clean-room implementations which might use different than GPL license. Otherwise see some of its results: 1x: https://raw.githubusercontent.com/stanio/xbrz-java/master/src/test/resources/net/sourceforge/xbrz/test/gbamockup.png 6x: https://raw.githubusercontent.com/stanio/xbrz-java/master/src/test/resources/net/sourceforge/xbrz/test/gbamockup%406xbrz.png 1x: https://raw.githubusercontent.com/stanio/xbrz-java/master/src/test/resources/net/sourceforge/xbrz/test/open-folder.png 6x: https://raw.githubusercontent.com/stanio/xbrz-java/master/src/test/resources/net/sourceforge/xbrz/test/open-folder%406xbrz.png [1] https://en.wikipedia.org/wiki/Pixel-art_scaling_algorithms [2] https://sourceforge.net/projects/xbrz/ [3] https://github.com/stanio/xbrz-java
Created attachment 288472 [details] Toolbar icons – Scaling factors and methods > 1. Icon scaling strategy > > Given there's a higher resolution variant available, it is always better to > downscale from it to the target resolution. Now that Bug 493455 is available in Eclipse 4.24M1, here's a visualization of current results – Eclipse upscaling the low-res variants compared to downscaling the hi-res variants (200%). As far as I can tell the latter produces better results even when using nearest-neighbor interpolation.