尝试使用颜色图绘制垂直线性渐变,但只使用了前 9 种颜色:为什么?
Trying to draw a vertical linear gradient using a map of colors, but only the first 9 colors are used: why?
(注意:在这个问题的末尾提供了一个最小的、完整的和可验证的例子)
总结
背景、目标和问题
我已经试过了
相关来源解释
预期结果、实际结果和问题
最小、完整且可验证的示例
背景、目标和问题
我正在尝试为一些像素设置动画以在 Java 中生成火焰动画。每个像素都被着色,从而绘制出从白色到黄色、黄色到红色以及红色到黑色的垂直线性渐变。此渐变从 canvas.
的底部到顶部
在执行开始时,所有像素都是黑色的,除了由坐标 y = height - 1
定义的白线,height
是 canvas 的高度。这条白线用于初始化渐变(“白色到黄色,黄色到...,等等。”)。
问题是渐变开始是正确的,但是在使用第9种颜色时就停止了。然后只有这个颜色被用来填充我的渐变,我不知道为什么。
我已经尝试过的
我有一个定义渐变的 RGB 值映射。
要知道将哪种颜色应用到名为 "A" 的像素的想法是检索其正下方像素的 RGB,然后在我的地图的所有 RGB 中获取此 RGB 的 ID。然后,我在同一张地图中获取此 ID + 1 下的 RGB 并将其应用于像素 A.
所以:
我检查了 returns RGB ID 的函数,给定这个 RGB:它似乎没问题,因为我没有抛出任何异常
我检查了我使用的缓冲图像是否正确更新。换句话说:如果一个像素已经着色的事实确实具有确定上面像素的颜色的结果:也可以
相关来源解释
调用绘制渐变的方法
想法是将所有像素设置为黑色,除了白色的底线。然后,我遍历每个 canvas' 像素并为其指定其下方垂直相邻像素的颜色。更准确地说,在我的颜色图中,我给它的颜色 ID = 该相邻像素颜色的 ID + 1。
Colors colors = new FireColors(new ArrayList<>());
gui.colorize(colors.getColorAtIndex(34), -1, -1); // Setting black anywhere
gui.colorize(colors.getColorAtIndex(0), -1, height - 1); // Setting white, in a lower line
try {
for(int y = height - 2; y >= 0; y--) {
for(int x = 0; x < width; x++) {
int below_pixel_rgb = gui.getRGBAtCoordinates(x, y + 1);
int index_of_found_color = colors.getIndexOfColor(below_pixel_rgb);
int index_of_color_to_apply = (index_of_found_color + 1) % colors.getSize();
gui.colorize(colors.getColorAtIndex(index_of_color_to_apply), x, y);
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
我如何给像素上色
我只是在遍历 canvas。
void colorize(Color color, int x_parameter, int y_parameter) {
for(int y = (y_parameter == -1 ? 0 : y_parameter); y <= (y_parameter == -1 ? this.getHeight() - 1 : y_parameter); y++) {
for(int x = (x_parameter == -1 ? 0 : x_parameter); x <= (x_parameter== -1 ? this.getWidth() - 1 : x_parameter); x++) {
buffered_image.setRGB(x, y, color.getRGB());
}
}
panel.repaint();
}
如何在颜色列表中找到像素颜色的索引?
int getIndexOfColor(int rgb) throws Exception {
for (int x = 0; x < colors.size(); x++) {
if(colors.get(x).getRGB() == rgb) {
return x;
}
}
throw new Exception("Color not found in the list!");
}
预期结果、实际结果和问题
我希望有几个垂直渐变(每个从下到上)。 "Several" 因为我的 canvas' 高度大于渐变颜色的数量,并且因为我使用模数来选择要应用的颜色。
实际结果是:我得到一个从白到黄的渐变,只有9种颜色,仅此而已。没有橙色,没有红色,没有黑色。确实:https://imgur.com/oQFJ52k
我的问题是:既然检索到了好 ID,并且为给定像素选择了好邻居,为什么我的渐变被阻挡到第 9 种颜色?换句话说:为什么不从一个精确的时刻选择好的颜色?
最小、完整且可验证的示例
Launcher.java
import java.util.ArrayList;
public class Launcher {
public static void main(String args[]) {
int width = 150, height = 150;
Gui gui = new Gui(width, height);
gui.setUp("DOOM-like fire");
gui.setVisible(true);
Colors colors = new FireColors(new ArrayList<>());
gui.colorize(colors.getColorAtIndex(34), -1, -1); // Setting black anywhere
gui.colorize(colors.getColorAtIndex(0), -1, height - 1); // Setting white, in a lower line
try {
for(int y = height - 2; y >= 0; y--) {
for(int x = 0; x < width; x++) {
int below_pixel_rgb = gui.getRGBAtCoordinates(x, y + 1);
int index_of_found_color = colors.getIndexOfColor(below_pixel_rgb);
int index_of_color_to_apply = (index_of_found_color + 1) % colors.getSize();
gui.colorize(colors.getColorAtIndex(index_of_color_to_apply), x, y);
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
Gui.java
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
class Gui extends JFrame {
private JPanel panel;
private BufferedImage buffered_image;
Gui(int width, int height) {
buffered_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
panel = new JPanel() {
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.drawImage(buffered_image, 0, 0, null);
}
};
}
void setUp(String title) {
setTitle(title);
setLayout(null);
setSize(buffered_image.getWidth(), buffered_image.getHeight());
setContentPane(panel);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
void colorize(Color color, int x_parameter, int y_parameter) {
for(int y = (y_parameter == -1 ? 0 : y_parameter); y <= (y_parameter == -1 ? this.getHeight() - 1 : y_parameter); y++) {
for(int x = (x_parameter == -1 ? 0 : x_parameter); x <= (x_parameter== -1 ? this.getWidth() - 1 : x_parameter); x++) {
buffered_image.setRGB(x, y, color.getRGB());
}
}
panel.repaint();
}
int getRGBAtCoordinates(int x, int y) {
return buffered_image.getRGB(x, y);
}
}
Colors.java
import java.awt.Color;
import java.util.List;
abstract class Colors {
List<Color> colors;
Color getColorAtIndex(int index) {
return colors.get(index);
}
int getIndexOfColor(int rgb) throws Exception {
for (int x = 0; x < colors.size(); x++) {
if(colors.get(x).getRGB() == rgb) {
return x;
}
}
throw new Exception("Color not found in the list!");
}
int getSize() {
return colors.size();
}
}
火灾Colors.java
import java.awt.Color;
import java.util.List;
class FireColors extends Colors {
FireColors(List<Color> colors) {
this.colors = colors;
this.colors.add(new Color(255, 255, 255));
this.colors.add(new Color(239, 239, 199));
this.colors.add(new Color(223, 223, 159));
this.colors.add(new Color(207, 207, 111));
this.colors.add(new Color(183, 183, 55));
this.colors.add(new Color(183, 183, 47));
this.colors.add(new Color(183, 175, 47));
this.colors.add(new Color(191, 175, 47));
this.colors.add(new Color(191, 167, 39));
this.colors.add(new Color(191, 167, 39));
this.colors.add(new Color(191, 159, 31));
this.colors.add(new Color(191, 159, 31));
this.colors.add(new Color(199, 151, 31));
this.colors.add(new Color(199, 143, 23));
this.colors.add(new Color(199, 135, 23));
this.colors.add(new Color(207, 135, 23));
this.colors.add(new Color(207, 127, 15));
this.colors.add(new Color(207, 119, 15));
this.colors.add(new Color(207, 111, 15));
this.colors.add(new Color(215, 103, 15));
this.colors.add(new Color(215, 95, 7));
this.colors.add(new Color(223, 87, 7));
this.colors.add(new Color(223, 87, 7));
this.colors.add(new Color(223, 79, 7));
this.colors.add(new Color(199, 71, 7));
this.colors.add(new Color(191, 71, 7));
this.colors.add(new Color(175, 63, 7));
this.colors.add(new Color(159, 47, 7));
this.colors.add(new Color(143, 39, 7));
this.colors.add(new Color(119, 31, 7));
this.colors.add(new Color(103, 31, 7));
this.colors.add(new Color(87, 23, 7));
this.colors.add(new Color(71, 15, 7));
this.colors.add(new Color(47, 15, 7));
this.colors.add(new Color(7, 7, 7));
}
}
您的问题是 FireColors
包含重复的颜色:
// FireColors, lines 20 and 21:
this.colors.add(new Color(191, 167, 39));
this.colors.add(new Color(191, 167, 39));
// more duplicate colors found later on!
问题出在你的选色算法上:
// Launcher lines 20 to 22:
int below_pixel_rgb = gui.getRGBAtCoordinates(x, y + 1);
int index_of_found_color = colors.getIndexOfColor(below_pixel_rgb);
int index_of_color_to_apply = (index_of_found_color + 1) % colors.getSize();
对于第 8 行,它从它下面的行读取颜色,找到它的索引 (7),添加一个和与颜色 #8 一致的颜色。
对于第 9 行,它从它下面的行读取颜色,找到它的索引 (8),添加一个和与颜色 #9 一致的颜色(与颜色 #8 相同)
对于第 10 行,它从它下面的行读取颜色,找到它的索引(8,因为 getIndexOfColor()
returns 第一个找到的索引,是 8,而不是 9!) , 添加一个和与颜色 #9 一致的颜色(与颜色 #8 相同)
要解决此问题,您应该重新设计颜色选择算法或使 FireColor
颜色独一无二。
(注意:在这个问题的末尾提供了一个最小的、完整的和可验证的例子)
总结
背景、目标和问题
我已经试过了
相关来源解释
预期结果、实际结果和问题
最小、完整且可验证的示例
背景、目标和问题
我正在尝试为一些像素设置动画以在 Java 中生成火焰动画。每个像素都被着色,从而绘制出从白色到黄色、黄色到红色以及红色到黑色的垂直线性渐变。此渐变从 canvas.
的底部到顶部在执行开始时,所有像素都是黑色的,除了由坐标 y = height - 1
定义的白线,height
是 canvas 的高度。这条白线用于初始化渐变(“白色到黄色,黄色到...,等等。”)。
问题是渐变开始是正确的,但是在使用第9种颜色时就停止了。然后只有这个颜色被用来填充我的渐变,我不知道为什么。
我已经尝试过的
我有一个定义渐变的 RGB 值映射。
要知道将哪种颜色应用到名为 "A" 的像素的想法是检索其正下方像素的 RGB,然后在我的地图的所有 RGB 中获取此 RGB 的 ID。然后,我在同一张地图中获取此 ID + 1 下的 RGB 并将其应用于像素 A.
所以:
我检查了 returns RGB ID 的函数,给定这个 RGB:它似乎没问题,因为我没有抛出任何异常
我检查了我使用的缓冲图像是否正确更新。换句话说:如果一个像素已经着色的事实确实具有确定上面像素的颜色的结果:也可以
相关来源解释
调用绘制渐变的方法
想法是将所有像素设置为黑色,除了白色的底线。然后,我遍历每个 canvas' 像素并为其指定其下方垂直相邻像素的颜色。更准确地说,在我的颜色图中,我给它的颜色 ID = 该相邻像素颜色的 ID + 1。
Colors colors = new FireColors(new ArrayList<>());
gui.colorize(colors.getColorAtIndex(34), -1, -1); // Setting black anywhere
gui.colorize(colors.getColorAtIndex(0), -1, height - 1); // Setting white, in a lower line
try {
for(int y = height - 2; y >= 0; y--) {
for(int x = 0; x < width; x++) {
int below_pixel_rgb = gui.getRGBAtCoordinates(x, y + 1);
int index_of_found_color = colors.getIndexOfColor(below_pixel_rgb);
int index_of_color_to_apply = (index_of_found_color + 1) % colors.getSize();
gui.colorize(colors.getColorAtIndex(index_of_color_to_apply), x, y);
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
我如何给像素上色
我只是在遍历 canvas。
void colorize(Color color, int x_parameter, int y_parameter) {
for(int y = (y_parameter == -1 ? 0 : y_parameter); y <= (y_parameter == -1 ? this.getHeight() - 1 : y_parameter); y++) {
for(int x = (x_parameter == -1 ? 0 : x_parameter); x <= (x_parameter== -1 ? this.getWidth() - 1 : x_parameter); x++) {
buffered_image.setRGB(x, y, color.getRGB());
}
}
panel.repaint();
}
如何在颜色列表中找到像素颜色的索引?
int getIndexOfColor(int rgb) throws Exception {
for (int x = 0; x < colors.size(); x++) {
if(colors.get(x).getRGB() == rgb) {
return x;
}
}
throw new Exception("Color not found in the list!");
}
预期结果、实际结果和问题
我希望有几个垂直渐变(每个从下到上)。 "Several" 因为我的 canvas' 高度大于渐变颜色的数量,并且因为我使用模数来选择要应用的颜色。
实际结果是:我得到一个从白到黄的渐变,只有9种颜色,仅此而已。没有橙色,没有红色,没有黑色。确实:https://imgur.com/oQFJ52k
我的问题是:既然检索到了好 ID,并且为给定像素选择了好邻居,为什么我的渐变被阻挡到第 9 种颜色?换句话说:为什么不从一个精确的时刻选择好的颜色?
最小、完整且可验证的示例
Launcher.java
import java.util.ArrayList;
public class Launcher {
public static void main(String args[]) {
int width = 150, height = 150;
Gui gui = new Gui(width, height);
gui.setUp("DOOM-like fire");
gui.setVisible(true);
Colors colors = new FireColors(new ArrayList<>());
gui.colorize(colors.getColorAtIndex(34), -1, -1); // Setting black anywhere
gui.colorize(colors.getColorAtIndex(0), -1, height - 1); // Setting white, in a lower line
try {
for(int y = height - 2; y >= 0; y--) {
for(int x = 0; x < width; x++) {
int below_pixel_rgb = gui.getRGBAtCoordinates(x, y + 1);
int index_of_found_color = colors.getIndexOfColor(below_pixel_rgb);
int index_of_color_to_apply = (index_of_found_color + 1) % colors.getSize();
gui.colorize(colors.getColorAtIndex(index_of_color_to_apply), x, y);
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
Gui.java
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
class Gui extends JFrame {
private JPanel panel;
private BufferedImage buffered_image;
Gui(int width, int height) {
buffered_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
panel = new JPanel() {
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.drawImage(buffered_image, 0, 0, null);
}
};
}
void setUp(String title) {
setTitle(title);
setLayout(null);
setSize(buffered_image.getWidth(), buffered_image.getHeight());
setContentPane(panel);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
void colorize(Color color, int x_parameter, int y_parameter) {
for(int y = (y_parameter == -1 ? 0 : y_parameter); y <= (y_parameter == -1 ? this.getHeight() - 1 : y_parameter); y++) {
for(int x = (x_parameter == -1 ? 0 : x_parameter); x <= (x_parameter== -1 ? this.getWidth() - 1 : x_parameter); x++) {
buffered_image.setRGB(x, y, color.getRGB());
}
}
panel.repaint();
}
int getRGBAtCoordinates(int x, int y) {
return buffered_image.getRGB(x, y);
}
}
Colors.java
import java.awt.Color;
import java.util.List;
abstract class Colors {
List<Color> colors;
Color getColorAtIndex(int index) {
return colors.get(index);
}
int getIndexOfColor(int rgb) throws Exception {
for (int x = 0; x < colors.size(); x++) {
if(colors.get(x).getRGB() == rgb) {
return x;
}
}
throw new Exception("Color not found in the list!");
}
int getSize() {
return colors.size();
}
}
火灾Colors.java
import java.awt.Color;
import java.util.List;
class FireColors extends Colors {
FireColors(List<Color> colors) {
this.colors = colors;
this.colors.add(new Color(255, 255, 255));
this.colors.add(new Color(239, 239, 199));
this.colors.add(new Color(223, 223, 159));
this.colors.add(new Color(207, 207, 111));
this.colors.add(new Color(183, 183, 55));
this.colors.add(new Color(183, 183, 47));
this.colors.add(new Color(183, 175, 47));
this.colors.add(new Color(191, 175, 47));
this.colors.add(new Color(191, 167, 39));
this.colors.add(new Color(191, 167, 39));
this.colors.add(new Color(191, 159, 31));
this.colors.add(new Color(191, 159, 31));
this.colors.add(new Color(199, 151, 31));
this.colors.add(new Color(199, 143, 23));
this.colors.add(new Color(199, 135, 23));
this.colors.add(new Color(207, 135, 23));
this.colors.add(new Color(207, 127, 15));
this.colors.add(new Color(207, 119, 15));
this.colors.add(new Color(207, 111, 15));
this.colors.add(new Color(215, 103, 15));
this.colors.add(new Color(215, 95, 7));
this.colors.add(new Color(223, 87, 7));
this.colors.add(new Color(223, 87, 7));
this.colors.add(new Color(223, 79, 7));
this.colors.add(new Color(199, 71, 7));
this.colors.add(new Color(191, 71, 7));
this.colors.add(new Color(175, 63, 7));
this.colors.add(new Color(159, 47, 7));
this.colors.add(new Color(143, 39, 7));
this.colors.add(new Color(119, 31, 7));
this.colors.add(new Color(103, 31, 7));
this.colors.add(new Color(87, 23, 7));
this.colors.add(new Color(71, 15, 7));
this.colors.add(new Color(47, 15, 7));
this.colors.add(new Color(7, 7, 7));
}
}
您的问题是 FireColors
包含重复的颜色:
// FireColors, lines 20 and 21:
this.colors.add(new Color(191, 167, 39));
this.colors.add(new Color(191, 167, 39));
// more duplicate colors found later on!
问题出在你的选色算法上:
// Launcher lines 20 to 22:
int below_pixel_rgb = gui.getRGBAtCoordinates(x, y + 1);
int index_of_found_color = colors.getIndexOfColor(below_pixel_rgb);
int index_of_color_to_apply = (index_of_found_color + 1) % colors.getSize();
对于第 8 行,它从它下面的行读取颜色,找到它的索引 (7),添加一个和与颜色 #8 一致的颜色。
对于第 9 行,它从它下面的行读取颜色,找到它的索引 (8),添加一个和与颜色 #9 一致的颜色(与颜色 #8 相同)
对于第 10 行,它从它下面的行读取颜色,找到它的索引(8,因为 getIndexOfColor()
returns 第一个找到的索引,是 8,而不是 9!) , 添加一个和与颜色 #9 一致的颜色(与颜色 #8 相同)
要解决此问题,您应该重新设计颜色选择算法或使 FireColor
颜色独一无二。