Nilai HSL ke RGB


17

Tujuan utama model warna RGB (Merah Hijau Biru) adalah untuk penginderaan, representasi dan tampilan gambar dalam sistem elektronik, seperti televisi dan komputer.

HSL (Hue Saturation Lightness) adalah model warna alternatif, yang dirancang pada tahun 1970-an oleh para peneliti grafis komputer untuk lebih menyelaraskan dengan cara penglihatan manusia memandang atribut-atribut pembuatan warna.

Berikut adalah artikel wiki untuk RGB dan HSL . Adalah umum untuk program grafis untuk melakukan perhitungan dalam HSL, dan kemudian dikonversi ke format yang disukai untuk sebagian besar layar: RGB.

Tugasnya adalah menulis fungsi / program yang menggunakan HSL sebagai input dan output RGB.

Anda dapat memilih representasi pilihan Anda untuk I / O, selama konsisten di antara mereka.

Misalnya, mereka dapat berupa array / tuple dengan 3 elemen atau objek dengan 3 properti bernama h,, sdan l, tetapi saya akan menerima variasi pintar lainnya, seperti menerima hsl sebagai integer (kehilangan presisi) dan menghasilkan integer rgb.

Input dapat dianggap aman dalam rentang dan format, yang keduanya dapat Anda putuskan. Saya sangat menyarankan rentang 0-1 0-1 0-1atau 0-360 0-100 0-100untuk hsl, dan 0-1 0-1 0-1atau 0-255 0-255 0-255untuk rgb.

Setiap jawaban diperlukan untuk menentukan kedua hal di atas, dan berikan berbagai variasi dalam jawaban Anda jika Anda sangat bangga dengan mereka, bahkan jika mereka tidak memiliki karakter yang lebih sedikit daripada variasi lainnya. Letakkan yang terkecil di atas.

Kasus uji semu untuk 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

Rumus untuk konversi dapat ditemukan di sini :

Ini sebagai cara yang bagus untuk memvisualisasikan konversi:


Kisaran disarankan untuk Hdari 0-360adalah [0,360), hal itu akan lebih baik ditulis sebagai 0-359?
Jonathan Allan

3
@ Jonathan Allan Saya pikir itu mungkin terlihat sedikit lebih membingungkan, bagi saya, yang menunjukkan bahwa 395.1 bukanlah input yang mungkin. Jika ada, menggunakan a-bnotasi itu salah dalam dirinya sendiri ketika berhadapan dengan nilai-nilai non-integer, tapi saya akan mengatakan itu ok untuk menjaga pertanyaan lebih mudah dibaca. Jika ada orang lain yang mengeluh, saya akan memikirkannya kembali, jadi terima kasih telah menunjukkannya
towc

Ya, menyetujui poin 359.1 - mungkin hanya menggunakan notasi standar [0,360)saat itu :)
Jonathan Allan

terkejut melihat tidak ada jawaban glsl;)
towc

Jawaban:


8

JavaScript (ES6), 98 95 94 byte

Mengambil H dalam [0,360) dan S / L dalam [0,1) . Output R , G dan B sebagai array dari 3 float di [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))

Uji kasus

Cuplikan ini mengubah hasilnya kembali menjadi [0,255] .

Bagaimana?

Kode inisialisasi

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)

Kode utama

[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]

Permutasi dari (0, C, X)

