13dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta/*
23dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * Copyright (C) 2014 The Android Open Source Project
33dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta *
43dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License");
53dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * you may not use this file except in compliance with the License.
63dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * You may obtain a copy of the License at
73dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta *
83dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta *      http://www.apache.org/licenses/LICENSE-2.0
93dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta *
103dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software
113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS,
123dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * See the License for the specific language governing permissions and
143dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * limitations under the License.
153dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta */
163dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
173dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptapackage android.graphics;
183dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
193dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.Composite;
203dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.CompositeContext;
213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.RenderingHints;
223dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.image.ColorModel;
233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.image.DataBuffer;
243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.image.Raster;
253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptaimport java.awt.image.WritableRaster;
263dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
273dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta/*
283dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * (non-Javadoc)
293dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * The class is adapted from a demo tool for Blending Modes written by
303dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * Romain Guy (romainguy@android.com). The tool is available at
313dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta * http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/
323dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta */
333dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Guptapublic final class BlendComposite implements Composite {
343dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public enum BlendingMode {
353dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        NORMAL,
363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        AVERAGE,
373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        MULTIPLY,
383dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        SCREEN,
393dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        DARKEN,
403dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        LIGHTEN,
413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        OVERLAY,
423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        HARD_LIGHT,
433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        SOFT_LIGHT,
443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        DIFFERENCE,
453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        NEGATION,
463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        EXCLUSION,
473dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        COLOR_DODGE,
483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        INVERSE_COLOR_DODGE,
493dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        SOFT_DODGE,
503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        COLOR_BURN,
513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        INVERSE_COLOR_BURN,
523dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        SOFT_BURN,
533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        REFLECT,
543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        GLOW,
553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        FREEZE,
563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        HEAT,
573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        ADD,
583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        SUBTRACT,
593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        STAMP,
603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        RED,
613dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        GREEN,
623dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        BLUE,
633dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        HUE,
643dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        SATURATION,
653dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        COLOR,
663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        LUMINOSITY
673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
693dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Normal = new BlendComposite(BlendingMode.NORMAL);
703dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Average = new BlendComposite(BlendingMode.AVERAGE);
713dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Multiply = new BlendComposite(BlendingMode.MULTIPLY);
723dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Screen = new BlendComposite(BlendingMode.SCREEN);
733dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Darken = new BlendComposite(BlendingMode.DARKEN);
743dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Lighten = new BlendComposite(BlendingMode.LIGHTEN);
753dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Overlay = new BlendComposite(BlendingMode.OVERLAY);
763dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite HardLight = new BlendComposite(BlendingMode.HARD_LIGHT);
773dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite SoftLight = new BlendComposite(BlendingMode.SOFT_LIGHT);
783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Difference = new BlendComposite(BlendingMode.DIFFERENCE);
793dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Negation = new BlendComposite(BlendingMode.NEGATION);
803dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Exclusion = new BlendComposite(BlendingMode.EXCLUSION);
813dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite ColorDodge = new BlendComposite(BlendingMode.COLOR_DODGE);
823dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite InverseColorDodge = new BlendComposite(BlendingMode.INVERSE_COLOR_DODGE);
833dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite SoftDodge = new BlendComposite(BlendingMode.SOFT_DODGE);
843dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite ColorBurn = new BlendComposite(BlendingMode.COLOR_BURN);
853dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite InverseColorBurn = new BlendComposite(BlendingMode.INVERSE_COLOR_BURN);
863dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite SoftBurn = new BlendComposite(BlendingMode.SOFT_BURN);
873dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Reflect = new BlendComposite(BlendingMode.REFLECT);
883dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Glow = new BlendComposite(BlendingMode.GLOW);
893dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Freeze = new BlendComposite(BlendingMode.FREEZE);
903dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Heat = new BlendComposite(BlendingMode.HEAT);
913dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Add = new BlendComposite(BlendingMode.ADD);
923dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Subtract = new BlendComposite(BlendingMode.SUBTRACT);
933dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Stamp = new BlendComposite(BlendingMode.STAMP);
943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Red = new BlendComposite(BlendingMode.RED);
953dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Green = new BlendComposite(BlendingMode.GREEN);
963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Blue = new BlendComposite(BlendingMode.BLUE);
973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Hue = new BlendComposite(BlendingMode.HUE);
983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Saturation = new BlendComposite(BlendingMode.SATURATION);
993dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Color = new BlendComposite(BlendingMode.COLOR);
1003dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static final BlendComposite Luminosity = new BlendComposite(BlendingMode.LUMINOSITY);
1013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private float alpha;
1033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private BlendingMode mode;
1043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1053dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private BlendComposite(BlendingMode mode) {
1063dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        this(mode, 1.0f);
1073dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1083dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1093dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private BlendComposite(BlendingMode mode, float alpha) {
1103dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        this.mode = mode;
1113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        setAlpha(alpha);
1123dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1143dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static BlendComposite getInstance(BlendingMode mode) {
1153dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return new BlendComposite(mode);
1163dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1173dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1183dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public static BlendComposite getInstance(BlendingMode mode, float alpha) {
1193dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return new BlendComposite(mode, alpha);
1203dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1223dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public BlendComposite derive(BlendingMode mode) {
1233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return this.mode == mode ? this : new BlendComposite(mode, getAlpha());
1243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1263dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public BlendComposite derive(float alpha) {
1273dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return this.alpha == alpha ? this : new BlendComposite(getMode(), alpha);
1283dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1293dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1303dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public float getAlpha() {
1313dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return alpha;
1323dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1333dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1343dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public BlendingMode getMode() {
1353dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return mode;
1363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1383dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private void setAlpha(float alpha) {
1393dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        if (alpha < 0.0f || alpha > 1.0f) {
1403dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            throw new IllegalArgumentException(
1413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    "alpha must be comprised between 0.0f and 1.0f");
1423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
1433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        this.alpha = alpha;
1453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1473dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    @Override
1483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public int hashCode() {
1493dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return Float.floatToIntBits(alpha) * 31 + mode.ordinal();
1503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1523dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    @Override
1533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public boolean equals(Object obj) {
1543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        if (!(obj instanceof BlendComposite)) {
1553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            return false;
1563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
1573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        BlendComposite bc = (BlendComposite) obj;
1593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        if (mode != bc.mode) {
1613dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            return false;
1623dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
1633dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1643dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return alpha == bc.alpha;
1653dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    public CompositeContext createContext(ColorModel srcColorModel,
1683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                          ColorModel dstColorModel,
1693dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                          RenderingHints hints) {
1703dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        return new BlendingContext(this);
1713dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
1723dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1733dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private static final class BlendingContext implements CompositeContext {
1743dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        private final Blender blender;
1753dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        private final BlendComposite composite;
1763dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1773dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        private BlendingContext(BlendComposite composite) {
1783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            this.composite = composite;
1793dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            this.blender = Blender.getBlenderFor(composite);
1803dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
1813dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1823dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        public void dispose() {
1833dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
1843dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1853dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
1863dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
1873dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
1883dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
1893dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                throw new IllegalStateException(
1903dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        "Source and destination must store pixels as INT.");
1913dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
1923dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1933dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int width = Math.min(src.getWidth(), dstIn.getWidth());
1943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int height = Math.min(src.getHeight(), dstIn.getHeight());
1953dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float alpha = composite.getAlpha();
1973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
1983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int[] srcPixel = new int[4];
1993dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int[] dstPixel = new int[4];
20047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta            int[] result = new int[4];
2013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int[] srcPixels = new int[width];
2023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int[] dstPixels = new int[width];
2033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            for (int y = 0; y < height; y++) {
2053dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                dstIn.getDataElements(0, y, width, 1, dstPixels);
20647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                if (alpha != 0) {
20747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                    src.getDataElements(0, y, width, 1, srcPixels);
20847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                    for (int x = 0; x < width; x++) {
20947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        // pixels are stored as INT_ARGB
21047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        // our arrays are [R, G, B, A]
21147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        int pixel = srcPixels[x];
21247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        srcPixel[0] = (pixel >> 16) & 0xFF;
21347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        srcPixel[1] = (pixel >>  8) & 0xFF;
21447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        srcPixel[2] = (pixel      ) & 0xFF;
21547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        srcPixel[3] = (pixel >> 24) & 0xFF;
21647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta
21747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        pixel = dstPixels[x];
21847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        dstPixel[0] = (pixel >> 16) & 0xFF;
21947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        dstPixel[1] = (pixel >>  8) & 0xFF;
22047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        dstPixel[2] = (pixel      ) & 0xFF;
22147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        dstPixel[3] = (pixel >> 24) & 0xFF;
22247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta
22347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        result = blender.blend(srcPixel, dstPixel, result);
22447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta
22547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        // mixes the result with the opacity
22647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        if (alpha == 1) {
22747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            dstPixels[x] = (result[3] & 0xFF) << 24 |
22847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                           (result[0] & 0xFF) << 16 |
22947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                           (result[1] & 0xFF) <<  8 |
23047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                           result[2] & 0xFF;
23147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        } else {
23247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            dstPixels[x] =
23347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
23447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
23547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) <<  8 |
2363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
23747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        }
23847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta
23947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                    }
24047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta            }
2413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                dstOut.setDataElements(0, y, width, 1, dstPixels);
2423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
2433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
2443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
2453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    private static abstract class Blender {
24747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta        public abstract int[] blend(int[] src, int[] dst, int[] result);
2483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2493dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        private static void RGBtoHSL(int r, int g, int b, float[] hsl) {
2503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float var_R = (r / 255f);
2513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float var_G = (g / 255f);
2523dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float var_B = (b / 255f);
2533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float var_Min;
2553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float var_Max;
2563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float del_Max;
2573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (var_R > var_G) {
2593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_Min = var_G;
2603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_Max = var_R;
2613dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            } else {
2623dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_Min = var_R;
2633dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_Max = var_G;
2643dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
2653dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (var_B > var_Max) {
2663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_Max = var_B;
2673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
2683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (var_B < var_Min) {
2693dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_Min = var_B;
2703dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
2713dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2723dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            del_Max = var_Max - var_Min;
2733dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2743dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            float H, S, L;
2753dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            L = (var_Max + var_Min) / 2f;
2763dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2773dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (del_Max - 0.01f <= 0.0f) {
2783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                H = 0;
2793dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                S = 0;
2803dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            } else {
2813dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                if (L < 0.5f) {
2823dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    S = del_Max / (var_Max + var_Min);
2833dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                } else {
2843dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    S = del_Max / (2 - var_Max - var_Min);
2853dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                }
2863dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2873dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                float del_R = (((var_Max - var_R) / 6f) + (del_Max / 2f)) / del_Max;
2883dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                float del_G = (((var_Max - var_G) / 6f) + (del_Max / 2f)) / del_Max;
2893dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                float del_B = (((var_Max - var_B) / 6f) + (del_Max / 2f)) / del_Max;
2903dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
2913dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                if (var_R == var_Max) {
2923dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    H = del_B - del_G;
2933dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                } else if (var_G == var_Max) {
2943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    H = (1 / 3f) + del_R - del_B;
2953dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                } else {
2963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    H = (2 / 3f) + del_G - del_R;
2973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                }
2983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                if (H < 0) {
2993dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    H += 1;
3003dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                }
3013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                if (H > 1) {
3023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    H -= 1;
3033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                }
3043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3053dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3063dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            hsl[0] = H;
3073dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            hsl[1] = S;
3083dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            hsl[2] = L;
3093dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
3103dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        private static void HSLtoRGB(float h, float s, float l, int[] rgb) {
3123dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            int R, G, B;
3133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3143dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (s - 0.01f <= 0.0f) {
3153dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                R = (int) (l * 255.0f);
3163dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                G = (int) (l * 255.0f);
3173dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                B = (int) (l * 255.0f);
3183dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            } else {
3193dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                float var_1, var_2;
3203dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                if (l < 0.5f) {
3213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    var_2 = l * (1 + s);
3223dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                } else {
3233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    var_2 = (l + s) - (s * l);
3243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                }
3253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                var_1 = 2 * l - var_2;
3263dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3273dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                R = (int) (255.0f * hue2RGB(var_1, var_2, h + (1.0f / 3.0f)));
3283dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                G = (int) (255.0f * hue2RGB(var_1, var_2, h));
3293dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                B = (int) (255.0f * hue2RGB(var_1, var_2, h - (1.0f / 3.0f)));
3303dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3313dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3323dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            rgb[0] = R;
3333dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            rgb[1] = G;
3343dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            rgb[2] = B;
3353dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
3363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        private static float hue2RGB(float v1, float v2, float vH) {
3383dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (vH < 0.0f) {
3393dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                vH += 1.0f;
3403dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if (vH > 1.0f) {
3423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                vH -= 1.0f;
3433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if ((6.0f * vH) < 1.0f) {
3453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                return (v1 + (v2 - v1) * 6.0f * vH);
3463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3473dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if ((2.0f * vH) < 1.0f) {
3483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                return (v2);
3493dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            if ((3.0f * vH) < 2.0f) {
3513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
3523dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
3533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            return (v1);
3543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
3553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
3563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        public static Blender getBlenderFor(BlendComposite composite) {
3573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            switch (composite.getMode()) {
3583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case NORMAL:
3593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
3603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
36147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
36247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            System.arraycopy(src, 0, result, 0, 4);
36347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
3643dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
3653dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
3663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case ADD:
3673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
3683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
36947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
37047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 4; i++) {
37147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = Math.min(255, src[i] + dst[i]);
37247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
37347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
3743dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
3753dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
3763dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case AVERAGE:
3773dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
3783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
37947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
38047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
38147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = (src[i] + dst[i]) >> 1;
38247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
38347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
38447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
3853dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
3863dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
3873dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case BLUE:
3883dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
3893dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
39047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
39147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            System.arraycopy(dst, 0, result, 0, 3);
39247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
39347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
3943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
3953dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
3963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case COLOR:
3973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
3983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
39947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
4003dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] srcHSL = new float[3];
4013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(src[0], src[1], src[2], srcHSL);
4023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] dstHSL = new float[3];
4033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
4043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
4053dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            HSLtoRGB(srcHSL[0], srcHSL[1], dstHSL[2], result);
4063dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
4073dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
4083dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return result;
4093dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4103dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case COLOR_BURN:
4123dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
41447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
41547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
41647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = src[i] == 0 ? 0 :
41747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    Math.max(0, 255 - (((255 - dst[i]) << 8) / src[i]));
41847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
41947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
42047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4223dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case COLOR_DODGE:
4243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
42647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
42747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
42847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = src[i] == 255 ? 255 :
42947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    Math.min((dst[i] << 8) / (255 - src[i]), 255);
43047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
43147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
43247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4333dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4343dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4353dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case DARKEN:
4363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
43847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
43947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
44047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = Math.min(src[i], dst[i]);
44147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
44247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
44347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case DIFFERENCE:
4473dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
44947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
45047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
45147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7);
45247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
45347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
45447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case EXCLUSION:
4583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
46047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
46147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
46247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7);
46347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
46447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
46547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case FREEZE:
4693dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4703dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
47147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
47247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
47347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = src[i] == 0 ? 0 :
47447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    Math.max(0, 255 - (255 - dst[i]) * (255 - dst[i]) / src[i]);
47547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
47647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
47747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4793dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4803dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case GLOW:
4813dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4823dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
48347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
48447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
48547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = dst[i] == 255 ? 255 :
48647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    Math.min(255, src[i] * src[i] / (255 - dst[i]));
48747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
48847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
48947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
4903dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
4913dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
4923dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case GREEN:
4933dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
4943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
49547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
4963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
4973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[0],
4983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1],
4993dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[2],
5003dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
5013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
5023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case HARD_LIGHT:
5053dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5063dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
50747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
5083dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
5093dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[0] < 128 ? dst[0] * src[0] >> 7 :
5103dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    255 - ((255 - src[0]) * (255 - dst[0]) >> 7),
5113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[1] < 128 ? dst[1] * src[1] >> 7 :
5123dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    255 - ((255 - src[1]) * (255 - dst[1]) >> 7),
5133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[2] < 128 ? dst[2] * src[2] >> 7 :
5143dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    255 - ((255 - src[2]) * (255 - dst[2]) >> 7),
5153dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
5163dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
5173dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5183dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5193dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case HEAT:
5203dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
52247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
5233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
5243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[0] == 0 ? 0 : Math.max(0, 255 - (255 - src[0]) * (255 - src[0]) / dst[0]),
5253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1] == 0 ? 0 : Math.max(0, 255 - (255 - src[1]) * (255 - src[1]) / dst[1]),
5263dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[2] == 0 ? 0 : Math.max(0, 255 - (255 - src[2]) * (255 - src[2]) / dst[2]),
5273dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
5283dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
5293dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5303dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5313dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case HUE:
5323dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5333dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
53447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
5353dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] srcHSL = new float[3];
5363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(src[0], src[1], src[2], srcHSL);
5373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] dstHSL = new float[3];
5383dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
5393dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
5403dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            HSLtoRGB(srcHSL[0], dstHSL[1], dstHSL[2], result);
5413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
5423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
5433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return result;
5443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case INVERSE_COLOR_BURN:
5473dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
54947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
5503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
5513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[0] == 0 ? 0 :
5523dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    Math.max(0, 255 - (((255 - src[0]) << 8) / dst[0])),
5533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1] == 0 ? 0 :
5543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    Math.max(0, 255 - (((255 - src[1]) << 8) / dst[1])),
5553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[2] == 0 ? 0 :
5563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    Math.max(0, 255 - (((255 - src[2]) << 8) / dst[2])),
5573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
5583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
5593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5613dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case INVERSE_COLOR_DODGE:
5623dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5633dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
56447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
5653dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
5663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[0] == 255 ? 255 :
5673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    Math.min((src[0] << 8) / (255 - dst[0]), 255),
5683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1] == 255 ? 255 :
5693dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    Math.min((src[1] << 8) / (255 - dst[1]), 255),
5703dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[2] == 255 ? 255 :
5713dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    Math.min((src[2] << 8) / (255 - dst[2]), 255),
5723dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
5733dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
5743dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5753dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5763dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case LIGHTEN:
5773dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
57947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
58047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
58147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = Math.max(src[i], dst[i]);
58247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
58347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
58447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
5853dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
5863dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
5873dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case LUMINOSITY:
5883dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
5893dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
59047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
5913dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] srcHSL = new float[3];
5923dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(src[0], src[1], src[2], srcHSL);
5933dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] dstHSL = new float[3];
5943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
5953dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
5963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            HSLtoRGB(dstHSL[0], dstHSL[1], srcHSL[2], result);
5973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
5983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
5993dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return result;
6003dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case MULTIPLY:
6033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
60547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
60647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
60747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = (src[i] * dst[i]) >> 8;
60847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
60947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
61047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
6113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6123dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case NEGATION:
6143dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6153dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
61647fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
6173dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
6183dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                255 - Math.abs(255 - dst[0] - src[0]),
6193dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                255 - Math.abs(255 - dst[1] - src[1]),
6203dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                255 - Math.abs(255 - dst[2] - src[2]),
6213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
6223dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
6233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case OVERLAY:
6263dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6273dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
62847fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
62947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            for (int i = 0; i < 3; i++) {
63047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 :
63147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                                    255 - ((255 - dst[i]) * (255 - src[i]) >> 7);
63247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            }
63347fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
63447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                            return result;
6353dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case RED:
6383dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6393dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
64047fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
6413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
6423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[0],
6433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1],
6443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[2],
6453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
6463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
6473dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6493dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case REFLECT:
6503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
65247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
6533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
6543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[0] == 255 ? 255 : Math.min(255, dst[0] * dst[0] / (255 - src[0])),
6553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[1] == 255 ? 255 : Math.min(255, dst[1] * dst[1] / (255 - src[1])),
6563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                src[2] == 255 ? 255 : Math.min(255, dst[2] * dst[2] / (255 - src[2])),
6573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
6583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
6593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6613dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case SATURATION:
6623dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6633dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
66447fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
6653dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] srcHSL = new float[3];
6663dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(src[0], src[1], src[2], srcHSL);
6673dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            float[] dstHSL = new float[3];
6683dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
6693dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
6703dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            HSLtoRGB(dstHSL[0], srcHSL[1], dstHSL[2], result);
6713dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            result[3] = Math.min(255, src[3] + dst[3]);
6723dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta
6733dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return result;
6743dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6753dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6763dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case SCREEN:
6773dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6783dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
67947fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
6803dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
6813dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                255 - ((255 - src[0]) * (255 - dst[0]) >> 8),
6823dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                255 - ((255 - src[1]) * (255 - dst[1]) >> 8),
6833dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                255 - ((255 - src[2]) * (255 - dst[2]) >> 8),
6843dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
6853dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
6863dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
6873dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
6883dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case SOFT_BURN:
6893dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
6903dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
69147fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
6923dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
6933dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[0] + src[0] < 256 ?
6943dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta	                                (dst[0] == 255 ? 255 :
6953dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                        Math.min(255, (src[0] << 7) / (255 - dst[0]))) :
6963dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                            Math.max(0, 255 - (((255 - dst[0]) << 7) / src[0])),
6973dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1] + src[1] < 256 ?
6983dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta	                                (dst[1] == 255 ? 255 :
6993dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                        Math.min(255, (src[1] << 7) / (255 - dst[1]))) :
7003dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                            Math.max(0, 255 - (((255 - dst[1]) << 7) / src[1])),
7013dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[2] + src[2] < 256 ?
7023dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta	                                (dst[2] == 255 ? 255 :
7033dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                        Math.min(255, (src[2] << 7) / (255 - dst[2]))) :
7043dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                            Math.max(0, 255 - (((255 - dst[2]) << 7) / src[2])),
7053dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
7063dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
7073dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
7083dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
7093dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case SOFT_DODGE:
7103dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
7113dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
71247fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
7133dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
7143dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[0] + src[0] < 256 ?
7153dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    (src[0] == 255 ? 255 :
7163dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                        Math.min(255, (dst[0] << 7) / (255 - src[0]))) :
7173dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                            Math.max(0, 255 - (((255 - src[0]) << 7) / dst[0])),
7183dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[1] + src[1] < 256 ?
7193dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    (src[1] == 255 ? 255 :
7203dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                        Math.min(255, (dst[1] << 7) / (255 - src[1]))) :
7213dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                            Math.max(0, 255 - (((255 - src[1]) << 7) / dst[1])),
7223dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                dst[2] + src[2] < 256 ?
7233dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                    (src[2] == 255 ? 255 :
7243dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                        Math.min(255, (dst[2] << 7) / (255 - src[2]))) :
7253dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                            Math.max(0, 255 - (((255 - src[2]) << 7) / dst[2])),
7263dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
7273dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
7283dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
7293dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
7303dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case SOFT_LIGHT:
7313dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    break;
7323dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case STAMP:
7333dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
7343dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
73547fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
7363dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
7373dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.max(0, Math.min(255, dst[0] + 2 * src[0] - 256)),
7383dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.max(0, Math.min(255, dst[1] + 2 * src[1] - 256)),
7393dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.max(0, Math.min(255, dst[2] + 2 * src[2] - 256)),
7403dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
7413dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
7423dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
7433dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
7443dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                case SUBTRACT:
7453dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    return new Blender() {
7463dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        @Override
74747fa5c920d6eb93e435794544b96a0e4ede4403aDeepanshu Gupta                        public int[] blend(int[] src, int[] dst, int[] result) {
7483dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            return new int[] {
7493dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.max(0, src[0] + dst[0] - 256),
7503dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.max(0, src[1] + dst[1] - 256),
7513dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.max(0, src[2] + dst[2] - 256),
7523dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                Math.min(255, src[3] + dst[3])
7533dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                            };
7543dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                        }
7553dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                    };
7563dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            }
7573dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta            throw new IllegalArgumentException("Blender not implement for " +
7583dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta                                               composite.getMode().name());
7593dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta        }
7603dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta    }
7613dfc1c21d58a7a6764a436cbf5c3c8ba09db45e5Deepanshu Gupta}
762