色譜簡介


色譜是指從一個顏色過渡另一個顏色的變化,這個變化中間可以經過多個顏色,也可以是兩個顏色之間的變化,例如灰階色譜就是由黑至白的雙色漸層色譜。

大部份的情況下我們可以直接使用RGB來指定繪圖色彩,但製作色譜在指定漸層色或陰影色時相當有用,這邊介紹簡單的256色譜製作,其中兩個顏色之間的變化共有240個色階(編號0至239),剩下的16個色階(編號240到255)則填上16色模式。

雙色漸層色譜

雙色漸層色譜兩個顏色之間的漸層變化,這樣的漸層變化適用於陰影色彩的指定,這邊介紹的色譜起始與結束顏色的指定可以是16色模式中的0∼7號顏色。

多色漸層色譜

多色漸層色譜是指兩個顏色的中間還經過數個顏色的色譜變化,例如指定藍色與洋紅色的話,中間會經過藍色->綠色->黃色->紅色- >洋紅色等顏色,中間任兩色之間以漸層的方式過渡。

多色循環色譜

如果您將多色漸層色譜的起始與終止顏色設定為相同的話,就是循環色譜了,這種色譜通常會使用圓來強調出循環變化。
以下是使用Java所製作的色譜變化程式參考:
  • Demo.java
package cc.openhome;

import java.awt.*;
import javax.swing.JApplet;

public class Demo extends JApplet {
protected static final Color[] COLOR_16 = {
new Color(0, 0, 0), new Color(0, 0, 255),
new Color(0, 255, 0), new Color(0, 255, 255),
new Color(255, 0, 0), new Color(255, 0, 255),
new Color(255, 255, 0), new Color(255, 255, 255),
new Color(192, 192, 192), new Color(128, 128, 255),
new Color(128, 255, 128), new Color(128, 255, 255),
new Color(255, 128, 128), new Color(255, 128, 255),
new Color(255, 255, 128), new Color(128, 128, 128)
};
protected Color[] colors = new Color[256];

// 雙色漸層色譜
public void setShdSpectra(int c0, int c1) {
int[] rgb = new int[3];
int[] col0 = new int[3];
int[] col1 = new int[3];

c0 = c0 % 8;
c1 = c1 % 8;
col0[0] = (c0 >> 2) & 1;
col0[1] = (c0 >> 1) & 1;
col0[2] = c0 & 1;
col1[0] = (c1 >> 2) & 1;
col1[1] = (c1 >> 1) & 1;
col1[2] = c1 & 1;

for (int i = 0; i < 240; i++) {
for (int j = 0; j < 3; j++) {
rgb[j] = 16 + col0[j] * (239 - i) + col1[j] * i;
}
colors[i] = new Color(rgb[0], rgb[1], rgb[2]);
}

for (int i = 240; i < 256; i++) {
colors[i] = COLOR_16[i - 240];
}
}

// 多色漸層色譜
public void setCycSpectra(int c0, int c1) {
int d;
int[] n = {0, 2, 1, 4, 5, 3};
int[] rgb = new int[6];
int[][] st = {{2, 4, 0},
{4, 0, 2},
{3, 5, 1},
{0, 2, 4},
{1, 3, 5},
{5, 1, 3}};

c0 = c0 % 8;
c1 = c1 % 8;
if ((c0 == 0) || (c0 == 7)) {
c0 = 1;
}
if ((c1 == 0) || (c1 == 7)) {
c1 = 1;
}
if (c0 == c1) {
d = 6;
} else {
d = (n[c1 - 1] - n[c0 - 1] + 6) % 6;
}

for (int i = 0; i < 240; i++) {
for (int j = 0; j < 3; j++) {
rgb[j] = getColor((i / (240 / d) + st[c0 - 1][j]) % 6,
i % (240 / d), d);
}
colors[i] = new Color(rgb[0], rgb[1], rgb[2]);
}

for (int i = 240; i < 256; i++) {
colors[i] = COLOR_16[i - 240];
}
}

private int getColor(int i, int j, int d) {
switch (i) {
case 0: return 255;
case 1: return 255 - d * j;
case 2: return 15 + d;
case 3: return 15 + d;
case 4: return 15 + d + d * j;
case 5: return 255;
default: return 0;
}
}

public void paint(Graphics g) {
setBackground(Color.white);

setShdSpectra(0, 7);
for (int i = 0; i < 256; i++) {
g.setColor(colors[i]);
g.drawLine(30 + i, 30, 30 + i, 120);
}

setCycSpectra(2, 8);
for (int i = 0; i < 256; i++) {
g.setColor(colors[i]);
g.drawLine(30 + i, 150, 30 + i, 240);
}
}
}

