HSB 颜色选择器

问题描述

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

HSB

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

但是由于我非常擅长编码,所以我不知道该怎么办。我不太了解HSB。这是我的代码和我现在拥有的图片。

SS

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 更容易使用。 这是维基百科的图表: HSV Color Clynder 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 位置)
  • 顶部图像显示了具有相同饱和度和亮度的彩虹渐变,因此可以保持不变:
  • 只需将 i0-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[] 可以快得多。 但是有一些曲线球:

  1. 您需要先调用 loadPixels() 才能读取像素
  2. 您需要将 x,y 位置转换为一维数组索引:index = x + y * width
  3. 您需要在将值设置为 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();
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...