Java程序结构模板——美颜相机案例

news/2024/10/31 3:18:04/

我们以美颜相机举例,分析一个程序都需要什么。

        1、UI界面:大部分需要交互的程序都需要UI界面来实现交流互动。

        2、监听器:人们在UI中的操作需要监听器来捕捉和执行相应的命令。

        3、工具类:将执行命令的方法单独封装成工具类,供监听器调用。

1. UI界面

实现UI界面,需要一个窗体,并在其中添加各种各样的功能区域、按钮。

美颜相机中需要显示和绘制图像的区域、各种特效工具按钮的区域。(可以再细分)

并且要给鼠标加上监听器以知道人们操作了什么。

我们用美颜相机项目的代码详细说明。

public class UI{// 监听器对象 整个程序只创建一个// 这种只有一个对象的模式称为 单例模式 是Java设计中最简单的设计模式,值得去了解一下ImageListener imgl = new ImageListener ();public void initUI(){// 创建一个窗体,并且使用 边界布局 ,组件可以被放在 东 西 南 北 中 5个区域中。JFrame jf = new JFrame ("美颜相机");jf.setSize (1000, 750);jf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);// 添加面板JPanel imgshowPanel = new JPanel ();//图像显示面板JPanel btnPanel = new JPanel ();//工具面板imgshowPanel.setBackground (Color.GRAY);btnPanel.setBackground (new Color (200, 200, 200));// 尺寸Dimension dim = new Dimension (300, 0);btnPanel.setPreferredSize (dim);// 添加按钮,需要添加的功能按钮很多,于是封装addButton方法再调用this.addButton (btnPanel);// 图像显示面板添加到中心区域,工具面板添加到 东 区域jf.add (btnPanel, BorderLayout.EAST);jf.add (imgshowPanel, BorderLayout.CENTER);jf.setVisible (true);//获取Graphics 从 ImageJPanel上Graphics graphics1 = imgshowPanel.getGraphics ();// 赋值转递 传递的都是对象的引用地址imgl.gr=graphics1;}// 单独写方法 添加按钮public void addButton(JPanel btnjp){String[] btnstr = {"原图", "清空", "马赛克","黑白", "灰度", "油画", "波点","旋转","插值放大", "柔化", "锐化"};Dimension dim = new Dimension (120,35);for(int i = 0; i < btnstr.length; i++){JButton btn = new JButton (btnstr[i]);btn.setBackground (Color.WHITE);btn.setPreferredSize (dim);// 按钮添加监听器btn.addActionListener (imgl);// 添加到面板btnjp.add (btn);}}public static void main(String[] args){UI ui = new UI ();UI.initUI ();}
}

2. 监听器

人们在UI中的操作需要监听器来捕捉和执行相应的命令。

我们用美颜相机项目的代码详细说明。

public class ImageListener extends MouseAdapter implements ActionListener {// 监听器类继承MouseAdapter类,重写了所有的监听器中的抽象方法Graphics gr;// gr变量 赋值转递 传递的都是对象的引用地址int g;// 基本数据类型的变量 存储的值// 初始化一个图片操作对象Utils utils = new Utils ();BufferedImage buffimg = null;int[][] imgarr = {};{// 代码块 初始化(创建对象时自动调用) 图片的转化buffimg = Utils.getImage ("C:\\Users\\win\\Desktop\\****.jpeg");imgarr = Utils.getImageArray (buffimg);}// 动作监听器的方法public void actionPerformed(ActionEvent e){String action = e.getActionCommand ();if(action.equals ("原图")){imageUtils.normal (buffimg, gr);} else if(action.equals ("马赛克")){imageUtils.mosaic (imgarr, gr);} else if(action.equals ("灰度")){imageUtils.graylevel (imgarr, gr);} else if(action.equals ("黑白")){imageUtils.black_white (imgarr, gr);} else if(action.equals ("波点")){imageUtils.point (imgarr, gr);}else if(action.equals ("清空")){imageUtils.clean (imgarr, gr);}else if(action.equals ("旋转")){imageUtils.rotate(buffimg, gr);}else if(action.equals ("插值放大")){imageUtils.bigpro(imgarr, gr);}}
}

