среда, 31 октября 2012 г.

Blend Modes: How to convert HSV <--> RGB and apply Hue/Saturation filters?


Step 1: RGB to HSV;
Step 2: Blending;
Step 3: HSV to RGB.

Blends:

  • The Hue blend mode preserves the luma and chroma of the bottom layer, while adopting the hue of the top layer.
  • The Saturation blend mode preserves the luma and hue of the bottom layer, while adopting the chroma of the top layer.
  • The Color blend mode preserves the luma of the bottom layer, while adopting the hue and chroma of the top layer.
  • The Luminosity blend mode preserves the hue and chroma of the bottom layer, while adopting the luma of the top layer.


#define ROUND(x) ((int) ((x) + 0.5))
void rgb_to_hsv (    int *red,
                     int *green,
                     int *blue)
{
    double  r, g, b;
    double  h, s, v;
    int     min;
    double  delta;
    
    r = *red;
    g = *green;
    b = *blue;
    
    if (r > g)
    {
        v = max(r, b);
        min = min(g, b);
    }
    else
    {
        v = max (g, b);
        min = min (r, b);
    }
    
    delta = v - min;
    
    if (v == 0.0)
        s = 0.0;
    else
        s = delta / v;
    
    if (s == 0.0)
    {
        h = 0.0;
    }
    else
    {
        if (r == v)
            h = 60.0 * (g - b) / delta;
        else if (g == v)
            h = 120 + 60.0 * (b - r) / delta;
        else
            h = 240 + 60.0 * (r - g) / delta;
        
        if (h < 0.0)
            h += 360.0;
        
        if (h > 360.0)
            h -= 360.0;
    }
    
    *red   = ROUND (h);
    *green = ROUND (s * 255.0);
    *blue  = ROUND (v);
    
    if (*red == 360)
        *red = 0;
}

void hsv_to_rgb (    int *hue,
                     int *saturation,
                     int *value)
{
    double h, s, v, h_temp;
    double f, p, q, t;
    int i;
    
    if (*saturation == 0)
    {
        *hue        = *value;
        *saturation = *value;
        *value      = *value;
    }
    else
    {
        h = *hue;
        s = *saturation / 255.0;
        v = *value      / 255.0;
        
        if (h == 360)
            h_temp = 0;
        else
            h_temp = h;
        
        h_temp = h_temp / 60.0;
        i = floor (h_temp);
        f = h_temp - i;
        p = v * (1.0 - s);
        q = v * (1.0 - (s * f));
        t = v * (1.0 - (s * (1.0 - f)));
        
        switch (i)
        {
            case 0:
                *hue        = ROUND (v * 255.0);
                *saturation = ROUND (t * 255.0);
                *value      = ROUND (p * 255.0);
                break;
                
            case 1:
                *hue        = ROUND (q * 255.0);
                *saturation = ROUND (v * 255.0);
                *value      = ROUND (p * 255.0);
                break;
                
            case 2:
                *hue        = ROUND (p * 255.0);
                *saturation = ROUND (v * 255.0);
                *value      = ROUND (t * 255.0);
                break;
                
            case 3:
                *hue        = ROUND (p * 255.0);
                *saturation = ROUND (q * 255.0);
                *value      = ROUND (v * 255.0);
                break;
                
            case 4:
                *hue        = ROUND (t * 255.0);
                *saturation = ROUND (p * 255.0);
                *value      = ROUND (v * 255.0);
                break;
                
            case 5:
                *hue        = ROUND (v * 255.0);
                *saturation = ROUND (p * 255.0);
                *value      = ROUND (q * 255.0);
                break;
        }
    }
}

void hueLayers (int *rs, int  *gs, int *bs, int  *rd, int  *gd, int *bd)
{
    rgb_to_hsv(rs, gs, bs);
    rgb_to_hsv(rd, gd, bd);
    
    hsv_to_rgb(rs, gd, bd);
    *gs = *gd;
    *bs = *bd;
}


void satLayers (int *rs, int  *gs, int *bs, int  *rd, int  *gd, int *bd)
{
    rgb_to_hsv(rs, gs, bs);
    rgb_to_hsv(rd, gd, bd);
    
    hsv_to_rgb(rd, gs, bd);
    *rs = *rd;
    *bs = *bd;
}

//Tests
void saturationTest(){

    int sr = (int)(0x55);
    int sg = (int)(0x66);
    int sb = (int)(0x77);

    int dr = (int)0xAA;
    int dg = (int)0xFF;
    int db = (int)0x99;
    
    int bgr = dr;
    int bgg = dg;
    int bgb = db;
    
    float a = 0.5f;

    satLayers(&sr, &sg, &sb, &dr, &dg, &db);
    printf("   SaturationBlend = #%02X %02X %02X \n", sr, sg, sb);
}

void hueTest(){
    
    int sr = (int)(0x55);
    int sg = (int)(0x66);
    int sb = (int)(0x77);
    
    int dr = (int)0xAA;
    int dg = (int)0xFF;
    int db = (int)0x99;
    
    int bgr = dr;
    int bgg = dg;
    int bgb = db;
    
    float a = 0.25f;
    
    hueLayers(&sr, &sg, &sb, &dr, &dg, &db);
    printf("   HUE Blend = #%02X %02X %02X \n", sr, sg, sb);
}


Комментариев нет:

Отправить комментарий