什么是存储颜色的好方法?

时间:2016-09-23 13:42:45

标签: c++ colors

我开始制作生活游戏"我想,如果我的状态可以超过1或0,那该怎么办。

但后来我需要不同的颜色。我希望颜色链接到网格/对象(网格是一个类)。

什么是存放彩色托盘以便快速/轻松访问的好/好的方式?

我目前不太理想的解决方案是为每个红色,绿色,蓝色和alpha值提供4个内存指针。

在我的班级中,我有一个函数将值v的颜色设置为rgba:

SetColor(v, r, g, b, a) //Set v to the appropriate color values

我想保留此功能以轻松修改颜色。

5 个答案:

答案 0 :(得分:6)

我使用的是非常简单的东西:4个花车

struct Color {
    float r, g, b, a;
};

然后,您可以拥有类似彩色托盘的东西:

// a Palette of 8 colors:
using palette_t = std::array<Color, 8>

palette_t myPalette { /* ... */ };

然后,在您的网格或对象类中,您可以使用索引引用颜色:

struct Grid {
    // lot's of code

private:
    std::size_t colorIndex = 0;
};

但后来你问如何轻松访问颜色(我想简单的访问来自Grid类)

有很多解决方案可以存在,而且大多数都取决于您的项目结构。这是其他许多想法。我希望它会激励你。

您可以存储返回正确颜色的函数:

struct Grid {
    // lot's of code

private:
    std::size_t colorIndex = 0;
    std::function<Color(std::size_t)> color;
};

然后,有一些能够正确创建网格的东西:

struct GridCreator {
    GridCreator(const palette_t& aPalette) : palette{aPalette} {}

    Grid create(std::size_t color) const {
        Grid grid;

        // create the grid

        grid.color = [this](std::size_t index) {
            return palette[index];
        };

        return grid;
    }

private:
    const palette_t& palette;
};

然后您可以自由访问调色板,而无需直接知道Grid类中的调色板。

答案 1 :(得分:4)

有一系列颜色:

std::vector<std::array<unsigned char, 4>> palette {
    {255, 0, 0, 255},  // red
    {0, 255, 0, 255},  // green
    {0, 0, 255, 255},  // blue
};

然后为每个字段存储数组中的索引(类型为size_t)。例如:

auto id = field[5][2];
auto color = palette[id];
auto r = color[0], alpha = color[3];

更改颜色非常简单:

palette[id] = {255, 0, 0, 127};

要添加新颜色,请使用:

palette.push_back({255, 0, 0, 127}).

或者,您可以定义一个简单的结构,以便您可以使用color.rcolor.alpha等并编写构造函数以便于颜色创建。

请注意,此示例是C ++ 11代码。

答案 2 :(得分:1)

Enums非常适合颜色类型的结构。

  1. 更多代码可读性。
  2. 更好的编译时优化。

    enum Color { red, green, blue };
    Color r = red;
    switch(r)
    {
        case red  : std::cout << "red\n";   break;
        case green: std::cout << "green\n"; break;
        case blue : std::cout << "blue\n";  break;
    }
    
  3. 针对您的特殊情况。 您可以将每个点的颜色存储为单个整数。

    uint32_t point_color = field[5][2].color;
    unsigned char* color = (unsigned char*)point_color[id];
    auto r = color[0], alpha = color[3];
    
    ///// 
    
    void SetColor(uint32_t& point_color,unsigned char r,
                   unsigned char g,unsigned char b,unsigned char a){
       point_color=r | (b*(1<<8)) | (g*(1<<16)) | (a*(1<<24));   
    }
    

    这种结构的优点

    1. 较小的杂乱。
    2. 仅限更快的位操作。
    3. 较小的记忆。

答案 3 :(得分:0)

你的问题是二元的:

  • 什么是存储颜色的好方法?
  • 什么是存放彩色托盘的好/体面的方式?

如果您真的只想存储颜色,我的建议不是将颜色存储为引用,而是将RGB值存储在类中的一个INT32中,您可以在其中获取并设置Reg / Green / Blue值。将此与.NET的相关方式进行比较。

这种方法的优点是它没有比使用指针更多的空间,并且它在get / set / comparisons中很快。

彩色调色板是一组颜色。如果要将所有使用的颜色切换为不同的颜色,则经常使用此功能。例如,如果你想要所有浅蓝色到朦胧蓝色,所有火红色到砖红色。

通过将调色板定义为预定义大小的数组或RGB值来使用它。历史上,调色板包含16,64或256个值,或者如果您只需要黑/白图片,则有时为2。 如果使用调色板,则网格中的每个点在调色板阵列中都有一个索引,并且您的网格具有当前的调色板。然后,网格G的点X的RGB值是G.CurrentPallette [X.PaletIndex]。一次更改网格的所有颜色意味着切换到另一个调色板:G.CurrentPalette = otherPalette。这是一种非常快速有效的方式来更改网格中的颜色

是否使用RGB方法或Palette方法取决于您的需要:

  • 您是否只想使用所有可能颜色的子集,是否要将完整子集更改为不同的子集:使用Palette方法
  • 是否要更改具有特定状态的点的颜色,例如将所有黄点更改为绿色,请使用调色板方法:将调色板中的黄色更改为绿色
  • 但是,如果您只想更改网格上的单个点,则使用RGB方法可能更有效。

答案 4 :(得分:0)

任何颜色值的间隔都是0到255,因此您需要3个unsigned char变量和另一个alph。我们做了一件事,将它们映射成一个结构:

typedef struct Color
{
    unsigned char _ucRed;
    unsigned char _ucGreen;
    unsigned char _ucBlue;
    unsigned char _ucAlpha;
}COLOR;