有過ui設計經驗的一定對2d圖形渲染中的color gradient 或多或少有些接觸,很多程式設計
語言也提供了gradient的接口,但是想知道它是怎麼實作的嘛?
本文介紹三種簡單的顔色梯度變化算法,就可以很容易實作常見的梯度變化算法
三種都要求提供兩個參數即起始顔色rgb值, 最終顔色rgb的值。
垂直梯度顔色變化,效果如下:
水準梯度顔色變化,效果如下:
水準與垂直兩個方向疊加梯度變化效果如下:
算法代碼及其解釋
計算起始顔色和終點顔色rgb之間內插補點代碼如下:
float rr = startcolor[0] - endcolor[0];
float gg = startcolor[1] - endcolor[1];
float bb = startcolor[2] - endcolor[2];
實作垂直梯度變化的代碼如下:
r = endcolor[0] + (int)(rr * ((float)row/255.0f) +0.5f);
g = endcolor[1] + (int)(gg * ((float)row/255.0f) +0.5f);
b = endcolor[2] + (int)(bb * ((float)row/255.0f) +0.5f);
實作水準梯度變化代碼如下:
// set gradient color valuefor each pixel
r = endcolor[0] + (int)(rr * ((float)col/255.0f) +0.5f);
g = endcolor[1] + (int)(gg * ((float)col/255.0f) + 0.5f);
b = endcolor[2] + (int)(bb * ((float)col/255.0f) +0.5f);
實作水準和垂直兩個方向上gradient疊加代碼如下:
r = endcolor[0] + (int)(rr * (((float)col * (float)row)/size) +0.5f);
g = endcolor[1] + (int)(gg * (((float)col * (float)row)/size) +0.5f);
b = endcolor[2] + (int)(bb * (((float)col * (float)row)/size) +0.5f);
程式對上面三種gradient方法分别放在三個不同的方法中,根據參數調用。
程式的完全java源代碼如下:
import java.awt.borderlayout;
import java.awt.dimension;
import java.awt.graphics;
import java.awt.graphics2d;
import java.awt.renderinghints;
import java.awt.image.bufferedimage;
import javax.swing.jcomponent;
import javax.swing.jframe;
public class colorgradientdemo extends jcomponent {
/**
*
*/
private static final long serialversionuid = -4134440495899912869l;
private bufferedimage image = null;
protected void paintcomponent(graphics g) {
graphics2d g2 = (graphics2d)g;
g2.setrenderinghint(renderinghints.key_antialiasing, renderinghints.value_antialias_on);
g2.drawimage(getimage(4), 5, 5, image.getwidth(), image.getheight(), null);
}
public bufferedimage getimage(int type) {
if(image == null) {
image = new bufferedimage(256, 256, bufferedimage.type_int_argb);
int[] rgbdata = new int[256*256];
if(type == 1) {
generatevgradientimage(rgbdata);
} else if(type == 2) {
generatehgradientimage(rgbdata);
} else {
generatehvgradientimage(rgbdata);
}
setrgb(image, 0, 0, 256, 256, rgbdata);
}
return image;
private void generatevgradientimage(int[] rgbdata) {
int[] startcolor = getstartcolor();
int[] endcolor = getendcolor();
float rr = startcolor[0] - endcolor[0];
float gg = startcolor[1] - endcolor[1];
float bb = startcolor[2] - endcolor[2];
int a=255;
int r=0, g=0, b=0;
int index = 0;
for(int row=0; row<256; row++) {
for(int col=0; col<256; col++) {
// set random color value for each pixel
// set gradient color value for each pixel
r = endcolor[0] + (int)(rr * ((float)row/255.0f) + 0.5f);
g = endcolor[1] + (int)(gg * ((float)row/255.0f) + 0.5f);
b = endcolor[2] + (int)(bb * ((float)row/255.0f) + 0.5f);
rgbdata[index] = ((a & 0xff) << 24) |
((r & 0xff) << 16) |
((g & 0xff) << 8) |
((b & 0xff));
index++;
private void generatehgradientimage(int[] rgbdata) {
r = endcolor[0] + (int)(rr * ((float)col/255.0f) + 0.5f);
g = endcolor[1] + (int)(gg * ((float)col/255.0f) + 0.5f);
b = endcolor[2] + (int)(bb * ((float)col/255.0f) + 0.5f);
private void generatehvgradientimage(int[] rgbdata) {
float size = (float)math.pow(255.0d, 2.0);
r = endcolor[0] + (int)(rr * (((float)col * (float)row)/size) + 0.5f);
g = endcolor[1] + (int)(gg * (((float)col * (float)row)/size) + 0.5f);
b = endcolor[2] + (int)(bb * (((float)col * (float)row)/size) + 0.5f);
public int[] getstartcolor() {
return new int[]{246,53,138};
public int[] getendcolor() {
return new int[]{0,255,255};
public void setrgb( bufferedimage image, int x, int y, int width, int height, int[] pixels ) {
int type = image.gettype();
if ( type == bufferedimage.type_int_argb || type == bufferedimage.type_int_rgb )
image.getraster().setdataelements( x, y, width, height, pixels );
else
image.setrgb( x, y, width, height, pixels, 0, width );
public static void main(string[] args) {
jframe frame = new jframe("gradient color panel");
frame.setdefaultcloseoperation(jframe.exit_on_close);
frame.getcontentpane().setlayout(new borderlayout());
// display the window.
frame.getcontentpane().add(new colorgradientdemo(), borderlayout.center);
frame.setpreferredsize(new dimension(280,305));
frame.pack();
frame.setvisible(true);
}