如何在 RGB332 中创建抖动垂直渐变?

问题描述 投票:0回答:1

我正在尝试为 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));
        }
    }
}
c++ colors
1个回答
0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.