/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <math.h>
#include <stdlib.h> /* For abs */
#include "filters.h"

double fastevalPoly(double *poly,int n, double x){

    double f =x;
    double sum = poly[0]+poly[1]*f;
    int i;
    for (i = 2; i < n; i++) {
        f*=x;
        sum += poly[i]*f;
    }
    return sum;
}

void rgb2hsv( unsigned char *rgb,int rgbOff,unsigned short *hsv,int hsvOff)
{
    int iMin,iMax,chroma;
    int ABITS = 4;
    int HSCALE = 256;

    int k1=255 << ABITS;
    int k2=HSCALE << ABITS;

    int ri = rgb[rgbOff+0];
    int gi = rgb[rgbOff+1];
    int bi = rgb[rgbOff+2];
    short rv,rs,rh;

    if (ri > gi) {
        iMax = MAX (ri, bi);
        iMin = MIN (gi, bi);
    } else {
        iMax = MAX (gi, bi);
        iMin = MIN (ri, bi);
    }

    chroma = iMax - iMin;
    // set value
    rv = (short)( iMax << ABITS);

    // set saturation
    if (rv == 0)
        rs = 0;
    else
        rs = (short)((k1*chroma)/iMax);

    // set hue
    if (rs == 0)
        rh = 0;
    else {
        if ( ri == iMax ) {
            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
            if (rh >= k2) rh -= k2;
        } else if (gi  == iMax)
            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
        else // (bi == iMax )
                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
    }
    hsv[hsvOff+0] = rv;
    hsv[hsvOff+1] = rs;
    hsv[hsvOff+2] = rh;
}

void hsv2rgb(unsigned short *hsv,int hsvOff, unsigned char *rgb,int rgbOff)
{
    int ABITS = 4;
    int HSCALE = 256;
    int m;
    int H,X,ih,is,iv;
    int k1=255<<ABITS;
    int k2=HSCALE<<ABITS;
    int k3=1<<(ABITS-1);
    int rr=0;
    int rg=0;
    int rb=0;
    short cv = hsv[hsvOff+0];
    short cs = hsv[hsvOff+1];
    short ch = hsv[hsvOff+2];

    // set chroma and min component value m
    //chroma = ( cv * cs )/k1;
    //m = cv - chroma;
    m = ((int)cv*(k1 - (int)cs ))/k1;

    // chroma  == 0 <-> cs == 0 --> m=cv
    if (cs == 0) {
        rb = ( rg = ( rr =( cv >> ABITS) ));
    } else {
        ih=(int)ch;
        is=(int)cs;
        iv=(int)cv;

        H = (6*ih)/k2;
        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;

        // removing additional bits --> unit8
        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
        m=m >> ABITS;

        // ( chroma + m ) --> cv ;
        cv=(short) (cv >> ABITS);
        switch (H) {
        case 0:
            rr = cv;
            rg = X;
            rb = m;
            break;
        case 1:
            rr = X;
            rg = cv;
            rb = m;
            break;
        case 2:
            rr = m;
            rg = cv;
            rb = X;
            break;
        case 3:
            rr = m;
            rg = X;
            rb = cv;
            break;
        case 4:
            rr = X;
            rg = m;
            rb = cv;
            break;
        case 5:
            rr = cv;
            rg = m ;
            rb = X;
            break;
        }
    }
    rgb[rgbOff+0] =  rr;
    rgb[rgbOff+1] =  rg;
    rgb[rgbOff+2] =  rb;
}

