Jack Berkhout / HSV

Dependents:   RGB_Matrix_Test

HSV.cpp

Committer:
JackB
Date:
2015-04-28
Revision:
0:e3c23a157dee
Child:
1:a06dfdf279e2

File content as of revision 0:e3c23a157dee:

/* mbed HSV Library
 *  
 * Copyright (c) 2013-2013 JackB, cstyles
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "HSV.h"
 
HSV::HSV() {
    Rgb.Out = 4095.0;
    SetRcf(1.0);
    SetGcf(1.0);
    SetBcf(1.0);
    SetWcf(1.0);
    SetH(0.0); // Hue
    SetS(1.0); // Saturation
    SetV(1.0); // Value
    SetP(1.0); // Power
    SetPower(true);
}
 
void HSV::SetPower(bool Power)
{
    _Power = Power;
}


int HSV::UseWeb(char* String)
{
    // #c08040
    char Str[3];
    Str[2] = '\0';
    Str[0] = String[1];
    Str[1] = String[2];
    int R  = (int)strtol(Str, NULL, 16);
    Str[0] = String[3];
    Str[1] = String[4];
    int G  = (int)strtol(Str, NULL, 16);
    Str[0] = String[5];
    Str[1] = String[6];
    int B  = (int)strtol(Str, NULL, 16);
    return (int)(((R & 0xf8) << 8) + ((G & 0xfc) << 3) + ((B & 0xf8) >> 3));
}

int HSV::UseRGB(int R, int G, int B)
{
    return (int)(((R & 0xf8) << 8) + ((G & 0xfc) << 3) + ((B & 0xf8) >> 3));
}

int HSV::UseHSV(float H, float S, float V)
{
    Hsv.H = H;
    Hsv.S = S;
    Hsv.V = V;
    HSV_to_RGB();
    int R = (int) (sqrt(Rgb.R) * (float)255.0);
    int G = (int) (sqrt(Rgb.G) * (float)255.0);
    int B = (int) (sqrt(Rgb.B) * (float)255.0);
    return (int)(((R & 0xf8) << 8) + ((G & 0xfc) << 3) + ((B & 0xf8) >> 3));
}

void HSV::SetRcf(float Rcf)
{
  Rgb.Rcf = Rcf;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetGcf(float Gcf)
{
  Rgb.Gcf = Gcf;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetBcf(float Bcf)
{
  Rgb.Bcf = Bcf;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetWcf(float Wcf)
{
  Rgb.Wcf = Wcf;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetH(float Hue)
{
  Hsv.H = Hue;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetS(float Saturation)
{
  Hsv.S = Saturation;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetV(float Value)
{
  Hsv.V = Value * Value;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetP(float Value)
{
  Hsv.P = Value;
  HSV_to_RGB();
//  RGB_to_HSV();
}

void HSV::SetW(float White)
{
  Rgb.W = White;
}

uint16_t HSV::GetRout(void)
{
    if (_Power)
        return (uint16_t)(Rgb.R * Rgb.Rcf * Rgb.Out);
    return 0;
}

uint16_t HSV::GetGout(void)
{
    if (_Power)
        return (uint16_t)(Rgb.G * Rgb.Gcf * Rgb.Out);
    return 0;
}

uint16_t HSV::GetBout(void)
{
    if (_Power)
        return (uint16_t)(Rgb.B * Rgb.Bcf * Rgb.Out);
    return 0;
}

uint16_t HSV::GetWout(void)
{
    if (_Power)
        return (uint16_t)(Rgb.W * Rgb.Wcf * Rgb.Out);
    return 0;
}

float HSV::GetR(void)
{
  return Rgb.R;
}

float HSV::GetG(void)
{
  return Rgb.G;
}

float HSV::GetB(void)
{
  return Rgb.B;
}

float HSV::GetW(void)
{
  return Rgb.W;
}

float HSV::GetH(void)
{
  return Hsv.H;
}

float HSV::GetS(void)
{
  return Hsv.S;
}

float HSV::GetV(void)
{
  return Hsv.V;
}

float HSV::GetH2(void)
{
  return Hsv2.H;
}

float HSV::GetS2(void)
{
  return Hsv2.S;
}

float HSV::GetV2(void)
{
  return Hsv2.V;
}

void HSV::HSV_to_RGB(void)
{
    // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1].
    // RGB are each returned on [0, 1].
    Rgb.W = ((float)1.0 - Hsv.S) * Hsv.V * Hsv.P;
    while (Hsv.H < (float)0.0)
        Hsv.H += (float)1.0;
    while (Hsv.H >= (float)1.0)
        Hsv.H -= (float)1.0;
    float h_div = (float)1.0 / (float)6.0;
    float h = Hsv.H/h_div;
    float s = Hsv.S;
    float v = Hsv.V * Hsv.P;
    float m, n, f;
    int i = floor(h);
    f = h - (float) i;
    if ( !(i&1) )
        f = 1 - f; // if i is even
    m = v * (1 - s);
    n = v * (1 - s * f);
    switch (i) {
        case 0  : Rgb.R = v;  Rgb.G = n;  Rgb.B = m; break;
        case 1  : Rgb.R = n;  Rgb.G = v;  Rgb.B = m; break;
        case 2  : Rgb.R = m;  Rgb.G = v;  Rgb.B = n; break;
        case 3  : Rgb.R = m;  Rgb.G = n;  Rgb.B = v; break;
        case 4  : Rgb.R = n;  Rgb.G = m;  Rgb.B = v; break;
        case 5  : Rgb.R = v;  Rgb.G = m;  Rgb.B = n; break;
        default : Rgb.R = v;  Rgb.G = n;  Rgb.B = m; break;
    }
}

void HSV::RGB_to_HSV(void)
{
    float rgbMin, rgbMax;
    
    rgbMin = Rgb.R < Rgb.G ? (Rgb.R < Rgb.B ? Rgb.R : Rgb.B) : (Rgb.G < Rgb.B ? Rgb.G : Rgb.B);
    rgbMax = Rgb.R > Rgb.G ? (Rgb.R > Rgb.B ? Rgb.R : Rgb.B) : (Rgb.G > Rgb.B ? Rgb.G : Rgb.B);
    
    Hsv2.V = rgbMax;
    if (Hsv2.V == 0.0)
    {
        Hsv2.H = 0.0;
        Hsv2.S = 0.0;
        return;
    }
    
    Hsv2.S = (rgbMax - rgbMin) / Hsv2.V;
    if (Hsv2.S == 0.0)
    {
        Hsv2.H = 0.0;
        return;
    }
    
    if (rgbMax == Rgb.R)
        Hsv2.H =           1.0/6.0 * (Rgb.G - Rgb.B) / (rgbMax - rgbMin);
    else if (rgbMax == Rgb.G)
        Hsv2.H = 1.0/3.0 + 1.0/6.0 * (Rgb.B - Rgb.R) / (rgbMax - rgbMin);
    else
        Hsv2.H = 2.0/3.0 + 1.0/6.0 * (Rgb.R - Rgb.G) / (rgbMax - rgbMin);
}