首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HSB色选器

HSB色选器
EN

Stack Overflow用户
提问于 2021-04-14 14:29:16
回答 1查看 1.1K关注 0票数 1

对于学校作业,我需要做这样的事情:

该500x500矩形应显示不同的色调,饱和度和亮度的任何颜色鼠标所指向的,有点像一个颜色选择器。

但既然我编码太烂了,我不知道该怎么做。我不太理解HSB。这是我的代码和一张我现在拥有的图片。

代码语言:javascript
复制
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);
}

任何帮助都将不胜感激。非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-14 22:24:11

使用colorMode(HSB)渲染彩虹已经做得很好了。我会将嵌套的for循环移动到安装程序中,以使其更高效:它只呈现一次并停留在那里,因为您没有调用background(),而且rect(0,50,500,500);低于彩虹梯度。

HSB实际上比RGB更容易使用。这是维基百科的一张图表:

SharkD,CC BY-SA3.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位置)
  • 上面的图像显示具有相同饱和度和亮度的彩虹梯度,因此可以保持不变:
  • 简单地将i0-499范围映射到0-100以映射到色调

例如:

代码语言:javascript
复制
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, 0, 499, 0, 100));
      int s = 100;
      int b = 100; 
      stroke(h, s, b);
      point(i, j);
    }
  }
  
  noStroke();
  
}

void draw() {
  fill(map(mouseX, 0, width, 0, 100), map(mouseY, 0, height, 0, 100), 100);
  rect(0, 50, 500, 500);
}

在这种情况下,0-500到0-50范围是微不足道的: 500 / 100 = 5,因此:

代码语言:javascript
复制
int h = i / 5;

将获得与int h = round(map(i, 0, 499, 0, 100));相同的结果,只是不必过多地考虑算术问题。

在嵌套的for循环中,您正在设置HSB颜色。在下一部分中,您需要获取/读取HSB颜色,幸运的是,处理已经为您提供了色调()饱和()亮度()。对于颜色选择器,您只需要hue()

要获取光标位置下的颜色,只需调用get(x, y),它将返回一个颜色,即这些坐标。

如果您查看渐变图像,您会注意到:

  • 左侧完全饱和,右侧完全饱和(灰色):X轴必须映射饱和度。
  • 顶部位是光的,底部是暗的:y轴必须映射亮度。

如果在顶部彩虹梯度上单击鼠标时读取hue(),则只需将x,y坐标映射到饱和度和亮度,就可以产生更大的梯度波纹:

代码语言:javascript
复制
float hue;

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, 0, 499, 0, 100));
      int s = 100;
      int b = 100; 
      stroke(h, s, b);
      point(i, 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, 0, 500, 100, 0));
      // swap output mapping range: brightness goes up when y decreases
      int brightness = round(map(j, 50, 550, 100, 0));
      stroke(hue, saturation, brightness);
      point(i, j);
    }
  }
}

你会注意到这有点慢。使用pixels[]可以更快。然而,有一些曲线球:

  1. 在读取像素之前,需要调用loadPixels()
  2. 您需要将x,y位置转换为一维数组索引:index = x + y * width
  3. 在将值设置为updatePixels()以更新后,需要调用pixels[]

这将运行得更快:

代码语言:javascript
复制
float hue;

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, 0, 499, 0, 100));
      int s = 100;
      int b = 100; 
      stroke(h, s, b);
      point(i, 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 , brightness mapping
  for (int i = 0; i < 500; i++) {
    for (int j = 50; j < 550; j++) {
      int saturation = round(map(i, 0, 500, 100, 0));
      // swap output mapping range: brightness goes up when y decreases
      int brightness = round(map(j, 50, 550, 100, 0));
      //stroke(hue, saturation, brightness);
      //point(i, j);
      pixels[i + j * width] = color(hue, saturation, brightness);
    }
  }
  // update
  updatePixels();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67093678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档