java实现照相客户端功能

本文介绍了一个使用Java图形界面编程实现的简易拍照项目,通过整合多个核心jar包,如log4j、commons-codec和thumbnailator,实现了照相、图片压缩等功能。项目采用OpenCV进行图像捕获,支持拍照、重拍及关闭操作,并提供了图片预览和保存功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前期系统中需要使用照相功能,在百度和同事的帮助下做出了一个简易版的项目,最近有时间整理一下,分享出来。
这个项目实现起来也不是很复杂,不过所依赖的核心jar包比较大,我创建的是一个普通java project,没有创建maven工程,也可以使用maven,不过会引入大量使用不到的jar包。这个项目我已经放到GitHub上面了,文章末尾会给出地址,依赖的pom文件会一起放在项目中,方便查找。
1.项目结构:
在这里插入图片描述
项目使用java的图形界面编程,需要一定的基础,不过也不是很难,主要是几个Listener的编写,TuPianJieQuActionListener是保存文件的主要监听类。

2.jar包:
在这里插入图片描述
使用log4j-1.2.17.jar记录日志,commons-codec-1.13.jar是用来进行BASE64编码的,thumbnailator-0.4.8.jar可以便捷的实现图片压缩,其他的基本都是照相的核心jar包,如果使用maven创建会多出很多不需要的jar包,需要注意一下。

3.TakePhoto照相核心类的实现:

/**
 * 
 * @author jinghuaixin
 * @date 2019/11/28
 */
public class TakePhoto {
    private static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
    private static CanvasFrame canvas = null;

    private static Map<String, Object> map;

    public static void main(String[] args) {
        try {
            takePhoto();
        } catch (Exception | InterruptedException e) {
            e.printStackTrace();
            LogUtil.getLog().error("客户端照相异常!", e);
        }
    }

    public static void takePhoto() throws Exception, InterruptedException {
        int captureWidth = 640;
        int captureHeight = 480;

        OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
        grabber.setImageWidth(captureWidth);
        grabber.setImageHeight(captureHeight);
        try {
            grabber.start();
        } catch (Exception e) {
            LogUtil.getLog().error("照相客户端初始化异常!", e);
            JOptionPane.showMessageDialog(null, "摄像头准备失败:请检查摄像头是否正确接入!", "提示:", JOptionPane.WARNING_MESSAGE);
            if (grabber != null) {
                grabber.close();
            }
            return;
        }
        // 开始获取摄像头数据
        canvas = new CanvasFrame("照相");
        // CanvasFrame canvas = new CanvasFrame("照相");//新建一个窗口
        canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        canvas.setAlwaysOnTop(true);

        Camera camera = new Camera();
        MyPanel shangChuanPanel = new MyPanel(canvas, map);
        // 增加按钮
        Container con = canvas.getContentPane();

        JPanel optionPanel = new JPanel();
        JButton btn_paiZhao = new JButton("拍照");
        JButton btn_chongPai = new JButton("重拍");

        JButton btn_guanBi = new JButton("关闭");
        JLabel info = new JLabel("<html><font color='red'>(连接成功!)</font></html>");
        JPanel bott = new JPanel();
        // 向面板添加按钮
        optionPanel.add(btn_chongPai, BorderLayout.NORTH);
        optionPanel.add(btn_paiZhao, BorderLayout.NORTH);
        optionPanel.add(btn_guanBi, BorderLayout.NORTH);

        con.add(optionPanel, BorderLayout.NORTH);
        bott.add(info, BorderLayout.SOUTH);
        con.add(bott, BorderLayout.SOUTH);
        JPanel east = new JPanel();
        east.setSize(new Dimension(600, 600));
        JLabel eastlabel = new JLabel(getSapce(220));

        if (shangChuanPanel != null) {
            east.add(shangChuanPanel, BorderLayout.SOUTH);
            shangChuanPanel.add(eastlabel);

            con.add(shangChuanPanel, BorderLayout.EAST);

        }
        // 添加监听事件
        PaiZhaoMouseListener pzListener = new PaiZhaoMouseListener(converter, grabber, camera, shangChuanPanel);
        btn_paiZhao.addMouseListener(pzListener);
        btn_guanBi.addMouseListener(new GuanBiMouseListener(canvas));
        btn_chongPai.addMouseListener(new ChongPaiMouseListener(camera));
        Frame grab = grabber.grab();
        shangChuanPanel.setMat(converter.convertToMat(grab));
        while (true) {
            if (!canvas.isDisplayable()) {// 窗口是否关闭
                grabber.stop();// 停止抓取
                // System.exit(2);//退出
                break;
            }
            if (camera.getState()) {
                grab = grabber.grab();// 获取摄像头图像并放到窗口上显示, 这里的Frame frame=grabber.grab(); frame是一帧视频图像
            }
            if (grab != null) {
                canvas.showImage(grab);
            }
            Thread.sleep(50);// 50毫秒刷新一次图像
        }
    }

