United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-8011764 : Drawing in the scaled VolatileImage is inaccurate.

Details
Type:
Bug
Submit Date:
2013-04-09
Status:
Closed
Updated Date:
2014-01-23
Project Name:
JDK
Resolved Date:
2013-10-07
Component:
client-libs
OS:
Sub-Component:
2d
CPU:
Priority:
P2
Resolution:
Not an Issue
Affected Versions:
7u40,8
Fixed Versions:
8

Related Reports
Relates:
Relates:

Sub Tasks

Description
Some rendering operations to the non-scaled BufferedImage and to the scaled VolatileImage is inconsistent. See example in the test.
                                    

Comments
Why do you consider this bug is not an issue? You did not leave any explanation of your decision in comments.
                                     
2013-10-31
Here are the relevant parts of an email conversation that I had with Sergey on the topic:

The problem is that the rendering is done with "stroke control" on. That setting allows us to perturb lines for quality purposes.  In the case of 1:1 rendering, that setting is important as it allows us to move the line by 1/2 a pixel to make it appear crisp, so regular non-retina 1:1 rendering of lines is already biased to "fake" coordinates.  With the advent of retina rendering at a 2:1 scale, integer lines are already crisp and require no bias to make them look nice and so the retina (full scale) rendering is actually correct whereas the non-retina rendering is a compromise that we've lived with for 20 years.

When you draw a line at point=1, then the line is a 1-pixel wide box centered on that coordinate and so it goes from 0.5 to 1.5.  Under AA we bump that up by half a pixel to 1.0 to 2.0 so that it isn't a 2-pixel wide and half-intensity line.  Under non-AA we bump it up by a different amount (I think the rounding factor is .25 pixels so that line widths grow evenly for lines on integer coordinates).

We specifically added the STROKE_CONTROL hints early on because of this issue that developers expected a line at x=1 to be "that pixel column that is separated from the edge of the drawable by a 1 pixel margin" even though the math would have it be a fractional coordinate straddling the edge of the pixels.

Under retina, the line would be at point=2 and it would extend twice as far (2 full pixels total width, so it extends 1.0 pixels on either side of the true coordinate) and so it actually a box from 1.0 to 3.0 and it is already on pixel boundaries so the line biasing code does not come into play for AA and I'd have to do the math, but it would probably also be off by a "retina pixel" on retina displays as well.

If you look at the full resolution image you see that the line drawn at x=1 is 1 pixel from the border and that is absolutely correct according to the geometry of drawing a 1-unit line on an integer coordinate in a scaled coordinate system.

Note that the down-scaled version of the retina image is performed with the default scaling algorithm which, I believe, is NEAREST_NEIGHBOR and so the pixels that end up in the final image are a subset of the pixels in the original image.  If the rounding went the other way, then there would be a pixel gap to the edge of the image in the down-sampled image because it would have chosen the first (green) pixel to include, and then the third (red) pixel.  But, given our default rounding that considers the edges of pixels to be included in the pixel that is below and to their right, sampling the full-res image at 1.0 chooses the second pixel instead, and we get no border.

So, the full res image shows what drawLines really truly should look like, and then when you combine that with the rounding choices made by the default algorithm, they conspire to produce a final image that has no gap at the left edge of the resulting down-scaled image.

The down-scaling algorithm can be specified by the KEY_INTERPOLATION hint, but the test case does not set any hints and relies on the defaults.  Unfortunately, there is no hint for "choose the pixels out of the image that would represent what we would have drawn at half the scale".
                                     
2013-10-31
Sergey, please comment
                                     
2013-10-31
Here, BitmapImage and a snapshot of a Volatile image, taken  with retina emulator, differ in similar fashion: line and oval are drawn one pixel off.
2D_VolatileImageTiger/TransparentVolatileImageTest
 
Expectedly, if you run DrawLineRound.java with scaling factor==1 instead of 2 on retina, it has exactly the same inaccuracy as with factor 2. 

2D_Image/ArcScale
2D_Image/FLoopScale
2D_Image/OvalScale
2D_Image/RectScale
2D_Image/RoundRectScale
                                     
2013-05-28
Looks like the problem in the PixelToParallelogramConverter.drawGeneralLine.
Possibly PixelToParallelogramConverter.normalize should take into account current scale of the graphics?
                                     
2013-04-09



Hardware and Software, Engineered to Work Together