javafx - How to use ColorAdjust to set a target Color? -


situation

i have image circle filled radial gradient ranges white black/transparency. serves particle , needs colorized during lifecycle.

problem

i'm using coloradjust apply different colors image. problem colors aren't way want them be. if use green target color, pink ball.

question

how calculate coloradjust's hue value match given target color? or there better way colorize images? can't use shape because using imageview way faster using shape.

code

here's code. problem hue difference current color:

import javafx.application.application; import javafx.scene.node; import javafx.scene.scene; import javafx.scene.snapshotparameters; import javafx.scene.effect.coloradjust; import javafx.scene.image.image; import javafx.scene.image.imageview; import javafx.scene.image.writableimage; import javafx.scene.layout.hbox; import javafx.scene.paint.color; import javafx.scene.paint.cyclemethod; import javafx.scene.paint.radialgradient; import javafx.scene.paint.stop; import javafx.scene.shape.circle; import javafx.stage.stage;   public class main extends application {      @override     public void start(stage primarystage) {              hbox root = new hbox();              // create alpha masked image             image image = createimage(createalphamaskedball(200));              // create original imageview             imageview original = new imageview( image);              // create imageview color adjustment             imageview modified = new imageview( image);              // coloradjust effect             coloradjust coloradjust = new coloradjust();              // set saturation 1, otherwise hue won't have effect             coloradjust.setsaturation(1);               // define target color             color targetcolor = color.green;               // calculate hue: map [0,360] [-1,1]; todo: here's problem             double hue = map( targetcolor.gethue(), 0, 360, -1, 1);              coloradjust.sethue(hue);               // apply color adjustment             modified.seteffect(coloradjust);              root.getchildren().addall( original, modified);              scene scene = new scene(root,1024,500, color.black);             primarystage.setscene(scene);             primarystage.show();      }      /**      * snapshot image out of node, consider transparency.      * @param node      * @return      */     public static image createimage( node node) {          writableimage wi;          snapshotparameters parameters = new snapshotparameters();         parameters.setfill(color.transparent);           int imagewidth = (int) node.getboundsinlocal().getwidth();         int imageheight = (int) node.getboundsinlocal().getheight();          wi = new writableimage( imagewidth, imageheight);         node.snapshot(parameters, wi);          return wi;      }         /**      * create alpha masked ball gradient colors white black/transparent. used e. g. particles.      *      * @param radius      * @return      */     public static node createalphamaskedball( double radius) {          circle ball = new circle(radius);          radialgradient gradient1 = new radialgradient(0,             .1,             0,             0,             radius,             false,             cyclemethod.no_cycle,             new stop(0, color.white.derivecolor(1,1,1,1)),             new stop(1, color.black.derivecolor(1,1,1,0)));          ball.setfill(gradient1);          return ball;     }     public static double map(double value, double start, double stop, double targetstart, double targetstop) {         return targetstart + (targetstop - targetstart) * ((value - start) / (stop - start));    }      public static void main(string[] args) {         launch(args);     } } 

and screenshot:

enter image description here

thank help!


edit:

solution

working extended version rgb sliders , josé's solution applied, ones who'd toy around it:

import javafx.application.application; import javafx.beans.value.changelistener; import javafx.beans.value.observablevalue; import javafx.event.actionevent; import javafx.event.eventhandler; import javafx.geometry.insets; import javafx.scene.node; import javafx.scene.scene; import javafx.scene.snapshotparameters; import javafx.scene.control.combobox; import javafx.scene.control.contentdisplay; import javafx.scene.control.label; import javafx.scene.control.listcell; import javafx.scene.control.listview; import javafx.scene.control.slider; import javafx.scene.effect.coloradjust; import javafx.scene.image.image; import javafx.scene.image.imageview; import javafx.scene.image.writableimage; import javafx.scene.layout.borderpane; import javafx.scene.layout.gridpane; import javafx.scene.layout.hbox; import javafx.scene.paint.color; import javafx.scene.paint.cyclemethod; import javafx.scene.paint.radialgradient; import javafx.scene.paint.stop; import javafx.scene.shape.circle; import javafx.scene.shape.rectangle; import javafx.stage.stage; import javafx.util.callback;  /**  * modify coloradjust given target color matched.  */ public class main extends application {      color[] presetcolors = new color[] {color.red, color.green, color.blue, color.yellow, color.magenta, color.cyan, color.dodgerblue, color.lightgrey, color.darkgray, color.black, color.white, color.brown};      color targetcolor;      rectangle referencecolorrectangle; // display target color reference (rgb)      coloradjust coloradjust;     slider redslider;     slider greenslider;     slider blueslider;     combobox<color> colorcombobox;      @override     public void start(stage primarystage) {              borderpane root = new borderpane();              // content             // -------------------------              hbox content = new hbox();             content.setstyle("-fx-background-color:black");              // create alpha masked image             image image = createimage(createalphamaskedball(100));              // create original imageview             imageview original = new imageview( image);              // create imageview color adjustment             imageview modified = new imageview( image);              // coloradjust effect             coloradjust = new coloradjust();             modified.seteffect(coloradjust);              content.getchildren().addall( original, modified);              // toolbar             // -------------------------             gridpane toolbar = new gridpane();              // presets: show colors rectangles in combobox list, hex color in combobox selection             colorcombobox = new combobox<>();             colorcombobox.getitems().addall( presetcolors);              colorcombobox.setonaction(new eventhandler<actionevent>() {                  @override                 public void handle(actionevent event) {                      updatesliders();                  }              });             colorcombobox.setcellfactory(new callback<listview<color>, listcell<color>>() {                 @override                 public listcell<color> call(listview<color> p) {                   return new listcell<color>() {                     private final rectangle rectangle;                     {                       setcontentdisplay(contentdisplay.graphic_only);                       rectangle = new rectangle(100, 10);                     }                      @override                     protected void updateitem(color item, boolean empty) {                       super.updateitem(item, empty);                        if (item == null || empty) {                         setgraphic(null);                       } else {                         rectangle.setfill(item);                         setgraphic(rectangle);                       }                     }                   };                 }               });              // sliders, value initialized later             redslider = createslider( 0,255, 0);             greenslider = createslider( 0,255, 0);             blueslider = createslider( 0,255, 0);              // reference rectangle in rgb             referencecolorrectangle = new rectangle( 0, 0, 100, 100);             referencecolorrectangle.setstroke(color.black);              // listener: new target color sliders , apply              changelistener<number> listener = new changelistener<number>() {                  @override                 public void changed(observablevalue<? extends number> observable, number oldvalue, number newvalue) {                      updatecolor();                  }              };               redslider.valueproperty().addlistener(listener);             greenslider.valueproperty().addlistener(listener);             blueslider.valueproperty().addlistener(listener);              // add nodes gridpane             toolbar.addrow(0, new label( "preset"), colorcombobox);             toolbar.addrow(1, new label( "red"), redslider);             toolbar.addrow(2, new label( "green"), greenslider);             toolbar.addrow(3, new label( "blue"), blueslider);              toolbar.add(referencecolorrectangle, 2, 0, 1, 4);              // margin gridpane nodes             for( node node: toolbar.getchildren()) {                 gridpane.setmargin(node, new insets(5,5,5,5));             }              // layout             root.settop(toolbar);             root.setcenter(content);              // create scene             scene scene = new scene(root,800,400, color.black);              primarystage.setscene(scene);             primarystage.show();              // set height of combobox list             colorcombobox.lookup(".list-view").setstyle("-fx-pref-height: 200");              // select 1st color , implicitly initialize sliders , colors             colorcombobox.getselectionmodel().selectfirst();      }      private void updatecolor() {          // create target color         targetcolor = color.rgb( (int) redslider.getvalue(), (int) greenslider.getvalue(), (int) blueslider.getvalue());          // update reference         referencecolorrectangle.setfill(targetcolor);          // update coloradjust         // see http://stackoverflow.com/questions/31587092/how-to-use-coloradjust-to-set-a-target-color         double hue = map( (targetcolor.gethue() + 180) % 360, 0, 360, -1, 1);         coloradjust.sethue(hue);          // use saturation         double saturation = targetcolor.getsaturation();         coloradjust.setsaturation(saturation);          // use white in masked ball creation => inverse brightness         double brightness = map( targetcolor.getbrightness(), 0, 1, -1, 0);         coloradjust.setbrightness(brightness);          // system.out.println("target color: " + targetcolor + ", hue 0..360: " + targetcolor.gethue() + ", hue 0..1: " + hue);      }      private void updatesliders() {          color referencecolor = colorcombobox.getvalue();          redslider.setvalue( map( referencecolor.getred(), 0, 1, 0, 255));         greenslider.setvalue( map( referencecolor.getgreen(), 0, 1, 0, 255));         blueslider.setvalue( map( referencecolor.getblue(), 0, 1, 0, 255));      }      private slider createslider( double min, double max, double value) {          slider slider = new slider( min, max, value);         slider.setprefwidth(600);         slider.setshowticklabels(true);         slider.setshowtickmarks(true);          return slider;     }      /**      * snapshot image out of node, consider transparency.      * @param node      * @return      */     public static image createimage( node node) {          writableimage wi;          snapshotparameters parameters = new snapshotparameters();         parameters.setfill(color.transparent);           int imagewidth = (int) node.getboundsinlocal().getwidth();         int imageheight = (int) node.getboundsinlocal().getheight();          wi = new writableimage( imagewidth, imageheight);         node.snapshot(parameters, wi);          return wi;      }         /**      * create alpha masked ball gradient colors white black/transparent. used e. g. particles.      *      * @param radius      * @return      */     public static node createalphamaskedball( double radius) {          circle ball = new circle(radius);          radialgradient gradient1 = new radialgradient(0,             0,             0,             0,             radius,             false,             cyclemethod.no_cycle,             new stop(0, color.white.derivecolor(1,1,1,1)),             new stop(1, color.white.derivecolor(1,1,1,0)));          ball.setfill(gradient1);          return ball;     }     public static double map(double value, double start, double stop, double targetstart, double targetstop) {         return targetstart + (targetstop - targetstart) * ((value - start) / (stop - start));    }      public static void main(string[] args) {         launch(args);     } } 

enter image description here

or short version of solution:

double hue = map( (targetcolor.gethue() + 180) % 360, 0, 360, -1, 1); coloradjust.sethue(hue);  // use saturation double saturation = targetcolor.getsaturation(); coloradjust.setsaturation(saturation);  // use white in masked ball creation => inverse brightness double brightness = map( targetcolor.getbrightness(), 0, 1, -1, 0); coloradjust.setbrightness(brightness); 

if have @ color on center of circle (for pure white, 100% opacity), result of applying coloradust effect, have magenta #ff00ffff.

the color applying has hue value of 120 (color.green.gethue()), , if create color:

color color = color.hsb(120,1,1); system.out.println(color); 

it print #00ff00ff, green (100% opacity), , precisely opposite color in terms of r,g,b.

based on this, other way around: if want green result, need set inital color magenta, hue value of 300:

targetcolor = color.web("#ff00ffff"); 

if have on color wheel:

color hue

you notice diametrically opposite colors, separated 180º.

so general rule can add 180º hue color want display.

double hue = map( targetcolor.gethue()+180, 0, 360, -1, 1); 

in test i've added slider check it:

enter image description here


Comments

Popular posts from this blog

javascript - Karma not able to start PhantomJS on Windows - Error: spawn UNKNOWN -

Nuget pack csproj using nuspec -

c# - Display ASPX Popup control in RowDeleteing Event (ASPX Gridview) -