    /**
     * 扩展canvasFrame的右边空间
     * 
     * @param count
     * @return
     */
    public static String getSapce(int count) {
        count = count < 0 ? 0 : count;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(" ");
        }
        return sb.toString();
    }

    /**
     * @return the canvas
     */
    public static CanvasFrame getCanvas() {
        return canvas;
    }

}

4.设备:
实现照相你需要一个照相设备,使用USB摄像头就可以。

5.项目演示:
运行main方法,弹出拍照页面:
在这里插入图片描述
点击拍照按钮进行图片拍照,点击重拍按钮可以重新拍摄
在这里插入图片描述
红色方框可拖动,用于截取照片,选中合适的区域双击即可实现类似于截图的功能
在这里插入图片描述
现在看到的就是剪切以后的图片,点击上传即可保存到本地,上传按钮是因为实际应用中该项目使用WebSocket实现与浏览器通信,实现上传效果
在这里插入图片描述
保存后关闭页面去项目地址下即可发现刚刚的截图

6.项目地址:
java-简易拍照项目地址

首先到sun下载最新的jmf,然后安装。http://java.sun.com/products/java-media/jmf/index.jsp   然后,说一下需求   1. 用摄像头拍照   2. 在文本框输入文件名   3. 按下拍照按钮,获取摄像头内的图像   4. 在拍下的照片上有一红框截取固定大小的照片。   5. 保存为本地图像为jpg格式,不得压缩画质   技术关键,相信也是大家最感兴趣的部分也就是如何让一个摄像头工作,并拍下一张照片了。 --------------------------------------------------------------------------------------------------------------   利用jmf,代码很简单: //利用这三个类分别获取摄像头驱动,和获取摄像头内的图像流,获取到的图像流是一个swing的component组件类 public static player player = null; private capturedeviceinfo di = null; private medialocator ml = null; //文档中提的驱动写法,为何这么写我也不知:) string str1 = "vfw:logitech usb video camera:0"; string str2 = "vfw:microsoft wdm image capture (win32):0"; di = capturedevicemanager.getdevice(str2); ml = di.getlocator(); try {  player = manager.createrealizedplayer(ml);  player.start();  component comp;  if ((comp = player.getvisualcomponent()) != null)  {   add(comp, borderlayout.north);  } } catch (exception e) {  e.printstacktrace(); }   接下来就是点击拍照,获取摄像头内的当前图像。   代码也是很简单: private jbutton capture; private buffer buf = null; private buffertoimage btoi = null; private imagepanel imgpanel = null; private image img = null; private imagepanel imgpanel = null; jcomponent c = (jcomponent) e.getsource(); if (c == capture)//如果按下的是拍照按钮 {  framegrabbingcontrol fgc =(framegrabbingcontrol)  player.getcontrol("javax.media.control.framegrabbingcontrol");  buf = fgc.grabframe(); // 获取当前祯并存入buffer类  btoi = new buffertoimage((videoformat) buf.getformat());  img = btoi.createimage(buf); // show the image  imgpanel.setimage(img); }   保存图像的就不多说了,以下为示例代码 bufferedimage bi = (bufferedimage) createimage(imgwidth, imgheight); graphics2d g2 = bi.creategraphics(); g2.drawimage(img, null, null); fileoutputstream out = null; try {  out = new fileoutputstream(s); } catch (java.io.filenotfoundexception io) {  system.out.println("file not found"); } jpegimageencoder encoder = jpegcodec.createjpegencoder(out); jpegencodeparam param = encoder.getdefaultjpegencodeparam(bi); param.setquality(1f, false);//不压缩图像 encoder.setjpegencodeparam(param); try {  encoder.encode(bi);  out.close(); } catch (java.io.ioexception io) {  system.out.println("ioexception"); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder-文小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值