图像处理
图片的组成原理:
-
图片是由若干个像素点组成的。当我们把图片无限放大时,可以看到不同颜色的若干个矩形,这就是像素的形状,所以说一个像素是一个矩阵,并且由一种颜色填充。
-
red、green、blue是计算机中的三基色,每种颜色用1byte(8bit)存储。
- red:1000 0010 —— 130
- green:1101 0010 —— 210
- blue:0101 0101 —— 85
-
一般的,一个像素点用一个int来存储,由于1int–4byte–32bit,所以可以把int看成一个每行有8位二进制码,一共四行的矩阵:
- 0000 0000
0000 0000
0000 0000
0000 0000
如果一个像素的颜色是由红、绿、蓝三者合成的,那么存储它的int就是:
- 0000 0000
1000 1000 (R)
1101 0010 (G)
0101 0101 (B)
然后这一串1和0会被转换成一个int类型的数字呈现给我们,这里是8_573_525。
- 0000 0000
那么问题来了,当我们只有一个int的数字时,我们该如何知道它的R、G、B分别对应的数是多少呢?
毕竟我们在new Color(r,g,b)时,传入的三个参数只是32个bit中的某8个对应的十进制数,而不是8,573,525这样的东西。
位移运算符
- 位移运算符分为 >>(右移),<<(左移),以及>>>(无符号右移)三种,由于int有且只有32位,所以我以 1100 0101 1011 1001 这样一个数为例,如果我们想取得它的 9–16位,只需要将它右移8位,这样后面的 1011 1001 就被踢出了这个int。
int x = 50617; //BIN: 1100 0101 1011 1001
int x1 = x>>8;
System.out.println(x1); //DEC = 197 和我计算器中只计算1100 0101的结果相同
- 同理,如果我们想要得到1 - 8位,只需要先将这个数左移24位,把9位以后的数全从左侧挤出去,然后再右移回来。需要注意的是,int最左边(32位上)的0和1是表示符号的,当原先第8位的1走到32位时,它不在有计数的意义,而是相当于一个负号。所以在右移时,应当用>>>。
int x = 50617; //BIN: 1100 0101 1011 1001
int x2 = (x<<24)>>24; //DEC = -71 错误
int x3 = (x<<24)>>>24; //DEC = 185 正确
- 但是这个方法有些麻烦,更为简单的方法是利用&(与运算)。我们把需要的数先右移到最右侧,然后我们想保留几位,就和几个1做&运算(这里的1是二进制码)。
以1100 0101 1011 1001为例,要获得1 - 8位,就拿这个数 &(0000 0000 1111 1111),前面8个0会消去9 - 16位上的1,而后面8个1则会保留1 - 8位上的1。
int x = 50617;
int y = 255; //将1111 1111 转换为十进制
int x4 = x & y; //x4的值仍为185
- 所以对于上面提到的8_573_525,要得到它的RGB,做法如下:
int rgb = 8_573_525; /*BIN = 0000 0000
1000 1000
1101 0010
0101 0101 */
int red = (rgb>>16)&255; //DEC = 130
int green = (rgb>>8)&255; //DEC = 210
int blue = rgb&255; //DEC = 85