Быстрый, оптимизированный и точный код преобразования RGB <-> HSB в C - PullRequest
2 голосов
/ 07 июля 2011

Я ищу быструю и точную реализацию RGB для HSB и HSB для RGB в чистом C. Обратите внимание, что я специально ищу оттенки, насыщенность, яркость и не HSL (яркость) .

Конечно, я много гуглил, но здесь очень важна скорость, и я ищу какие-то конкретные рекомендации для надежного, быстрого и надежного кода.

Ответы [ 3 ]

5 голосов
/ 07 июля 2011

Вот простая реализация в стандарте C.

Это - без дальнейшего контекста - настолько хорошо, насколько это возможно.Возможно, вам захочется пролить немного света на

  • как вы храните ваши сэмплы RGB (биты / пиксель для начала!?)
  • как вы храните свои данные пикселей (хотитечтобы эффективно преобразовывать большие буферы, если это так, что за организация)
  • как вы хотите представить результат (я предполагал, что теперь это число с плавающей точкой)

Я мог бы придуматьоптимизированная версия (возможно, такая, которая хорошо использует инструкции SSE4 ...)

Все это говорит о том, что при компиляции с оптимизацией это работает не слишком плохо:

#include <stdio.h>
#include <math.h>

typedef struct RGB_t { unsigned char red, green, blue; } RGB;
typedef struct HSB_t { float hue, saturation, brightness; } HSB;

/*
 * Returns the hue, saturation, and brightness of the color.
 */
void RgbToHsb(struct RGB_t rgb, struct HSB_t* outHsb)
{
    // TODO check arguments

    float r = rgb.red / 255.0f;
    float g = rgb.green / 255.0f;
    float b = rgb.blue / 255.0f;
    float max = fmaxf(fmaxf(r, g), b);
    float min = fminf(fminf(r, g), b);
    float delta = max - min;
    if (delta != 0)
    {
        float hue;
        if (r == max)
        {
            hue = (g - b) / delta;
        }
        else
        {
            if (g == max)
            {
                hue = 2 + (b - r) / delta;
            }
            else
            {
                hue = 4 + (r - g) / delta;
            }
        }
        hue *= 60;
        if (hue < 0) hue += 360;
        outHsb->hue = hue;
    }
    else
    {
        outHsb->hue = 0;
    }
    outHsb->saturation = max == 0 ? 0 : (max - min) / max;
    outHsb->brightness = max;
}

Типичное использование и тест:

int main()
{
    struct RGB_t rgb = { 132, 34, 255 };
    struct HSB_t hsb;

    RgbToHsb(rgb, &hsb);

    printf("RGB(%u,%u,%u) -> HSB(%f,%f,%f)\n", rgb.red, rgb.green, rgb.blue,
           hsb.hue, hsb.saturation, hsb.brightness);
    // prints: RGB(132,34,255) -> HSB(266.606354,0.866667,1.000000)

    return 0;
}
3 голосов
/ 07 июля 2011

Сначала

HSB и HLS были разработаны для указания числового оттенка, насыщенности и яркости (или оттенка, яркости и насыщенности) в возрасте, когда пользователям приходилось указывать цвета численно.Обычные формулировки HSB и HLS изменяются в отношении свойств цветового зрения.Теперь, когда пользователи могут выбирать цвета визуально, или выбирать цвета, связанные с другими носителями (такими как PANTONE), или использовать системы на основе восприятия, такие как L * u * v * и L * a * b *, HSB и HLS должны быть оставлены [source]

Посмотрите на реализацию Java с открытым исходным кодом здесь

Повышение библиотеки (я знаю, это C ++) казалось содержит преобразование в HSB одновременно, но в настоящее время я могу найти только преобразование яркости ( здесь )

0 голосов
/ 07 июля 2011

Я бы предложил использовать справочную таблицу для хранения значений HSB и RGB.Сначала преобразуйте значение RGB (которое предположительно составляет 8 бит на компонент) в 16-битное значение (5 бит на компонент).Значения HSB, также 16-битные значения, могут быть преобразованы таким же образом, при этом здесь компонент оттенка, вероятно, должен использовать больше битов, чем насыщенность и яркость, вероятно, 8 бит на компонент, а насыщенность и яркость - 4 бита каждый.Конечно, обратное будет применяться при преобразовании из HSB в RGB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...