如何解决HSB 颜色选择器
对于学校作业,我需要做这样的事情: 500x500 矩形应该显示鼠标指向的任何颜色的不同色调、饱和度和亮度,有点像颜色选择器。
但是由于我非常擅长编码,所以我不知道该怎么办。我不太了解HSB。这是我的代码和我现在拥有的图片。
void setup() {
size(500,550);
}
void draw() {
nostroke();
colorMode(HSB,100);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 50; j++) {
int h = i-200;
int s = j+500;
int b = 500 + j;
stroke(h,s,b);
point(i,j);
}
}
nostroke();
fill(mouseX,mouseY);
rect(0,50,500,500);
}
任何帮助将不胜感激。非常感谢!
解决方法
您使用 colorMode(HSB)
渲染彩虹已经做得很好。
我会将嵌套的 for 循环移动到 setup 以使其更高效:它会渲染一次并停留在那里,因为您没有调用 background()
并且 rect(0,50,500,500);
低于彩虹渐变。
HSB 实际上比 RGB 更容易使用。 这是维基百科的图表: SharkD,CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0,来自维基共享资源
值与亮度相同。 色调通常在 0-360 度范围内,因此图片在彩虹圈中旋转,从红色开始,以红色结束。 假设您从红色开始,0 度色相,而您知道黄色是 60 度色相。直觉上,您会在 30 度的红色和黄色之间找到橙色。 事实上,如果你每 60 度旋转一次,你会在 360/0 处穿过红色、黄色、绿色、青色、蓝色、洋红色并返回红色。
饱和度和亮度通常在 0-100% 之间。 请注意上图中的饱和度从中心增加:0 饱和度 = 灰色,100% 饱和度 = 全色调。
亮度在图表中从下到上增加。
将色调、饱和度和亮度映射到 0-100 范围有点奇怪。也许目的是通过将色调也视为百分比来简化事情。
让事情变得更简单的一件事是 map()
函数。
它将数字从一个范围映射到另一个范围。
例如,这段代码试图将 i、j 位置重新映射到色调和饱和度。
-
i,j
在 0-500,0-50 范围内(x,y 位置) - 顶部图像显示了具有相同饱和度和亮度的彩虹渐变,因此可以保持不变:
- 只需将
i
从0-499
范围映射到0-100
以映射到色调
例如:
void setup() {
size(500,550);
colorMode(HSB,100);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 50; j++) {
// remap i (x -> width) to 0 - 100 range for hue
// since map returns a float,round helps make that an int
int h = round(map(i,499,100));
int s = 100;
int b = 100;
stroke(h,s,b);
point(i,j);
}
}
noStroke();
}
void draw() {
fill(map(mouseX,width,100),map(mouseY,height,100);
rect(0,500);
}
在这种特殊情况下,0-500 到 0-50 的范围是微不足道的:500 / 100 = 5, 因此:
int h = i / 5;
会得到与 int h = round(map(i,100));
相同的结果,
只是不必过多考虑算术。
在嵌套的 for 循环中,您正在设置 HSB 颜色。
对于下一部分,您需要获取/读取 HSB 颜色
幸运的是,Processing 已经为您提供了 hue()、saturation() 和 brightness()。对于颜色选择器,您只需要 hue()
。
要获取光标位置下的颜色,只需调用 get(x,y)
即可返回这些坐标的颜色。
如果您查看渐变图像,您会注意到:
- 左侧完全饱和,右侧去饱和(灰色):x 轴必须映射饱和
- 顶部亮而底部暗:y 轴必须映射亮度
如果您在鼠标点击顶部彩虹渐变时阅读 hue()
,则可以通过简单地将 x、y 坐标映射到饱和度和亮度来制作更大的渐变:
float hue;
void setup() {
size(500,j);
}
}
noStroke();
}
void draw() {
// pick colour (hue)
if(mousePressed){
// check if the mouse was pressed on the top side only
if((mouseX >= 0 && mouseX <= 500) &&
(mouseY >= 0 && mouseY <= 50)){
hue = hue(get(mouseX,mouseY));
}
}
// render saturation,brightness mapping
for (int i = 0; i < 500; i++) {
for (int j = 50; j < 550; j++) {
int saturation = round(map(i,100,0));
// swap output mapping range: brightness goes up when y decreases
int brightness = round(map(j,550,0));
stroke(hue,saturation,brightness);
point(i,j);
}
}
}
您会注意到这运行速度有点慢。使用 pixels[]
可以快得多。
但是有一些曲线球:
- 您需要先调用
loadPixels()
才能读取像素 - 您需要将 x,y 位置转换为一维数组索引:
index = x + y * width
- 您需要在将值设置为
pixels[]
后调用updatePixels()
进行更新
这会运行得更快:
float hue;
void setup() {
size(500,j);
}
}
noStroke();
}
void draw() {
// make latest pixels[] data available
loadPixels();
// pick colour (hue)
if(mousePressed){
// check if the mouse was pressed on the top side only
if((mouseX >= 0 && mouseX <= 500) &&
(mouseY >= 0 && mouseY <= 50)){
//hue = hue(get(mouseX,mouseY));
hue = hue(pixels[mouseX + mouseY * width]);
}
}
// render saturation,0));
//stroke(hue,brightness);
//point(i,j);
pixels[i + j * width] = color(hue,brightness);
}
}
// update
updatePixels();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。