【问题标题】:Convert from HEX color to RGB struct in C在 C 中从 HEX 颜色转换为 RGB 结构
【发布时间】:2011-04-13 00:53:42
【问题描述】:

如何仅使用 C 库(不使用 C++ 或模板)将颜色 HEX 代码转换为纯 C 中的 RGB? RGB结构可能是这样的:

typedef struct RGB {
    double r;
    double g;
     double b;
} RGB1;

我正在寻找的函数应该返回 RGB1。

【问题讨论】:

  • 我不确定我是否理解这个问题。我相信将事物标记为代码和/或在问题的关键位置插入换行符可能有助于使人们更容易阅读(并因此回答)问题。

标签: c colors hex rgb


【解决方案1】:

RGB 值可以通过 0xRRGGBB 以整数形式存储。例子:

  • 红色:0xff0000
  • 绿色:0x00ff00
  • 蓝色:0x0000ff

00 是十进制 0 的十六进制,而 ff 是 255。0 对应于 0.0,255 对应于 1.0。 (实际上你没有指定范围是多少。我假设是 0.0 到 1.0。)

因此,根据上述假设,您需要提取每个分量并除以 255。因为这听起来很像家庭作业问题,所以我将向您展示如何做红色分量。

int hex = 0x123456;
c.r = ((hex >> 16) & 0xff) / 255.0;

每个十六进制数字占用 4 位。因此向右移动 16 位(将所有内容向右移动 4 位)以使 0xRRGGBB 变为 0xRR。现在你有了红色组件。 (以防万一整数中有更高的数据,您可以通过& 0xff 屏蔽数据来摆脱它。)

如果您正在处理字符串"#FFFFFF",那么您首先必须将其转换为整数才能使上述操作生效。

【讨论】:

    【解决方案2】:

    假设您的十六进制值是 32 位“int”类型,并且我们使用上述 RGB 结构,那么可能会执行以下操作:

    struct RGB colorConverter(int hexValue)
    {
      struct RGB rgbColor;
      rgbColor.r = ((hexValue >> 16) & 0xFF) / 255.0;  // Extract the RR byte
      rgbColor.g = ((hexValue >> 8) & 0xFF) / 255.0;   // Extract the GG byte
      rgbColor.b = ((hexValue) & 0xFF) / 255.0;        // Extract the BB byte
    
      return rgbColor; 
    }
    

    【讨论】:

    • 有点扯掉@konforce 给出的答案,不是吗?
    • 不。那里也有用于字符串处理的代码,但是 konforce 关于这可能是一个家庭作业问题的观点是一个很好的问题。因此,我编辑了这个答案,使其更像上面发布的一个 kon。
    • hexValue 应该是 unsigned int 类型吗?我认为 &0xFF 取消了算术移位,但是像 0xFFFFFF 这样的值在传入时不会导致溢出吗?
    • 'unsigned int' 可能会更好一些。也就是说,在这种情况下,这并不重要,因为 RRGGBB 适合 24 位,而“int”类型(非常普遍)长度为 32 位。这个答案确实假设 RRGGBB 位以某种方式存储在 int 中,尽管......所以请注意。
    【解决方案3】:

    我猜 RGB 在某些系统上可以存储为 0xRRGGBB,但在 Windows 中它实际上存储为 0xBBGGRR(请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/dd183449)。正如文章中提到的,已经有 GetRValue、GetGValue 和 GetBValue 宏可用。

    【讨论】:

      【解决方案4】:

      如果十六进制码是字符串,可以这样解析

      char *str = "0000FF";
      int r, g, b;
      sscanf(str, "%02x%02x%02x", &r, &g, &b);
      

      这是整数,而不是双精度数。还要检查 sscanf 是否返回 3,即读取的项目数。

      【讨论】:

      • 如果你想解析成unsigned short值,请使用格式字符串"%2hx%2hx%2hx"
      • 我使用 sscanf(str.c_str(), "%02hhx%02hhx%02hhx", &r, &g, &b);std::string 将其解析为 unsigned char 值,
      • 我对 Tor 的回答赞不绝口!优雅的解决方案。
      【解决方案5】:

      我知道这已经很老了,但我还想提供一个没有任何位运算的联合解决方案。

      union Color
      {
          unsigned int hex;
          struct { unsigned char b, g, r; };
      };
      

      通过这种方式,您可以轻松地从 HEX 转换为 RGB,从 RGB 转换为 HEX。

      union Color hex;
      hex.hex = 0x07C73C;
      
      union Color rgb;
      rgb.r = 7;
      rgb.g = 199;
      rgb.b = 60;
      
      printf("RGB(%d, %d, %d), HEX(%06x)", hex.r, hex.g, hex.b, rgb.hex);
      

      输出:

      RGB(7, 199, 60), HEX(07c73c)
      

      要映射 0.0 到 1.0 范围内的值,只需将其除以 255.0 :)

      编辑: 以上代码^^仅在Little-Endian CPU架构下支持,更好的方式是check what endianness does the system runs on

      然后你可以检查字节序来定义结构变量的顺序。

      union Color
      {
          unsigned int hex;
      
      #if IS_BIG_ENDIAN
          struct { unsigned char a, r, g, b; };
      #else
          struct { unsigned char b, g, r, a; };
      #endif
      };
      

      此代码还支持 RGBA 中的 alpha(透明度)。

      【讨论】:

      • 很好的答案,但您应该检查字节顺序以确保答案完整。参考stackoverflow.com/q/18863913/8339821
      • 好点,我会做一些测试并更新答案。
      • 太好了,请在更新时发表评论。 mb 你会得到一个赞成票;)
      • @yvw 我更新了支持两种字节序的答案,我非常不确定 Windows 系统是否只有小字节序,最终使用了 CPU 检查宏。
      • BSD 似乎有 <endian.h><sys/endian.h>。其他系统可能根本没有标头。
      猜你喜欢
      • 2019-02-08
      • 2018-06-16
      • 2012-02-06
      • 2021-04-18
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 2011-04-17
      • 2022-11-25
      相关资源
      最近更新 更多