美颜相机的实现

需求:

创建一个能修改润色图片的程序,拥有打开,保存等基本功能,并且实现马赛克,灰度,画笔等对图片进行修改的功能。

1.设计界面

  程序创建了一个包含图像显示、操作按钮和图像文件列表的图形用户界面(GUI),用户可以通过点击按钮对图像进行打开、保存、应用滤镜、绘制图形等操作,还能从文件列表中选择图像进行加载显示。

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class ImageProUI {
    ImageListener imgl = new ImageListener();
    ImageUtils imgUtils = new ImageUtils();
    ImagePanel imgPanel = new ImagePanel();
    public void showUI() {
        // 创建窗体
        JFrame jf = new JFrame();
        jf.setTitle("美颜相机");
        jf.setSize(1000, 800);
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel btnPanel = new JPanel();
        JPanel listPanel = new JPanel();
        // 设置面板的属性
        btnPanel.setBackground(Color.DARK_GRAY);
        listPanel.setBackground(Color.LIGHT_GRAY);
        imgPanel.setBackground(Color.BLACK);
        // 设置宽高
        Dimension dim = new Dimension(200, 100);
        btnPanel.setPreferredSize(dim);
        listPanel.setPreferredSize(dim);
        // 初始化按钮面板
        initBtnPanel(btnPanel);
        initListPanel(listPanel);
        // 添加到窗体上
        jf.add(btnPanel, BorderLayout.SOUTH);
        jf.add(listPanel, BorderLayout.WEST);
        jf.add(imgPanel, BorderLayout.CENTER);
        jf.setVisible(true);
        imgPanel.addMouseListener(imgl);
        imgPanel.addMouseMotionListener(imgl);
        // 三个对象之间交替传递
        imgPanel.addImageUtils(imgUtils);
        imgl.addImagePanel(imgPanel);
        imgl.addImageUtils(imgUtils);
    }
    public void initBtnPanel(JPanel btnPanel) {
        String[] btnTexts = {"打开", "保存", "原图", "马赛克", "灰度"};
        for (int i = 0; i < btnTexts.length; i++) {
            JButton btn = new JButton(btnTexts[i]);
            btn.setBackground(Color.WHITE);
            btnPanel.add(btn);
            btn.addActionListener(imgl);
        }
        String[] btnTexts2 = {"画笔", "直线", "矩形", "填充", "截图", "马赛克画笔", "灰 度画笔"};
        for (int i = 0; i < btnTexts2.length; i++) {
            JButton btn = new JButton(btnTexts2[i]);
            btn.setBackground(Color.WHITE);
            btnPanel.add(btn);
            btn.addActionListener(imgl);
        }
 }
        public void initListPanel(JPanel listPanel) {
           //获取文件地址
            String rootPath = "C:\\Users\\sheng\\Desktop\\新建文件夹 (2)";
            listPanel.setLayout(new BorderLayout());
            JTextField tf = new JTextField(rootPath);
            listPanel.add(tf, BorderLayout.NORTH);
            JPanel imgBtnPanel = new JPanel();
            imgBtnPanel.setLayout(new GridLayout(0, 1));
            File rootFile = new File(rootPath);
            File[] files = rootFile.listFiles();
            for (int i = 0; i < files.length; i++) {
                // files[i].getName()
                File imgFile = files[i];
                JButton btn = new JButton(imgFile.getName());
                BufferedImage btnImage = imgUtils.getBtnImage(imgFile);
                btn.setIcon(new ImageIcon(btnImage));
                btn.setBackground(Color.WHITE);
                btn.setPreferredSize(new Dimension(200, 100));
                imgBtnPanel.add(btn);
                btn.addActionListener(e -> { String fileName = e.getActionCommand();
                    tf.setText(rootPath + "\\" + fileName);
                    imgUtils.loadImage(tf.getText());
                    imgPanel.repaint();
                });
            }
            JScrollPane jsp = new JScrollPane();
            jsp.setViewportView(imgBtnPanel);
            listPanel.add(jsp, BorderLayout.CENTER);
        }
        public static void main(String[] args) {
            ImageProUI ipu = new ImageProUI();
            ipu.showUI();
        }
}
  • ImageListener imgl:用于处理各种用户交互事件,如按钮点击、鼠标操作等。
  • ImageUtils imgUtils:图像处理器,负责图像的加载、保存、滤镜处理等操作。
  • ImagePanel imgPanel:用于显示和绘制图像的面板,支持鼠标交互。
  • showUI() 方法
  • 创建主窗口:创建一个 JFrame 对象,设置窗口标题、大小、位置和关闭操作。
  • 创建面板:创建三个面板,分别为按钮面板 btnPanel、图像文件列表面板 listPanel 和图像显示面板 imgPanel,并设置它们的背景颜色和大小。
  • 初始化面板:调用 initBtnPanel 和 initListPanel 方法初始化按钮面板和图像文件列表面板。
  • 添加面板到窗口:将三个面板添加到主窗口的不同位置(底部、左侧和中间)。
  • 显示窗口:设置窗口可见。
  • 添加监听器:为图像显示面板添加鼠标监听器和鼠标移动监听器,并在三个对象之间建立关联。

