Не могу конвертировать из HSL в RGB

У меня проблема с преобразованием цвета из HSL в RGB. Я написал следующую функцию:

struct RGB {
float r, g, b;
};
RGB hslToRgb( float hue, float saturation, float lightness ) {

RGB rgb1, rgbResult;

float chroma = ( 1.0 - (float) abs( 2.0 * lightness - 1.0 ) ) * saturation;
float h1 = hue / 60.0;
float x = chroma * ( 1.0 - (float) abs( (float) ( (int) h1 % 2 ) - 1.0 ) );

if ( ( 0 <= h1 ) && ( h1 < 1 ) ) {

rgb1.r = chroma;
rgb1.g = x;
rgb1.b = 0.0;

} else if ( ( 1 <= h1 ) && ( h1 < 2 ) ) {

rgb1.r = x;
rgb1.g = chroma;
rgb1.b = 0.0;

} else if ( ( 2 <= h1 ) && ( h1 < 3 ) ) {

rgb1.r = 0.0;
rgb1.g = chroma;
rgb1.b = x;

} else if ( ( 3 <= h1 ) && ( h1 < 4 ) ) {

rgb1.r = 0.0;
rgb1.g = x;
rgb1.b = chroma;

} else if ( ( 4 <= h1 ) && ( h1 < 5 ) ) {

rgb1.r = x;
rgb1.g = 0.0;
rgb1.b = chroma;

} else if ( ( 5 <= h1 ) && ( h1 < 6 ) ) {

rgb1.r = chroma;
rgb1.g = 0;
rgb1.b = x;

} else {

rgb1.r = 0.0;
rgb1.g = 0.0;
rgb1.b = 0.0;

}

float m = lightness - 0.5 * chroma;

rgbResult.r = rgb1.r + m;
rgbResult.g = rgb1.g + m;
rgbResult.b = rgb1.b + m;

return rgbResult;

}

вот его тест:

float cHue = 0.0;
while ( cHue < 360 ) {
RGB rgb1 = hslToRgb( (int) cHue, 1.0, 0.5 ); // max on saturation and a middle value for lightness
printf( "r = %f, g = %f, b = %f\n", rgb1.r, rgb1.g, rgb1.b );
cHue += 1.0;
}

но я получаю только 1,0 и 0,0, когда мне нужно получить весь диапазон между этими «целыми числами».

r = 1.000000, g = 0.000000, b = 1.000000
r = 1.000000, g = 0.000000, b = 1.000000
r = 1.000000, g = 0.000000, b = 1.000000
r = 1.000000, g = 0.000000, b = 0.000000
r = 1.000000, g = 0.000000, b = 0.000000
r = 1.000000, g = 0.000000, b = 0.000000

Может ли кто-нибудь помочь мне с этим кодом?
Формулы из: http://en.wikipedia.org/wiki/HSL_and_HSV

2

Решение

Использовать с плавающей точкой по модулю fmodf как:

float x = chroma * ( 1.0 - (float) abs( fmodf(h1, 2.0) - 1.0 ));
4

Другие решения

Прекратить использование бросков в стиле C (например, (int) а также (float)) в коде C ++. использование fabs когда вам нужна абсолютная функция с плавающей точкой. Разбейте сложные формулы на несколько этапов, вы не получите никакой эффективности, выполняя все в одной строке.

Делайте 1 расчет на строку. Сохраните результат в переменной нужного вам типа с описательным именем. Посмотрим, сможете ли вы когда-либо избежать использования int если вы не должны явно округлить.

1

Ваше значение цветности кажется выключенным. У вас это как

float chroma = ( 1.0 - (float) abs( 2.0 * lightness - 1.0 ) ) * saturation;

но я думаю, что это должно быть

float chroma = saturation * lightness;

так как Википедия говорит,

From HSV

Given a color with hue H ∈ [0°, 360°), saturation SHSV ∈ [0, 1], and value V ∈ [0, 1],
we first find chroma:

C = V \times S_{HSV}
0

На вашей линии:

float x = chroma * ( 1.0 - (float) abs( (float) ( (int) h1 % 2 ) - 1.0 ) );

Ваш кастинг (int) потому что модуль заставляет его удалить все десятичные дроби с плавающей точкой. Тем самым делая это двоичной функцией.

Вам нужна функция модуля с плавающей точкой, как Майкл Ш описал.

-1
По вопросам рекламы [email protected]