Monday, August 20, 2012

Beach coding...

Aloha everyone,
back home after two weeks in Greece being completely offline (I had to promise my wife that I do not take any electronical equipment with me). Feels good to be connected again.
Because I had no electronic device with me I decided to take my Devoxx notebook and a pen with me. And in fact I've found some time to do some beach coding and here is the result...


As you could (hopefully) read it's about an elliptical gradient. This was something I would like to do for a while and now finally did it. Unfortunately it was not as much work as I first thought.
The biggest challenge was to remember some mathematics without the chance to check it on the web...but as I've transfered the "beach code" to real java code and the result I've got was like this...


Again I have used the WritableImage and PixelWriter feature of JavaFX 2.2 to generate this elliptical gradient. Sometimes this elliptical gradient could be useful to visualize lights etc. so it's up to your creativity...
I've compared the gradient to the elliptical gradient that could be generated in Adobe Fireworks and it seems that they are a bit different. I did not found the time to figure out the details but as soon as I know I will let you know.

The code to create this gradient is really simple, you loop over each pixel in the WriteableImage and simply check if the current point is within the ellipse or not. If it is in the ellipse you just simply calculate the distance from the center and normalize it to one. The result could be used to lookup the color in a given gradient.

This is the code to generate a simple two color gradient...

Stop[] stops    = {
  new Stop(0.0, Color.RED), 
  new Stop(1.0, Color.BLUE)
};
int     width   = 500;
int     height  = 200;
double  a       = width / 2.0;
double  aSquare = a * a;
double  b       = height / 2.0;
double  bSquare = b * b;

WritableImage raster      = new WritableImage(width, height);
PixelWriter   pixelWriter = raster.getPixelWriter();

double isInside;
for (int y = 0 ; y < height ; y++) {
  for (int x = 0 ; x < width ; x++) {
    isInside = ((x - a) * (x - a)) / aSquare + 
               ((y - b) * (y - b)) / bSquare;
    isInside = isInside > 1 ? 1 : isInside;
    Color color = interpolateColor(stops[0].getColor(), 
                                   stops[1].getColor(),
                                   isInside);
    pixelWriter.setColor(x, y, color);
  }
}

// now raster contains the following gradient

A the end raster contains the following image... 



The code of the interpolateColor() method is like follows...

private Color interpolateColor(Color c1, Color c2, double frac) {
  frac = frac < 0 ? 0 : (frac > 1 ? 1 : frac);
  double red   = 
      c1.getRed()+(c2.getRed()-c1.getRed())*frac;
  double green = 
      c1.getGreen()+(c2.getGreen()-c1.getGreen())*frac;
  double blue  = 
      c1.getBlue()+(c2.getBlue()-c1.getBlue())*frac;
  double alpha = 
      c1.getOpacity()+(c2.getOpacity()-c1.getOpacity())*frac;
  return new Color(red, green, blue, alpha);
}

In the code you could download further down I've implemented a version that is able to create multicolor gradients too. This code is also part of the JFXtras labs util package.

Grab the source here.

So that's it for today...nothing special but again fun...keep coding...

3 comments:

  1. LOL. Had to promise the same, but I negotiated that I could bring the netbook. Can't code on that, but not completely offline.

    ReplyDelete
  2. JavaFX has built-in Interpolator instances and Color implements Interpolatable, so you can easily use different kinds of interpolation (such as EASE_BOTH to give a smooth gradient, DISCRETE to give a hard edged gradient or LINEAR to get the same effect as the posted interpolation function) if you replace the interpolateColor function call with color = (Color) Interpolator.LINEAR.interpolate(sortedStops.get(i).getColor(), sortedStops.get(i + 1).getColor(), fraction)

    ReplyDelete
    Replies
    1. You're right, somehow I missed that one (I think I've used my own implementation too often).
      Thanx for the useful hint,

      Cheers,

      Gerrit

      Delete