2.监听器设置

实现了 ActionListenerMouseMotionListener 和 MouseListener 接口,用于处理图像操作界面中的各种事件,包括按钮点击事件和鼠标操作事件。

package Camera;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageListener implements ActionListener, MouseMotionListener,
        MouseListener{
    ImagePanel imagePanel;
    ImageUtils imgUtils;
    String drawType = "画笔";
    public void addImageUtils(ImageUtils imgUtils) {
        this.imgUtils = imgUtils;
    }
    public void addImagePanel(ImagePanel imagePanel) {
        this.imagePanel = imagePanel;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        String ac = e.getActionCommand();
        System.out.println("ac:" + ac);
        if (ac.equals("打开")) {
            JFileChooser jfc = new JFileChooser("C:\\Users\\");
            // 文件名过滤器
            FileNameExtensionFilter filter = new FileNameExtensionFilter
                    ("JPG & PNG", "jpg", "png");
            jfc.setFileFilter(filter);
            int state = jfc.showOpenDialog(null);
            if (state == JFileChooser.APPROVE_OPTION) {
                String path = jfc.getSelectedFile().getAbsolutePath();
                // 图像处理对象 调用加载图片的方法 转为像素二维数组
                imgUtils.loadImage(path);
            }
        } else if (ac.equals("保存")) {
            JFileChooser jfc = new JFileChooser();
            FileNameExtensionFilter filter = new FileNameExtensionFilter
                    ("JPG & PNG", "jpg", "png");
            jfc.setFileFilter(filter);
            int state = jfc.showSaveDialog(null);
            if (state == JFileChooser.APPROVE_OPTION) {
                File file = jfc.getSelectedFile();
                BufferedImage lastImage = imgUtils.getLastImage();
                try {
                    ImageIO.write(lastImage, "PNG", file);
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
                System.out.println("保存完成");
            }
        } else if (ac.equals("原图")) {
            imgUtils.drawImage();
        } else if (ac.equals("灰度")) {
            imgUtils.drawGray();
        } else if (ac.equals("马赛克")) {
        } else {
            drawType = ac;
        }
        // 刷新面板
        imagePanel.repaint();
    }
    @Override
    public void mouseClicked(MouseEvent e) {
    }
    @Override
    public void mousePressed(MouseEvent e) {
    }
    @Override
    public void mouseReleased(MouseEvent e) {
        oldX = 0;
        oldY = 0;
    } @Override
    public void mouseEntered(MouseEvent e) {
    }
    @Override
    public void mouseExited(MouseEvent e) {
    }
    int oldX, oldY;
    @Override
    public void mouseDragged(MouseEvent e) {
        // 获取拖动时的坐标
        int x = e.getX();
        int y = e.getY();
        // 要在图片绘制 ,将面板的坐标与图片的坐标进行转换
        int pw = imagePanel.getWidth();
        int ph = imagePanel.getHeight();
        BufferedImage lastImage = imgUtils.getLastImage();
        int iw = lastImage.getWidth();
        int ih = lastImage.getHeight();
        int dx = (pw - iw) / 2;
        int dy = (ph - ih) / 2;
        Graphics imgGra = lastImage.getGraphics();
        imgGra.setColor(Color.RED);
        x = x - dx;
        y = y - dy;
        if (oldX <= 0 || oldY <= 0) {
            oldX = x;
            oldY = y;
        }
        if (x > iw || y > ih) {
            return;
        }
        if (drawType.equals("画笔")) {
            imgGra.drawLine(x, y, oldX, oldY);
        } else if (drawType.equals("马赛克画笔")) {
            // 画笔马赛克 从图片上取出对应位置的像素 将像素放大 绘制出来
            int rgb = imgUtils.getLastImage().getRGB(x, y);
            Color color = new Color(rgb);
            imgGra.setColor(color);
            imgGra.fillRect(x, y, 20, 20);
        } else if (drawType.equals("灰度画笔")) {
            for (int i = 0; i < 20; i++) {
                for (int j = 0; j < 20; j++) {
                    int rgb = imgUtils.getLastImage().getRGB(x + i, y + j); Color color = new Color(rgb);
                    int gray = (color.getRed() + color.getGreen() + color.getBlue()) /
                            3;
                    Color gColor = new Color(gray, gray, gray);
                    imgGra.setColor(gColor);
                    imgGra.fillRect(x + i, y + j, 1, 1);
                }
            }
        }
        oldX = x;
        oldY = y;
        imagePanel.repaint();
        System.out.println("拖动绘制直线 ");
    }
    @Override
    public void mouseMoved(MouseEvent e) {
    }

}
  • ImageListener 类:用于处理图像界面的交互事件,包括按钮点击和鼠标操作。
  • 成员变量
    • imagePanelImagePanel 类型的对象,用于显示和绘制图像,并且在事件处理后可以调用其 repaint 方法刷新面板。
    • imgUtilsImageUtils 类型的对象,负责执行加载图片、滤镜处理等操作。
    • drawTypeString 类型,用于记录当前的绘制类型,默认值为 "画笔"
    • oldX 和 oldYint 类型,用于记录鼠标拖动时的上一个位置。
  • actionPerformed(ActionEvent e)
  • 功能:处理按钮点击事件,根据按钮的命令执行相应的操作。
  • 具体操作
    1. 打开图片:当点击 “打开” 按钮时,弹出文件选择器,用户可以选择 JPG 或 PNG 格式的图片,选择后调用 imgUtils.loadImage(path) 方法加载图片。
    2. 保存图片:当点击 “保存” 按钮时,弹出文件保存对话框,用户可以选择保存的文件路径和文件名,选择后将 imgUtils 中最后一张图片保存为 PNG 格式的文件。
    3. 显示原图:当点击 “原图” 按钮时,调用 imgUtils.drawImage() 方法显示原始图片。
    4. 灰度处理:当点击 “灰度” 按钮时,调用 imgUtils.drawGray() 方法对图片进行灰度处理。
    5. 其他操作:对于其他按钮,将按钮的命令赋值给 drawType,用于后续的鼠标绘制操作。
    6. 刷新面板:无论执行哪种操作,最后都会调用 imagePanel.repaint() 方法刷新图像显示面板。
  • mouseDragged(MouseEvent e)
  • 功能:处理鼠标拖动事件,根据 drawType 的值进行不同的绘制操作。
  • 具体操作
    1. 坐标转换:将鼠标在面板上的坐标转换为图片上的坐标。
    2. 画笔绘制:当 drawType 为 "画笔" 时,在图片上绘制一条从上次位置到当前位置的红色直线。
    3. 马赛克画笔绘制:当 drawType 为 "马赛克画笔" 时,从图片上取出当前位置的像素颜色,将该颜色填充到一个 20x20 的矩形区域。
    4. 灰度画笔绘制:当 drawType 为 "灰度画笔" 时,从图片上取出当前位置周围 20x20 区域的像素颜色,将每个像素转换为灰度颜色后填充到对应的位置。
    5. 更新位置:将当前位置更新为 oldX 和 oldY,并调用 imagePanel.repaint() 方法刷新面板。

3.在面板上显示并且绘制图片

package Camera;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ImagePanel extends JPanel {
    ImageUtils imgUtils;
    public void addImageUtils(ImageUtils imgUtils) {
        this.imgUtils = imgUtils;
    }
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        paintImage(g);
        System.out.println("绘制最后一张照片");
    }
    public void paintImage(Graphics g) {
        BufferedImage lastImage = imgUtils.getLastImage();
        if (lastImage == null) {
            return;
        }
        int w = lastImage.getWidth();
        int h = lastImage.getHeight();
        int x = this.getWidth() / 2 - w / 2;
        int y = (this.getHeight() - h) / 2;
        g.drawImage(lastImage, x, y, null);
    }

}

