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

Posted

技术标签:

【中文标题】将 rgb 数字数组转换为十六进制颜色字符串【英文标题】:Convert rgb number array to hexadecimal color string 【发布时间】:2020-09-28 07:55:19 【问题描述】:

我已经写了一个工作方法,可以将 rgb 值数组转换为十六进制颜色字符串:

/**
 * @param Number[] arr Array with three entries (rgb: [0-255, 0-255, 0-255]).
 * @return String Hex color as a string (rgb: '#000000' - '#ffffff').
 */
function arrToHex(arr) 
  return '#' + arr
    .map(v => ('0' + v.toString(16)).slice(-2))
    .join('');

但我不确定这种方法是否是提高效率的最佳方法。这个方法在我的代码中经常被调用。

尤其是带有('0' + v.toString(16)).slice(-2)(获得双十六进制)的部分对我来说似乎太复杂了。这可以做得更好吗?这种functional 方法是不是最好的?


性能评估:

如果使用 Google Chrome v83(64 位,Linux)运行,结果显示由 console.time 计算的平均秒数。 从最好到最差排序。

selbie 的迭代和查找表解决方案:(~1.1sec)

const hextable = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
function arrToHex(arr) 
  let s = '#';
  for (let i = 0; i < arr.length; i++) 
    s += hextable[(arr[i] / 16) | 0];
    s += hextable[arr[i] % 16 | 0];
  
  return s;


console.time('arrToHex');
for (var r = 0; r < 256; r++)
for (var g = 0; g < 256; g++)
for (var b = 0; b < 256; b++) 
  arrToHex([r, g, b]);

console.timeEnd('arrToHex');

selbie 的迭代且无查找表解决方案:(~1.8 秒)

function arrToHex(arr) 
  let s = '#';
  for (let i = 0; i < arr.length; i++) 
    s += ((arr[i] / 16) | 0).toString(16);
    s += ((arr[i] % 16) | 0).toString(16);
  
  return s;

console.time('arrToHex');
for (var r = 0; r < 256; r++)
for (var g = 0; g < 256; g++)
for (var b = 0; b < 256; b++) 
  arrToHex([r, g, b]);

console.timeEnd('arrToHex');

[deleted] 的非迭代解决方案:(~2.6sec)

function arrToHex(arr) 
  const rgb = arr[2] | (arr[1] << 8) | (arr[0] << 16);
  return '#' + rgb.toString(16).padStart(6, '0');


console.time('arrToHex');
for (var r = 0; r < 256; r++)
for (var g = 0; g < 256; g++)
for (var b = 0; b < 256; b++) 
  arrToHex([r, g, b]);

console.timeEnd('arrToHex');

我的坏 functional 方法:(~6.5 秒)

function arrToHex(arr) 
  return '#' + arr
    .map(v => ('0' + v.toString(16)).slice(-2))
    .join('');


console.time('arrToHex');
for (var r = 0; r < 256; r++)
for (var g = 0; g < 256; g++)
for (var b = 0; b < 256; b++) 
  arrToHex([r, g, b]);

console.timeEnd('arrToHex');

【问题讨论】:

.toString(16).padStart(2,'0') 是另一种确保你有 2 个十六进制数字的方法,除此之外,你的代码看起来很可行 鉴于浏览器可以自己完成转换,因为以下每种颜色都是css中的有效颜色:#rgb#rrggbb#rrggbbaargb(r,g,b)rgba(r,g,b,a),并且转换将由本机代码而不是javascript完成,是否有任何真正的理由进行转换?在不了解更多信息的情况下,我不会将整个方法简化为大致等效的:reurn( 'rgb(' +r+ ',' +g+ ',' +b+ ')' ); @enhzflep 我已经知道 CSS 中的 rgb 函数,但这对我的用例没有帮助。 【参考方案1】:

您可以尝试对这段代码进行基准测试:

const hextable = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];

function arrToHex(arr) 
    let s = '#';
    for (let i = 0; i < arr.length; i++) 
        s += hextable[(arr[i] / 16) | 0];
        s += hextable[arr[i] % 16 | 0];
    
    return s;

或者如 cmets 中所讨论的,避免表查找并依赖运行时进行映射:

function arrToHex(arr) 
    let s = '#';
    for (let i = 0; i < arr.length; i++) 
        s += ((arr[i] / 16) | 0).toString(16);
        s += ((arr[i] % 16) | 0).toString(16);
    
    return s;

【讨论】:

简洁,但 Math.floor 函数可以减少:Math.floor(arr[i] / 16)arr[i] / 16 | 0Math.floor(arr[i] % 16)arr[i] % 16 这是个好主意。我已将其设为arr[i]%16|0,因此它也可以合理地支持十进制数字。它不能完美地处理负值或超出范围的值。这是 OP(你)要考虑的练习。 为什么不hextable = [...'0123456789abcdef']hextable[0|arr[i]/16]? (顺便说一下,第二个可能会提高性能) JS 文档定义了允许赋予函数,其他一切都不会打扰我。 |@selbie @YevgenGorbunkov 我将进行性能分析并编辑我的答案以提供结果。给我一点时间...

以上是关于将 rgb 数字数组转换为十六进制颜色字符串的主要内容,如果未能解决你的问题,请参考以下文章

将 RGB 颜色值转换为十六进制字符串

如何将字符串颜色转换为其十六进制代码或 RGB 值?

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

在Javascript中将rgb字符串转换为十六进制

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

将ARGB十六进制字符串转换为RGB