从 Guid 生成颜色

3

我的数据库中有各种被唯一的System.Guid标识的对象。当我展示它们时,我希望每个对象都有一个基于其guid的唯一颜色。

所以我想要像这样的东西:

public Color ColorFromGuid(Guid guid) { /* ?? */ }

在哪里

ColorFromGuid(databaseObject1.Guid) == ColorFromGuid(databaseObject1.Guid)
ColorFromGuid(databaseObject2.Guid) == ColorFromGuid(databaseObject2.Guid)
ColorFromGuid(databaseObject1.Guid) != ColorFromGuid(databaseObject2.Guid)

什么是最好的方法来实现这个? 编辑 显然,唯一标识符(guid)的数量比颜色多得多,因此不可能每个guid都有自己独特的颜色。我只是想要一些不错的多样性。

1
我认为Guid是36个字符。前12个字符用于红色,第二个12个字符用于绿色,第三个12个字符用于蓝色。将这12个字符转换为int,并通过该值生成0-255的随机数。 - Habib Zare
@LarsTech 该数组中可能会有数万亿条记录。这似乎有点低效... - Entity
5个回答

5
您可以这样做:
return Color.FromArgb(guid.GetHashCode());

如果你需要不透明的颜色,可以使用 Color.FromArgb 的重载,并指定 alpha 值。如果想生成非常不同的颜色类似 GUID,可以对 GUID 执行不同类型的哈希,例如 MD5 哈希,并从中获取数字以生成所需的颜色。

3
像这样的东西怎么样:
public Color ColorFromGuid(Guid guid)
{
    var values = guid.ToByteArray().Select(b => (int)b);
    int red = values.Take(5).Sum() % 255;
    int green = values.Skip(5).Take(5).Sum() % 255;
    int blue = values.Skip(10).Take(5).Sum() % 255;

    Color color = Color.FromArgb(red, green, blue);
    return color;
}

这可能不是理想的方法,但您可以为每个GUID生成一种颜色,同样的GUID每次都应该生成相同的颜色。


使用“.Cast<int>()”而不是“.Select(b => (int)b)”可以吗? - Adam
@codesparkle:这会在LINQPad中引发“InvalidCastException”异常。我没有费心去运行Visual Studio。 - user203570
确实,在VS中得到相同的结果,因为Cast<T>会将输入序列中的项装箱。 - Adam

1

如果你使用函数来实现这个功能,你会感到失望。

Guids 的数量比颜色多得多,因此许多 Guids 将映射到相同的颜色。许多 Guids 将映射到太接近以至于无法区分的颜色(例如 #FFFF9999 和 #FFFF9998)。实际上,你只能区分少数颜色——最多只有50种。

Guids 不是随机的。请反复告诉自己:Guids 不是随机的。特别是如果你使用数据库生成的 Guids,它们可能是所谓的“顺序唯一标识符”,其中 Guid 的前半部分是相同的。这是否意味着你将为每个 Guid 得到不同的粉色阴影?也许吧。

因此,除非你知道你的 Guids 的分布并能够创建一个将该分布映射到适当颜色分布的函数,否则你将不会满意函数生成的颜色。

在 IT 相关领域,以可扩展的方式最简单的方法是在数据库中创建一个简单的表格,其中包含两列 - 颜色(名称、十六进制代码或 RGB 值)和 Guid。最耗时的部分将是选择颜色。这样可以更改特定项目的颜色,如果它与另一种颜色太相似。没有什么诀窍,只是简单的映射。

1
如果您需要为HTML添加颜色,可以使用以下代码或类似代码:
cssColorcode =  "#" + myguid.Substring(0, 6); 
// result can be something like: #ab3fa4

Guid是一种十六进制数字,而HTML CSS颜色代码可以以类似的格式表示。也许不完美,但很简单。

0

我在我的几个应用程序中使用类似以下的东西。

Color = Color.ParseColor("#" + (Guid.NewGuid().ToString()).Substring(0, 6));

从 GUID 中取前 6 个字符,并将其解析为十六进制颜色代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接