以下是使用HTML5 Canvas的方式(如果瀏覽器支援HTML5 Canvas,例如最新版的Firexfox、Chrome、IE9等,可以直接將下面的內容存為HTML或按下檔名連結,直接載入瀏覽器執行觀看結果:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=Big5" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
function Color(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
this.toString = function() {
return 'rgb(' +
[this.r, this.g, this.b].join() + ')';
};
}

var COLOR_16 = [
new Color(0, 0, 0), new Color(0, 0, 255),
new Color(0, 255, 0), new Color(0, 255, 255),
new Color(255, 0, 0), new Color(255, 0, 255),
new Color(255, 255, 0), new Color(255, 255, 255),
new Color(192, 192, 192), new Color(128, 128, 255),
new Color(128, 255, 128), new Color(128, 255, 255),
new Color(255, 128, 128), new Color(255, 128, 255),
new Color(255, 255, 128), new Color(128, 128, 128)
];

var colors = [];

// 雙色漸層色譜
function setShdSpectra(c0, c1) {
var rgb = [];
var col0 = [];
var col1 = [];

c0 = c0 % 8;
c1 = c1 % 8;
col0[0] = (c0 >> 2) & 1;
col0[1] = (c0 >> 1) & 1;
col0[2] = c0 & 1;
col1[0] = (c1 >> 2) & 1;
col1[1] = (c1 >> 1) & 1;
col1[2] = c1 & 1;

for(var i = 0; i < 240; i++) {
for(var j = 0; j < 3; j++) {
rgb[j] = 16 + col0[j] * (239 - i) + col1[j] * i;
}
colors[i] = new Color(rgb[0], rgb[1], rgb[2]);
}

for(var i = 240; i < 256; i++) {
colors[i] = COLOR_16[i - 240];
}
}

// 多色漸層色譜
function setCycSpectra(c0, c1) {
var d;
var n = [0, 2, 1, 4, 5, 3];
var rgb = [];
var st = [
[2, 4, 0],
[4, 0, 2],
[3, 5, 1],
[0, 2, 4],
[1, 3, 5],
[5, 1, 3]
];

c0 = c0 % 8;
c1 = c1 % 8;
if ((c0 === 0) || (c0 === 7)) {
c0 = 1;
}
if ((c1 === 0) || (c1 === 7)) {
c1 = 1;
}
if (c0 === c1) {
d = 6;
} else {
d = (n[c1 - 1] - n[c0 - 1] + 6) % 6;
}

for(var i = 0; i < 240; i++) {
for(var j = 0; j < 3; j++) {
rgb[j] = getColor(
(parseInt(i / (240 / d)) + st[c0 - 1][j]) % 6,
i % (240 / d), d);
}
colors[i] = new Color(rgb[0], rgb[1], rgb[2]);
}

for(var i = 240; i < 256; i++) {
colors[i] = COLOR_16[i - 240];
}
}

function getColor(i, j, d) {
switch (i) {
case 0: return 255;
case 1: return 255 - d * j;
case 2: return 15 + d;
case 3: return 15 + d;
case 4: return 15 + d + d * j;
case 5: return 255;
default: return 0;
}
}

var canvas1 = document.getElementById('canvas1');
var context = canvas1.getContext('2d');


setShdSpectra(0, 7);
for(var i = 0; i < 256; i++) {
context.beginPath();
context.strokeStyle = colors[i].toString();
context.moveTo(30 + i, 30);
context.lineTo(30 + i, 120);
context.stroke();
context.closePath();
}


setCycSpectra(2, 8);
for(var i = 0; i < 256; i++) {
context.beginPath();
context.strokeStyle = colors[i].toString();
context.moveTo(30 + i, 150);
context.lineTo(30 + i, 240);
context.stroke();
context.closePath();
}
};
</script>
</head>
<body>
<canvas id="canvas1" width="300" height="300"></canvas>
</body>
</html>

以下是在Firefox中觀看的結果: