RGB色彩
RGB色彩模式是工業(yè)界的一種顏色標(biāo)準(zhǔn),是通過對紅(R)椒袍、綠(G)藕施、藍(lán)(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的寇损,RGB即是代表紅、綠裳食、藍(lán)三個通道的顏色矛市。
HSL色彩( HSL color )
HSL色彩模式是工業(yè)界的一種顏色標(biāo)準(zhǔn),是通過對色相(H)诲祸、飽和度(S)浊吏、亮度(L)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,HSL即是代表色相救氯,飽和度卿捎,亮度三個通道的顏色。
H: Hue 色相
S:Saturation 飽和度
L :Lightness 亮度
HSL的H(hue)分量径密,代表的是人眼所能感知的顏色范圍午阵,這些顏色分布在一個平面的色相環(huán)上,取值范圍是0°到360°的圓心角享扔,每個角度可以代表一種顏色底桂。色相值的意義在于,我們可以在不改變光感的情況下惧眠,通過旋轉(zhuǎn)色相環(huán)來改變顏色籽懦。
HSL的S(saturation)分量,指的是色彩的飽和度氛魁,它用0%至100%的值描述了相同色相暮顺、亮度下色彩純度的變化。數(shù)值越大秀存,顏色中的灰色越少捶码,顏色越鮮艷,呈現(xiàn)一種從理性(灰度)到感性(純色)的變化或链。
HSL的L(lightness)分量惫恼,指的是色彩的亮度,作用是控制色彩的亮暗變化澳盐。它同樣使用了0%至100%的取值范圍祈纯。數(shù)值越小令宿,色彩越暗,越接近于黑色腕窥;數(shù)值越大粒没,色彩越亮,越接近于白色簇爆。
RGB轉(zhuǎn)HSL算法
(1)把RGB值轉(zhuǎn)成區(qū)間[0革娄,1]內(nèi)的數(shù)值。
(2)找出R,G和B中的最大值冕碟。
(3)計算亮度:L=(maxcolor + mincolor)/2
(4)如果最大和最小的顏色值相同拦惋,即表示灰色,那么S定義為0安寺,而H未定義并在程序中通常寫成0厕妖。
(5)否則,根據(jù)亮度L計算飽和度S:
????If L<0.5, S=(maxcolor-mincolor)/(maxcolor + mincolor)
????If L>=0.5, S=(maxcolor-mincolor)/(2.0-maxcolor-mincolor)
(6)計算色調(diào)H:
????If R=maxcolor, H=(G-B)/(maxcolor-mincolor)
????If G=maxcolor, H=2.0+(B-R)/(maxcolor-mincolor)
????If B=maxcolor, H=4.0+(R-G)/(maxcolor-mincolor)
????H=H*60.0,如果H為負(fù)值挑庶,則加360言秸。
HSL轉(zhuǎn)RGB算法。
(1)If S=0,表示灰色迎捺,定義R,G和B都為L.
(2)否則举畸,測試L:
????If L<0.5,temp2=L*(1.0+S)
????If L>=0.5,temp2=L+S-L*S
(3)temp1=2.0*L-temp2
(4)把H轉(zhuǎn)換到0~1。
(5)對于R,G,B凳枝,計算另外的臨時值temp3抄沮。方法如下:
????for R, temp3=H+1.0/3.0
????for G, temp3=H
????for B, temp3=H-1.0/3.0
????if temp3<0, temp3=temp3+1.0
????if temp3>1, temp3=temp3-1.0
(6)對于R,G,B做如下測試:
????If 6.0*temp3<1,color=temp1+(temp2-temp1)*6.0*temp3
????Else if 2.0*temp3<1,color=temp2
????Else if 3.0*temp3<2,
????color=temp1+(temp2-temp1)*((2.0/3.0)-temp3)*6.0
????Else color=temp1
色彩轉(zhuǎn)換JAVA實現(xiàn)代碼
public class TransformColor {
public static final double MaxRGB = 255.0;
public void rgbToHsl(Pixel pixel) {
int red = pixel.red;
int blue = pixel.blue;
int green = pixel.green;
double b, delta, g, max, min, r;
double hue, saturation, luminosity;
/*
* Convert RGB to HSL colorspace.
*/
r = (double) red / MaxRGB;
g = (double) green / MaxRGB;
b = (double) blue / MaxRGB;
max = Math.max(r, Math.max(g, b));
min = Math.min(r, Math.min(g, b));
hue = 0.0;
saturation = 0.0;
luminosity = (min + max) / 2.0;
delta = max - min;
if (delta == 0.0) {
pixel.hue = hue;
pixel.saturation = saturation;
pixel.luminosity = luminosity;
return;
}
saturation = delta / ((luminosity <= 0.5) ? (min + max) : (2.0 - max - min));
if (r == max)
hue = (g == min ? 5.0 + (max - b) / delta : 1.0 - (max - g) / delta);
else if (g == max)
hue = (b == min ? 1.0 + (max - r) / delta : 3.0 - (max - b) / delta);
else
hue = (r == min ? 3.0 + (max - g) / delta : 5.0 - (max - r) / delta);
hue /= 6.0;
pixel.hue = hue;
pixel.saturation = saturation;
pixel.luminosity = luminosity;
}
public void hslToRgb(Pixel pixel) {
double hue, saturation, luminosity;
// int red, green, blue;
double b, g, r, v, x, y, z;
hue = pixel.hue;
saturation = pixel.saturation;
luminosity = pixel.luminosity;
/*
* Convert HSL to RGB colorspace.
*/
v = (luminosity <= 0.5) ? (luminosity * (1.0 + saturation))
: (luminosity + saturation - luminosity * saturation);
if (saturation == 0.0) {
pixel.red = (int) (MaxRGB * luminosity + 0.5);
pixel.green = (int) (MaxRGB * luminosity + 0.5);
pixel.blue = (int) (MaxRGB * luminosity + 0.5);
return;
}
y = 2.0 * luminosity - v;
x = y + (v - y) * (6.0 * hue - Math.floor(6.0 * hue));
z = v - (v - y) * (6.0 * hue - Math.floor(6.0 * hue));
switch ((int) (6.0 * hue)) {
case 0:
r = v;
g = x;
b = y;
break;
case 1:
r = z;
g = v;
b = y;
break;
case 2:
r = y;
g = v;
b = x;
break;
case 3:
r = y;
g = z;
b = v;
break;
case 4:
r = x;
g = y;
b = v;
break;
case 5:
r = v;
g = y;
b = z;
break;
default:
r = v;
g = x;
b = y;
break;
}
pixel.red = (int) (MaxRGB * r + 0.5);
pixel.green = (int) (MaxRGB * g + 0.5);
pixel.blue = (int) (MaxRGB * b + 0.5);
}
}
輔助類Pixel代碼:
import java.awt.image.*;
public class Pixel {
public int red;
public int green;
public int blue;
public int alpha=0xFF;
public double hue;
public double saturation;
public double luminosity;
private int rgb;
public Pixel() {
}
public void setRGB(int rgb) {
red = (rgb & 0x00FF0000) / 0x00010000;
green = (rgb & 0x0000FF00) / 0x00000100;
blue = rgb & 0x000000FF;
alpha = (rgb >> 24)&0x0ff;
this.rgb = rgb;
}
public int getRGB() {
rgb = alpha<<24 | 0x00010000 * red | 0x00000100 * green | blue;
return this.rgb;
}
public static void setRgb(BufferedImage image, int x, int y, int red, int green, int blue) {
int rgb = 0xFF000000 | red * 0x00010000 | green * 0x00000100 | blue;
image.setRGB(x, y, rgb);
}
public static int pixelIntensity(int rgb) {
int red = (rgb&0x00FF0000)/0x00010000;
int green = (rgb&0x0000FF00)/0x00000100;
int blue = rgb&0x000000FF;
return (int) (0.299 * red + 0.587 * green + 0.114 * blue + 0.5);
}
}
改變圖像亮度、對比度飽和度
我們可以通過把對HSL顏色的處理實現(xiàn)對圖像亮度岖瑰,對比度飽和度的調(diào)節(jié)
調(diào)節(jié)亮度叛买、色相、對比度代碼如下
public static void modulate(double percent_hue, double percent_saturation, double percent_brightness, Pixel pixel) {
TransformColor transform = new TransformColor();
/*
* Increase or decrease color brightness, saturation, or hue.
*/
transform.rgbToHsl(pixel);
pixel.luminosity *= (0.01) * percent_brightness;
if (pixel.luminosity < 0.0)
pixel.luminosity = 0.0;
else if (pixel.luminosity > 1.0)
pixel.luminosity = 1.0;
pixel.saturation *= (0.01) * percent_saturation;
if (pixel.saturation < 0.0)
pixel.saturation = 0.0;
else if (pixel.saturation > 1.0)
pixel.saturation = 1.0;
pixel.hue *= (0.01) * percent_hue;
if (pixel.hue < 0.0)
pixel.hue += 1.0;
else if (pixel.hue > 1.0)
pixel.hue -= 1.0;
transform.hslToRgb(pixel);
}
public static BufferedImage hslImage(BufferedImage image, double satuPer, double huePer, double lumPer) {
BufferedImage bimg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Pixel pixel = new Pixel();
for (int y = 0; y < bimg.getHeight(); y++) {
for (int x = 0; x < bimg.getWidth(); x++) {
pixel.setRGB(image.getRGB(x, y));
modulate(huePer, satuPer, lumPer, pixel);
bimg.setRGB(x, y, pixel.getRGB());
}
}
return bimg;
}
調(diào)節(jié)對比度代碼如下:
public static void contrast(double percent, Pixel pixel) {
TransformColor transform = new TransformColor();
double alpha = percent / 100.0;
/*
* Enhance contrast: dark color become darker, light color become lighter.
*/
transform.rgbToHsl(pixel);
pixel.luminosity += alpha * (alpha * (Math.sin(Math.PI * (pixel.luminosity - alpha)) + 1.0) - pixel.luminosity);
if (pixel.luminosity > 1.0)
pixel.luminosity = 1.0;
else if (pixel.luminosity < 0.0)
pixel.luminosity = 0.0;
transform.hslToRgb(pixel);
}
public static BufferedImage contractImage(BufferedImage image, double percent) {
BufferedImage bimg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Pixel pixel = new Pixel();
for (int y = 0; y < bimg.getHeight(); y++) {
for (int x = 0; x < bimg.getWidth(); x++) {
pixel.setRGB(image.getRGB(x, y));
contrast(percent, pixel);
bimg.setRGB(x, y, pixel.getRGB());
}
}
return bimg;
}
實現(xiàn)效果
以下是對圖像亮度蹋订,飽和度率挣、對比度分別增加和減少的測試代碼:
public static void main(String[] argv) throws IOException {
BufferedImage img = read(new File("D:\\eclipse-workspace\\image-toolkit\\images\\girl.jpg"));
BufferedImage img2 = hslImage(img, 0, 0.5, 0);
ImageIO.write(img2, "jpeg", new File("girl-s+.jpg"));
img2 = hslImage(img, 0, -0.5, 0);
ImageIO.write(img2, "jpeg", new File("girl-s-.jpg"));
img2 = hslImage(img, 0, 0, 0.5);
ImageIO.write(img2, "jpeg", new File("girl-l+.jpg"));
img2 = hslImage(img, 0, 0, -0.5);
ImageIO.write(img2, "jpeg", new File(girl-l-.jpg"));
img2 = contractImage(img, 0.7);
ImageIO.write(img2, "jpeg", new File("girl-c+.jpg"));
img2 = contractImage(img, -0.7);
ImageIO.write(img2, "jpeg", new File("girl-c-.jpg"));
}
實現(xiàn)效果
其中第一張為原始圖片,第二三張為飽和度調(diào)節(jié)圖片露戒,第四五張為亮度調(diào)節(jié)圖片椒功,第六七張為對比度調(diào)節(jié)圖片