JS: Mengubah Warna RGB Menjadi HSV

Saat membuat aplikasi yang berkenaan dengan gambar dan warna, ada kalanya kita perlu mengkonversi representasi warna dari satu color space ke color space lain. Pada tulisan ini kita akan membuat ramuan yang bisa mengubah representasi warna RGB menjadi HSV.

Pada tahun 2011 aku pertama kali membuat plugin color picker untuk jQuery. Dan karena pemilihan warna oleh pengguna lebih natural dilakukan dengan color space HSV, sedangkan kode warna yang umum dipakai pada aplikasi web adalah RGB, maka konversi dari RGB ke HSV, dan sebaliknya, adalah bagian yang penting.

Pada dasarnya algoritma untuk mengkonversi hanya berkutat pada perhitungan matematika. Oleh karena itu walaupun pembahasan kali ini menggunakan JavaScript, namun implementasinya dapat dilakukan pada bahasa pemrograman apapun.

Berikut ini adalah potongan fungsi konversi HSV ke RGB dari plugin jQuery Wheel Color Picker yang pernah aku buat. Parameter input berupa tiga nilai untuk R, G, dan B, dengan skala 0-255.

function rgbToHsv( r, g, b ) {
	
	var h;
	var s;
	var v;

	var maxColor = Math.max(r, g, b);
	var minColor = Math.min(r, g, b);
	var delta = maxColor - minColor;
	
	// Calculate hue
	// To simplify the formula, we use 0-6 range.
	if(delta == 0) {
		h = 0;
	}
	else if(r == maxColor) {
		h = (6 + (g - b) / delta) % 6;
	}
	else if(g == maxColor) {
		h = 2 + (b - r) / delta;
	}
	else if(b == maxColor) {
		h = 4 + (r - g) / delta;
	}
	else {
		h = 0;
	}
	// Then adjust the range to be 0-1
	h = h/6;
	
	// Calculate saturation
	if(maxColor != 0) {
		s = delta / maxColor;
	}
	else {
		s = 0;
	}
	
	// Calculate value
	v = maxColor / 255;
	
	return { h: h, s: s, v: v };
};

Penjelasan

Model warna HSL dan HSV. (Oleh Jacob Rus / CC-BY-SA 3.0)

Color space HSV atau HSB terdiri dari tiga komponen:

  • Hue
  • Saturation
  • Value atau Brightness

Di sini kita perlu menghitung nilai untuk masing-masing komponen H, S, dan V. Pada contoh di atas proses konversi dilakukan dalam sebuah fungsi bernama rgbToHsv(). Pertama-tama kita buat sebuah fungsi yang menerima tiga parameter: R, G, B, dan siapkan tiga variabel untuk menampung hasil perhitungan H, S, dan V.

Nilai R, G, B menggunakan skala 0..255, sedangkan H, S, dan V menggunakan skala 0..1.

Fungsi rgbToHsv() akan mengembalikan nilai HSV dalam bentuk objek.

function rgbToHsv( r, g, b ) {
	
	var h;
	var s;
	var v;

	// Perhitungan HSV di sini...

	return { h: h, s: s, v: v };
}

Menghitung Hue

	var maxColor = Math.max(r, g, b);
	var minColor = Math.min(r, g, b);
	var delta = maxColor - minColor;

	// Calculate hue
	// To simplify the formula, we use 0-6 range.
	if(delta == 0) {
		h = 0;
	}
	else if(r == maxColor) {
		h = (6 + (g - b) / delta) % 6;
	}
	else if(g == maxColor) {
		h = 2 + (b - r) / delta;
	}
	else if(b == maxColor) {
		h = 4 + (r - g) / delta;
	}
	else {
		h = 0;
	}
	// Then adjust the range to be 0-1
	h = h/6;

Komponen Hue digambarkan sebagai gradasi warna dari merah, hijau, biru, dan kembali ke merah. Jika dihubungkan dengan komponen warna R, G, dan B, maka Hue bisa dibagi menjadi 6 segmen.

Hubungan antara RGB dengan Hue.
SegmenRGB
11 (max)0..10 (min)
20..11 (max)0 (min)
30 (min)1 (max)0..1
40 (min)0..11 (max)
50..10 (min)1 (max)
61 (max)0 (min)0..1

Pada implementasinya, nilai skala pada sumbu Y (gambar) ditentukan berdasarkan nilai terbesar dan terkecil di antara komponen R, G, dan B. Dan untuk memudahkan perhitungan, sumbu X kita beri skala 0..6.

