如何将图片黑白化 本帖最后由 soulmachine 于 2010-02-06 17:53:07 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我用png和图片试过了, 没有任何问题.估计是你的图片格式, 不防用png试试.下面的输出结果Biao: ~/Desktop $ ls1.png BiImage.java 如何将图片黑白化.webarchiveBiao: ~/Desktop $ javac BiImage.java Biao: ~/Desktop $ java BiImage 1.png 2.png2306520trueBiao: ~/Desktop $ javac BiImage.java Biao: ~/Desktop $ java BiImage 1.png 3.png2306520trueBiao: ~/Desktop $ java BiImage 4.png 5.png3664440trueBiao: ~/Desktop $ alpha肯定是指不透明度 对jpg之类的图片应该没有影响 你所指的小问题是什么? alpha对于黑白化应该没有影响。 图片保存为PNG BMP 格式的好用,结果为TRUE;图片保存为JPG JPEG格式的依然可以黑白化,但结果为FALSE; 恩,非常感谢,我再认真测试了一下,对于PNG,GIF,BMP,是没有问题的,检测通过1. JPG检测通不过,我觉得还是alpha通道没有处理好。所以,小问题就是,为什么JPG黑白化失败?2. alpha没有处理的原因,是因为我不太明白 TYPE_INT_ARGB 和 TYPE_INT_RGB 的区别。我的意思是,java在保存图片时,会不会修改某些像素的值,导致检测通不过? jpg是有损压缩格式 存储的时候本身不是按照rgb的方式存储的 读取的时候需要解压缩 转换为rgb的颜色信息 而这个过程是有损的 会产生非黑白的颜色信息也就不足为奇了 也就是说 A像素的颜色信息存为jpg格式再读取出来后和原来A像素的信息有可能是不相等的 TYPE_INT_ARGB 代表图像8位RGBA像素的彩色包装成整数部分。TYPE_INT_RGB 代表图像8位RGB像素的彩色包装成整数部分。RGBA是对原始的RGB的扩展,它加入了第四个参数:alpha通道。 用 TYPE_INT_ARGB 处理alpha通道 我个人认为,LZ说的不太对,我觉得alpha通道与你最好反回FALSE没有关系。再说经测试黑白化是成功的,只是读到判断时不好用。 万分感谢各位。现在疑问解决了。不过我有个新的疑问。现在这个黑白化思路很简单,就是 r*r +g*g +b*b < 3*128*128,则为黑色,大于则是白色。当一张白色背景,有一个淡黄颜色的字,用这方法一黑白化,就全部是白色了。我把这张图片用photoshop,光影魔术手之类的软件黑白话,这些软件能正常转化,字变成了黑色,没有消失。请问下大家,这是怎么做到的?于是我继续google,发现把图片黑白化一般是先转化为灰度图,再转化为黑白图(gray大于128,为白色,小于,为黑色,很简单),公式是 Gray = 0.212671 * R + 0.715160 * G + 0.072169 * B 。我按这个写了一个灰度化函数,不过转化出来的图很奇怪,代码如下:/** * 将彩色图转化为灰度图 * * @param imgFile 图片文件路径 * @return 一个图片对象 */ public BufferedImage gray(String imgFile) { int newPixels[] = new int[width * height]; for(int i = 0; i < width * height; i++) { int r = (pixels[i] >> 16) & 0xff; int g = (pixels[i] >> 8) & 0xff; int b = (pixels[i]) & 0xff; // 方法1,图像很奇怪 int gray = (int)(0.229 * r + 0.587 * g + 0.114 * b); newPixels[i] = gray << 16 + gray << 8 + gray; //方法2,图像偏蓝,不是灰度图 //newPixels[i] = gray; } // 基于 newPixels 构造一个 BufferedImage BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); bi.setRGB(0, 0, width, height, newPixels, 0, width); newPixels = null; try { // 写入磁盘 BiImage.writeImageToFile(imgFile, bi); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bi; }参考资料:http://topic.csdn.net/t/20040705/16/3147285.html 我也搞了很久 甚至用笔花了半天 最后发现原来是运算符优先级问题汗。。这句应该加括号 newPixels[i]= (gray<<16)+ (gray<<8)+ gray;这样出来的灰度图就很完美了 knightzhuwei,我崇拜你,问题果然在这里。难道Java中运算符优先级和C语言有很大不同吗,太诡异了。newPixels[i] = gray << 16 + gray << 8 + gray;newPixels[i]= (gray < <16)+ (gray < <8)+ gray; 这两者有区别吗,按说括号是不必要的吧。不过,问题解决了,感谢各位,给分结贴!各位真的好热心,再次感谢! Java 如何将窗口内所有文本框重置 求助!!! 网页问题~~!新手求助 如何得到当前web应用中有多少session?每个session都有那些属性? 如何清空panel中的控件? 几个名词翻译----急用! 一品狐在吗,追分 Java3D的鼠标捕捉事件(高手请进) java简单问题再问,是不会还是不帮? 我想通过按钮多次改变文字的颜色,但只能改变一次,刚学不怎么会! 还是java单线程问题··· 扫雷的展开怎么做啊?怎么递归?【超级菜鸟】
估计是你的图片格式, 不防用png试试.
下面的输出结果
Biao: ~/Desktop $ ls
1.png BiImage.java 如何将图片黑白化.webarchive
Biao: ~/Desktop $ javac BiImage.java
Biao: ~/Desktop $ java BiImage 1.png 2.png
230652
0
true
Biao: ~/Desktop $ javac BiImage.java
Biao: ~/Desktop $ java BiImage 1.png 3.png
230652
0
true
Biao: ~/Desktop $ java BiImage 4.png 5.png
366444
0
true
Biao: ~/Desktop $
图片保存为JPG JPEG格式的依然可以黑白化,但结果为FALSE;
1. JPG检测通不过,我觉得还是alpha通道没有处理好。所以,小问题就是,为什么JPG黑白化失败?
2. alpha没有处理的原因,是因为我不太明白 TYPE_INT_ARGB 和 TYPE_INT_RGB 的区别。我的意思是,java在保存图片时,会不会修改某些像素的值,导致检测通不过?
存储的时候本身不是按照rgb的方式存储的 读取的时候需要解压缩 转换为rgb的颜色信息 而这个过程是有损的 会产生非黑白的颜色信息也就不足为奇了
TYPE_INT_RGB 代表图像8位RGB像素的彩色包装成整数部分。RGBA是对原始的RGB的扩展,它加入了第四个参数:alpha通道。
用 TYPE_INT_ARGB 处理alpha通道
再说经测试黑白化是成功的,只是读到判断时不好用。
/**
* 将彩色图转化为灰度图
*
* @param imgFile 图片文件路径
* @return 一个图片对象
*/
public BufferedImage gray(String imgFile) {
int newPixels[] = new int[width * height];
for(int i = 0; i < width * height; i++) {
int r = (pixels[i] >> 16) & 0xff;
int g = (pixels[i] >> 8) & 0xff;
int b = (pixels[i]) & 0xff;
// 方法1,图像很奇怪
int gray = (int)(0.229 * r + 0.587 * g + 0.114 * b);
newPixels[i] = gray << 16 + gray << 8 + gray;
//方法2,图像偏蓝,不是灰度图
//newPixels[i] = gray;
}
// 基于 newPixels 构造一个 BufferedImage
BufferedImage bi = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
bi.setRGB(0, 0, width, height, newPixels, 0, width);
newPixels = null;
try {
// 写入磁盘
BiImage.writeImageToFile(imgFile, bi);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bi;
}参考资料:http://topic.csdn.net/t/20040705/16/3147285.html
这句应该加括号 newPixels[i]= (gray<<16)+ (gray<<8)+ gray;
这样出来的灰度图就很完美了
newPixels[i] = gray << 16 + gray << 8 + gray;newPixels[i]= (gray < <16)+ (gray < <8)+ gray; 这两者有区别吗,按说括号是不必要的吧。不过,问题解决了,感谢各位,给分结贴!各位真的好热心,再次感谢!