4.用于处理图像的各种操作,如加载图像、获取图像缩略图、将图像转换为灰度图、绘制图像等

package Camera;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class ImageUtils {
    private int[][] imgArr;
    private int w;
    private int h;
    private ArrayList<BufferedImage> imgList = new ArrayList<>();
    public BufferedImage getBtnImage(File file) {
        try {
            BufferedImage image = ImageIO.read(file);
            BufferedImage minImg = new BufferedImage(190, 100, 2);
            Graphics minG = minImg.getGraphics();
            minG.drawImage(image, 0, 0, 190, 100, null);
            return minImg;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public void addImage(BufferedImage image) {
        imgList.add(image);
    }
    public BufferedImage getLastImage() {
        if (imgList.isEmpty()) {
            return null;
        }
        return imgList.get(imgList.size() - 1);
    }
    public BufferedImage getFirstImage() {
        if (imgList.isEmpty()) {
            return null;
        }
        return imgList.get(0);
    }
    // 加载图片
    public void loadImage(String path) {

        File file = new File(path);
        try {
            BufferedImage image = ImageIO.read(file);
            addImage(image);
            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);
                }
            }
            System.out.println("加载图片完成");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public BufferedImage 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);
            }
        }
        addImage(image);
        return image;
    }
    public BufferedImage 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;
                Color grayColor = new Color(gray, gray, gray);
                imgGra.setColor(grayColor);
                imgGra.fillRect(i, j, 1, 1);
            }
        }
        addImage(image);
        return image;
    }

}
loadImage(String path)
  • 功能:根据给定的文件路径加载图像,将图像的像素值存储到 imgArr 中,并将图像对象添加到 imgList 中。
  • 具体操作
    1. 创建一个 File 对象 file,表示指定路径的文件。
    2. 使用 ImageIO.read(file) 方法读取文件的图像。
    3. 将读取的图像添加到 imgList 中。
    4. 获取图像的宽度 w 和高度 h
    5. 创建一个二维数组 imgArr,用于存储图像的像素值。
    6. 遍历图像的每个像素,将其 RGB 值存储到 imgArr 中。
    7. 打印提示信息 “加载图片完成”。
