美颜相机Pro————整合界面中的处理方法

之前写了美颜相机的简单系统,但是仅仅可以实现传入图片的地址,完成加载,灰度化,马赛克等等,本次的美颜相机不仅包含这些方法,还进行鼠标绘制,文件管理的操作等等

首先分为3个类进行操作,界面类ImageProUI,监听器类ImageListener,图形绘制类ImageUtils

在界面类中,我们还是常规的新建JFream界面,这一次不使用流式布局,用边框布局,在界面中个设置面板,将面板放在窗体的4个方向,设置宽度形成布局。

    public void shouUI(){
        //创建窗体
        JFrame jf = new JFrame();
        jf.setTitle("美颜相机.增强版V1");
        jf.setSize(2000,1200);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
        //设置边框布局


        //创建面板
        JPanel btnPanel = new JPanel();
        JPanel imgPanel = new JPanel();
        //设置颜色
        btnPanel.setBackground(Color. DARK_GRAY);
        imgPanel.setBackground(Color. BLACK);
        //设置宽高
        Dimension dim = new Dimension(0,100);
        btnPanel.setPreferredSize(dim);

        //初始化按钮
        initBtnPanel(btnPanel);

        //添加到窗体,东西南北指示方向
        jf.add(btnPanel,BorderLayout.NORTH);
        jf.add(imgPanel,BorderLayout.CENTER);

        jf.setVisible(true);
    }
    
    public static void main(String[] args) {
        ImageProUI imageProUI = new ImageProUI();
        imageProUI.shouUI();
    }

由于按钮的种类很多,我们采用String数组的形式来统一创建

    public void initBtnPanel(JPanel btnPanel){
        String[] btnText ={"打开","保存","原图","马赛克","灰度"};
        for (int i = 0; i < btnText.length; i++) {
            JButton btn = new JButton(btnText[i]);
            btn.setBackground(Color. WHITE);
            btnPanel.add(btn);
        }



        String[] btnText2 ={"画笔","直线","矩形","填充","截图","马赛克画笔"};
        for (int i = 0; i < btnText.length; i++) {
            JButton btn = new JButton(btnText2[i]);
            btn.setBackground(Color. WHITE);
            btnPanel.add(btn);
        }
    }

现在就基本完成了界面的设计(下方操作暂定未写)

接下来要对这几个按钮添加动作监听器,将按钮与功能联系起来

在监听器类中,添加动作监听器,用来监听点击按钮上的文字,对文字进行匹配,来实现对应操作

    @Override
    public void actionPerformed(ActionEvent e) {
        String ac=e.getActionCommand();
        System.out.println("ac:"+ac);
        if (ac.equals("打开")){

        }

        } else if (ac.equals("保存")) {
            
        } else if (ac.equals("原图")) {

        } else if (ac.equals("灰度")) {

        } else if (ac.equals("马赛克")) {
            
        }
    }

处理打开按钮,打开时要获取图片的绝对路径,让File类能检索到

这样的话就可以使用文件选择器,在选中图片点击确认时,获取当前选中的文件的路径(String)

之后传入文件处理类中

在文件选择器中,所有文件都在其中,需要对文件选择器添加文件名过滤器,只出现图片

       if (ac.equals("打开")){
            //打开是为了获取图像的绝对地址,传递给图片处理类
            JFileChooser jfc = new JFileChooser();
            //文件名过滤器
            FileNameExtensionFilter filter=new FileNameExtensionFilter
                    ("JPG &PNG","jpg","png");
            jfc.setFileFilter(filter);
            jfc.showOpenDialog(null);//位置居中
            int state =jfc.showOpenDialog(null);
            if (state == JFileChooser.APPROVE_OPTION){//点击了确认按钮
                String path=jfc.getSelectedFile().getAbsolutePath();//根据选择的文件,获取绝对路径
                imageUtils.loadImage(path);
            }

        }

传入文件处理类中

loadImage操作中使用一个try,catch,将文件的存放在一个二维数组中取出图片的长宽,来定制数组的长度,在对每一个像素取出RGB值,存入

    //属性
    int[][] imgArr;
    int w;
    int h;
    Graphics gra;//从绘制面板上传过来

    //加载照片
    public void loadImage(String path){
        File file = new File(path);
        try {
            BufferedImage image= ImageIO.read(file);
            w = image.getWidth();
            h = image.getHeight();
            //创建一个空的数组,来存储图片像素值
            imgArr = new int[w][h];
            //分别存入像素值
            for (int i = 0; i < w; i++) {
                for (int j = 0; j < h; j++) {
                    imgArr[i][j] = image.getRGB(i, j);//获取RGB值,存入
                }
            }
            System.out.println("加载图片完成");
        }catch (IOException e){
            throw new RuntimeException(e);
        }
    }

现在加载图片就实现了,接下来就是绘制原图

为了加速这个原图的绘制过程,可以先创建一个空的图片,获取这个图片的渲染器,再在循环完成后一次性会在窗体上

    public void drawImage(){
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        //获取这个图片对象的图像渲染器
        Graphics imgGra = image.getGraphics();
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                int pixNum = imgArr[i][j];
                Color color = new Color(pixNum);
                imgGra.setColor(color);
                imgGra.fillRect(i, j, 1, 1);
            }
        }
        //循环结束一次性的绘制在窗体上
        gra.drawImage(image, 0, 0, null);
    }

(回到监听器类) 

    ImageUtils imageUtils = new ImageUtils();
else if (ac.equals("原图")) {
            imageUtils.drawImage();
        }

为了能生成在界面类中的窗体上,需要将界面类中创建的Graphics传递到图片处理类

        Graphics gra = imgPanel.getGraphics();
        imgl.imageUtils.gra=gra;

接下来是常见的灰度处理方法

    public void drawGray(){
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        //获取这个图片对象的图像渲染器
        Graphics imgGra = image.getGraphics();
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                int pixNum = imgArr[i][j];
                Color color = new Color(pixNum);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int gray = (red + green + blue)/3;
                imgGra.setColor(new Color(gray, gray, gray));
                imgGra.drawRect(i, j, 1, 1);
            }
        }
        gra.drawImage(image, 0, 0, null);
    }

现在的图片在加载时是直接创建在左上角,为了能在出现时就在屏幕中间,需要再写一个类ImagePanel,这个类继承JPanel,以绘制一个矩形为例

import javax.swing.*;
import java.awt.*;

public class ImagePanel extends JPanel {

    //实现绘制(函数paint)绘制图片
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        int w=800,h=600;
        //计算居中位置
        int x=this.getWidth()/2-w/2;
        int y=this.getHeight()/2-h/2;
        g.setColor(Color.white);
        g.fillRect(x,y,w,h);
    }
}

将图像绘制类中的方法范围值改为BufferedImage,返回图片

    public BufferedImage drawImage(){
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
     ...
        return image;

    }

再新建一个数组,用来存放这些图片,将返回的图片都存入数组中,再在ImagePanel中调用

else if (ac.equals("原图")) {
            BufferedImage img = imageUtils.drawImage();
            imgList.add(img);
        } else if (ac.equals("灰度")) {
            BufferedImage img = imageUtils.drawGray();
            imgList.add(img);
        } 

传进来

    ImageListener imgl = new ImageListener();

    public void addImageL(ImageListener l) {
        imgl = l;
    }
//实现绘制(函数paint)绘制图片
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        if (imgl.imgList.isEmpty()) {
            return;
        }
        //从数组中获取最后一张图片
        int lastImageIndex= imgl.imgList.size()-1;
        BufferedImage img = imgl.imgList.get(lastImageIndex);
        int w=img.getWidth();
        int h=img.getHeight();
        //计算居中位置
        int x=this.getWidth()/2-w/2;
        int y=this.getHeight()/2-h/2;

        g.drawImage(img,x,y,null);

    }

为了能在打开图片时可以直接刷新页面,要在监听器类中新建一个面板,实现刷新

        //面板
        ImagePanel imagePanel;

        //进行面板刷新
        imagePanel.repaint();

在UI类中

imgl.imagePanel=imgPanel;//在点击按钮时刷新面板

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值