style font color colors rgb

colors - font - Fórmula más rápida para obtener Hue de RGB



rgb to hex (4)

Si recibe valores de rojo, verde y azul que van de 0 a 255, ¿cuál sería el cálculo más rápido para obtener solo el valor de tono? Esta fórmula se utilizará en cada píxel de una imagen de 640x480 a 30 fps (9.2 millones de veces por segundo), por lo que cada poco de optimización de velocidad ayuda.

He visto otras fórmulas pero no estoy contento con la cantidad de pasos que implican. Estoy buscando una fórmula real, no una función de biblioteca integrada.


  1. Convierta los valores RGB al rango 0-1, esto se puede hacer dividiendo el valor por 255 para la profundidad de color de 8 bits (r, g, b - se dan valores):

    R = r / 255 = 0.09 G = g / 255 = 0.38 B = b / 255 = 0.46

  2. Encuentra los valores mínimo y máximo de R, G y B.

  3. Dependiendo de qué canal de color RGB es el valor máximo. Las tres fórmulas diferentes son: If Red is max, then Hue = (GB)/(max-min) If Green is max, then Hue = 2.0 + (BR)/(max-min) If Blue is max, then Hue = 4.0 + (RG)/(max-min)

El valor de Tono que obtenga debe multiplicarse por 60 para convertirlo en grados en el círculo de color. Si el tono se vuelve negativo, debe agregar 360, porque un círculo tiene 360 ​​grados.

Aquí está el artículo completo .


Además de la respuesta de Umriyaev:

Si solo se necesita el tono, no es necesario dividir los colores de 25 a 255 con 255.

El resultado de ex (green - blue) / (max - min) será el mismo para cualquier rango (siempre que los colores estén en el mismo rango, por supuesto).

Aquí está el ejemplo de java para obtener el tono:

public int getHue(int red, int green, int blue) { float min = Math.min(Math.min(red, green), blue); float max = Math.max(Math.max(red, green), blue); if (min == max) { return = 0; } float hue = 0f; if (max == red) { hue = (green - blue) / (max - min); } else if (max == green) { hue = 2f + (blue - red) / (max - min); } else { hue = 4f + (red - green) / (max - min); } hue = hue * 60; if (hue < 0) hue = hue + 360; return Math.round(hue); }

Edición: se agregó la comprobación si min y max son iguales, ya que el resto del cálculo no es necesario en este caso, y para evitar la división por 0 (ver comentarios)


Debe especificar qué idioma necesita. C #, Java y C son lenguajes muy diferentes y pueden ejecutarse en diferentes plataformas

640x480 no es muy grande en comparación con las resoluciones comunes actuales. Debes probar todas las posibles soluciones y benchmark. Un algoritmo que tiene muchos pasos no es necesariamente más lento que uno más corto porque el ciclo de instrucciones no es fijo y hay muchos otros factores que afectan el rendimiento, como la coherencia de la memoria caché.

Para el algoritmo Umriyaev mencionado anteriormente, puede reemplazar la división por 255 con una multiplicación por 1.0/255 , lo que mejorará el rendimiento con un error aceptable.

En C puedes vectorizarlo para mejorarlo aún más. También puede utilizar la aceleración de hardware.

En C # y Java no tienes muchas opciones. Puede ejecutar código no seguro en C #, o si está usando Mono, puede usar el tipo de vector que ya es compatible con SSE. En Java puedes ejecutar código nativo a través de JNI.


// convert rgb values to the range of 0-1 var h; r /= 255, g /= 255, b /= 255; // find min and max values out of r,g,b components var max = Math.max(r, g, b), min = Math.min(r, g, b); if(max == r){ // if red is the predominent color h = (g-b)/(max-min); } else if(max == g){ // if green is the predominent color h = 2 +(b-r)/(max-min); } else if(max == b){ // if blue is the predominent color h = 4 + (r-g)/(max-min); } h = h*60; // find the sector of 60 degrees to which the color belongs // https://www.pathofexile.com/forum/view-thread/1246208/page/45 - hsl color wheel if(h > 0){ // h is a positive angle in the color wheel return Math.floor(h); } else{ // h is a negative angle. return Math.floor(360 -h); }