1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.effect;
  27 
  28 import javafx.beans.property.DoubleProperty;
  29 import javafx.beans.property.DoublePropertyBase;
  30 import javafx.beans.property.ObjectProperty;
  31 import javafx.scene.Node;
  32 
  33 import com.sun.javafx.util.Utils;
  34 import com.sun.javafx.effect.EffectDirtyBits;
  35 import com.sun.javafx.geom.BaseBounds;
  36 import com.sun.javafx.geom.transform.BaseTransform;
  37 import com.sun.javafx.scene.BoundsAccessor;
  38 
  39 
  40 /**
  41  * An effect that allows for per-pixel adjustments of hue, saturation,
  42  * brightness, and contrast.
  43  *
  44  * <p>
  45  * Example:
  46  * <pre><code>
  47  * ColorAdjust colorAdjust = new ColorAdjust();
  48  * colorAdjust.setContrast(0.1);
  49  * colorAdjust.setHue(-0.05);
  50  * colorAdjust.setBrightness(0.1);
  51  * colorAdjust.setSaturation(0.2);
  52  *
  53  * Image image = new Image("boat.jpg");
  54  * ImageView imageView = new ImageView(image);
  55  * imageView.setFitWidth(200);
  56  * imageView.setPreserveRatio(true);
  57  * imageView.setEffect(colorAdjust);
  58  * </pre></code>
  59  * <p> The code above applied on this image: </p>
  60  * <p>
  61  * <img src="doc-files/photo.png"/>
  62  * </p>
  63  * <p> produces the following: </p>
  64  * <p>
  65  * <img src="doc-files/coloradjust.png"/>
  66  * </p>
  67  * @since JavaFX 2.0
  68  */
  69 public class ColorAdjust extends Effect {
  70     /**
  71      * Creates a new instance of ColorAdjust with default parameters.
  72      */
  73     public ColorAdjust() {}
  74 
  75     /**
  76      * Creates a new instance of ColorAdjust with the specified hue, saturation,
  77      * brightness, and contrast.
  78      * @param hue the hue adjustment value
  79      * @param saturation the saturation adjustment value
  80      * @param brightness the brightness adjustment value
  81      * @param contrast the contrast adjustment value
  82      * @since JavaFX 2.1
  83      */
  84     public ColorAdjust(double hue,
  85                        double saturation,
  86                        double brightness,
  87                        double contrast) {
  88         setBrightness(brightness);
  89         setContrast(contrast);
  90         setHue(hue);
  91         setSaturation(saturation);
  92     }
  93 
  94     @Override
  95     com.sun.scenario.effect.ColorAdjust impl_createImpl() {
  96         return new com.sun.scenario.effect.ColorAdjust();
  97     };
  98     /**
  99      * The input for this {@code Effect}.
 100      * If set to {@code null}, or left unspecified, a graphical image of
 101      * the {@code Node} to which the {@code Effect} is attached will be
 102      * used as the input.
 103      * @defaultValue null
 104      */
 105     private ObjectProperty<Effect> input;
 106 
 107 
 108     public final void setInput(Effect value) {
 109         inputProperty().set(value);
 110     }
 111 
 112     public final Effect getInput() {
 113         return input == null ? null : input.get();
 114     }
 115 
 116     public final ObjectProperty<Effect> inputProperty() {
 117         if (input == null) {
 118             input = new EffectInputProperty("input");
 119         }
 120         return input;
 121     }
 122 
 123     @Override
 124     boolean impl_checkChainContains(Effect e) {
 125         Effect localInput = getInput();
 126         if (localInput == null)
 127             return false;
 128         if (localInput == e)
 129             return true;
 130         return localInput.impl_checkChainContains(e);
 131     }
 132 
 133     /**
 134      * The hue adjustment value.
 135      * <pre>
 136      *       Min: -1.0
 137      *       Max: +1.0
 138      *   Default:  0.0
 139      *  Identity:  0.0
 140      * </pre>
 141      * @defaultValue 0.0
 142      */
 143     private DoubleProperty hue;
 144 
 145 
 146     public final void setHue(double value) {
 147         hueProperty().set(value);
 148     }
 149 
 150     public final double getHue() {
 151         return hue == null ? 0 : hue.get();
 152     }
 153 
 154     public final DoubleProperty hueProperty() {
 155         if (hue == null) {
 156             hue = new DoublePropertyBase() {
 157 
 158                 @Override
 159                 public void invalidated() {
 160                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 161                     effectBoundsChanged();
 162                 }
 163 
 164                 @Override
 165                 public Object getBean() {
 166                     return ColorAdjust.this;
 167                 }
 168 
 169                 @Override
 170                 public String getName() {
 171                     return "hue";
 172                 }
 173             };
 174         }
 175         return hue;
 176     }
 177 
 178     /**
 179      * The saturation adjustment value.
 180      * <pre>
 181      *       Min: -1.0
 182      *       Max: +1.0
 183      *   Default:  0.0
 184      *  Identity:  0.0
 185      * </pre>
 186      * @defaultValue 0.0
 187      */
 188     private DoubleProperty saturation;
 189 
 190 
 191     public final void setSaturation(double value) {
 192         saturationProperty().set(value);
 193     }
 194 
 195     public final double getSaturation() {
 196         return saturation == null ? 0 : saturation.get();
 197     }
 198 
 199     public final DoubleProperty saturationProperty() {
 200         if (saturation == null) {
 201             saturation = new DoublePropertyBase() {
 202 
 203                 @Override
 204                 public void invalidated() {
 205                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 206                     effectBoundsChanged();
 207                 }
 208 
 209                 @Override
 210                 public Object getBean() {
 211                     return ColorAdjust.this;
 212                 }
 213 
 214                 @Override
 215                 public String getName() {
 216                     return "saturation";
 217                 }
 218             };
 219         }
 220         return saturation;
 221     }
 222 
 223     /**
 224      * The brightness adjustment value.
 225      * <pre>
 226      *       Min: -1.0
 227      *       Max: +1.0
 228      *   Default:  0.0
 229      *  Identity:  0.0
 230      * </pre>
 231      * @defaultValue 0.0
 232      */
 233     private DoubleProperty brightness;
 234 
 235 
 236     public final void setBrightness(double value) {
 237         brightnessProperty().set(value);
 238     }
 239 
 240     public final double getBrightness() {
 241         return brightness == null ? 0 : brightness.get();
 242     }
 243 
 244     public final DoubleProperty brightnessProperty() {
 245         if (brightness == null) {
 246             brightness = new DoublePropertyBase() {
 247 
 248                 @Override
 249                 public void invalidated() {
 250                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 251                     effectBoundsChanged();
 252                 }
 253 
 254                 @Override
 255                 public Object getBean() {
 256                     return ColorAdjust.this;
 257                 }
 258 
 259                 @Override
 260                 public String getName() {
 261                     return "brightness";
 262                 }
 263             };
 264         }
 265         return brightness;
 266     }
 267 
 268     /**
 269      * The contrast adjustment value.
 270      * <pre>
 271      *       Min: -1.0
 272      *       Max: +1.0
 273      *   Default:  0.0
 274      *  Identity:  0.0
 275      * </pre>
 276      * @defaultValue 0.0
 277      */
 278     private DoubleProperty contrast;
 279 
 280 
 281     public final void setContrast(double value) {
 282         contrastProperty().set(value);
 283     }
 284 
 285     public final double getContrast() {
 286         return contrast == null ? 0 : contrast.get();
 287     }
 288 
 289     public final DoubleProperty contrastProperty() {
 290         if (contrast == null) {
 291             contrast = new DoublePropertyBase() {
 292 
 293                 @Override
 294                 public void invalidated() {
 295                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 296                     effectBoundsChanged();
 297                 }
 298 
 299                 @Override
 300                 public Object getBean() {
 301                     return ColorAdjust.this;
 302                 }
 303 
 304                 @Override
 305                 public String getName() {
 306                     return "contrast";
 307                 }
 308             };
 309         }
 310         return contrast;
 311     }
 312 
 313     @Override
 314     void impl_update() {
 315         Effect localInput = getInput();
 316         if (localInput != null) {
 317             localInput.impl_sync();
 318         }
 319 
 320         com.sun.scenario.effect.ColorAdjust peer =
 321                 (com.sun.scenario.effect.ColorAdjust) impl_getImpl();
 322         peer.setInput(localInput == null ? null : localInput.impl_getImpl());
 323         peer.setHue((float)Utils.clamp(-1, getHue(), 1));
 324         peer.setSaturation((float)Utils.clamp(-1, getSaturation(), 1));
 325         peer.setBrightness((float)Utils.clamp(-1, getBrightness(), 1));
 326         peer.setContrast((float)Utils.clamp(-1, getContrast(), 1));
 327     }
 328 
 329     /**
 330      * @treatAsPrivate implementation detail
 331      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 332      */
 333     @Deprecated
 334     @Override
 335     public BaseBounds impl_getBounds(BaseBounds bounds,
 336                                      BaseTransform tx,
 337                                      Node node,
 338                                      BoundsAccessor boundsAccessor) {
 339         return getInputBounds(bounds, tx, node, boundsAccessor, getInput());
 340     }
 341 
 342     /**
 343      * @treatAsPrivate implementation detail
 344      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 345      */
 346     @Deprecated
 347     @Override
 348     public Effect impl_copy() {
 349         ColorAdjust ca = new ColorAdjust(this.getHue(), this.getSaturation(),
 350                 this.getBrightness(), this.getContrast());
 351         ca.setInput(ca.getInput());
 352         return ca;
 353     }
 354 }