美颜相机1.0

美颜相机1.0

基本功能介绍

如下图所示:(功能待完善)
在这里插入图片描述

基本实现类

1.ImageUI(界面显示)
该类主要实现的功能为:
1. 窗体显示
2. 面板添加
3. 按钮添加及显示
4. 菜单栏的添加及显示
public class ImageUI extends JFrame  {
		//监听器对象,整个程序中只有一个
		ImageListener imgl =new ImageListener();
		//添加面板 // 自己写一个类 继承JPanel 替换面板
		ImagePanel imgshowPanel = new ImagePanel();
		/**
		 * 初始化界面
		 * 创建窗体
		 * 给监听器中 传入 绘制面板对象
		 * 从监听器对象中拿到ImageArray 对象 传入 绘制面板中
		 */
		public void showUI() {
			//初始化界面
			this.setTitle("美颜相机");
			this.setSize(1500,750);
			this.setLocationRelativeTo(null);
			this.setDefaultCloseOperation(EXIT_ON_CLOSE);	
			//添加面板
			JPanel btnjPanel= new JPanel();
		
			//主动调用repaint方法 让窗体 和画板  自己 画出图片
			//尺寸
			Dimension  dm1 = new Dimension(300,0);
			btnjPanel.setPreferredSize(dm1);
			//设置背景颜色
			imgshowPanel.setBackground(Color.LIGHT_GRAY);
			btnjPanel.setBackground(new Color(220,220,220));	
			//将面板添加到窗体上
			this.add(btnjPanel,BorderLayout.EAST);			
			this.add(imgshowPanel,BorderLayout.CENTER);
			//添加按钮,封装成方法,传入的是面板对象
			this.addbutton(btnjPanel);
//			//添加滑杠
//			JSlider jSlider  = new JSlider();
//			jSlider.setPreferredSize(new Dimension(100,100));			
//			btnjPanel.add(jSlider);		
			//菜单栏
			this.setJMenuBar(initMenu());
			this.setVisible(true);
			//赋值传递,传递的都是对象的应用地址
			//将监听器中初始化好的imageArray 数组对象 传入面板中
			imgl.setShowImagePanel(imgshowPanel);
		}
		public JMenuBar initMenu() {
			String[] menus= {
					"文件","编辑","导航","工具","视图","帮助"
			};
			String[] menuFiles  = {
					"新建","打开","设置","保存","刷新","退出"
			};
			String[]  menuTools = {
					"图像滤镜工具","图像绘制工具"
			};
			String[] imageFunction = {
					"灰度","美白","二值化","红色通道","绿色通道","蓝色通道","饱和度"
					,"色调","锐化","高斯模糊"
			};
			String[]  imageFunction2 = {
				"直线","矩形","椭圆","圆"	
			};
			//菜单栏
			JMenuBar menuBar = new JMenuBar();
			//创建菜单
			for(int i=0;i<menus.length;i++) {
				JMenu menu = new JMenu(menus[i]);
				if (i==0) {//文件按钮
					for (int j = 0; j < menuFiles.length; j++) {
						JMenuItem menuItem = new JMenuItem(menuFiles[j]);
						menu.add(menuItem);
					}
				}//工具按钮
				else if (i==3) {
					for (int j = 0; j < menuTools.length; j++) {
						JMenu menu1 = new JMenu(menuTools[j]);
						if (j==0) {
							for (int k = 0; k < imageFunction.length; k++) {
								JMenuItem menuItem1 = new JMenuItem(imageFunction[k]);
								menu1.add(menuItem1);
								menuItem1.addActionListener(imgl);
							}
						}
						else {
							for (int k = 0; k < imageFunction2.length; k++) {
								JMenuItem menuItem2 = new JMenuItem(imageFunction2[k]);
								menu1.add(menuItem2);
								menuItem2.addActionListener(imgl);
							}
						}
						menu.add(menu1);
					}
				}
				menuBar.add(menu);
			}
			return menuBar;
		}
		public void addbutton(JPanel btnJPanel) {
			String[] name = { "原图","美白", "怀旧", "马赛克", "噪声","去色" ,"油画","二值化","撤回","打开","保存"};
			for (int i = 0; i < name.length; i++) {
				JButton jButton = new JButton(name[i]);
				jButton.setPreferredSize(new Dimension(120,35) );
				//给按钮添加监听器
				jButton.addActionListener(imgl);
				//添加到面板
				btnJPanel.add(jButton);
			}
		}
		public static void main(String[]  args) {
			ImageUI	image = new ImageUI();
			image.showUI();
			image.initMenu();
		}
}			
2.ImagePanel(重绘面板类)
  1. 通过继承JPanel 类实现面板的重绘功能,因为图片的覆盖性,所以每次重绘只需绘制出最后一张图片即可
  2. 所以通过存储图片的二维数组,找到最后一张图片的索引,即int imgIndex= imageArray.getSize()-1; 再取出图片,调用画笔重绘功能即可

