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

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

有过UI设计经验的一定对2D图形渲染中的Color Gradient 或多或少有些接触,很多编程


语言也提供了Gradient的接口,但是想知道它是怎么实现的嘛?



本文介绍三种简单的颜色梯度变化算法,就可以很容易实现常见的梯度变化算法


三种都要求提供两个参数即起始颜色RGB值, 最终颜色RGB的值。



垂直梯度颜色变化,效果如下:

0_1322353157O172.png



水平梯度颜色变化,效果如下:


0_1322353179JbbD.png


水平与垂直两个方向叠加梯度变化效果如下:

0_1322353186ulsG.png


算法代码及其解释



计算起始颜色和终点颜色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);
  }
 
}
相关文章
|
自然语言处理 算法 前端开发
C++与Doxygen:精通代码文档化之道
C++与Doxygen:精通代码文档化之道
797 0
|
10月前
|
人工智能 数据可视化 API
自学记录鸿蒙API 13:Calendar Kit日历功能从学习到实践
本文介绍了使用HarmonyOS的Calendar Kit开发日程管理应用的过程。通过API 13版本,不仅实现了创建、查询、更新和删除日程等基础功能,还深入探索了权限请求、日历配置、事件添加及查询筛选等功能。实战项目中,开发了一个智能日程管理工具,具备可视化管理、模糊查询和智能提醒等特性。最终,作者总结了模块化开发的优势,并展望了未来加入语音助手和AI推荐功能的计划。
604 1
|
10月前
|
缓存 Python
深入理解Python中的装饰器
本文旨在通过具体实例和详细解释,帮助读者深入理解Python中装饰器的工作原理及其在实际开发中的应用。我们将从装饰器的基本概念开始,逐步深入到其高级用法,包括自定义装饰器、带参数的装饰器以及类装饰器等。通过本文的学习,读者将能够掌握装饰器的核心思想,提高代码的可读性和可维护性。
|
Web App开发 前端开发
canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式
canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式
823 0
|
图形学 Python
pyqt的学习(三)----鼠标点击和按键处理
pyqt的学习(三)----鼠标点击和按键处理
312 1
|
算法
关于YUV转RGB的一些理论知识
YUV与RGB转换的那点事
867 0
|
测试技术
48【软件工程】面向对象开发全面总结
面向对象开发(OOP)是一种重要的编程范式,它将现实世界中的事物抽象成程序中的对象,通过对象之间的交互实现系统的功能。本文将全面介绍面向对象开发的含义、原则、基本原则、方法等方面的内容,帮助读者更好地理解和应用面向对象开发方法,提高代码的可维护性、可扩展性和可重用性。
336 0
|
IDE 编译器 开发工具
OpenMV颜色阈值设置
OpenMV颜色阈值设置
1124 0
|
Linux 芯片 Python
在树莓派中配置can接口
在树莓派中配置can接口
在树莓派中配置can接口