栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

        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 ());
		// 先声明一个缓冲图片 img
		BufferedImage img = null;
		try {
			// IO操作 读取到的缓冲图片对象赋给 img
			img = 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 和 插值放大 的方法,插值放大可以避免普通放大每个像素的模糊和锯齿问题。小伙伴们可以自取哦。

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781411.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号