public class ImagePanel  extends JPanel{
	private ImageArray imageArray;
	
	/**
	 *   设置ImageArray 的传值方法
	 *   第一次点击按钮时 
	 * @param imageArray
	 */
	public void setImageArray(ImageArray imageArray) {
		this.imageArray = imageArray;
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		//涉及数据结构索引操作 一定先确定0是否越界
		//绘制 栈顶  因为图片是相互覆盖的  ,  所以运用栈的思想 取出图片
		//先确定最后一张存入的图片的位置  -  定位
		if (imageArray==null) {
			return;
		}
		int imgIndex= imageArray.getSize()-1;
		if (imgIndex<0) {
			return;//不执行
		}
		//取出图片对象
		BufferedImage img = imageArray.get(imgIndex); 
		//绘制
		g.drawImage(img,(int)(this.getWidth()*0.1),(int)(this.getHeight()*0.1),
				(int)(this.getWidth()*0.8),(int)(this.getHeight()*0.8),null);
		//将一个小矩形 放置在一个大矩形中  要居中  需要计算小矩形左上角的坐标在大矩形的哪里
	}
}
3.ImageListener (监听器)

基本功能实现:

  1. 初始化得到图片的二维数组
  2. 通过点击按钮实现监听功能,并调用响应的方法绘制出图片
public class ImageListener extends MouseAdapter implements ActionListener {
	/**
	 * 	绘制面板
	 */
	private ImagePanel showImagePanel;
	/**
	 * 	图像绘制工具
	 */
	private Graphics gr;
	/**
	 * 	图像处理工具 可以调用图像处理工具的方法
	 */
	private ImageUtils imageUtils = new ImageUtils();
	/**
	 * 	当前操作的缓存图片对象
	 */
	private BufferedImage bufferedImage = null;
	/**
	 * 	当前加载的图片 对应的图像数组
	 */
	private int [][] imagrr = {};
	/**
	 * 	初始化 缓存图片对象  / 图片数组
	 */
	{//代码块  初始化(创建对象时自动调用)图片的转化
		bufferedImage=imageUtils.getImage("./imgs/3.jpg");
		imagrr =imageUtils.getImageArray(bufferedImage);
	}
	//声明存储图像线性表   数组  初始化是定容量的 不方便扩容
	BufferedImage[] buffimgList = new BufferedImage[100];
	/**
	 * 	存储图片的动态数组
	 */
	private ImageArray imageArray = new ImageArray(1000);
	/**
	 * 	设置	绘制面板
	 * @param showImagePanel
	 */
	public void setShowImagePanel(ImagePanel imagePanel) {
		this.showImagePanel = imagePanel;
	}
	/**
	 * 	动作监听器的方法
	 * 	获取 图形类型按钮的字符串
	 * 	选择图形特效类	对应的方法来执行绘制
	 * 	注意 if(){} else if(){}
	 * 	 if(){}  if(){}
	 * 	@param e
	 */
	public void actionPerformed(ActionEvent e) {
		String action = e.getActionCommand();
		if (gr==null) {	//gr 第一次为null时, 初始赋值
			//获取Graphics对象
			gr=showImagePanel.getGraphics();
			showImagePanel.setImageArray(imageArray);
		}
		//获取吃力之后的图片
		//存入数组中
		drawImage(action);
		//刷新绘制
		showImagePanel.repaint();
	}
	/**
	 * 	处理图片选择流程
	 * @param action 按钮字符串
	 */
	public void drawImage(String action) {
		if (action.equals("原图")) {
			BufferedImage img=imageUtils.drawImage(imagrr, gr);
			imageArray.add(img);
		} else if (action.equals("马赛克")) {
			BufferedImage img =imageUtils.drawImage03(imagrr, gr);
			imageArray.add(img);
		} else if (action.equals("二值化")) {
			BufferedImage img =imageUtils.drawImage02(imagrr, gr);
			imageArray.add(img);
			
		} else if (action.equals("去色")) {
			BufferedImage img =imageUtils.drawImage01(imagrr, gr);
			imageArray.add(img);
			
		} else if (action.equals("噪声")) {
			BufferedImage img =imageUtils.drawImage04(imagrr, gr);
			imageArray.add(img);
			
		}
	}
}
4.ImageUtils(图像处理类)

