在之前的文章中,给大家介绍了如果使用WebCamp来使用电脑的摄像头以及如何为图片添加各种滤镜,那么在这我们进行一个相互结合,就构成了一个我们pc端的美颜相机。
1.第一步和之前一样,就是框体 的创建,以及按钮的相关设置
public class Draw0211 { public void get(){ JFrame jFrame=new JFrame(); jFrame.setTitle("小浩美颜相机摄像"); jFrame.setSize(800,900); jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame.setLocationRelativeTo(null); BorderLayout borderLayout=new BorderLayout(); jFrame.setLayout(borderLayout); //面板类对象的设定以及添加到窗体,和设置窗体的位置 JPanel center=new JPanel(); //颜色设定 center.setBackground(Color.cyan); //设置爱完以后需要添加到窗体,否则无效 jFrame.add(center,BorderLayout.CENTER); //监听器的设置 Mouse0211 mouse0211=new Mouse0211(); //开始定义菜单,菜单栏以及相关按钮 JMenuBar jMenuBar=new JMenuBar(); jFrame.add(jMenuBar,BorderLayout.NORTH); //定义在菜单栏中的菜单选项 String[]name1={"文件","视频","图片","拍照","特殊滤镜","编辑","帮助"}; //开辟一个menu数组来存储调用与添加 JMenu[]menu=new JMenu[name1.length]; for (int i=0;i< name1.length;i++) { JMenu jMenu = new JMenu(name1[i]); menu[i]=jMenu; jMenuBar.add(jMenu); } //子菜单中的菜单选项 String[]name={"打开","关闭","退出"}; for (int i=0;i<name.length;i++) { JMenuItem jMenuItem = new JMenuItem(name[i]); jMenuItem.addActionListener(mouse0211); menu[0].add(jMenuItem); } String[]name2={"打开摄像头","关闭摄像头","录制"}; for (int i=0;i<name2.length;i++) { JMenuItem jMenuItem = new JMenuItem(name2[i]); jMenuItem.addActionListener(mouse0211); menu[1].add(jMenuItem); } String[]name3={"原图","马赛克","灰度","油画","珠纹","素描"}; for (int i=0;i<name3.length;i++) { JMenuItem jMenuItem = new JMenuItem(name3[i]); jMenuItem.addActionListener(mouse0211); menu[2].add(jMenuItem); } String[]name4={"打开","关闭","保存"}; for (int i=0;i<name4.length;i++) { JMenuItem jMenuItem = new JMenuItem(name4[i]); jMenuItem.addActionListener(mouse0211); menu[3].add(jMenuItem); } String[]name5={"怀旧","梦幻","浮雕","卷积","哈哈镜"}; for (int i=0;i<name5.length;i++) { JMenuItem jMenuItem = new JMenuItem(name5[i]); jMenuItem.addActionListener(mouse0211); menu[4].add(jMenuItem); } String[]name6={"左旋转90度","右旋转90度","左旋转180度","右旋转180度"}; for (int i=0;i<name6.length;i++) { JMenuItem jMenuItem = new JMenuItem(name6[i]); jMenuItem.addActionListener(mouse0211); menu[5].add(jMenuItem); } String[]name7={"撤回"}; for (int i=0;i<name7.length;i++) { JMenuItem jMenuItem = new JMenuItem(name7[i]); jMenuItem.addActionListener(mouse0211); menu[6].add(jMenuItem); } jFrame.setVisible(true); //画笔的传输 mouse0211.graphicsmouse=center.getGraphics(); } public static void main(String[] args) { Draw0211 draw0211=new Draw0211(); draw0211.get(); } }
2.第二步通过监听器来获取按钮的点击,来获取调动命令,并对线程的启用以及滤镜的编写
public class Mouse0211 implements ActionListener { //画笔 public Graphics graphicsmouse; //name来获取点击的名字 public String name; //类来传递数据 public Thread0211 thread0211; //监听器的接口方法使用 public void actionPerformed(ActionEvent e){ name=e.getActionCommand(); System.out.println("正在点击的操作按钮为:"+name); if ("打开摄像头".equals(name)){ //开始启动多线程,并且同时创建线程对象则显示线程创建一次 if (thread0211==null){ thread0211=new Thread0211(graphicsmouse,this); //开始启动线程 thread0211.start(); } }else if ("关闭摄像头".equals(name)){ thread0211.flag=false; System.out.println("关闭"); }if("原图".equals(name)){ thread0211.name="原图"; }if ("灰度".equals(name)){ thread0211.name="灰度"; }if ("马赛克".equals(name)){ thread0211.name="马赛克"; }if ("油画".equals(name)){ thread0211.name="油画"; }if ("哈哈镜".equals(name)){ thread0211.name="哈哈镜"; }if ("珠纹".equals(name)){ thread0211.name="珠纹"; }if ("素描".equals(name)){ thread0211.name="素描"; } } //灰度算法 public BufferedImage drawHD(int[][] pixelArr) { //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); for (int i = 0; i < pixelArr.length; i++) { for (int j = 0; j < pixelArr[0].length; j++) { // 像素值 int pixel = pixelArr[i][j]; // 马赛克,灰度,底片 // 转成Color对象,设置给画笔,画出像素点 Color color = new Color(pixel); // 取出三原色 int red = color.getRed(); int blue = color.getBlue(); int green = color.getGreen(); // 算法平均值 int num = (red + blue + green) / 3; Color pixelColor = new Color(num, num, num); //设置缓冲区的像素值 bufferedImage.setRGB(i, j, pixelColor.getRGB()); // 把像素点画在缓冲图片上 // buffG.setColor(pixelColor); // buffG.drawLine(i + 100, j + 100, i + 100, j + 100); } } return bufferedImage; } //马赛克算法 public BufferedImage drawMSK(int[][] pixelArr) { //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); for (int i = 0; i < pixelArr.length; i += 3) { for (int j = 0; j < pixelArr[0].length; j += 3) { // 像素值 int pixel = pixelArr[i][j]; // 把像素点画在缓冲图片上 buffG.setColor(new Color(pixel)); buffG.fillRect(i, j, 10, 10); } } return bufferedImage; } //哈哈镜算法 public BufferedImage drawHHJ(int x,int y,int[][] pixelArr) {; int w= pixelArr.length; int h= pixelArr[0].length; //计算中心点位置 int zx=x-100; int zy=y-100; //放大半径,自己设置 int r=100; //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); for (int i = 0; i <w; i++) { for (int j = 0; j <h;j++) { //计算当前位置是否在中心位置 int tx=i-zx; int ty=j-zy; //当前点到中心点的距离 int dis=(int) Math.sqrt(tx*tx+ty*ty); if (dis<r){ //越靠近中心点,偏移量越大 int nx=tx*dis/r+zx; int ny=ty*dis/r+zy; bufferedImage.setRGB(i,j,pixelArr[nx][ny]); } } } return bufferedImage; } //油画算法 public BufferedImage drawYH(int[][] pixelArr) { //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); for (int i = 0; i < pixelArr.length; i++) { for (int j = 0; j < pixelArr[0].length; j++) { int pixel = pixelArr[i][j]; Color color = new Color(pixel); buffG.setColor(color); Random random = new Random(); int r = random.nextInt(10) + 5; buffG.fillOval(i, j, r, r); } } return bufferedImage; } //珠纹算法 public BufferedImage drawZW(int[][] pixelArr) { //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); for (int i = 0; i < pixelArr.length; i += 4) { for (int j = 0; j < pixelArr[0].length; j += 4) { int pixel = pixelArr[i][j]; Color color = new Color(pixel); buffG.setColor(color); buffG.fillOval(i, j, 8, 8); } } return bufferedImage; } //素描算法 public BufferedImage drawSM(int[][] pixelArr) { //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); for (int i = 0; i < pixelArr.length; i += 2) { for (int j = 0; j < pixelArr[0].length; j += 2) { int pixel = pixelArr[i][j]; Color color = new Color(pixel); int b = color.getBlue(); if (b < 60) { buffG.setColor(Color.black); } else { buffG.setColor(Color.WHITE); } buffG.fillOval(i, j, 4, 4); } } return bufferedImage; } //旋转算法 public BufferedImage drawXZ(int[][] pixelArr) { //创建缓冲区 BufferedImage bufferedImage = new BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB); // 获取缓冲区画笔 Graphics buffG = bufferedImage.getGraphics(); int[][] newArr = new int[pixelArr[0].length][pixelArr.length]; for (int i = 0, n = pixelArr.length - 1; i < pixelArr.length; i++, n--) { for (int j = 0; j < pixelArr[0].length; j++) { newArr[j][n] = pixelArr[i][j]; } } return bufferedImage; } }
3.线程类,并通过按钮调动滤镜算法
public class Thread0211 extends Thread { //画笔初始化 public Graphics graphicsthread; //flag做标记来实现开关视频 public boolean flag = true; //flag做标记来实现开关视频 public int flag1 = 0; //滤镜名称 public String name="原图"; //类的对象构造 public Mouse0211 mouse11; //处理后的缓冲图片 public BufferedImage buffered; //构造方法进行参数的传递,初始化画笔对象 public Thread0211(Graphics graphicsthread, Mouse0211 mouse11) { this.graphicsthread = graphicsthread; this.mouse11 = mouse11; } //处理线程,启动线程后运行的程序,run 方法执行完,该线程结束,线程一旦结束不能再次启动 public void run() { //这个this给到的是什么 System.out.println("启动线程.." + this.getName()); //启动摄像头,在这个线程中使用 Webcam webcam = Webcam.getDefault(); webcam.open(); while (flag) { // 获取摄像头拍到的数据 BufferedImage bufferedImage = webcam.getImage(); // if (name.equals("原图")) { // graphicsthread.drawImage(bufferedImage, 100, 100, 500, 400, null); // } // if (name.equals("灰度")) { // int[][] pixel = getImagePixel(bufferedImage); // buffered = mouse11.drawHD(pixel); // break; // } // if (name.equals("马赛克")){ // int[][] pixel = getImagePixel(bufferedImage); // buffered = mouse11.drawMSK(pixel); // System.out.println("222222222222222222"); // break; // } switch (name) { case "原图": graphicsthread.drawImage(bufferedImage, 100, 100, 600,600,null); break; case "灰度": int[][] pixel = getImagePixel(bufferedImage); buffered =mouse11.drawHD(pixel); break; case "马赛克": int[][] pixel1 = getImagePixel(bufferedImage); buffered = mouse11.drawMSK(pixel1); break; case "哈哈镜": int[][] pixel2 = getImagePixel(bufferedImage); buffered = mouse11.drawHHJ(200,200,pixel2); break; case "油画": int[][] pixel3 = getImagePixel(bufferedImage); buffered = mouse11.drawYH(pixel3); break; case "珠纹": int[][] pixel4 = getImagePixel(bufferedImage); buffered = mouse11.drawZW(pixel4); break; case "素描": int[][] pixel5 = getImagePixel(bufferedImage); buffered = mouse11.drawSM(pixel5); break; } //绘制滤镜效果 graphicsthread.drawImage(buffered, 100, 100,600,600, null); if (name.equals("保存")){ //保存图片的文件 File file=new File(""); try { ImageIO.write(buffered,"PNG",file); break; }catch (IOException e){ e.printStackTrace(); } } } } public int[][] getImagePixel(BufferedImage buffImage) { int w = buffImage.getWidth(); int h = buffImage.getHeight(); int[][] pixelArr = new int[w][h]; // 获取图片中的每一个像素值保存到二维数组中 for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { int pixel = buffImage.getRGB(i, j); pixelArr[i][j] = pixel; } } return pixelArr; } }
4.效果如下(菜单栏中些许功能没有完善,后续会继续完善)
(马赛克,油画,灰度,哈哈镜效果)