位运算——如何改变现有的颜色?

Posted

技术标签:

【中文标题】位运算——如何改变现有的颜色?【英文标题】:Bitwise Operations-- How to change existing color? 【发布时间】:2012-09-02 10:10:24 【问题描述】:

我已经阅读了按位运算符 (& | ^) 并且我明白如果我要这样做:

alpha = 0xFF000000 >> 24 ;
blue = 0xFF0000FF & 0x000000FF;
red = 0xFFFF0000>>16 & 0x000000FF;
green = 0xFF00FF00>>8 & 0x000000FF;

然后我可以掩盖其他颜色,只使用红色或蓝色(等...)组件 如果我要这样做

int color = alpha | blue | red | green;

然后我可以重新构造颜色。我很好奇的是,如果我想在 Java 中创建两种颜色之间的双线性插值会怎样。我将如何构建它? 我想从标准绿色(0xFF00FF00)开始,以黑色(0xFF000000)结束,中间的颜色将从绿色变为深绿色,直到最终变为黑色。我认为我必须做一些事情,我创建一个从顶部开始为绿色的 bufferedImage,然后可能创建一个 for 循环来读取前一个像素的颜色,然后移动一些东西直到前一个颜色的新版本被创建等等。不幸的是,我不确定如何实现这一点,因为我理解按位运算和理论上的移位,但不确定如何将它们应用于此目的。任何帮助将不胜感激!提前谢谢!

【问题讨论】:

【参考方案1】:

我明白如果我这样做:

不,你根本不明白。在所有四种情况下,所有位移的结果都是0xff,这显然是不正确的。 alpha 蒙版是0xff000000,蓝色蒙版是0xff,红色蒙版是0xff0000,绿色蒙版是0xff00。这些是 掩码, 需要使用 & 运算符应用于实际像素,以屏蔽相关通道。您需要先了解这一点,然后才能走得更远。

【讨论】:

【参考方案2】:

作为EJP noted,掩码用于过滤掉颜色分量/通道之一(红色、绿色、蓝色)的值。这通常是您对位移/屏蔽操作所做的。您对获得的值所做的其他一切都是算术或更高级的数学。

颜色通道的范围是 0-255,或 0x00 - 0xFF(十六进制值)。要重建它,您需要将组件值位移回它们的位置。可以用简单的算术加法组合起来:

// Example values
int r = 255; // 0xFF
int g = 1;   // 0x01
int b = 15;  // 0x0F

// go back to original form:
                      //    A  R  G  B
int color = r << 16;  // 0x00.FF.00.00
color += g << 8;      // 0x00.FF.01.00
color += b;           // 0x00.FF.01.0F

// just add back the alpha if it is going to be full on
color = += 255 << 24; // 0xFF.FF.01.0F

如果你想在颜色之间做一些插值,你需要对每个颜色分量分别进行插值,而不是把它们全部放在一个整数中。在某些情况下,将表示形式从 [0-255] 更改为十进制 [0.0f-1.0f] 也是一个好主意:

// Darken red value by 50%
int color = ...; // some color input
int mask = 0xFF;

int a = (color >> 24) & mask;
int r = (color >> 16) & mask;
int g = (color >> 8) & mask;
int b = color & mask;

// convert to decimal form:
float rDecimal = r / 255f; 
  // Let r: 0x66 = 102 => rDecimal: 0.4

// darken with 50%, basically divide it by two
rDecimal = r/2; 
  // rDecimal: 0.2

// Go back to original representation and put it back to r
r = (int)(rDecimal * 255); 
  // r: 51 = 0x33

// Put it all back in place
color = (a << 24) + (r << 16) + (g << 8) + b;

希望这会有所帮助。

【讨论】:

如果我想对颜色进行插值并将其映射到 BufferedImage 上,我该怎么做? @MasqueradeToday:你想到了什么样的插值?你读过BufferedImage java api 页面吗?如果你想从简单的开始,里面有 getRBG()setRBG() 方法。你必须遍历所有像素for图片的所有x和y坐标。 编写良好且清晰的代码。将表示转换为十进制是否有任何性能提升? @akhyar:我这样做是为了可读性而不是性能......我个人只是发现以十进制形式调试颜色值更容易(主要是因为我在大学学习过信号处理使用这种形式)。与大多数优化一样,我会在事情变得“缓慢”时开始分析(当您认为缓慢的代码最终不是真正的罪魁祸首/瓶颈时,这总是令人惊讶)。 不是&lt;&lt; 24而不是32吗?

以上是关于位运算——如何改变现有的颜色?的主要内容,如果未能解决你的问题,请参考以下文章

HSQL 和按位运算?

位运算

64 位数学运算,不会丢失任何数据或精度

Luabit的位运算

objective-C和C --- 《位运算》的使用之二进制颜色的转换

位运算---整数间的转化