views:

525

answers:

1

Why does the following code lead to a blocky gradient? i.e. the gradient is not smooth, you can see some of the rectangles that make it up.

Is there a way to fix this?
BTW I'm running this on Vista, but I've also experienced this on a Mac as well.

var stage:Stage = Stage {
title: "Louis' Photo Wall"
width: 900
height: 600

scene: Scene {
    content : Rectangle {
        width:  bind stage.scene.width
        height: bind stage.scene.height
        fill:LinearGradient {
            startX : 0.0
            startY : 0.0
            endX : 0.0
            endY : 1.0
            stops: [
                Stop {
                    color : Color {
                        red:0.0
                        blue:0.0
                        green:0.0
                    }

                    offset: 0.0
                },
                Stop {
                    color : Color {
                        red:0.8
                        blue:0.8
                        green:0.8
                    }
                    offset: 1.0
                },

            ]
        }

    }//OuterRectangle
}

}

+1  A: 

The blocky amount is not dramatic.

Shifting to a endX of 1.0 seems to give a more obvious variation with a diagonalization of the blocky result.

A hypothesis is that a couple of things are going on. 1. A r/g/b color is not really continuous, but has 256 steps. (8 bits). A 0.8 of 255 is 204. 2. When one maps from 0 to 0.8 for a color into 600 pixels, one gets an increment per pixel that cannot be completely smooth. The scene size is actually 792x566 when I make a run. So the gradient would use has 566/204 = 2.775 pixels for one color before shifting to the next. That causes fluctuation where transitions are made.

This doesn't explain why using 0.0 to 1.0 for the stops (instead of 0.0 to 0.8) results (at least in my runs) with what seems to be a smooth transition.


Follow-up: There is an ofTheWay method that LinearGradient probably uses for interpolation. A code example and results...

for (v in [0.00..1.00 step 1.0/600]) {
   println("{%7.5f v} {Color.WHITE.ofTheWay(Color.BLACK,v)}");
}

which prints

0.00000 javafx.scene.paint.Color[red=255,green=255,blue=255,opacity=1.0]
0.00167 javafx.scene.paint.Color[red=255,green=255,blue=255,opacity=1.0]
0.00333 javafx.scene.paint.Color[red=254,green=254,blue=254,opacity=1.0]
0.00500 javafx.scene.paint.Color[red=254,green=254,blue=254,opacity=1.0]
0.00667 javafx.scene.paint.Color[red=253,green=253,blue=253,opacity=1.0]
0.00833 javafx.scene.paint.Color[red=253,green=253,blue=253,opacity=1.0]
0.01000 javafx.scene.paint.Color[red=252,green=252,blue=252,opacity=1.0]
0.01167 javafx.scene.paint.Color[red=252,green=252,blue=252,opacity=1.0]
0.01333 javafx.scene.paint.Color[red=252,green=252,blue=252,opacity=1.0]
0.01500 javafx.scene.paint.Color[red=251,green=251,blue=251,opacity=1.0]
0.01667 javafx.scene.paint.Color[red=251,green=251,blue=251,opacity=1.0]
...
Refactor
Examination of the actual colors present (from the viewpoint of JavaFX) on the gradient shows 2 to 5 occurrences of each specific color level. So the bands present are 2 pixels to 5 pixels high for the stage height in use.
Refactor