c++,stl。将具有 rgb 颜色的字符串转换为 3 个 int 值?

Posted

技术标签:

【中文标题】c++,stl。将具有 rgb 颜色的字符串转换为 3 个 int 值?【英文标题】:c++, stl. Convert string with rgb color to 3 int values? 【发布时间】:2013-08-23 08:39:23 【问题描述】:

字符串看起来像“#123456”,结果应该是:

int r = 0x12;
int g = 0x34;
int b = 0x56;

或者简单地在 c++ 中这个任务的逆操作:

How to convert RGB int values to string color

我知道我可以将当​​前字符串拆分为 3 个子字符串,但是如何将它们实现为十六进制值?

【问题讨论】:

见std::stoi和朋友们。 @juanchopanza:这些函数没有一种方便的方法来处理非十进制数,是吗? @juanchopanza: 看起来我的库不完整或被删减了,我没有这个功能 @KerrekSB 对我来说足够方便。 int i = std::stoi("0x20", 0, 16);int i = std::stoi("20", 0, 16);. @user2083364 它需要 C++11 库支持。根据您的编译器,您可能必须打开它,或者您可能根本没有它。 【参考方案1】:

使用标准库的std::hex:

#include <iostream>
#include <sstream>

int main()

   // The hex code that should be converted ...
   std::string hexCode;
   std::cout << "Please enter the hex code: ";
   std::cin >> hexCode;

   // ... and the target rgb integer values.
   int r, g, b;

   // Remove the hashtag ...
   if(hexCode.at(0) == '#') 
      hexCode = hexCode.erase(0, 1);
   

   // ... and extract the rgb values.
   std::istringstream(hexCode.substr(0,2)) >> std::hex >> r;
   std::istringstream(hexCode.substr(2,2)) >> std::hex >> g;
   std::istringstream(hexCode.substr(4,2)) >> std::hex >> b;

   // Finally dump the result.
   std::cout << std::dec << "Parsing #" << hexCode 
      << " as hex gives (" << r << ", " << g << ", " << b << ")" << '\n';

【讨论】:

【参考方案2】:

你应该先得到数字,去掉#。

然后,你可以使用字符串流:

#include <sstream>

...


  using namespace std;
  stringstream ss("123456");
  int num;

  ss >> hex >> num;

最后通过除法得到各个分量:

// Edit: I did it from memory and got it wrong, its % 0x100, not % 0xff.
int r = num / 0x10000;
int g = (num / 0x100) % 0x100;
int b = num % 0x100;

编辑: 不知道 std::stoi(C++11 可用)。感谢@juanchopanza。有了它,您可以更改代码的第一部分:

#include <string>

...

  using namespace std;
  int num = stoi("123456", 0, 16);

  int r = ....

【讨论】:

这是不正确的。 E57139 显示 (229, 87, 144) 但在 Photoshop 和使用计算器时显示为 (229, 113, 57)。我的意思是你在 std::stoi 之前的代码 把所有出现的 0xff 换成 0x100 我会批准的 已修复,抱歉。 请注意,std::stoi 系列函数自 C++11 起可用。可能值得一提。 正如我已经提到的,我的编译器是 Apple LLVM 编译器 4.2。如何检测它是否使用c++11?【参考方案3】:

您可以创建三个子字符串,将它们转换为整数,然后使用 std::hex?

见this。

【讨论】:

【参考方案4】:

将每个部分都包含在字符串中后,使用strtol() 将其转换为数字。确保使用 16 作为“基础”参数,因为您的值是十六进制的。

【讨论】:

【参考方案5】:

在将字符串分成 3 个单独的数字后尝试 sscanf()。

【讨论】:

【参考方案6】:

这是一个幼稚的解决方案:

unsigned int str_to_hex(char const * p, char const * e) noexcept

    unsigned int result = 0;
    while (p != e)
    
        result *= 16;
        if ('0' <= *p && *p <= '9')  result += *p - '0';  continue; 
        if ('A' <= *p && *p <= 'F')  result += *p + 10 - 'A'; continue; 
        if ('a' <= *p && *p <= 'f')  result += *p + 10 - 'a'; continue; 
        return -1;
    


std::tuple<unsigned char, unsigned char, unsigned char>
str_to_col(std::string const & s)

    if (str.length() != 7 || s[0] == '#')  /* error */ 

    auto r = str_to_hex(str.data() + 1, str.data() + 3);
    auto g = str_to_hex(str.data() + 3, str.data() + 5);
    auto b = str_to_hex(str.data() + 5, str.data() + 7);

    if (r == -1 || g == -1 || b == -1)  /* error */ 

    return r, g, b;

如果您在其他地方验证了您的输入,您可以将最后一个函数缩写为仅表示 return str_to_hex(...), ... ;


或者,您根本不需要拆分字符串:

std::string s = "#123456";

auto n = str_to_hex(s.data() + 1, s.data() + 7);

auto r = n / 0x10000, g = (n / 0x100) % 0x100, b = n % 0x10000;

除了自制的str_to_hex 函数,您还可以使用标准库的转换函数,例如std::strtoul(s.substring(1), nullptr, 16)

【讨论】:

为什么要重写一个已经以多种方式完成的函数,比如将字符串转换为十六进制的函数? @rcrmn:无聊?渴望权力、黄金和中立?对引用字符串 API 缺乏信心? 哦,对了。那你就可以走了!但它们大多工作得很好。 @rcrmn:我(和许多其他人)真正缺少的一件事是以统一的方式引用现有字符串(和数组)的方法。对于string_refarray_ref 类有几个提议(我认为Boost 有一个),但当然这样的类不会像大多数标准容器那样是“拥有价值”,所以它需要用户的特别关注。但这将是非常值得拥有的。小字符串优化可能会使我对s.substring(1) 的使用相当有效,但是......有时人们觉得它应该做得更好:-) 嗯,是的,但是为操作所需的内容编写如此多的代码有点太费力了。不过,我可以看到string_ref 和类似类的使用。感谢您的参考,有时人们只是坚持提供的内容,而不寻找其他可能更好的可能性。【参考方案7】:

反之亦然:uint8_t 三元组转字符串

#include <string>
#include <iostream>
#include <sstream>

std::string to_hex_string(uint8_t red, uint8_t green, uint8_t blue) 
    // r, g, b -> "#RRGGBB"
    std::ostringstream oss;
    oss << '#';
    oss.fill('0');
    oss.width(6);
    oss << std::uppercase << std::hex << ((red << 16) | (green << 8) | blue);
    return oss.str();

【讨论】:

以上是关于c++,stl。将具有 rgb 颜色的字符串转换为 3 个 int 值?的主要内容,如果未能解决你的问题,请参考以下文章

C++如何将使用16进制表达的颜色色彩RGB字符串转化为整型或者浮点型表达?(颜色转换色彩转换)

如何在 C++ 中将 RGB 颜色值转换为十六进制值?

将 rgb 数字数组转换为十六进制颜色字符串

在 C 中从 HEX 颜色转换为 RGB 结构

如何将“背景颜色”转换为 rgb() 格式?

C++のeasyx5:函数BGRGetBValueGetGValueGetRValue的运用