Значення HSL до RGB


17

Основна мета кольорової моделі RGB (червоний зелений синій) полягає в зондуванні, представленні та відображенні зображень в електронних системах, таких як телевізори та комп'ютери

HSL (Hue Saturation Lightness) - альтернативна кольорова модель, розроблена в 1970-х роками дослідниками комп'ютерної графіки для більш тісного узгодження з тим, як людський зір сприймає кольорові атрибути

Ось статті із вікі для RGB та HSL . Для графічних програм звичайно робити обчислення в HSL, а пізніше конвертувати у бажаний формат для більшості екранів: RGB.

Завдання полягає в тому, щоб написати функцію / програму, яка приймає HSL як вхід і виводить RGB.

Ви можете вибрати бажане подання для вводу / виводу, якщо воно відповідає їм.

Наприклад, вони можуть бути масивом / кортежем з 3 елементами або об'єктом з 3 властивостями, названими h, sі l, але я прийму інші розумні варіанти, як-от отримання hsl як цілого числа (втрачає точність) та виведення цілого числа rgb.

Вхід може вважатися безпечним у діапазоні та форматі, обидва ви можете вирішити. Я настійно пропоную або діапазони, 0-1 0-1 0-1або 0-360 0-100 0-100для hsl, 0-1 0-1 0-1або 0-255 0-255 0-255для rgb.

Кожну відповідь потрібно вказати на обидва вищезгадані, і вкладайте різні варіанти у свої відповіді, якщо ви особливо пишаєтесь ними, навіть якщо вони не мають менше символів, ніж ваші інші варіанти. Зверху покладіть найменший.

Псевдопроби для 0-360 0-100 0-1000-255 0-255 0-255

h   s   l   → r   g   b

0   0   0   → 0   0   0
90  56  17  → 43  68  19
202 19  39  → 81  104 118
72  55  26  → 88  103 30

Формули для конверсії можна знайти тут :

Це як хороший спосіб візуалізації конверсії:


Ваш запропонований діапазон Hвід 0-360це [0,360), було б краще , як написано 0-359?
Джонатан Аллан

3
@JonathanAllan Я думаю, що це може виглядати дещо заплутаніше, як на мене, що говорить про те, що 395.1 - це не можливий внесок. Якщо що-небудь, використання a-bпозначень неправильно саме по собі при роботі з цілими значеннями, але я б сказав, що це нормально, щоб питання було більш зрозумілим. Якщо хтось скаржиться, я переосмислю його, тому дякую, що вказав на це
towc

Так, домовились про 359,1 бал - можливо просто використати стандартне позначення [0,360)тоді :)
Джонатан Аллан

здивований, не побачивши відповідей glsl;)
towc

Відповіді:


8

JavaScript (ES6), 98 95 94 байт

Бере H в [0,360) і S / L в [0,1) . Виводи R , G і B у вигляді масиву з 3 плавків у [0,1) .

(H,S,L)=>[5,3,1].map(i=>A(L*2)*S*([1,Y,0,0,Y,1][(i-~H)%6]-.5)+L,Y=(A=n=>n>1?2-n:n)((H/=60)%2))

Тестові справи

Цей фрагмент перетворює результати назад у [0,255] .

Як?

Код ініціалізації

Y = (                  // we compute Y = 1 - |(H/60) mod 2 - 1| = X / C
  A = n =>             // A = function that returns 1 - |n - 1|
    n > 1 ?            //   first compare n with 1
      2 - n            //     which allows to simplify the formula to either 2 - n
    :                  //   or
      n                //     just n
)((H /= 60) % 2)       // divide H by 60 and compute Y = A(H % 2)

Основний код

[5, 3, 1].map(i =>     // for each i in (5, 3, 1):
  A(L * 2) * S * (     //   compute (1 - |2L - 1|) * S (this is C), and multiply it by:
    [1, Y, 0, 0, Y, 1] //     either 0, 1 or Y (let's call this factor K), picked from
    [(i - ~H) % 6]     //     a cyclic sequence of period 6, using i and ~H (-6 ≤ ~H ≤ -1)
    - .5               //     minus 1/2
  )                    //   this gives: C(K - 1/2) = CK - C/2, where CK = 0, C or X
  + L                  //   we add L, leading to CK - C/2 + L = CK + m
)                      // end of map() --> returns [R, G, B]