3. 工具类

public class Utils {public BufferedImage getImage(String path){// 根据指定文件路径 创建文件对象// 文件是存在磁盘上的一些数据体// 文件对象 是内存中的一个对象File file = new File (path);System.out.println (file.getPath ());// 先声明一个缓冲图片 imgBufferedImage img = null;try {// IO操作 读取到的缓冲图片对象赋给 imgimg = ImageIO.read (file);} catch (IOException e) {e.printStackTrace ();}// 方法返回值 img 对象return img;}// 缓存图片转为二维数组public int[][] getImageArray(BufferedImage img){// 根据图片的宽高 初始化一个二维数组int[][] imgarr = new int[img.getWidth ()][img.getHeight ()];// img 对象可以调用的方法// 遍历存入 img 对象中取出的像素值for(int i = 0; i < img.getWidth (); i++){for(int j = 0; j < img.getHeight (); j++){int rgb = img.getRGB (i, j);imgarr[i][j] = rgb;}}// 返回二维数组return imgarr;}// 根据二维数组 绘制滤镜效果	// 原图public void normal(BufferedImage img,Graphics g){g.drawImage (img,0,0,null);}// 黑白二值化效果public void black_white(int[][] imgarr, Graphics g){for(int i = 0; i < imgarr.length; i++){for(int j = 0; j < imgarr[i].length; j++){// 取出像素值int i1 = imgarr[i][j];// 拆分为 三原色值int red = (i1 >> 16) & 0xFF;int green = (i1 >> 8) & 0xFF;int blue = (i1 >> 0) & 0xFF;int gray = (red + green + blue) / 3;// 二值化 抠图if(gray < 100){g.setColor (Color.BLACK);} else{g.setColor (Color.WHITE);}g.fillRect (i, j , 1, 1);}}}// 灰阶效果public void graylevel (int[][] imgarr, Graphics g){for(int i = 0; i < imgarr.length; i++){for(int j = 0; j < imgarr[i].length; j++){// 取出像素值int i1 = imgarr[i][j];// 拆分为 三原色值int red = (i1 >> 16) & 0xFF;int green = (i1 >> 8) & 0xFF;int blue = (i1 >> 0) & 0xFF;// 操作三原色值 实现滤镜// 明暗度 red green blue 等值递减 递加// gray r=g=b 整个图片就会失去彩色 黑 白 灰度int gray = (red + green + blue) / 3;Color color = new Color (gray, gray, gray);g.setColor (color);g.fillRect ( i, j , 1, 1);}}}// mosaic马赛克效果public void mosaic(int[][] imgarr, Graphics g){for(int i = 0; i < imgarr.length; i+=10){for(int j = 0; j < imgarr[i].length; j+=10){// 取出像素值int i1 = imgarr[i][j];Color color = new Color(i1 );g.setColor(color);g.fillRect ( i, j , 10, 10);}}}//波点效果public void point (int[][] imgarr, Graphics g){for(int i = 0; i < imgarr.length; i+=10){for(int j = 0; j < imgarr[i].length; j+=10){// 取出像素值int i1 = imgarr[i][j];Color color = new Color(i1 );g.setColor(color);g.fillOval ( i, j , 10, 10);}}}// 清空画布public void clean (int[][] imgarr, Graphics g){g.setColor(Color.WHITE);g.fillRect ( 0,0 ,1000, 1000);}public void rotate(BufferedImage img,Graphics g){BufferedImage img1 = rotateImage(img,30,Color.WHITE);g.drawImage (img1,0,0,null);}public BufferedImage rotateImage(BufferedImage image, double theta,Color backgroundColor) {int width = image.getWidth();int height = image.getHeight();double angle = theta * Math.PI / 180; // 度转弧度double[] xCoords = getX(width / 2, height / 2, angle);double[] yCoords = getY(width / 2, height / 2, angle);int WIDTH = (int) (xCoords[3] - xCoords[0]);int HEIGHT = (int) (yCoords[3] - yCoords[0]);BufferedImage resultImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);for (int i = 0; i < WIDTH; i++) {for (int j = 0; j < HEIGHT; j++) {int x = i - WIDTH / 2;int y = HEIGHT / 2 - j;double radius = Math.sqrt(x * x + y * y);double angle1;if (y > 0) {angle1 = Math.acos(x / radius);} else {angle1 = 2 * Math.PI - Math.acos(x / radius);}x = (int) (radius * Math.cos(angle1 - angle));y = (int) (radius * Math.sin(angle1 - angle));if (x < (width / 2) & x > -(width / 2) & y < (height / 2) & y > -(height / 2)) {int rgb = image.getRGB(x + width / 2, height / 2 - y);resultImage.setRGB(i, j, rgb);}else {int rgb = ((0 & 0xff) << 24) | ((backgroundColor.getRed() & 0xff) << 16) | ((backgroundColor.getGreen() & 0xff) << 8)| ((backgroundColor.getBlue() & 0xff));resultImage.setRGB(i, j, rgb);}}}return resultImage;}// 获取四个角点旋转后Y方向坐标private double[] getY(int i, int j, double angle) {double results[] = new double[4];double radius = Math.sqrt(i * i + j * j);double angle1 = Math.asin(j / radius);results[0] = radius * Math.sin(angle1 + angle);results[1] = radius * Math.sin(Math.PI - angle1 + angle);results[2] = -results[0];results[3] = -results[1];Arrays.sort(results);return results;}// 获取四个角点旋转后X方向坐标private double[] getX(int i, int j, double angle) {double results[] = new double[4];double radius = Math.sqrt(i * i + j * j);double angle1 = Math.acos(i / radius);results[0] = radius * Math.cos(angle1 + angle);results[1] = radius * Math.cos(Math.PI - angle1 + angle);results[2] = -results[0];results[3] = -results[1];Arrays.sort(results);return results;}public void bigpro(int[][] imgarr ,Graphics g){for(int i = 0; i < imgarr.length-1; i++){for(int j = 0; j < imgarr[i].length-1; j++){// 取出像素值int i1 = imgarr[i][j];int i2 = imgarr[i+1][j];int i3 = imgarr[i][j+1];int i4 = imgarr[i+1][j+1];// 拆分为 三原色值int red1 = (i1 >> 16) & 0xFF;int green1 = (i1 >> 8) & 0xFF;int blue1 = (i1 >> 0) & 0xFF;int red2 = (i2 >> 16) & 0xFF;int green2 = (i2 >> 8) & 0xFF;int blue2 = (i2 >> 0) & 0xFF;int red3 = (i3 >> 16) & 0xFF;int green3 = (i3 >> 8) & 0xFF;int blue3 = (i3 >> 0) & 0xFF;int red4 = (i4 >> 16) & 0xFF;int green4 = (i4 >> 8) & 0xFF;int blue4 = (i4 >> 0) & 0xFF;Color color1 = new Color (red1,green1,blue1);g.setColor(color1);g.fillRect ( i*2, j*2, 1, 1);Color color2 = new Color ((red1+red2)/2,(green1+green2)/2,(blue1+blue2)/2);g.setColor(color2);g.fillRect ( i*2+1, j*2, 1, 1);Color color3 = new Color ((red1+red3)/2,(green1+green3)/2,(blue1+blue3)/2);g.setColor(color3);g.fillRect ( i*2, j*2+1, 1, 1);Color color4 = new Color ((red1+red4)/2,(green1+green4)/2,(blue1+blue4)/2);g.setColor(color4);g.fillRect ( i*2+1, j*2+1, 1, 1);}}}
}

图片工具中还封装了旋转rotate 和 插值放大 的方法,插值放大可以避免普通放大每个像素的模糊和锯齿问题。小伙伴们可以自取哦。

欢迎评论或者私信交流问题和心得~


http://www.ppmy.cn/news/437090.html

相关文章

P8美颜相机的实现

美颜相机 一. 基础知识二. 图片处理将一个图片转化为一个二维数组并封装 三.写一个界面并添加画板和按钮四. 添加监听器并将图片信息传递给监听器中五.马赛克六.灰度七.素描美白油画轮廓检测 一. 基础知识 一幅图就是无数个像素点组成&#xff0c;可以看成宽w高h的二维数组图像…

大疆口袋相机美颜怎么设置_大疆(DJI)Pocket2 | 深度测评口袋相机:超多配件随心搭,自带美颜的拍摄助手!-极果...

写在前面 你真的需要一台DJI Pocket 2吗?嘿,大家好~我是抖音博主无情剪辑狗,作为一名摄影教学类博主很高兴能体验到DJI Pocket 2,经过自己一个星期的体验,来和大家分享一下这款产品我的心得体会以及什么样的人适合入手这样一台设备。 下面通过这则视频可以先简单的了解一…

基于OpenCV和OpenGL 的简易美颜相机

版本信息 AndroidStudio 3.5.2 OpenCV 4.1.2 OpenGL 2 OpenCV是什么 维基百科 在本Demo中&#xff0c;OpenCV实现面部识别功能 OpenGL是什么 维基百科 在本Demo中&#xff0c;OpenGL实现美颜功能 配置OpenCV环境 在AndroidStudio中新建C项目 下载OpenCV Android版 …

美颜相机的设计与实现

美颜相机的实现&#xff08;利用Webcam&#xff09; 如何实现美颜相机&#xff1f; 首先&#xff0c;需要导入三个外部jar包来调用摄像头 美颜相机是要调用我们的电脑摄像头实时获取我们的视频数据&#xff0c;视频就是由一帧一帧的图片组成的&#xff0c;所以我们需要先将一…

java简易美颜相机

一、图片处理的原理 首先我们知道数码照片只要是存储在计算机上的内容都是二进制码组成&#xff0c;而图片RGB值是由三组byte组成的&#xff08; 255.0.0&#xff08;红色&#xff09;&#xff09;&#xff0c;所以它可以看成一个整数&#xff0c;红色即为&#xff1a;1671168…

NDK 开发实战 - 实现相机美颜功能

在 《图形图像处理 - 实现图片的美容效果》 一文中提到了图片的美容&#xff0c;采用双边滤波算法来实现&#xff0c;具体的算法流程和实现思路&#xff0c;大家可以在上篇文章中了解&#xff0c;这篇文章就在不再反复啰嗦了。这里我们再次来看下处理效果&#xff1a; 上面的效…

iOS-美颜相机 by GPUImage

之前网上有个段子说&#xff1a;日本女人靠化妆&#xff0c;韩国女人靠整容&#xff0c;中国女人靠美颜 足以证明相机美颜功能在中国地位是多么高&#xff0c;关于美颜相机的 App 在中国是那么的火 其实美颜相机的实现原理很简单&#xff0c;就是给采集到的图像通过添加滤镜进…

android 美颜相机开发,Android OpenGL ES从入门到进阶(一)—— 五分钟开发一款美颜相机...

源码链接:https://github.com/smzhldr/AGLFramework 一、前言 商店里有数十款的美颜相机类产品,以及像抖音,唱吧之类带有视频的软件,功能很强大,其实现原理基本上都是以OpenGL ES为核心的特效处理,笔者码了一个很轻量级的Android OpenGL ES及Camera开发框架,意在使用的时…