/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

<<
private float getHue() {
    return getEffect().getHue() / 2f;
}

private float getSaturation() {
    return getEffect().getSaturation() + 1f;
}

private float getBrightness() {
    return getEffect().getBrightness() + 1f;
}

private float getContrast() {
    float c = getEffect().getContrast();
    if (c > 0) c *= 3f;
    return (c + 1f);
}
>>

param sampler baseImg;
param float hue;
param float saturation;
param float brightness;
param float contrast;

float3 rgb_to_hsb(float3 v)
{
    float h, s, b;
    float cmax = max(v.r, v.g);
    cmax = max(cmax, v.b);
    float cmin = min(v.r, v.g);
    cmin = min(cmin, v.b);

    // hue/saturation
    if (cmax > cmin) {
        float3 c = (cmax - v) / (cmax - cmin);
        if (v.r == cmax) {
            h = c.b - c.g;
        } else if (v.g == cmax) {
            h = 2.0 + c.r - c.b;
        } else {
            h = 4.0 + c.g - c.r;
        }
        h /= 6.0;
        if (h < 0.0) {
            h += 1.0;
        }

        s = (cmax - cmin) / cmax;
    } else {
        h = 0.0;
        s = 0.0;
    }

    // brightness
    b = cmax;

    return float3(h, s, b);
}

float3 hsb_to_rgb(float3 v)
{
    //if (v.g == 0.0) {
    //    return float3(v.b);
    //}

    float3 res = float3(0.0);
    float h = v.r;
    float s = v.g;
    float b = v.b;

    h = (h - floor(h)) * 6.0;
    float f = h - floor(h);
    float p = b * (1.0 - s);
    float q = b * (1.0 - (s * f));
    float t = b * (1.0 - (s * (1.0 - f)));

    h = floor(h);
    if (h < 1.0) {
        res.r = b;
        res.g = t;
        res.b = p;
    } else if (h < 2.0) {
        res.r = q;
        res.g = b;
        res.b = p;
    } else if (h < 3.0) {
        res.r = p;
        res.g = b;
        res.b = t;
    } else if (h < 4.0) {
        res.r = p;
        res.g = q;
        res.b = b;
    } else if (h < 5.0) {
        res.r = t;
        res.g = p;
        res.b = b;
    } else {
        res.r = b;
        res.g = p;
        res.b = q;
    }

    return res;
}

// based on HSBCImageOp.java (by Jasper Potts, as part of the Iris project)
void main()
{
    float4 src = sample(baseImg, pos0);
    if (src.a > 0.0) {
        src.rgb /= src.a;
    }

    // adjust contrast
    src.rgb = ((src.rgb - 0.5) * contrast) + 0.5;

    // convert from rgb -> hsb
    float3 hsb = rgb_to_hsb(src.rgb);

    // adjust hue
    hsb.r += hue;
    if (hsb.r < 0.0) {
        hsb.r += 1.0;
    } else if (hsb.r > 1.0) {
        hsb.r -= 1.0;
    }

    // adjust saturation
    if (saturation > 1.0) {
        float sat = saturation - 1.0;
        hsb.g += (1.0 - hsb.g) * sat;
    } else {
        hsb.g *= saturation;
    }

    // adjust brightness
    if (brightness > 1.0) {
        float brt = brightness - 1.0;
        hsb.g *= 1.0 - brt;
        hsb.b += (1.0 - hsb.b) * brt;
    } else {
        hsb.b *= brightness;
    }

    // clamp saturation and brightness values
    hsb.gb = clamp(hsb.gb, 0.0, 1.0);

    // convert back from hsb -> rgb (retaining original alpha)
    color.rgb = src.a * hsb_to_rgb(hsb);
    color.a = src.a;
}
