Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both

Tags:

c++

c

algorithm

I am looking for color space converter from RGB to HSV, specifically for the range 0 to 255 for both color spaces.

like image 435
jmasterx Avatar asked Jun 10 '10 20:06

jmasterx


People also ask

Can HSV color be converted to RGB?

RGB = hsv2rgb( HSV ) converts the hue, saturation, and value (HSV) values of an HSV image to red, green, and blue values of an RGB image. rgbmap = hsv2rgb( hsvmap ) converts an HSV colormap to an RGB colormap.

How do you change RGB to HSV in Python?

To convert RGB color values to HSV color values in Python, import colorsys library, call rgb_to_hsv() function, and pass the Red, Green, and Blue values as arguments. rgb_to_hsv() function takes Red, Blue, and Green values as arguments, and returns a tuple containing Hue, Saturation, and Value.

What is HSV algorithm?

Algorithm Steps In the HSV representation of color, hue determines the color you want, saturation determines how intense the color is and value determines the lightness of the image. As can be seen in the image below, 0 on the wheel would specify a mild red color and 240 would specify a blue color.


2 Answers

I've used these for a long time - no idea where they came from at this point... Note that the inputs and outputs, except for the angle in degrees, are in the range of 0 to 1.0.

NOTE: this code does no real sanity checking on inputs. Proceed with caution!

typedef struct {     double r;       // a fraction between 0 and 1     double g;       // a fraction between 0 and 1     double b;       // a fraction between 0 and 1 } rgb;  typedef struct {     double h;       // angle in degrees     double s;       // a fraction between 0 and 1     double v;       // a fraction between 0 and 1 } hsv;  static hsv   rgb2hsv(rgb in); static rgb   hsv2rgb(hsv in);  hsv rgb2hsv(rgb in) {     hsv         out;     double      min, max, delta;      min = in.r < in.g ? in.r : in.g;     min = min  < in.b ? min  : in.b;      max = in.r > in.g ? in.r : in.g;     max = max  > in.b ? max  : in.b;      out.v = max;                                // v     delta = max - min;     if (delta < 0.00001)     {         out.s = 0;         out.h = 0; // undefined, maybe nan?         return out;     }     if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash         out.s = (delta / max);                  // s     } else {         // if max is 0, then r = g = b = 0                       // s = 0, h is undefined         out.s = 0.0;         out.h = NAN;                            // its now undefined         return out;     }     if( in.r >= max )                           // > is bogus, just keeps compilor happy         out.h = ( in.g - in.b ) / delta;        // between yellow & magenta     else     if( in.g >= max )         out.h = 2.0 + ( in.b - in.r ) / delta;  // between cyan & yellow     else         out.h = 4.0 + ( in.r - in.g ) / delta;  // between magenta & cyan      out.h *= 60.0;                              // degrees      if( out.h < 0.0 )         out.h += 360.0;      return out; }   rgb hsv2rgb(hsv in) {     double      hh, p, q, t, ff;     long        i;     rgb         out;      if(in.s <= 0.0) {       // < is bogus, just shuts up warnings         out.r = in.v;         out.g = in.v;         out.b = in.v;         return out;     }     hh = in.h;     if(hh >= 360.0) hh = 0.0;     hh /= 60.0;     i = (long)hh;     ff = hh - i;     p = in.v * (1.0 - in.s);     q = in.v * (1.0 - (in.s * ff));     t = in.v * (1.0 - (in.s * (1.0 - ff)));      switch(i) {     case 0:         out.r = in.v;         out.g = t;         out.b = p;         break;     case 1:         out.r = q;         out.g = in.v;         out.b = p;         break;     case 2:         out.r = p;         out.g = in.v;         out.b = t;         break;      case 3:         out.r = p;         out.g = q;         out.b = in.v;         break;     case 4:         out.r = t;         out.g = p;         out.b = in.v;         break;     case 5:     default:         out.r = in.v;         out.g = p;         out.b = q;         break;     }     return out;      } 
like image 143
David H Avatar answered Oct 26 '22 09:10

David H


You can also try this code without floats (faster but less accurate):

typedef struct RgbColor {     unsigned char r;     unsigned char g;     unsigned char b; } RgbColor;  typedef struct HsvColor {     unsigned char h;     unsigned char s;     unsigned char v; } HsvColor;  RgbColor HsvToRgb(HsvColor hsv) {     RgbColor rgb;     unsigned char region, remainder, p, q, t;      if (hsv.s == 0)     {         rgb.r = hsv.v;         rgb.g = hsv.v;         rgb.b = hsv.v;         return rgb;     }      region = hsv.h / 43;     remainder = (hsv.h - (region * 43)) * 6;       p = (hsv.v * (255 - hsv.s)) >> 8;     q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8;     t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8;      switch (region)     {         case 0:             rgb.r = hsv.v; rgb.g = t; rgb.b = p;             break;         case 1:             rgb.r = q; rgb.g = hsv.v; rgb.b = p;             break;         case 2:             rgb.r = p; rgb.g = hsv.v; rgb.b = t;             break;         case 3:             rgb.r = p; rgb.g = q; rgb.b = hsv.v;             break;         case 4:             rgb.r = t; rgb.g = p; rgb.b = hsv.v;             break;         default:             rgb.r = hsv.v; rgb.g = p; rgb.b = q;             break;     }      return rgb; }  HsvColor RgbToHsv(RgbColor rgb) {     HsvColor hsv;     unsigned char 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);      hsv.v = rgbMax;     if (hsv.v == 0)     {         hsv.h = 0;         hsv.s = 0;         return hsv;     }      hsv.s = 255 * long(rgbMax - rgbMin) / hsv.v;     if (hsv.s == 0)     {         hsv.h = 0;         return hsv;     }      if (rgbMax == rgb.r)         hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);     else if (rgbMax == rgb.g)         hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);     else         hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);      return hsv; } 

Note that this algorithm uses 0-255 as it's range (not 0-360) as that was requested by the author of this question.

like image 43
Leszek Szary Avatar answered Oct 26 '22 11:10

Leszek Szary