# Draw a smooth color scale and assign specific values to it

### Question

I'm considering a new way of implementation a simple 2D graphical matrix, where colors of its items depend on individual values assigned to those items. So far, I used for this purpose a following schema:

1) Provide an interval-based color scale reference (builded of, say, 20 blocks), to which I could assign specific range of values, e.g. 100-1000.

2) Link matrix items individual values with colors from the scale mentioned above, thus item with value 100 will be e.g `BLUE`, and item with value 1000 will be `RED`.

The problem with such solution, is that I had to build my color scale from "blocks", and so it looks like this: This solution is not so bad, but I want to go further, and implement much accurate `value-color` matching with help of color scale as showed below: Next, there will be nothing so much different of the drill described above. I will "put" this scale between values of given range (e.g. 100-1000), and depend on the individual value of the matrix item, I'll pick proper color from the scale and assign it to the given item.

But how could I draw such scale and put it in a range of a specific values trying to avoid `ItemValue-To-SpecificColorBlock` matching problem from my old solution?

1
3
8/9/2014 1:55:27 AM

In statistics (visualization) this is called a heat map.

To compute the color for a given value, with MIN <= value < MAX, I would interpolate it onto the range Color.BLUE.getHue() - Color.RED.getHue().

i.e.

``````double hue = Color.BLUE.getHue() + (Color.RED.getHue() - Color.BLUE.getHue()) * (value - MIN) / (MAX - MIN) ;
``````

Then use the hue to create the color with full saturation and brightness:

``````Color color = Color.hsb(hue, 1.0, 1.0);
``````

To create the color scale image, create a WritableImage, grab the pixel writer, iterate over all pixels, and set the color of each pixel using the formula above with the value interpolated along the x axis from 0 to the width of the image. (If you want a vertical color scale, similarly interpolate along the y-axis.)

Here's an example which draws the color scale. You can use the `getColorForValue(...)` method to compute the color for a given value, for displaying the matrix.

``````import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class HeatMap extends Application {

private final static double MIN = 100 ;
private final static double MAX = 1000 ;
private final static double BLUE_HUE = Color.BLUE.getHue() ;
private final static double RED_HUE = Color.RED.getHue() ;

@Override
public void start(Stage primaryStage) {
Image colorScale = createColorScaleImage(600, 120, Orientation.HORIZONTAL);
ImageView imageView = new ImageView(colorScale);
StackPane root = new StackPane(imageView);
Scene scene = new Scene(root, 800, 400);
primaryStage.setScene(scene);
primaryStage.show();
}

private Color getColorForValue(double value) {
if (value < MIN || value > MAX) {
return Color.BLACK ;
}
double hue = BLUE_HUE + (RED_HUE - BLUE_HUE) * (value - MIN) / (MAX - MIN) ;
return Color.hsb(hue, 1.0, 1.0);
}

private Image createColorScaleImage(int width, int height, Orientation orientation) {
WritableImage image = new WritableImage(width, height);
PixelWriter pixelWriter = image.getPixelWriter();
if (orientation == Orientation.HORIZONTAL) {
for (int x=0; x<width; x++) {
double value = MIN + (MAX - MIN) * x / width;
Color color = getColorForValue(value);
for (int y=0; y<height; y++) {
pixelWriter.setColor(x, y, color);
}
}
} else {
for (int y=0; y<height; y++) {
double value = MAX - (MAX - MIN) * y / height ;
Color color = getColorForValue(value);
for (int x=0; x<width; x++) {
pixelWriter.setColor(x, y, color);
}
}
}
return image ;
}

public static void main(String[] args) {
launch(args);
}
}
``````
7
8/9/2014 2:57:41 AM