Bagian yang sedikit rumit adalah untuk menghasilkan permutasi yang benar (0, C, X) sesuai dengan sudut komponen rona. Seperti yang ditunjukkan pada gambar berikut, setiap nilai kolom diambil dari urutan siklus yang sama dari periode 6 , mulai dari offset yang berbeda. Dalam kode di atas, kita menggunakan - ~ H bukan hanya + H karena kita perlu memaksa H ke integer. Maka dari itu offset (5,3,1) bukannya (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

Akankah mengambil Hdi [0,6)dan keluaran di [0,1]save beberapa byte?
Jonathan Allan

@ Jonathan Allan Ah, saya tidak melihat format I / O longgar. Terima kasih!
Arnauld

4

Mathematica, 155 byte

(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)&


Cobalah online!



1
@ sebenarnya manusia saya tidak berpikir itu benar seperti HueHSB (AKA HSV) bukan HSL (lihat gambar 2a dan 2b di halaman Wikipedia yang terhubung).
Jonathan Allan

1
Jenny - jika benar tidak ada alasan untuk tidak mempostingnya sebagai jumlah byte dengan non-bawaan Anda di bawah ini!
Jonathan Allan

1
@ Jonathan Allan Oh, begitulah. Agak menyebalkan bagaimana RGBColorada tapi HSLColortidak. > _>
totallyhuman

Apakah ada versi yang tidak disunat ini?
user76284

4

Python 2 , 32 byte

from colorsys import*;hls_to_rgb

Cobalah online!

Fungsi ini sebenarnya dibangun ke dalam Python melalui bagian hls_to_rgbdalam colorsysperpustakaan. Input format tambang adalah rentang 0-1 dari HLS (bukan HSL, keduanya adalah akronim umum untuk hal yang sama [meskipun, HSL lebih umum]). Dan tambang menghasilkan nilai RGB dalam tupel dengan rentang dari 0 hingga 1.

Kredit

Terima kasih kepada Jonathan Allan untuk menunjukkan bahwa saya hanya perlu mengimpornya (dan kemudian membantu saya mengurangi jumlah byte).


Saya pikir ini hanya bisa 31 byte from colorsys import hls_to_rgbkarena daripada memberi kita fungsi yang dapat digunakan kembali. Edit - jadikan 21 sebagai from colorsys import*.
Jonathan Allan

1
@JonathanAllan Terima kasih, diperbarui.
Neil

Sebenarnya mungkin hanya import colorsysuntuk 15!
Jonathan Allan

@ JonathanAllan Bagus, diperbarui lagi.
Neil

1
betapapun benarnya, saya pikir ini mempengaruhi semangat codegolfing terlalu banyak: /
towc

4

C ++, 228 221 byte

-7 byte terima kasih kepada Zacharý

#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)}

Argumen keduanya adalah array yang memiliki ukuran minimal 3 elemen (yaitu float hsl[3]danint rgb[3]

Baik. Sekarang, bagaimana cara kerjanya? Apa itu array panjang?

Yah, ini bukan array panjang, ini intarray. Di samping lelucon, array menunjukkan dengan berapa banyak posisi kita menggeser CX dan 0 ketika kita ingin memilih permutasi yang benar, + 2. Ingat bagaimana R ', G' dan B 'dipilih?

Bagaimana R ', G' dan B 'dipilih

Katakanlah kita memiliki urutan "normal" yaitu {C, X, 0}

Sekarang, ketika permutasi pertama (yaitu {C, X, 0}) dipilih, Anda tidak perlu menggeser, yang persis sama dengan pergeseran kanan oleh 0. Jadi 3 elemen pertama dari array adalah 0,0 dan 0

Untuk permutasi kedua ({X, C, 0}), kita perlu menggeser ke kanan C sebesar 1, dan menggeser ke kiri X sebesar -1, sehingga elemen array keempat, kelima dan keenam adalah 1, -1 dan 0

Dan seterusnya...

Dengan kasus permutasi ke-3 dan ke-4, saya harus ke kiri menggeser 0 dengan 2, jadi bergeser ke kanan dengan -2. Karena ada lebih dari 2 angka yang negatif, saya lebih suka menambahkan 2 untuk setiap elemen dalam array dan mengurangi 2 pada saat runtime (untuk alasan bermain golf, hanya memiliki seluruh angka dalam array).



4

Python 2 , 119 112 byte

def f(h,s,l):c=(1-abs(2*l-1))*s;m=l-c/2;x=c*(1-abs(h%2-1))+m;c+=m;return[c,m,x,c,m,x,m,c,x,m][7-int(h)*5%9:][:3]

Cobalah online!

Mengambil input sebagai H=[0,6[, S=[0,1], L=[0,1]


3

HTML + JavaScript (ES6), 8 + 88 = 96 byte

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>

Mengambil input sebagai sudut dan dua persentase. Saya mencetak snippet HTML <p id=p>dan fungsi tanda panah JavaScript. Saya tidak tahu apa yang digunakan browser pembulatan, jadi jawaban saya mungkin sedikit berbeda dari milik Anda.


2

Cepat 4, 218 byte

Menerima nilai HSL dalam rentang [0,1] sebagai argumen, dan mengembalikan array yang berisi nilai RGB dalam rentang yang sama:

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]}

Idenya adalah untuk mengkonversi input pertama dari HSL ke HSB, kemudian menggunakan konstruktor HSB dari objek warna bawaan di Cocoa untuk mengambil nilai RGB.

Versi UIKit memiliki panjang yang sama persis, karena satu-satunya penggantian adalah:

  • CocoaUIKit
  • NSColorUIColor

Tidak Disatukan:

#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]
}

Potongan berikut dapat digunakan untuk pengujian, dengan hanya mengganti nilai-nilai h, sdan 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)

Sayangnya saya tidak dapat memberikan tautan ke kotak pasir online, karena semuanya berjalan di Linux, yang tidak termasuk Cocoa.


2

GLSL (GL_ES) 160 144 134 131 byte

Hue berada di kisaran 0-6 (menghemat 3 byte)
Sat, light dan 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);}

Cobalah di buku shader

Alat colorpicker yang digunakan pada printscreen untuk menguji output yang benar,
kecuali kesalahan kecil pada 202 19 39 → 81 104 118, yang memberi 80 104 118


1

R , 88 byte

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))}

Cobalah online!

Fungsi ini sebagai input nilai H, S, dan L sebagai nilai rentang 0-1 dan menghasilkan nilai RGB sebagai nilai rentang 0-255. Ia mengubah representasi HSL ke representasi HSV, kemudian menggunakan hsv()untuk mengubah representasi HSV ke warna R (yaitu representasi hex - #rrggbb), kemudian digunakan col2rgb()untuk mengubah warna R ke nilai RGB.


1

Jelly ,  39  32 byte

-1 berkat caird coinheringaahing ( %2hanya saja )
-1 dan / atau inspirasi untuk -4 terima kasih kepada caird coinheringaahing juga!

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

Program lengkap yang mengambil tiga argumen baris perintah:

  • L, H, SDalam rentang [0,1), [0,6)dan [0,1)masing-masing

yang mencetak daftar yang memberikan format RGB sebagai

  • [R, G, B] dengan masing-masing dari tiga nilai dalam rentang [0,1]

Catatan: Hmungkin juga membungkus seperti biasa [0,360).

Cobalah online!

Bagaimana?

Ḥ;Ḃ’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

Ups, tentu saja. Terima kasih!
Jonathan Allan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.