图像处理之颜色梯度变化 (Color Gradient)

简介: 有过UI设计经验的一定对2D图形渲染中的Color Gradient 或多或少有些接触,很多编程 语言也提供了Gradient的接口,但是想知道它是怎么实现的嘛?   本文介绍三种简单的颜色梯度变化算法,就可以很容易实现常见的梯度变化算法 三种都要求提供两个参数即起始颜色RGB值, 最终颜色RGB的值。

有过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) {
		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 gradient color value for 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);
				
				rgbData[index] = ((a & 0xff) << 24) |
								((r & 0xff) << 16)  |
								((g & 0xff) << 8)   |
								((b & 0xff));
				index++;
			}
		}
	}
	
	private void generateHVGradientImage(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;
		float size = (float)Math.pow(255.0d, 2.0);
		for(int row=0; row<256; row++) {
			for(int col=0; col<256; col++) {
				// set random color value for each pixel
				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);
				
				rgbData[index] = ((a & 0xff) << 24) |
								((r & 0xff) << 16)  |
								((g & 0xff) << 8)   |
								((b & 0xff));
				index++;
			}
		}
	}
	
	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);
	}

}


目录
相关文章
|
机器学习/深度学习 API Python
100天搞定机器学习 番外:使用FastAPI构建机器学习API
100天搞定机器学习 番外:使用FastAPI构建机器学习API
100天搞定机器学习 番外:使用FastAPI构建机器学习API
|
Java 关系型数据库 MySQL
maven项目中添加MySql依赖失败(以及maven的安装到maven项目的使用过程)
maven项目中添加MySql依赖失败(以及maven的安装到maven项目的使用过程)
3837 1
maven项目中添加MySql依赖失败(以及maven的安装到maven项目的使用过程)
|
2月前
|
人工智能 数据可视化 API
私有化部署大模型并配置可视化界面
Ollama 是一款专为大模型本地私有化部署设计的轻量级工具,支持跨平台运行,兼容 Windows、macOS、Linux 系统及多种硬件架构。通过简单的命令行操作,用户可一键启动、下载与管理主流大语言模型,如 Llama 3、Mistral、Gemini、Phi 等。其核心优势在于自动化处理模型依赖、资源调度及环境配置,大幅简化部署流程,即使非专业技术人员也能快速上手。Ollama 的本地运行模式确保数据全程在私有环境流转,规避隐私泄露风险,适用于企业内部知识库、客服助手、本地数据分析等场景。
465 0
私有化部署大模型并配置可视化界面
|
8月前
|
Java C# C++
如何简单地理解Python中的if __name__ == '__main__'
本文介绍了Python中`__name__ == &#39;__main__&#39;`的作用和原理,解释了它如何作为程序入口控制代码执行。当.py文件直接运行时,`if __name__ == &#39;__main__&#39;`下的代码块会被执行;而当文件作为模块被导入时,该代码块不会执行。此外,文章还探讨了`__name__`变量在包结构中的作用,以及`__main__.py`文件与`python -m`命令的关系,详细说明了不同运行方式对模块路径的影响。
499 18
|
算法 Java 计算机视觉
图像处理之颜色梯度变化 (Color Gradient)
图像处理之颜色梯度变化 (Color Gradient)
252 0
|
Linux 数据安全/隐私保护
Linux cp命令使用指南:详细教程及实际应用场景解析
Linux cp命令使用指南:详细教程及实际应用场景解析
4317 0
|
机器学习/深度学习 存储 数据可视化
【MATLAB第45期】基于MATLAB的深度学习SqueezeNet卷积神经网络混凝土裂纹图像识别预测模型
【MATLAB第45期】基于MATLAB的深度学习SqueezeNet卷积神经网络混凝土裂纹图像识别预测模型
|
机器学习/深度学习 数据库
【MATLAB第49期】基于MATLAB的深度学习ResNet-18网络不平衡图像数据分类识别模型
【MATLAB第49期】基于MATLAB的深度学习ResNet-18网络不平衡图像数据分类识别模型
西门子S7-1200PLC变量表如何使用?如何声明、选用、显示、定义、更改变量?变量保持性如何设置?
在S7-1200 CPU的编程理念中,特别强调符号寻址的使用,在开始编写程序之前,用户应当为输入、输出、中间变量定义相应的符号名,也就是标签。具体步骤如下:
西门子S7-1200PLC变量表如何使用?如何声明、选用、显示、定义、更改变量?变量保持性如何设置?