我正在编写一个简短的程序,使用Java媒体框架(JMF)从网络摄像头中提取图像。
我似乎遇到了一个很多人在我之前遇到的问题,但对于这个问题,没有一个明确的解决方案。我正在使用日食,我的程序在那里工作正常。我添加了 jmf.jar 作为外部库。
现在,问题是如果我将程序导出为 jar,在命令行上运行它时会出现以下错误:
Exception in thread "main" java.lang.NullPointerException
at recorder.SimpleRecorder.<init>(SimpleRecorder.java:46)
at recorder.SimpleRecorder.main(SimpleRecorder.java:67)
46号线ml = di.getLocator();
。(我已经包含了下面的代码。
这与我不添加 jmf.jar 作为外部库并尝试在 eclipse 中运行程序时遇到的错误相同。
互联网上的一些资源,比如这个
https://forums.oracle.com/forums/thread.jspa?threadID=1277297
建议文件 jmf.properties 是问题的根源。因此,我尝试了上述资源建议的几件事:
将 jmf.properties 文件的路径添加到 jar 的清单中。之后,清单如下所示:
清单版本:1.0
类路径:。"C:\Program Files (x86)\JMF2.1.1e\lib\jmf.properties"
主类:录音机。简单记录器
我不确定这是否是向清单添加路径的正确方法。
我还尝试从文件夹 C:\Program Files (x86)\Java\jre7\lib 中删除 jmf.jar,因为它在那里似乎会导致 eclipse 出现问题,因为它是 jmf 可用两次(离开它而不添加 jmf.jar作为外部库会导致上述错误)。
将 jmf.properties 添加到 jar 文件所在的文件夹会产生不同的错误:
线程"VFW Request Thread" java.lang.UnsatisfiedLinkError:JMFSecurityManager: java.lang.UnsatisfiedLinkError: no jmvfw in java.library.path at com.sun.media.JMFSecurityManager.loadLibrary(JMFSecurityManager.java:206) at com.sun.media.protocol.vfw.VFWCapture.(VFWCapture.java:19) at com.sun.media.protocol.vfw.VFWSourceStream.doConnect(VFWSourceStream.java:241) at com.sun.media.protocol.vfw.VFWSourceStream.run(VFWSourceStream.java:763) at java.lang.Thread.run(未知来源)
将 jmf.properties 文件复制到任何其他位置,包括 jar 内部(如上述资源中所建议的)没有任何效果。
我希望有人知道如何解决这个问题 - 我非常乐意提供更多信息。
谢谢
乔纳斯
package recorder;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import javax.media.Buffer;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.control.FrameGrabbingControl;
import javax.media.format.VideoFormat;
import javax.media.util.BufferToImage;
import javax.swing.JFrame;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class SimpleRecorder extends JFrame{
public static Player player = null;
public CaptureDeviceInfo di = null;
public MediaLocator ml = null;
public Buffer buf = null;
public Image img = null;
public VideoFormat vf = null;
public BufferToImage btoi = null;
public SimpleRecorder(String title) {
super(title);
String str2 = "vfw:Microsoft WDM Image Capture (Win32):0";
di = CaptureDeviceManager.getDevice(str2);
if(di == null) System.out.println("di is null.");
ml = di.getLocator();
try
{
player = Manager.createRealizedPlayer(ml);
player.start();
Component comp;
if ((comp = player.getVisualComponent()) != null)
{
add(comp,BorderLayout.CENTER);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args){
SimpleRecorder frame = new SimpleRecorder("Simple Recorder");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(335,275);
frame.setLayout(new BorderLayout());
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
playerclose();
System.exit(0);}});
System.out.println("Waiting for camera to get ready...");
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Start recording...");
while(true){
frame.recordImage();
try {
Thread.sleep(350);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
private void recordImage(){
// Grab a frame
FrameGrabbingControl fgc = (FrameGrabbingControl)
player.getControl("javax.media.control.FrameGrabbingControl");
buf = fgc.grabFrame();
// Convert it to an image
btoi = new BufferToImage((VideoFormat)buf.getFormat());
img = btoi.createImage(buf);
// Get current directory
String currentDir = new File("./Extracted_Image.jpg").getAbsolutePath();
// save image
saveJPG(img,currentDir);
}
public static void saveJPG(Image img, String s)
{
BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
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");
}
if(out == null) System.out.println("Could not create file output stream.");
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
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 playerclose()
{
player.close();
player.deallocate();
}
}
要检查的一件事是你的日食.ini。 我看到了工作区的 installed-jre 与 eclipse.ini 指定的 VM 不一致的问题。 如果 ini 使用 1.6 而工作区使用 1.7,那么某些 eclipse 插件可能会尝试使用 1.6 工具处理 1.7 字节码或源代码,从而导致各种问题
- 编辑日食.ini
-
检查 VM 设置为预期版本
-虚拟机c:/java/jdk1.7.0_05/jre/bin/server/jvm.dll