JDK-8090349 : Add property to control antialiasing of ImageView
  • Type: Enhancement
  • Component: javafx
  • Sub-Component: graphics
  • Affected Version: 8
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2011-02-26
  • Updated: 2021-04-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Blocks :  
Blocks :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
The smooth variable on ImageView only controls filtering when scaling the image itself up or down to fit in the ImageView. It does not control whether the image should be antialiased, for example, when rotating the image. This needs a new attribute on ImageView. See RT-6933 for a description of why this is the case.

Comments
Affected tests: JavaFXCompatibilityTestSuite/graphics/api/imageview/SmoothTest.java
01-11-2013

Some of it is out of date, for example, anything talking about the SG* objects, which were part of the long-defunct Swing/Scenario pipeline, but the basic idea for what is needed in Prism still holds. What we would eventually need for this is something that will control whether or not you want antialiasing on a per-edge basis. Possibly an AA mode switch (enum) with three values: ALL/NONE/EDGE where the latter would then pay attention to 4 booleans. We could also consider providing more than just on/off per edge (e.g., explicit clamping modes). We might want to consider for FX 8 just providing "ALL" or "NONE" as options and foregoing the per-edge control.
04-06-2013

The analysis from Chris Campbell is quite interesting but I wonder how much of it is still valid as a lot of the internals of JavaFX have probably changed since it was made.
04-06-2013

We might want the same rendering hints for ImageView that we are proposing for Shape in RT-6475
01-06-2013

Comment from RT-6933 (which is marked internal). This is from Chris Campbell: Here's the long (long, long) evaluation... The reason I've been slow to act on this is that there are two use cases here at odds with each other. A) The developer has two or more images, and he/she wants them all to be perfectly adjacent and stitched together without seams (as in the 3-slice example presented in this bug report). B) The developer has any number of images, and he/she will be rotating them and wants the edges to look smooth in a transformed context, not unlike how a Rectangle node has smooth edges when rotated. (See RT-5249.) In Sun's implementation of Java2D, our image transform loops lean towards use case (A), in that we do not antialias the edges of a transformed image, so adjacent images will be stitched together seamlessly. The downside of this is that rotated images have jaggy edges by default. See StitchAndSmooth_sun2d.png, attached. Note that Apple's implementation of Java2D optionally uses Quartz (well, currently it is on by default in their latest Java releases), which does antialias the edges of rotated images, as long as you set the ANTIALIAS_ON RenderingHint. (See the SmoothEdge.java testcase. SmoothEdge_quartz.png demonstrates that Apple's Quartz renderer does honor the ANTIALIASING RenderingHint, but SmoothEdge_sun2d.png shows that Sun's renderer does not.) So in the Swing-based JavaFX stack, running with Apple's Quartz renderer, you may or may not see smooth image edges depending on whether a shape node (with smooth=true) was rendered at some point prior to rendering the image node. See StitchAndSmooth_quartz.png, attached. Notice that rotated images have nicely smoothed edges, but that this causes visible seams between adjacent images. In Prism, as of the "fix" for RT-5249, we were leaning towards use case (B) and I hadn't taken use case (A) into account. My solution for providing smooth edges worked reasonably well for images with a simple rotation (no scale involved), but breaks down rather spectacularly for a large scale. See the StitchAndSmooth.fx testcase and StitchAndSmooth_prism_current.png, attached. Part of the problem is that I made CLAMP_TO_ZERO the default edge mode for all textures in Prism, which doesn't really cause problems under "normal" transforms, but as you can see in the StitchAndSmooth testcase, if you blow up a 2x2 image with a large scale factor (along with my solution for RT-5249) you will not get correct results, due to the way that OpenGL samples neighboring texels with GL_LINEAR filtering mode. As I mentioned earlier, there are two equally valid use cases here, but unfortunately they are at odds with each other. If we chose only one behavior, the other class of developers would be left in the cold. Normally I'd resist exposing API for something like this, but in this case I think the only way to please both camps is to expose a variable on ImageView and MediaView to allow the developer to choose the behavior best suited for a particular scenario. I recommend that this new flag be treated as a hint, as some platforms (e.g. mobile) might not be capable of image edge smoothing. I would also recommend that the flag be disabled by default, partially because the current Swing-based implementation of JavaFX does not smooth image edges (modulo the Quartz case, which is a mixed bag in its current state), and partially because there may be a significant performance cost in doing the edge smoothing, depending on the rendering backend, so this should really be an opt-in type of thing. It's tough to make an educated guess about which group is in the majority. Many developers care only about speed and want to fly some (possibly rotated) images around the screen and, because of the animation, don't care if the images have jaggy edges. Other developers, the Jaspers of the world :), care a lot about quality and want smooth edges, especially in static cases like in the Facebook demo from JavaOne, where the icons were portraits with a slight, random rotation. All the more reason to expose this as a switch at the API level. (I'll save my recommendations for the naming of this API for a separate discussion, because it's a bit convoluted due to the relationship with the existing "smooth" variable, which really controls the interpolation mode.) Trust me, this is all building up to a grand conclusion. Have patience, I'll get there eventually! Getting back to the original bug here, our first priority (based on the needs of the TV team) should be to fix Prism so that image transform behavior gets back closer to the current behavior of the Swing stack (and Sun's Java2D implementation). This will get the Prism stack back to a reasonable baseline (i.e., compatible with the Swing stack). In doing so, I plan to purposely break the image smoothing fix that I introduced with RT-5249, because it will make it easier to focus on getting Prism back to that baseline. As the second step, I will re-open RT-5249 (see also RT-5448) so that we can focus on the question of how to provide image edge smoothing for both the Swing and Prism stacks, and whether we will be providing new API to allow the developer to control this behavior. I should really save any further discussion of how to provide edge smoothing for RT-5249 or RT-5448, but since I'm on a roll... One possible solution would be to use TexturePaint (aka ImagePattern, in the case of Prism) to provide edge smoothing, as suggested in an older blog entry of mine: http://weblogs.java.net/blog/campbell/archive/2007/03/java_2d_tricker_1.html In other words, update NG{Image,Media}View and SG{Image,Media}View to render the image as a fillRect() operation with a TexturePaint/ImagePattern paint, with antialiasing enabled, if the edge smoothing flag is enabled. This approach would have to take the optional viewport (source region) into account. In the case of the Swing stack, this would imply BufferedImage.getSubimage(), which might defeat hardware acceleration of the TexturePaint operation. In the case of the Prism stack, we might be able to update the (Prism) ImagePattern implementation to allow for control of the source region, and update the ImagePattern shader to take this into account. If we go with this approach, we need to be careful to set the anchor rectangle (and/or source region) appropriately, otherwise you may see pixels from an opposite edge leak through due to TexturePaint's wrapping behavior. You can see this issue in the attached screenshots from the StitchAndSmooth, which demonstrate the use of the new ImagePattern API in FX. Another thing to consider is that, as mentioned earlier, Apple's Quartz-based renderer already does edge smoothing if you enable the ANTIALIAS_ON RenderingHint. So an alternate fix would be to detect that we're running on the Quartz renderer, and if so, simply set ANTIALIAS_ON if the edge smothing flag is enabled. I haven't measured it yet, but I would imagine that this approach would offer better performance than the TexturePaint trick on Apple's JDK. (Either way, I strongly recommend that we fix SG{Image,Media}View to *explicitly* set ANTIALIAS_OFF or ANTIALIAS_ON, depending on the edge smoothing flag, so that we get consistent behavior. As mentioned above, right now you may or may not get smooth edges when you are running on the Quartz renderer, depending on whether a shape node was rendered before the image node.)
01-06-2013