Misalkan untuk warna ██████ (#3465a4) memiliki nilai RGB sebagai berikut:
R: 52, G: 101, B: 164

Maka nilai min adalah 52, dan max adalah 164. Selisih max dan min (delta) adalah 112.

Jika seluruh nilai R, G, B sama (max = min) maka nilai H tidak bisa ditentukan. Oleh sebab itu kita beri nilai H = 0 saja.

Jika nilai R terbesar dan G terkecil, maka H berada di segmen 6 (5 ≤ H < 6).
Jika nilai R terbesar dan B terkecil, maka H berada di segmen 1 (0 ≤ H < 1).

Jika nilai G terbesar dan B terkecil, maka H berada di segmen 2 (1 ≤ H < 2).
Jika nilai G terbesar dan R terkecil, maka H berada di segmen 3 (2 ≤ H < 3).

Jika nilai B terbesar dan R terkecil, maka H berada di segmen 4 (3 ≤ H < 4).
Jika nilai B terbesar dan G terkecil, maka H berada di segmen 5 (4 ≤ H < 5).

Pada contoh di atas nilai terbesar adalah B (164) dan nilai terkecil adalah R (52), jadi H berada di antara 3.0 hingga 4.0 (segmen 4). Untuk mengetahui nilai pastinya, kita pertimbangkan intensitas G terhadap delta. Apabila melihat gambar di atas, semakin besar intensitas G, maka H semakin ke kiri. Semakin kecil intensitas G, posisi H semakin ke kanan. Jadi H dapat dirumuskan sebagai berikut.

H = 4 - (G / delta)
= 4 - (101 / 112)
= 3.098214286

Lain halnya jika B terbesar, dan G yang merupakan nilai terkecil. Semakin besar intensitas R maka H semakin ke kanan. Semakin kecil intensitas R maka H semakin ke kiri. Jadi rumusannya berkebalikan.

H = 3 + (R / delta)

Untuk kasus B terbesar, kita dapat menggabungkan kedua rumus di atas menjadi:

H = 2 + (R - G) / delta

Demikian pula untuk kasus jika R atau G merupakan nilai terbesar.

Hasil perhitungan di atas masih menggunakan skala 0..6. Karena kita ingin nilai H antara 0..1, maka nilai H dibagi 6.

Apabila Hue digambarkan dalam bentuk lingkaran, maka nilai H juga bisa dikonversikan ke dalam satuan derajat dengan mengalikan nilai H dengan 360.

Menghitung Saturation

	// Calculate saturation
	if(maxColor != 0) {
		s = delta / maxColor;
	}
	else {
		s = 0;
	}

Saturation menunjukkan seberapa berwarnanya sebuah warna. Semakin tinggi nilai S, maka semakin berwarna. Apabila nilai S adalah 0, maka tidak berwarna sama sekali (antara hitam ke putih). Pada color space RGB, nilai S bisa diukur dari jarak antara komponen dengan nilai tertinggi dan terendah (delta). Nilai ini masih relatif terhadap nilai tertinggi. Agar diperoleh nilai absolut dengan skala 0..1, maka nilai tadi dibagi nilai terbesar (maxColor).

S = ( max(R,G,B) - min(R,G,B) ) / max(R,G,B)

Misalkan untuk warna ██████ (#3465a4) memiliki nilai RGB sebagai berikut:
R: 52, G: 101, B: 164

Nilai S dihitung menggunakan rumus di atas:

S = ( max(R,G,B) - min(R,G,B) ) / max(R,G,B)
= ( 164 - 52 ) / 164
= 0.68292682926829

Apabila warna yang dipilih adalah hitam (#000000) maka maxColor bernilai 0 sehingga perhitungan akan error. Karena itu perlu dilakukan pengecekan terhadap nilai maxColor.

Menghitung Value / Brightness

	// Calculate value
	v = maxColor / 255;

Menghitung kecerahan atau Value atau Brightness sangatlah mudah. Yaitu dengan mengambil nilai terbesar dari komponen R, G, B. Karena R, G, B menggunakan skala 0..255 sedangkan V menggunakan skala 0..1, maka nilai terbesar (maxColor) dibagi 255.

Misalkan untuk warna ██████ (#3465a4) memiliki nilai RGB sebagai berikut:
R: 52, G: 101, B: 164

Maka nilai V-nya adalah:

V = max(R,G,B) / 255
= 164 / 255
= 0.643137255

Contoh

Setelah menyelesaikan fungsi rgbToHsv(), mari coba gunakan dalam program.

var r = prompt("Nilai R");
var g = prompt("Nilai G");
var b = prompt("Nilai B");
var hsv = rgbToHsv(r, g, b);
alert("Warna rgb(" + r + "," + g + "," + b + ") dalam HSV adalah \nH: " + hsv.h + ", S: " + hsv.s + ", V: " + hsv.v);

Demikianlah cara mengubah warna dari color space RGB menjadi HSV. Kalau dibalik, bagaimana caranya untuk mengubah HSV menjadi RGB?

Tulis Komentar