滤镜添加
加载图片
加载图片时我们要用到import javax.imageio.ImageIO这个包,在代码里添上一句 image = ImageIO.read(file) 这时系统会报错,将鼠标移动到错误提示的地方,会出现两个选项:
点击第二个选项,这时会出现这样的几行代码:
try {
image = ImageIO.read(file);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
我们要做的就是在try里面插入我们想要的图片并把它画出来
image = ImageIO.read(file);
// 图片高为行,宽为列
data = new int[image.getHeight()][image.getWidth()];
for (int i = 0; i < image.getHeight(); i++) {// 行
for (int j = 0; j < image.getWidth(); j++) {// 列
data[i][j] = image.getRGB(j, i);
color = new Color(data[i][j]);
bg.setColor(color);
bg.drawLine(j + 50, i + 150, j + 50, i + 150);
}
}
g.drawImage(bf, 0, 0, null);
这就是我们写在try里面的方法,它的作用是先把我们选中的图片提取成一个二维数组对象,data[ i ][ j ]表示的是图像上某个点的颜色。最后我们再用这个颜色将图片在画板上画出来。
添加滤镜
已经把图片画好了,那我们就要给它加上一个滤镜,所谓滤镜其实就是对图像的颜色进行处理。但是上面 data[ i ][ j ] = image.getRGB(j, i) 这里拿到的颜色是一个点的混合颜色,我们进行图像处理时一定是对图像的rgb三种颜色分别进行处理,所以我们要通过一个位运算将每个点的红黄蓝提取出来。
int red = (0x00ff0000 & value) >> 16;
int green = (0x0000ff00 & value) >> 8;
int blue = (0xff & value);
在这里我们以黑白滤镜为例子。
黑白滤镜的处理方法就是将每个点的RGB颜色都提取出来后算出三个颜色的平均值,如果这三个颜色的平均值超过了某一个值,那就设置这个点的颜色为白色,如果没有超过就将它设置为黑色,用这行代码实现:
int avage = (int)((red+green+blue)/3);
Color color =avage>=125 ? new Color(255,255,255):new Color(0,0,0);
缓存画笔
在我们绘画的过程中,我们会发现如果直接用graphics在画图板上画的话,它的速度会非常慢,这是我们就需要加一个缓存画笔,先把图片画到缓存上,再将缓存贴到画板上,这样速度就会快很多。将图片画到缓存上其实很简单,只需要添加三行代码:
BufferedImage bf = new BufferedImage(800, 900, BufferedImage.TYPE_INT_ARGB);
Graphics bg = bf.getGraphics();
这里我用了自己的画板举了个例子,具体的对象和尺寸要由自己的作品来定。这几行代码要加在画图的前面。写完这两行代码后,我们就要将所有的画笔转成缓存画笔,将所有的Graphics对象改成换成缓存画布对象,也就是上面的bg。
用缓存画笔画完之后我们还要用一行代码将缓存画布画到画板上。
g.drawImage(bf, 0, 0, null);
这样我们画画的速度就快多了。
鼠标魔法
我们在进行图像处理时,往往是给按钮添加一个监听器,在监听器类里面写一个处理图像的方法,然后点击监听器就可以直接使整张图片变成自己想要的效果。这样的操作很快捷简便但是却缺少新意。今天给大家介绍的鼠标魔法其实就是一种不同的呈现处理后的图像的方式,这种方式的最终效果是点击图像按钮后,让鼠标在图片上拖动,拖动过的地方的图片像素会被处理,而没有被鼠标“临幸”过的地方就不会发生任何变动。
MouseMotionListener
要实现这样的效果,只依靠MouseListener和ActionListener是不行的,所以要引入一个MouseMotionListener,在这个监听器里有两种方法,一个是鼠标拖动,一个是鼠标移动,今天我们所要用到的方法就是鼠标移动。
public void mouseDragged(MouseEvent e) {
x = e.getX();
y = e.getY();
}
这样我们就可以获取到鼠标拖动时鼠标所在的点。
自创画笔
画笔的形状在本质上其实就是在鼠标周围的一个特定的范围内进行的图像处理。我们可以将它设置为圆形,正方形,甚至心形等等。在这里我们就先用圆形做示范。假设半径为r。
在获取到鼠标位置之后我们就可以图片数组进行遍历,若图像上的某个点与鼠标所在位置的点小于r的话,那么我们就要对这个点进行图像处理,这样最后的效果就是当鼠标在图片上点击一下,那么以鼠标为中心,r为半径的圆内会进行图像的处理。
public void drag(int x, int y) {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
//计算图片上的点与鼠标位置的距离
int d = (int) (Math.sqrt((x - j - 50) * (x - j - 50) + (y - i - 150) * (y - i - 150)));
if (d <= 25)
memory(i, j);//图像处理的方法
}
}
}
这个方法就可以在MouseMotionListener的鼠标移动方法里面调用。
使用方法
在了解了大致的思想之后我们就要使用这个方法了,使用方法很简单,在按钮中添加监听器,当鼠标点击按钮后就可以使用方法。
读取,保存本地文件
读取本地文件
以前我们在对图像进行处理的时候,只能对提前设置好的一张图片进行处理,如果我们想换一张图片还要对代码进行各种操作和修改,这样就很麻烦。我们可以用JFrameChooser来解决这个问题。在API文档中,找到JFrameChooser,里面有一段代码,我们可以复制过来直接用。
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"JPG & GIF Images", "jpg", "gif");
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(parent);
if(returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " +
chooser.getSelectedFile().getName());
}
这段代码弹出一个针对用户主目录的文件选择器,其中只显示 .jpg 和 .gif 图像。
我们将第五行代码中的parent改成null。将这段代码添加到try/catch那段代码的前面,新建一个文件对象,路径就是在上面这段代码拿到的 chooser.getSelectedFile().getName()。不过因我们要用到的是路径,所以我们将getName()换成getAbsolutePath()。
完整代码如下:
JFileChooser chooser = new JFileChooser("D:/Java图片/");//指定路径打开图片
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Images", "jpg", "gif");//第一个字符串是下拉框中会显示的东西
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName());
}
File file = new File(chooser.getSelectedFile().getAbsolutePath());
try {
image = ImageIO.read(file);
// 图片高为行,宽为列
data = new int[image.getHeight()][image.getWidth()];
for (int i = 0; i < image.getHeight(); i++) {
for (int j = 0; j < image.getWidth(); j++) {
data[i][j] = image.getRGB(j, i);
color = new Color(data[i][j]);
bg.setColor(color);
bg.drawLine(j + 50, i + 150, j + 50, i + 150);
}
}
g.drawImage(bf, 0, 0, null);
}
保存图片
保存图片和打开图片差不多,唯一的区别是要将int returnVal = chooser.showOpenDialog(null)中的showOpenDialog改成ShowSaveDialog。
JFileChooser chooser = new JFileChooser("D:/Java图片/");
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Images", "jpg", "gif");
chooser.setFileFilter(filter);
int returnVal = chooser.showSaveDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName());
}
try {
ImageIO.write(bf, "png", chooser.getSelectedFile());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
其中ImageIO.write(bf, “png”, chooser.getSelectedFile())句bf是缓存画布对象,png为我们要保存的图片类型,最后一个是保存在我们选中的图片中。
摄像头的调用
关于电脑摄像头的调用,有以下这几行代码:
//获取摄像头
Webcam cam = Webcam.getDefault();
//设置摄像头的大小
cam.setViewSize(WebcamResolution.VGA.getSize());
//打开摄像头
cam.open();
//获取图像
BufferedImage buffer = cam.getImage();
//关闭摄像头
cam.close();
打开了摄像头之后,我们要将摄像头获取到的图片画到我们的界面上来,画界面的方法就和前面打开一张图片将它画到界面上来是一样的,先遍历数组,将每个点的RGB颜色取出来,在一一画上去。
for (int k = 0; k < 50; k++) {
// 获取图像
BufferedImage buffer = cam.getImage();
// 加载
System.out.println(k);
data = new int[buffer.getHeight()][buffer.getWidth()];
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
data[i][j] = buffer.getRGB(j, i);
bgg.setColor(new Color(data[i][j]));//bgg为缓存画布
bgg.drawLine(j + 50, i + 150, j + 50, i + 150);
}
}
g.drawImage(bff, 0, 0, null);//将缓存画布画到界面上去
}
将这位段代码添加到打开摄像头与获取图像之间就可以了。