Перестановки (0, C, X)

Трохи хитра частина полягає в генерації правильної перестановки (0, C, X) відповідно до кута компонента відтінку. Як показано на наступному малюнку, кожне значення стовпця вибирається з тієї ж циклічної послідовності періоду 6 , починаючи з різних зрушень. У наведеному вище коді ми використовуємо - ~ H замість просто + H, оскільки нам потрібно примусити H до цілого числа. Звідси компенсації (5,3,1) замість (0,4,2) .

                       C,X,0,0,X,C,C,X,0,0,X,C, ...
 +------> C,X,0,0,X,C  <--------->                  offset = 0, (0 - 1) mod 6 = 5
 | +----> X,C,C,X,0,0          <--------->          offset = 4, (4 - 1) mod 6 = 3
 | | +--> 0,0,X,C,C,X      <--------->              offset = 2, (2 - 1) mod 6 = 1
 | | |
(C,X,0) for   0 ≤ H <  60
(X,C,0) for  60 ≤ H < 120
(0,C,X) for 120 ≤ H < 180
(0,X,C) for 180 ≤ H < 240
(X,0,C) for 240 ≤ H < 300
(C,0,X) for 300 ≤ H < 360

Would приймати Hв [0,6)і виведення в [0,1]економії деяких байт?
Джонатан Аллан

@JonathanAllan Ах, я не помітив, що формат вводу / виводу був вільним. Спасибі!
Арнольд

4

Математика, 155 байт

