Tiñendo hacia o desde una tonalidad en un determinado porcentaje
Pregunta
Estoy intentando emular el Tinte Efecto de XML abiertos. Lo que hace es cambiar la tonalidad de los píxeles de una imagen cambiando la tonalidad. Se tarda 2 parámetros: 1) el hue
(en grados) y 2) la amt
(la cantidad, un porcentaje). Es # 2 que estoy teniendo problemas con. Los estados de especificaciones:
Tint : Cambia los valores de color de efecto ya sea hacia o lejos de tonalidad por el cantidad especificada.
- AMT (Cantidad) -. Especifica por cuánto se desplaza el valor del color
- tonalidad (Hue) -. Especifica el matiz hacia el que para teñir
Nunca ocupándose de la construcción XML, que puede emular los valores que tienen un amt
de 100%. Así, por ejemplo, si quiero Azul (matiz: 240 °), puedo crear esto (el Tinted una). He aquí un ejemplo:
ORIGINAL y Tinted (hue = 240, Monto = 100%).
Esto se logra simplemente poniendo el tono a 240, manteniendo la saturación y luminancia de la misma y la conversión de RGB y escribir cada píxel.
Esto es lo que no se puede lograr sin embargo:
Hue = 240 ( azul ), la cantidad = 30% , 50% y 80% , respectivamente
Una vez más, la especificación de Amount
dice especifica por cuánto se desplaza el valor del color . He intentado todo tipo de formas aquí para conseguir que esto funcione, pero parece que no puede (hue=hue*amount
, originalhue * amount + hue
, etc.)
Más ejemplos: Hue = 120 ( verde ), la cantidad = 30% , 50 % , 80% y 100% , respectivamente. La 100% que puedo conseguir.
Aquí están algunas listas de valores de un solo píxel en las imágenes de arriba:
Pixel 159, 116 - Azul Fotos
Hue Amount R G B | H S L Original 244 196 10 | 48 0.92 0.5 Blue 240 30% 237 30 45 | 356 0.85 0.52 Blue 240 50% 245 9 156 | 323 0.93 0.5 Blue 240 80% 140 12 244 | 273 0.91 0.5 Blue 240 100% 12 12 244 | 240 0.91 0.5
Pixel 159, 116 - Verde Fotos
Hue Amount R G B | H S L Original 244 196 10 | 48 0.92 0.5 Green 120 30% 211 237 30 | 68 0.85 0.52 Green 120 50% 159 237 30 | 83 0.85 0.52 Green 120 80% 81 237 29 | 105 0.85 0.52 Green 120 100% 29 237 29 | 120 0.85 0.52
Entonces, la pregunta es:? ¿Alguien sabe cómo se debe trabajar
Nota: Este es no un duplicado de:
- de cambiar el matiz de un mapa de bits, mientras la preservación de la general brillo
- Girar Hue usando ImageAttributes en C #
- ... o cualquier otra cosa que pude encontrar en SO
Solución
Estoy seguro de que los resultados de problemas de la forma en que se interpolación ángulos. Aquí está una función de interpolación (escrito en Python) que debe hacer el truco. Se basa en una sugerencia de la rosca foros de XNA más corta interpolación ángulo 2D .
def wrap(value, lower, upper):
distance = upper - lower
return value - ((value-lower)//distance)*distance
def shortestangle(a,b):
angle = wrap(b-a, 0, 360)
if angle>=180: angle -= 360
return angle
def interpolate(a,b,amount):
return (a+shortestangle(a,b)*amount)%360
Ahora, interpolate(originalHue,hue,amount)
debe producir el resultado deseado.
Editar: Es mi entendimiento de que su objetivo es hacer girar la tonalidad original, hacia una cierta tonalidad de destino por alguna cantidad dada. Estoy seguro de que ya está familiarizado con esto, pero en aras de la ilustración, he aquí una rueda de color.
(fuente: sapdesignguild.org )
El problema es que la mezcla (o de interpolación) dos ángulos no es trivial, por lo que un código como hue = ((hue - originalHue) * amount) + originalHue
no funcionará. Hay un número infinito de maneras de ir de un ángulo a otro a causa de la envolvente a 360 °. Para llegar desde 0 ° a 60 ° se podía girar 60 ° en sentido antihorario, 420 ° en sentido antihorario, 300 ° en sentido horario, etc. Por lo general, el ángulo más corto es el que desee uno.
Por ejemplo, vamos a considerar los cuellos de pingüino: si su tonalidad original es 30 ° (naranja), su objetivo es 240 ° (azul) y la cantidad es del 50%, se llega a los siguientes resultados:
//Linear Interpolation
(30° + (240° - 30°)*0.5) = 135° (green)
//"Shortest 2D Angle Interpolation"
(30° + shortestangle(30°,240°)*0.5) % 360 = (30° + (-150°)*0.5) % 360 = 315° (magenta)
Mi conjetura es que el segundo resultado es el que usted está buscando, pero puedo estar equivocado y el error podría ser un lugar completamente distinto ...
Otros consejos
Se debe echar un vistazo a TintParams en GDI + (no forma parte de .NET sin embargo) -. esto puede ser justo lo que está buscando