由于需要做一个自动拍照系统,所以在网上学习了使用java打开摄像头,很多人推荐javaCV,但是我不小心使用了JFM,所以先这样吧~~
在oracle网站下载window平台的JMF,如下图
从图中I586可以看出,我们的jdk也必须要是32位的,(尝试发现64位的JDK将导致JMF无法检测出摄像头,至少在我的电脑上是的)
目前我的本机64位win7 +32位jdk1.8;
将jmf-2_1_1e-windows-i586.exe双击按照提示安装成功后,在你的JDK安装目录\jre\lib\ext下,会多出两个文件:jmf.jar和sound.jar
接着在JMF的安装目录下打开bin/jmfregistry.exe
效果如下:
可以看出这是还没有检测到摄像头
接着点击左下角的Detect Capture Devices
点击确定后,摄像头依旧没出现,不知道什么原因(多点几次Detect Captur Devices就好了,并不是我一个人的电脑这样,很多人都这样的),最终效果如下
OK,这时候,摄像头成功注册了。
接下来可以编写代码了,下边的代码是我从网上照的前辈写的(被我删掉了一部分),点击进入源码地址,源码好像有拍照功能,但是无论是使用源码还是使用下边这段精简版,都会存在找不到拍照按钮
import javax.swing.*;//使用swing库
import javax.swing.event.*;
import java.io.*;
import javax.media.*;
import javax.media.format.*;
import javax.media.util.*;
import javax.media.control.*;
import javax.media.protocol.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import com.sun.image.codec.jpeg.*;
public class SwingCapture extends JPanel implements ActionListener//是JPanel里的子类,实现了ActionListener接口,动作侦听器
{
public static Player player = null;//一个播放对象,目前为空
public CaptureDeviceInfo di = null;//设备的配置信息
public MediaLocator ml = null;//
public JButton capture = null;//一个按钮
public Buffer buf = null;
public Image img = null;
public VideoFormat vf = null;
public BufferToImage btoi = null;
public ImagePanel imgpanel = null;//声明一个相片图片容器,ImagePanel类在后边声明
public SwingCapture()//构造函数,设置swing的外观风格。
{
this.setLayout(new BorderLayout());//设置布局,BorderLayout()一种布局管理器
this.setSize(10,10);//设置面板大小,数字是像素点
imgpanel = new ImagePanel();//相片图片容器
capture = new JButton("Capture");//照相按扭
capture.addActionListener(this);//使用窗体自身监听这个按扭
capture.setSize(10,10);
capture.setBackground(Color.BLUE);
String str1 = "vfw:Logitech USB Video Camera:0";
String str2 = "vfw:Microsoft WDM Image Capture (Win32):0";
di = CaptureDeviceManager.getDevice(str2);//获得设备控制权
ml= di.getLocator();//定位
setLayout(new GridLayout(3,1));
try
{
player = Manager.createRealizedPlayer(ml);//实现定位目标
player.start();//开始实现
Component comp;//创建一个组件
if ((comp = player.getVisualComponent()) != null)// 可视组件不为空
{
add(comp);//增加到组件容器
}
add(imgpanel);
add(capture);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void playerclose()//关闭窗体后,在exit程序之前,用于释放播放器资源
{
player.close();
player.deallocate();//停止播放器后必须释放内存中的资源
}
public static void saveJPG(Image img, String s)//保存图片
{
BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);//从buf中取得图片对像
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); //创建一个和指定输出流关联的JPEGImageEncoder对象
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); //此方法根据指定的压缩率浮点值
param.setQuality(0.5f,false); //压缩大小为一半
encoder.setJPEGEncodeParam(param);//将图片放进输出流
try
{
encoder.encode(bi); //编码这个输出流
out.close();//关闭
}
catch (java.io.IOException io)
{
System.out.println("IOException");
}
}
public static void main(String[] args)
{
JFrame f = new JFrame("SwingCapture");//创建一个窗体
SwingCapture cf = new SwingCapture();//创建一个面板
//给java做的图形界面添加关闭事件的时候,使用了WindowAdapter这个类
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
playerclose();//
System.exit(0);
}
}
);
f.add(cf,BorderLayout.CENTER);//向frame容器里输入swing风格中间大小帖的图片
f.pack();//打包放进容器
f.setSize(316,728);//设定JFrame的规格大小
f.setResizable(false);
f.setVisible(true); //显示一个Frame帖(没保存前先显示)
}
public void actionPerformed(ActionEvent e)//此类的侦听部分
{
JComponent c = (JComponent) e.getSource();//创建一个绘画对像
if (c == capture)//按拍照后
{
// Grab a frame
FrameGrabbingControl fgc = (FrameGrabbingControl)//从视频轨迹中抽取当前帧对像
player.getControl("javax.media.control.FrameGrabbingControl");//获取当前祯
buf = fgc.grabFrame();//抓下来的图片放在buffer的中
// Convert it to an image
btoi = new BufferToImage((VideoFormat)buf.getFormat());//取得一个视频格式对像
img = btoi.createImage(buf);//转化流格式 为图片格试
// show the image
imgpanel.setImage(img);//引用imgpanel面板显示图片
// save image
saveJPG(img,"C:\\Users\\fujiaxiaoshao\\Desktop\\照片.jpg");//保存图片到本地硬盘
}
}
class ImagePanel extends Panel//一个内部类,图片面板
{
public Image myimg = null;//创建一个图片对像
public ImagePanel()
{
setLayout(null);//设置布局
setSize(310,237);//设置布局大小
}
public void setImage(Image img)
{
this.myimg = img;
repaint();//重绘
}
public void paint(Graphics g) //绘画图形
{
if (myimg != null)
{
g.drawImage(myimg, 0, 0, this); //绘画图形
}
}
}
}
将代码存成如下文件:
在命令行模式下编译并运行(如果安装JMF后没有重启PC将会报错,所以一定要重启),如下图:
效果如下:
拍摄成功的照片:
PS:很多人会在ecliose中运行,会出现空指针报错,这应该是因为没有获取到摄像头驱动,应该
将jmf安装目录\lib目录下的jmf.jar,sound.jar,mediaplayer.jar三个文件导入工程,就可以正常运行了。
参考博客:http://my.oschina.net/hetiangui/blog/133189
http://blog.csdn.net/zajin/article/details/9288239
http://zhangjunhd.blog.51cto.com/113473/25475