(x~Clear~c;d=Piecewise@Table[{(P=Permutations)[P@{c,x,0}][[42,i]],(i-1)<=#<i*p},{i,6}];c=(1-Abs[2#3-1])#2;x=c(1-Abs[Mod[#/(p=60),2]-1]);m=#3-c/2;(m+d)255)&


Спробуйте в Інтернеті!



1
@totallyhuman Я не думаю, що це правильно, як Hueі HSB (AKA HSV), а не HSL (див. малюнки 2a та 2b на пов'язаній сторінці Вікіпедії).
Джонатан Аллан

1
Дженні - якщо це правильно, немає причин не розміщувати її як кількість байтів, що не вбудовані нижче!
Джонатан Аллан

1
@JonathanAllan О, так воно і є. Це трохи дратує, як RGBColorіснує, але HSLColorні. > _>
повністюлюдський

Чи існує така версія, що не має волі?
користувач76284

4

Python 2 , 32 байти

from colorsys import*;hls_to_rgb

Спробуйте в Інтернеті!

Ця функціональність фактично вбудована в Python через hls_to_rgbвнутрішню частину colorsysбібліотеки. Формати шахтного введення - це діапазон HLS 0-1 (замість HSL, обидва є загальними абревіатурами для одного і того ж (хоч HSL є більш поширеним)]. І шахта виводить значення RGB в кортежі з діапазоном від 0 до 1.

Кредити

Дякую Джонатану Аллану за те, що він зазначив, що мені просто потрібно імпортувати його (а потім ще більше допомагати мені зменшити кількість байтів).


Я думаю, що це може бути лише 31 байт, from colorsys import hls_to_rgbоскільки надає нам функцію, яку можна повторно використовувати. Редагувати - зробіть це 21 як from colorsys import*.
Джонатан Аллан

1
@JonathanAllan Спасибі, оновлено.
Ніл

Насправді, мабуть, лише import colorsysза 15!
Джонатан Аллан

@JonathanAllan Nice, оновлено знову.
Ніл

1
як би правда це не було, я думаю, що це занадто сильно впливає на дух кодового гольфу: /
towc

4

C ++, 228 221 байт

-7 байт завдяки Захарі

#define S(o,n)r[t[int(h[0])/60*3+o]+o-2]=(n+h[2]-c/2)*255;
void C(float*h,int*r){float g=2*h[2]-1,c=(g<0?1+g:1-g)*h[1],a=int(h[0])%120/60.f-1;int t[]={2,2,2,3,1,2,3,3,0,4,2,0,4,1,1,2,3,1};S(0,c)S(1,c*(a<0?1+a:1-a))S(2,0)}

Аргументи - це обидва масиви, які мають мінімальний розмір 3 елемента (тобто float hsl[3]іint rgb[3]

Добре. Тепер, як це працює? Що це за довгий масив?

Ну, це не довгий масив, це intмасив. Жартом вбік масив вказує, на скільки позицій ми змістимо CX і 0, коли хочемо вибрати правильну перестановку, + 2. Пригадайте, як обрані R ', G' і B '?

Як обрані R ', G' і B '

Скажімо, у нас є "нормальний" порядок, який становить {C, X, 0}

Тепер, коли обрана перша перестановка (тобто {C, X, 0}), вам не потрібно зміщувати, що є точно тим же, що і зсув правого на 0. Отже, перші 3 елементи масиву дорівнюють 0,0 і 0

Для другої перестановки ({X, C, 0}) нам потрібно зрушити правий C на 1, а зсув X на -1, тому четвертий, п'ятий та шостий елементи масиву дорівнюють 1, -1 та 0

І так далі...

У випадку 3-ї та 4-ї перестановки мені потрібно зліва змістити 0 на 2, тому правий зсув на -2. Оскільки є більше 2-х чисел, які є негативними, я радше додаю 2 до кожного елемента в масиві та підрезюмую 2 під час виконання (з міркувань гольфу, щоб у масиві були лише цілі числа).




3

HTML + JavaScript (ES6), 8 + 88 = 96 байт

f=
(h,s,l)=>(p.style.color=`hsl(${h},${s}%,${l}%)`,getComputedStyle(p).color.match(/\d+/g))
<div oninput=o.textContent=f(h.value,s.value,l.value)>H: <input type=number min=0 max=360 value=0 id=h>°<br>S: <input type=number min=0 max=100 value=0 id=s>%<br>L: <input type=number min=0 max=100 value=0 id=l>%<pre id=o>0,0,0</pre>
<p id=p>

Приймає вхід як кут і два відсотки. Я забиваю фрагмент HTML <p id=p>та функцію стрілки JavaScript. Я не знаю, що використовують браузери для округлення, тому мої відповіді можуть дещо відрізнятися від ваших.


2

Швидкий 4, 218 байт

Приймає значення HSL в діапазоні [0,1] як аргументи і повертає масив, що містить значення RGB в тому ж діапазоні:

import Cocoa;typealias F=CGFloat;func f(h:F,s:F,l:F)->[F]{var r=F(),g=F(),b=F(),x=s*min(1-l,l),n=2*x/max(l+x,1e-9);NSColor(hue:h,saturation:n,brightness:l+x,alpha:1).getRed(&r,green:&g,blue:&b,alpha:nil);return[r,g,b]}

Ідея полягає в тому, щоб спочатку перетворити вхід з HSL в HSB, потім за допомогою конструктора HSB вбудованого кольорового об'єкта в Какао для отримання значень RGB.

Версія UIKit точно такої ж довжини, тому що єдиними замінами є:

  • CocoaUIKit
  • NSColorUIColor

Безумовно:

#if os(iOS)
    import UIKit
    typealias Color = UIColor
#elseif os(OSX)
    import Cocoa
    typealias Color = NSColor
#endif

typealias F = CGFloat

func f(h: F,s: F,l: F) -> [F] {
    var r = F(), g = F(), b = F()

    let x = s * min(1 - l, l)
    let n = 2 * x / max(l + x, 1e-9)

    let color = Color(hue: h, saturation: n, brightness: l + x, alpha: 1)
    color.getRed(&r, green: &g,blue: &b, alpha: nil)

    return [r, g, b]
}

Наступний фрагмент коду може бути використана для тестування, шляхом заміни значення h, sі l:

let h: CGFloat = 0
let s: CGFloat = 0
let l: CGFloat = 0

let result = f(h: h/360, s: s/100, l: l/100).map { Int(round($0*255)) }
print(result)

На жаль, я не можу надати посилання на Інтернет-пісочницю, оскільки всі вони працюють на Linux, що не включає какао.


2

GLSL (GL_ES) 160 144 134 131 байт

Відтінок знаходиться в діапазоні 0-6 (економить 3 байти)
Sat, light і rgb - 0-1

vec3 f(vec3 c){return mix(c.bbb,mix(clamp(vec3(-1,2,2)-abs(c.r-vec3(3,2,4))*vec3(-1,1,1),0.,1.),vec3(c.b>.5),abs(.5-c.b)*2.),c.g);}

Спробуйте це на книзі шейдерів

Використовували інструмент для вибору кольорів на екрані друку для перевірки правильності виводу,
за винятком невеликої помилки на 202 19 39 → 81 104 118, яка дала 80 104 118


1

R , 88 байт

function(h,s,l){v=(2*l+s*(1-abs(2*l-1)))/2;col2rgb(hsv(h,ifelse(v==0,v,(2*(v-l))/v),v))}

Спробуйте в Інтернеті!

Ця функція приймає як вхідні значення H, S і L як значення 0-1 у діапазоні та виводить значення RGB як значення 0–255. Він перетворює представлення HSL в представлення HSV, потім використовує hsv()для перетворення представлення HSV в R-колір (тобто шестигранний подання - #rrggbb), потім використовує col2rgb()для перетворення кольору R в значення RGB.


1

Желе ,  39  32 байт

-1 завдяки caird coinheringaahing ( %2тільки-но )
-1 та / або натхнення для -4 завдяки також і птахам coinheringaahing !

Ḥ;Ḃ’ACש"⁵×\;0+³_®H¤⁴Ḟị336Œ?¤¤œ?

Повна програма, що бере три аргументи командного рядка:

  • L, H, SВ діапазонах [0,1), [0,6)і , [0,1)відповідно ,

який друкує список, надаючи формат RGB як

  • [R, G, B] з кожним із трьох значень у діапазоні [0,1]

Примітка: Hтакож може загортатися так, як [0,360)хотілося б.

Спробуйте в Інтернеті!

Як?

Ḥ;Ḃ’ACש"⁵×\;0+³_®H¤⁴Ḟị336Œ?¤¤œ? - Main link: number, L (in [0,1]); number, H (in [0,6))
Ḥ                                - double                 =     2L
  Ḃ                              - modulo by 2            =              H%2
 ;                               - concatenate            = [   2L   ,   H%2]

   ’                             - decrement              = [   2L-1 ,   H%2-1]
    A                            - absolute               = [  |2L-1|,  |H%2-1|]
     C                           - complement             = [1-|2L-1|,1-|H%2-1|]
                                 -                        = [C/S     ,C/X]
         ⁵                       - 3rd program argument   = S  (in [0,1])
        "                        - zip with:
      ×                          -   multiplication       = [C,C/X]
       ©                         -   (copy the result, C, to the register)
           \                     - cumulative reduce with:
          ×                      -   multiplication       = [C, C/X*C] = [C,X]
            ;0                   - concatenate zero       = [C,X,0]
               ³                 - 1st program argument   = L
              +                  - add (vectorises)       = [C+L,X+L,L]
                   ¤             - nilad followed by link(s) as a nilad:
                 ®               -   recall from register = C
                  H              -   halve                = C/2
                _                - subtract               = [C+L-C/2,X+L-C/2,L-C/2]
                             ¤   - nilad followed by link(s) as a nilad:
                    ⁴            -   2nd program argument = H
                     Ḟ           -   floor                = floor(H)
                            ¤    -   nilad followed by link(s) as a nilad:
                       336       -     literal 336
                          Œ?     -     Shortest permutation of natural numbers with a
                                 -     lexicographical index of 336 in all permutations
                                 -     thereof            = [3,5,6,4,2,1]
                      ị          -   index into (1-indexed & modular)
                              œ? - get that permutation of [C+L-C/2,X+L-C/2,L-C/2]
                                 - implicit print

На жаль, звичайно. Спасибі!
Джонатан Аллан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.