1. Introduction
1.导言
The RGB color model is widely used in various applications and devices because it aligns well with how electronic displays work. ‘R’ in RGB stands for Red, ‘G’ for Green, and ‘B’ for Blue. Combining these three primary colors at varying intensities can produce a broad spectrum of colors.
RGB 颜色模型广泛应用于各种应用和设备中,因为它与电子显示屏的工作原理非常吻合。RGB 中的 “R “代表红色,”G “代表绿色,”B “代表蓝色。将这三种三原色以不同的强度组合在一起,可以产生丰富的色彩。
In programming languages, including Java, a common practice is to represent an RGB color as a single integer, packing the three color components and, sometimes, an alpha (transparency) component into a 32-bit integer.
在包括 Java 在内的编程语言中,一种常见的做法是将 RGB 颜色表示为单个整数,将三个颜色分量,有时还有一个 alpha(透明度)分量打包成一个 32 位整数。
In this tutorial, we’ll look into methods of moving between these representations.
在本教程中,我们将研究在这些表示法之间移动的方法。
2. RGB Integer Representation
2.RGB 整数表示法
In a 32-bit integer representation of an RGB color, each color component is typically allocated 8 bits. The highest 8 bits are often used for the alpha channel (representing transparency), followed by red, green, and blue. The structure looks like this:
在 RGB 颜色的 32 位整数表示中,每个颜色成分通常分配 8 位。最高的 8 位通常用于阿尔法通道(表示透明度),其次是红、绿和蓝:
- Bits 24-31: Alpha (A)
- Bits 16-23: Red (R)
- Bits 8-15: Green (G)
- Bits 0-7: Blue (B)
3. RGB to Integer Conversion
3.RGB 转换为整数
We can create an integer representing an (A)RGB color by bitwise shifting individual components to their desired positions:
我们可以通过比特移位各个分量到所需位置来创建一个代表 (A)RGB 颜色的整数:
int alpha = 255; // Fully opaque
int red = 100;
int green = 150;
int blue = 200;
int argb = (alpha << 24) | (red << 16) | (green << 8) | blue;
If we’re working in a context where transparency isn’t needed, we might want to omit the alpha channel:
如果在不需要透明度的情况下工作,我们可能想省略 alpha 通道:
int rgb = (red << 16) | (green << 8) | blue;
3.1. Converting with Clamping
3.1.夹紧转换
Using that knowledge, we can write a function that takes RGB values and returns an integer representation. First, we can implement clamping to limit the input values to the appropriate range. Quitely keeping values in desired ranges can be very convenient while working with color transformations:
利用这些知识,我们可以编写一个接收 RGB 值并返回整数表示的函数。首先,我们可以实施箝位,将输入值限制在适当的范围内。在处理颜色变换时,将数值限制在所需范围内会非常方便:
int clamp(int value, int min, int max) {
return Math.max(min, Math.min(max, value));
}
Next, let’s implement a function that will use the clamp function to convert RGB values to integers:
接下来,让我们实现一个函数,使用 clamp 函数将 RGB 值转换为整数:
int rgbToInt(int alpha, int red, int green, int blue) {
alpha = clamp(alpha, 0, 255);
red = clamp(red, 0, 255);
green = clamp(green, 0, 255);
blue = clamp(blue, 0, 255);
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
We can also implement a version without an alpha channel:
我们还可以实现一个没有阿尔法通道的版本:
int rgbToInt(int red, int green, int blue) {
red = clamp(red, 0, 255);
green = clamp(green, 0, 255);
blue = clamp(blue, 0, 255);
return (red << 16) | (green << 8) | blue;
}
Finally, we can use the created function to convert RGB values:
最后,我们可以使用创建的函数来转换 RGB 值:
assertEquals(0x00ABCDEF, rgbToInt(171, 205, 239))
4. RGB to Integer Conversion
4.RGB 转换为整数
Extracting RGB components from an integer representation is as easy as shifting bits to bring the desired part to the lowest 8 bits and then masking off redundant higher bits. For example, to extract the red channel, we need to shift the integer value 16 bits to the right:
从整数表示中提取 RGB 分量非常简单,只需移动比特,将所需部分移动到最低的 8 比特,然后屏蔽掉多余的高比特。例如,要提取红色通道,我们需要将整数值向右移动 16 比特:
int red = (argb >> 16)
Now, the lowest 8 bits represent our red value, but we still need to mask the rest. We can do that by using bitwise and operator:
现在,最低的 8 位代表我们的红色值,但我们仍然需要屏蔽其余的位。我们可以使用比特和运算符来做到这一点:
int red = (argb >> 16) & 0xFF;
We can think about 0xFF number (255 in decimal) as a bit mask that has the first 8 bits equal 1 and all of the rest bits equal 0. So, in conjunction with the and operator, it’ll discard all but the first 8 bits. We can extract the rest of the RGB components in a similar fashion:
我们可以将 0xFF 数字(十进制 255)视为一个位掩码,其前 8 位等于 1,其余所有位等于 0。我们可以用类似的方法提取其余的 RGB 分量:
int alpha = (argb >> 24) & 0xFF;
int red = (argb >> 16) & 0xFF;
int green = (argb >> 8) & 0xFF;
int blue = argb & 0xFF;
5. Color Transformations
5.色彩转换
We can use the RGB color representation in various transformations to make the RGB color representation more practical.
我们可以在各种变换中使用 RGB 颜色表示法,使 RGB 颜色表示法更加实用。
5.1. Brightness Adjustment
5.1.亮度调节
Adjusting the brightness involves scaling the RGB components. Because the alpha channel has nothing to do with the brightness, we won’t scale it:
调整亮度需要缩放 RGB 分量。由于 Alpha 通道与亮度无关,因此我们不会对其进行缩放:
float scale = 0.8f; // darken by 20%
red = (int)(red * scale);
green = (int)(green * scale);
blue = (int)(blue * scale);
int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue;
5.2. Grayscale Conversion
5.2.灰度转换
To perform grayscale conversion, we’ll set all three color components to the same value. We can use the weighted average of the original colors:
要执行灰度转换,我们需要将三个颜色分量设置为相同的值。我们可以使用原始颜色的加权平均值:
int average = (int)(red * 0.299 + green * 0.587 + blue * 0.114);
int grayscaleArgb = (alpha << 24) | (average << 16) | (average << 8) | average;
Similarly to the previous example, the alpha channel is not affected because it doesn’t contain color information. We achieve different results by using different weights for each of the color components.
与前面的例子类似,alpha 通道不会受到影响,因为它不包含颜色信息。我们可以通过对每个颜色成分使用不同的权重来获得不同的结果。
5.3. Color Inversion
5.3.颜色反转
We can also invert a color by flipping its RGB components. To do that, we need to subtract the value of each color component from 255:
我们还可以通过翻转 RGB 分量来反转颜色。为此,我们需要从 255 减去每个颜色分量的值:
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
int invertedArgb = (alpha << 24) | (red << 16) | (green << 8) | blue;
6. Summary
6.总结
In this article, we learned how to use bitwise operations to move between RGB and integer representations. We also look at examples of how RGB representation can be used for various color transformations.
在本文中,我们学习了如何使用位操作在 RGB 和整数表示法之间移动。我们还将举例说明如何使用 RGB 表示法进行各种颜色变换。