该类主要实现了:

  1. 从文件获取图片,并返回图片对象
  2. 将得到的图片对象转化为一个图片二维数组,二维数组里面保存图片的像素(ts:从图片获取像素,有两种方法,一:遍历图片的二维数组,直接调用 对象.getRGB(); 获取像素 )
  3. 通过图片二维数组绘制出缓存图片(绘制在缓存图片上), 最后通过面板主动刷新功能,实现重绘
  4. 图片处理的功能,比如:去色,二值化,油画,怀旧等功能(ts:为了增加绘制图片的速度,采用了BufferedImage 这个缓存图片数组类,传入图片的二维数组,即可在缓存图片中把所需图片先绘制出来,最后在调用原画笔直接将整张图片绘制出来)具体实现如下:
BufferedImage buffimg  = new BufferedImage(imagrr.length, imagrr[0].length,BufferedImage.TYPE_INT_RGB);
		Graphics buffg = buffimg.getGraphics();
		for (int i = 0; i < imagrr.length; i += 10) {
			for (int j = 0; j < imagrr[i].length; j += 10) {
				// 取出照片的像素
				int i1 = imagrr[i][j];
				Color color = new Color(i1);
				buffg.setColor(color);
				buffg.fillRect(i, j, 10, 10);
			}
		}
		//g.drawImage(buffimg, 0, 0, null);
		return buffimg;

完整代码:

public class ImageUtils {
		 /*	从文件里读取缓冲图片,并返回一个缓冲图片对象
	  * 1. 创建一个文件类对象,实现从磁盘获取图片 
	 *	2.声明一个缓冲图片对象 ,采用BufferedImage类
	 *	3.通过对象调用ImageIO.read(file)方法读入图片
	 *  4. 返回BufferedImage对象img
	 */	 
	//构建方法两明确:1.返回值类型2.是否需要参数,参数类型,参数个数
	//弄清每个构建方法的目的,最后保持真个逻辑思维明确
	public BufferedImage getImage(String path) {
		//根据文件路径 创建一个文件对象
		File file = new File(path);
		//System.out.println(file.getPath());
		//先声明一个缓冲图片img
		BufferedImage img = null;
		try {
			img=ImageIO.read(file);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//返回img对象
		return img;
	}
	/*将缓冲图片 转化为 一个二维数组,并取出二维数组里面的像素
	 * 1.定义方法:返回值类型为 二维数组 ,参数是 BufferedImage对象 img
	 * 2.用缓冲图片对象来创建一个二维数组
	 * 3.
	 *//*
	 * public BufferedImage getImage(String path)  ImageIO.read(file)
	 * BufferedImage img 要求传入一个文件路径,返回一个缓冲图片对象
	 * public  int[][] getImageArray(BufferedImage img)
	 * 	要求传入一个 BufferedImage img 对象,以获取图片的数组以及像素 img.getRGBbu
	 * 	返回带有像素的二维数组
	 */
	public int[][] getImageArray(BufferedImage img){
		//创建一个二维数组
		int[][] imagrr =  new int [img.getWidth()][img.getHeight()];
		//获取缓存图片的Graphics 绘制的内容  	
		for (int i = 0; i < img.getWidth(); i++) {
			for (int j = 0; j < img.getHeight(); j++) {
				int rgb = img.getRGB(i, j);
				//将图片数据保存到数组中
				imagrr[i][j]=rgb;
			}
		}
		return imagrr;
	}
	public BufferedImage drawImage(int[][] imagrr, Graphics g) {
		BufferedImage buffimg = new BufferedImage(imagrr.length, imagrr[0].length, BufferedImage.TYPE_INT_ARGB);
		Graphics buffg = buffimg.getGraphics();
		for (int i = 0; i < imagrr.length; i++) {
			for (int j = 0; j < imagrr[i].length; j++) {		
				int rgb = imagrr[i][j];
				Color color =new Color(rgb);
				buffg.setColor(color);
				buffg.fillRect(i, j, 1, 1);
			}
		}
//		g.drawImage(buffimg, 0, 0, null);
		return buffimg;
	}
	/*
	1.首先遍历照片得到一个照片像素的二维数组
	2.将得到的像素拆分为三原色
	3.操作三原色值实现滤镜
	ps:滤镜实际上是对明暗度的调整
	*/
	//去色:本质上是对RGB三原色  的  递增 或 递减  就能实现 去色操作
	public BufferedImage drawImage01(int[][] imagrr,Graphics g) {
		//目的:加快绘制速度    思路:
		//创建一个空的缓存图片对象,通过缓存图片的画笔,将所需图片的像素直接绘制到缓存图片上,最后直接通过原画笔直接绘制出整张缓存图片
		BufferedImage buffimg = new BufferedImage(imagrr.length,imagrr[0].length,BufferedImage.TYPE_INT_ARGB);
		Graphics buffg   = buffimg.getGraphics();
		for (int i = 0; i < imagrr.length; i++) {
			for (int j = 0; j <imagrr[i].length; j++) {
				//取出照片的像素
				int i1 = imagrr[i][j];
				//拆分为三原色
				int red = (i1>>16)&0xFF;
				int green = (i1>>8)&0xFF;
				int blue = (i1>>0)&0xFF;
							
				int gray = (red+green+blue)/3;
				//灰度化图片   
				  Color color = new Color(gray,gray,gray);
//				  g.setColor(color); 
//				  g.fillRect(i,j,1,1);	
				  buffg.setColor(color);
				  buffg.fillRect(i,j,1,1);	 
			}
		}	
	//	g.drawImage(buffimg, 0,0,null);
		return buffimg;
	}	
	//二值化
	public BufferedImage drawImage02(int[][] imagrr,Graphics g) {
		BufferedImage buffimg = new BufferedImage(imagrr.length, imagrr[0].length, BufferedImage.TYPE_INT_ARGB);
		Graphics buffg = buffimg.getGraphics();
		for (int i = 0; i < imagrr.length; i++) {
			for (int j = 0; j < imagrr[i].length; j++) {
				//取出照片的像素
				int i1 = imagrr[i][j];
				//拆分为三原色
				int red = (i1>>16)&0xFF;
				int green = (i1>>8)&0xFF;
				int blue = (i1>>0)&0xFF;
				// ps: 明暗度  有三原色 等值 递减 或 递加
				// ps: 当red = green = blue 时,整个照片会失去色彩  
				//二值化 抠图
				int gray = (red+green+blue)/3;
				if (gray>100) {
						buffg.setColor(Color.BLACK);
						//g.setColor(Color.BLACK);
					}else {
						//g.setColor(Color.WHITE);
						buffg.setColor(Color.WHITE);
					}
				buffg.fillRect (i, j , 1, 1);
			
			}
		}
			//g.drawImage(buffimg, 0, 0, null);
			return buffimg;
	}
	//马赛克
	public BufferedImage drawImage03(int[][] imagrr, Graphics g) {
		BufferedImage buffimg  = new BufferedImage(imagrr.length, imagrr[0].length,BufferedImage.TYPE_INT_RGB);
		Graphics buffg = buffimg.getGraphics();
		for (int i = 0; i < imagrr.length; i += 10) {
			for (int j = 0; j < imagrr[i].length; j += 10) {
				// 取出照片的像素
				int i1 = imagrr[i][j];
				Color color = new Color(i1);
				buffg.setColor(color);
				buffg.fillRect(i, j, 10, 10);
			}
		}
		//g.drawImage(buffimg, 0, 0, null);
		return buffimg;
	}
	//随机绘制彩色噪声矩阵
	public BufferedImage drawImage04(int[][] imagrr, Graphics g) {
		BufferedImage buffimg = new BufferedImage(imagrr.length, imagrr[0].length, BufferedImage.TYPE_INT_ARGB);
		Graphics buffg = buffimg.getGraphics();
		Random random = new Random();
		for (int i = 0; i < imagrr.length; i++) {
			for (int j = 0; j < imagrr[i].length; j++) {
				Color color = new Color(random.nextInt(Integer.MAX_VALUE));
				buffg.setColor(color);
				buffg.fillRect( i,  j, 1, 1);
			}
		}
	//	g.drawImage(buffimg, 0,0,null);
		return buffimg;
	}
}
5.ImageArray(动态存储数组类)

基本介绍:

  • 用来存储图片的数组 , 方便 我们对每张图片的操作
  • 用来存储图片的动态数组类,可以实现数组自动扩容
  • 存储的图片对象类型时: BufferedImage
  • 目前实现了:
  • add方法
  • get方法
  • remove方法
  • size方法
import java.awt.image.BufferedImage;
/**
 *	这是一个用来存储图片的动态数组类,可以实现数组自动扩容
 *	存储的图片对象类型时:  BufferedImage
 *         目前实现了: 
 *  add方法
 *  get方法
 *  remove方法
 *  size方法
 *  
 * @author DELL
 *	@since 2022-04-05
 *	@version 1.0
 */
public class ImageArray {
	/**
	 *	用来存储图片的底层数组对象
	 * 	初始化为{   },避免出现空指针异常
	 */
	private BufferedImage[] imgArray = {};
	/**
	 * 	数组当前的空间容量
	 */
	private int length ;
	/**
	 * 	数组默认初始化容量
	 */
	private static final int defaultLength=10;
	/*
	 * 	 小标 以及 存储的元素个数
	 * 	一个变量 两个作用
	 */
	private int size;
	/**
	 * 	获取数组的元素个数,用来记录数组中元素的个数,即操作次数
	 * @return  数组中的元素个数
 	 */
	public int getSize() {
		return size;
	}
	/**
	 * 	图片动态数组的初始化构造方法
	 * 	初始化	数组
	 * 	构造方法	创建对象时对用
	 * 	永远不要相信别人给你的参数
	 * @param initSize	初始化的容量
	 */
	public ImageArray(int initSize) {
		if (initSize<10) {
			length=defaultLength;
			imgArray=new BufferedImage[length];//动态数组
			size=0;
		}
		//根据参数初始化
		if (initSize>10) {
			length=initSize;
			imgArray=new BufferedImage[length];		
			size=0;
		}
	}
	//添加图片
	public void add(BufferedImage img) {
		if (size>=length) {//判断数组空间需不需要扩容
			//扩容分两步:
			//第一:扩大数组长度
			//第二:数据迁移
			int oldlength = length;
			int newlength = oldlength+(oldlength>>1);//扩容1.5倍
			length = newlength;
			BufferedImage[] newArray =new BufferedImage[length];
			//将原数组中的数据转移至新数组中
			for(int i =0;i<oldlength;i++) {
				newArray[i]= imgArray[i];
			}
			//替换引用
			imgArray = newArray ;
			newArray=null;
		}
		imgArray[size++]=img;
	}
	/**
	 * 	获取一张图片
	 * @param index
	 * 		注意index的合法性
	 * @return
	 */
	public BufferedImage get(int index) {
		BufferedImage buffimg = imgArray[index];
		return buffimg;
	}
	/**
	 * 	删除
	 * 	删除后    后面的数据需要迁移 ,并且size要-1
	 * @param index
	 */
	public void remove(int index) {
		if (index>length-1) {
			System.out.println("你需要删除的数据不存在");
		}
		else {
			imgArray[index]=null;
			size--;		
		}
	}
}

后续功能还待完善~version1.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值