透明图片判定

for (int j = 0; j < height; j++) {
    for (int i = 0; i < width; i++) {
        int p = image.getRGB(i, j);

        int a = (p >> 24) & 0xff;
        int r = (p >> 16) & 0xff;
        int g = (p >> 8) & 0xff;
        int b = p & 0xff;

        p = (a << 24) | (r << 16) | (g << 8) | b;

        image.setRGB(i, j, p);
    }
}

其中这里的变量r,g,b就是对应的rgb值,那为什么要这样操作呢?先看一个图:


这里写图片描述

有了这个图相信大家就都看明白了,首先p是一个32位的二进制数,可以通过getRGB()方法得到,那么最前面的8位是alpha,后面依次是Red,Green,Blue。所以这就是代码中移位操作的意义,当然最后还要回归到原来的结构,那就用(a << 24) | (r << 16) | (g << 8) | b再拼装一次。

所以对图像中像素点的操作就可以这么写啦,后面具体是增强还是锐化,都是基于这样的操作做的。

记得在学计算机原理的时候,了解到计算机内的存储都是利用二进制的补码进行存储的。

复习一下,原码反码补码这三个概念

对于正数(00000001)原码来说,首位表示符号位,反码 补码都是本身

对于负数(100000001)原码来说,反码是对原码除了符号位之外作取反运算即(111111110),补码是对反码作+1运算即(111111111)

概念就这么简单。

当将-127赋值给a[0]时候,a[0]作为一个byte类型,其计算机存储的补码是10000001(8位)。

将a[0] 作为int类型向控制台输出的时候,jvm作了一个补位的处理,因为int类型是32位所以补位后的补码就是1111111111111111111111111 10000001(32位),这个32位二进制补码表示的也是-127.

发现没有,虽然byte->int计算机背后存储的二进制补码由10000001(8位)转化成了1111111111111111111111111 10000001(32位)很显然这两个补码表示的十进制数字依然是相同的。

但是我做byte->int的转化 所有时候都只是为了保持 十进制的一致性吗?

不一定吧?好比我们拿到的文件流转成byte数组,难道我们关心的是byte数组的十进制的值是多少吗?我们关心的是其背后二进制存储的补码吧

所以大家应该能猜到为什么byte类型的数字要&0xff再赋值给int类型,其本质原因就是想保持二进制补码的一致性。

当byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,&0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。

当然拉,保证了二进制数据性的同时,如果二进制被当作byte和int来解读,其10进制的值必然是不同的,因为符号位位置已经发生了变化。

象例2中,int c = a[0]&0xff;  a[0]&0xff=1111111111111111111111111 10000001&11111111=000000000000000000000000 10000001 ,这个值算一下就是129,

所以c的输出的值就是129。有人问为什么上面的式子中a[0]不是8位而是32位,因为当系统检测到byte可能会转化成int或者说byte与int类型进行运算的时候,就会将byte的内存空间高位补1(也就是按符号位补位)扩充到32位,再参与运算。上面的0xff其实是int类型的字面量值,所以可以说byte与int进行运算。

转载来自于:https://blog.csdn.net/sinat_36246371/article/details/72823438

https://www.cnblogs.com/think-in-java/p/5527389.html

猜你喜欢

转载自blog.csdn.net/weixin_41017246/article/details/82865736