我正在尝试为 ESPHome 显示编写一个函数,该函数将用颜色渐变填充给定的矩形。我在显示器上使用 RGB332 颜色,因此,它会创建颜色带而不是平滑过渡。这是我的代码:
void vGradient2(display::DisplayBuffer &it, int x1, int y1, int x2, int y2, Color &c1, Color &c2)
{
for(int y = y1; y <= y2; y++){
auto amnt = (float(y - y1) / float(y2 - y1)) * 255;
it.line(x1, y, x2, y, c1.gradient(c2, amnt));
}
}
我想知道我是否可以使用抖动 - 最好是拜耳抖动算法来改进这段代码。
是的,我尝试询问 ChatGPT,它在多次迭代后生成的代码仍然没有给我想要的结果。我认为这是因为它总是将颜色计算为 255 或 0。
void vgrad3(display::DisplayBuffer &it, int x1, int y1, int x2, int y2, Color &color1, Color &color2) {
// Compute the dimensions of the rectangle
int width = x2 - x1 + 1;
int height = y2 - y1 + 1;
// Allocate memory for the Bayer matrix
static uint8_t bayer[8][8] = {
{0, 48, 12, 60, 3, 51, 15, 63},
{32, 16, 44, 28, 35, 19, 47, 31},
{8, 56, 4, 52, 11, 59, 7, 55},
{40, 24, 36, 20, 43, 27, 39, 23},
{2, 50, 14, 62, 1, 49, 13, 61},
{34, 18, 46, 30, 33, 17, 45, 29},
{10, 58, 6, 54, 9, 57, 5, 53},
{42, 26, 38, 22, 41, 25, 37, 21}
};
// Iterate over each pixel in the rectangle
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
// Compute the color of the pixel based on the vertical gradient
float t = (float)(y - y1) / height;
uint8_t r = color1.red * (1 - t) + color2.red * t;
uint8_t g = color1.green * (1 - t) + color2.green * t;
uint8_t b = color1.blue * (1 - t) + color2.blue * t;
// Apply dithering using the Bayer matrix
int bx = x % 8;
int by = y % 8;
uint8_t threshold = bayer[bx][by];
uint8_t gray = (uint32_t)r * 77 + (uint32_t)g * 151 + (uint32_t)b * 28;
uint8_t color = (gray > threshold * 255) ? 255 : 0; // I do not think this is right
// Set the color of the pixel
uint8_t red = (color & 0xE0) >> 5;
uint8_t green = (color & 0x1C) >> 2;
uint8_t blue = color & 0x03;
uint8_t value = (red << 5) | (green << 2) | blue;
it.draw_pixel_at(x, y, ColorUtil::rgb332_to_color(value));
}
}
}
RGB332 是一种 8 位颜色,详见 https://en.wikipedia.org/wiki/List_of_monochrome_and_RGB_color_formats。 所以有 256 种不同的颜色表示。您期望什么样的平稳过渡?
此外,关于将 32 位值分配给 8 位变量,ChatGPT 是怎么说的? :)
uint8_t gray = (uint32_t)r * 77 + (uint32_t)g * 151 + (uint32_t)b * 28;
而且,正如您所建议的,这一行:
uint8_t color = (gray > threshold * 255) ? 255 : 0;// I do not think this is right
生成 255(白色)或 0(黑色)。不是我所说的任何类型的“渐变”。
那个片段
// Set the color of the pixel
uint8_t red = (color & 0xE0) >> 5;
uint8_t green = (color & 0x1C) >> 2;
uint8_t blue = color & 0x03;
似乎分解并重新组合了8位颜色,并没有改变原始值。
uint8_t value = (red << 5) | (green << 2) | blue;
最后,看起来 ESPHome 提供了一个
gradient()
功能:https://esphome.io/api/structesphome_1_1_color.html#abd2c92c49560dab88f43cfdeacf49138