import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
/**
* 我知道位运算是什么,怎么运算的,但我实在看不懂别人写的位运算代码,求高人指点我如何才能看懂别人写的位运算代码?
*
* 希望能得到详细的回答,除了将这个类的所有位运算都解释一遍,还请将位运算在java图像处理中有哪些应用告诉我,谢谢!
*/
public class DyedImageUtils {
/**
* 根据指定颜色过滤像素
*
* @param pixel
* @param filterColor
* @return
*/
private static int filter(int pixel, Color filterColor) {
int alpha = pixel >> 24 & 0xff;// 为什么要将pixel进行">> 24"呢,又为什么要"& 0xff"呢,能解释解释这句代码的意义吗?
if (alpha > 0) {
pixel = gray(pixel);
return pixel & filterColor.getRGB();// 同上,这句"按位与"的代码我也不明白为什么要这么做
} else {
return 0;
}
}
/**
* 处理颜色灰度
*
* @param rgb
* @return
*/
private static int gray(int rgb) {
int a = rgb & 0xff000000;// 同上,这句"按位与"的代码我也不明白为什么要这么做
int r = rgb >> 16 & 0xff;// 同上,不明白为什么要这么做
int g = rgb >> 8 & 0xff;// 同上
int b = rgb & 0xff;// 同上
rgb = r * 77 + g * 151 + b * 28 >> 8;// 同上
return a | rgb << 16 | rgb << 8 | rgb;// 同上
}
/**
* 对图片进行着色
*
* @param image
* @param color
* @return
*/
public static Image createDyedImage(Image image, Color color) {
if (color == null) {
return image;
} else {
if (image != null) {
int w = image.getWidth(null);
int h = image.getHeight(null);
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
try {
pg.grabPixels();
} catch (InterruptedException ex) {
ex.printStackTrace();
return null;
}
BufferedImage bi = new BufferedImage(w > 1 ? w : 1, h > 1 ? h : 1, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < pixels.length; i++) {
int pixel = pixels[i];
int row = i / w;
int col = i % w;
if (color != null) {
if (pixel != 0) {
pixel = filter(pixel, color);
}
}
bi.setRGB(col, row, pixel);
}
return bi;
} else {
return null;
}
}
}
}
你要理解RGB的2进制格式,R,G,B的取值范围是0-255,如果是ARGB,前面还有一个透明度0-255。255在2进制中占8位,也就是
ARGB像素格式(左边最高位,右边最低位):00000000RRRRRRRRGGGGGGGGBBBBBBBB。
到这个格式你那位移就清楚了,取A得值,只要后面24位都置成0,前8位为1,做与就行了。当然你要>>24&0xff也可以,只是没必要。>>24后,再最后处理完灰度后还得<<24回来。
取R,G,B都一样原理。
如果是基本的看懂得话,记着关键字,等结合它本身的意思,把变量带入就可以了。看代码时在头脑里一步一步的“执行”下去!其实就像读课文以样,都有固定的模式,多读几遍也就熟了
很容易理解,>>24就是取一个整数二进制的25~32位。它代表alpha(透明度)通道。
&0xff就是将这个整数的高位全部置为0,只保留它的低位。
比如
int rgb = 1110 0001 1011 0000 1100 0010 0010 0000 (这样写是不合法的,但是为了让你看清,我写成二进制形式)
a = rgb >> 24 就是往右边移24位,因为最高位是1,所以移动后最高位会填充1。
此时a = 1111 1111 1111 1111 1111 1111 1110 0001
然后&0xff就是按位and 0000 0000 0000 0000 0000 0000 1111 1111
结果就是 0000 0000 0000 0000 0000 0000 1110 0001
也就是1110 0001,可见将rgb的最高8位取了出来。
以此类推。
首先,你知道位运算是什么,也知道怎么运算的,这就足够了
其次,要想看懂别人代码,先要搞明白这段代码是干什么用的
比如这个filter,目的的根据指定颜色过滤像素的,
而且通过观察,会发现是一个一个像素进行处理的
这段代码中,你共提出了八处不理解的
这个颜色rgb值,你应该明白吧,百度一下就知道了。
每个值是0到255,占一个byte,rgb共占3个byte。
而这里一个像素用一个int表示的,int有4个byte。
那还有1个byte应该是标志什么玩意儿的,这个具体标志什么,应该和你做的项目有一定的关系。
下面来过一下8处位运算
首先假设当前像素值为:0xAABBCCDD
1. 右移24位,即得到0x00000000AA,位与0xff即取得最低的一个byte,即0xAA
为什么要位与0xff呢,可能是担心高位有不为0的值,其实一般情况下得到的就是0xAA了,
再位与一下0xff,只是一个保护措施,也是一个很好的习惯。
还有一种右移可能是循环右移,这样右移24位之后得到的是0xBBCCDDAA,这就很有必要位与一下0xff。
保证得到的是原来0xAABBCCDD最高的那个0xAA。当然,最后这种可能纯属个人意淫,可以略过。
2. 当前像素经过gray处理之后,又位与了一个getRGB,这个值可能是一个常量,就像掩码一样。
比如getRGB得到的是0x0000FF00,就表示,只保留RGB中的G的值。
再说明白点,就是保留getRGB的值中为1的位。
3. 这里是保留最高位,这个最高位就是上面说的当前像素的标志位(不属于RGB值)
在最后那个return处,也可以看到,a又位或返回了,说明当前像素的标志位没有改变
4. 5. 6. 这三个地方,分别得到了当前像素的R、G、B值
7. 这个计算有点意思,应该是灰度处理的一种算法,具体怎么得到这个公式的呢?
你问我,我也只能百度,估计也百度不出来,所以你可以查阅你当前的项目,或许可以查到灰度处理的这个公式。
8. 这个就是讲最后灰度处理之后的值,返回了。
那个左移16,左移8,这个还应该是上面说的某种公式,要这么做。
不过要注意一点的是,这个时候最高位a处的值,可能会被改变,而且这种位或也可能互相影响了RGB值。
具体什么作用,我也不装x解释了,因为关于颜色RGB灰度处理公式的玩意儿,我也不知道怎么回事!
最后,你问的那个,位运算在java图象处理中有哪些应用。这个要你自己查一下了。
你既然研究图象处理,肯定要自己多多查阅相关资料了。
希望这点儿解释能有帮到你什么忙。