drawImage()
  • 功能:根据 imgArr 中存储的像素值,创建一个新的 BufferedImage 对象,并将像素值绘制到图像上,然后将该图像添加到 imgList 中并返回。
  • 具体操作
    1. 创建一个新的 BufferedImage 对象 image,大小为 w x h。
    2. 获取 image 的 Graphics 对象 imgGra
    3. 遍历 imgArr 中的每个像素,根据像素值创建 Color 对象,并使用 imgGra.setColor 和 imgGra.fillRect 方法将像素绘制到图像上。
    4. 将绘制好的图像添加到 imgList 中。
    5. 返回绘制好的图像 image
drawGray()
  • 功能:将 imgArr 中存储的像素值转换为灰度值,创建一个新的 BufferedImage 对象,并将灰度像素值绘制到图像上,然后将该图像添加到 imgList 中并返回。
  • 具体操作
    1. 创建一个新的 BufferedImage 对象 image,大小为 w x h,类型为 BufferedImage.TYPE_INT_ARGB
    2. 获取 image 的 Graphics 对象 imgGra
    3. 遍历 imgArr 中的每个像素,根据像素的 RGB 值计算灰度值,创建 Color 对象,并使用 imgGra.setColor 和 imgGra.fillRect 方法将灰度像素绘制到图像上。
    4. 将绘制好的灰度图像添加到 imgList 中。
    5. 返回绘制好的灰度图像 image

实现效果如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值