Algorithm 计算24位颜色之间的差异而不拆分为单独的RGB字节?

Algorithm 计算24位颜色之间的差异而不拆分为单独的RGB字节?,algorithm,math,colors,Algorithm,Math,Colors,计算颜色之间距离的正常方法可能是: // R G B var color1 = 0xFF0000; var color2 = 0x00FF00; // Calculate points R G B var color1_p = [(color1&0xFF0000)>>16, (color1&0xFF00)>>8, color1&0xFF]; v

计算颜色之间距离的正常方法可能是:

//             R G B
var color1 = 0xFF0000;
var color2 = 0x00FF00;
// Calculate points      R                    G                  B
var color1_p = [(color1&0xFF0000)>>16, (color1&0xFF00)>>8, color1&0xFF];
var color2_p = [(color2&0xFF0000)>>16, (color2&0xFF00)>>8, color2&0xFF];

var distance = Math.sqrt((color1_p[0]-color2_p[0])*(color1_p[0]-color2_p[0]) + 
                         (color1_p[1]-color2_p[1])*(color1_p[1]-color2_p[1]) +
                         (color1_p[2]-color2_p[2])*(color1_p[2]-color2_p[2])) 
这只是正常的毕达哥拉斯距离。但是我必须创建一个数组或者保存RGB值。我可以在C++中解决这个问题:我猜:

uint32_t color = 0xFF0000;
uint8_t* color_p = (uint8_t*)&color; // [G, B, R, alpha, segmentation fault ...]
千万不要对
int
执行此操作,在某些奇怪的平台上,它可以从16位到64位不等


现在我的问题是,如果有一些聪明的数学可以直接对像
0xFF0000
(红色,
16711680
dec)和
0xFFCC00
(橙色,
16763904
dec)这样的数字进行计算距离或其他类型的差异。我在寻找线性差。通过线性差,我的意思是,如果A和B之间的距离相同,那么差也必须相同,但我不在乎它到底是什么数字。

无法避免计算的三维性质。使用3字节整数值的计算不考虑维度的独立性。使用整数值唯一安全的方法是检查是否相等,这确实比单独比较3个字节更有效(如果有许多相同的RGB值)。
您可以通过多种方式优化计算,但将颜色拆分为单独的R、G和B值始终是其中的一部分。像这样的东西将是最有效的,你可以做到这一点:

函数rgbDistanceSquared(x,y){ if(x==y)返回0;//如果期望有许多相同的RGB值 变量r=((x&0xFF0000)-(y&0xFF0000))>>16; 变量g=((x&0x00FF00)-(y&0x00FF00))>>8; 变量b=(x&0x0000FF)-(y&0x0000FF); 返回r*r+g*g+b*b; } 写入(RGB距离平方(0xFF0000,0xFFCC00)+“
”; 文件写入(rgbDistanceSquared(0x00CCFF,0x0000FF)+“
”;
写入(RGB距离平方(0x00CCFF,0xFFCC00)+“
正如@harold提到的,还有其他距离度量。最简单的是或出租车公制。这基本上是计算绝对值之和。如果点是(r1,g1,b1)和(r2,g2,b2),则找到| r1-r2 |+| g1-g2 |+| b1-b2 |。它被称为曼哈顿距离,因为它测量的是如果你只能沿着矩形网格的边缘移动,你将在两点之间移动的距离,就像曼哈顿的道路模式一样

设c1=0xrrggbb为(r1、g1、b1)的单字节表示,与c2类似。 如果我们知道r2>=r1,g2>=g1,b2>=b1,我们就可以找到
x=c2-c1
y=((x&0xFF0000)>>16)+((x&0x00FF00)>>8)+(x&0x0000FF)
。如果这些点可以是任意顺序的,那么我们必须担心每个字节都会溢出

黑客有一个很好的方法找到绝对值。如果有一个有符号的32位整数
x
,那么我们可以计算
y=x>>32;z=(x+y)^x
。给出了绝对值。我们可以这样做

int32_t r = ((c1 & 0xFF0000) - (c2 & 0xFF0000)) >> 16;
int32_t rsign = r >> 32; // fill with sign bit
int32_t result = (r+rsign)^r;
int32_t g = ((c1 & 0x00FF00) - (c2 & 0x00FF00)) >> 8;
int32_t gsign = g >> 32; // fill with sign bit
result += (g+gsign)^g;
int32_t b = ((c1 & 0x0000FF) - (c2 & 0x0000FF));
int32_t bsign = b >> 32; // fill with sign bit
result += (b+bsign)^b;

我想这需要23次手术。与@m69的答案相比,它并没有真正的优势,而且整数乘法在现代硬件上速度很快。

还有其他距离度量,但您到底想避免什么呢?在这里创建数组是很容易避免的,我不确定“保存”在“保存RGB值”中意味着什么(当然,您不必将它们保留任何时间)。@harold我试图完全避免使用临时变量。@harold Integer(称之为
diff
)范围从
0
N
,例如对于表示颜色RGB的点之间距离的每个数字
dist
,有一个
diff
。这意味着
diff
是通过将
dist
空间乘以大于或等于1的数字而产生的线性空间。该sqrt是一个昂贵的操作。如果你不关心实际值,只关心排名,你可以忽略它。我在评论中看到一些关于你到底在问什么的困惑。我可以推荐标题“计算24位颜色之间的差异而不拆分为单独的RGB字节吗?”