我正在制作一个每秒至少需要截屏24张的程序。目前使用下面的代码我每隔约94毫秒只得1个,所以每秒约10个。
我不想使用任何第三方库,因为我试图尽量减少它,但如果我的性能会有显着提高,我愿意。我也试图保持这个平台的独立性,但同样,如果这会是一个非常显着的性能提升,我愿意将它限制在Windows。
编辑:我现在也尝试了两种不同的方式;使用在oracles网站上找到的片段以及下面评论中指出的片段。所有三个都花费了大约相同的时间,210-2.2百万纳秒,这是非常低效的。
public abstract class Benchmark {
private final int iterations;
public Benchmark(int iterations) {
this.iterations = iterations;
}
public abstract void logic();
public void start() {
long start = System.nanoTime();
for (int iteration = 0; iteration < iterations; iteration++) {
long iterationStart = System.nanoTime();
logic();
System.out.println("iteration: " + iteration + " took: " + (System.nanoTime() - iterationStart) + " nanoseconds.");
}
long total = (System.nanoTime() - start);
System.out.println(iterations + " iterations took: " + total + " nanoseconds. Average iteration was: " + (total / iterations));
}
}
_
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
public class RobotBenchmark extends Benchmark {
private final Robot robot;
private final Rectangle screen;
public static void main(String[] args) {
Benchmark benchmark;
try {
benchmark = new RobotBenchmark(24);
benchmark.start();
} catch (AWTException e) {
e.printStackTrace();
}
}
public RobotBenchmark(int iterations) throws AWTException {
super(iterations);
robot = new Robot();
screen = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
}
@Override
public void logic() {
robot.createScreenCapture(screen);
}
}
_
import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.HeadlessException;
import java.awt.Rectangle;
public class DirectRobotBenchmark extends Benchmark {
private final GraphicsDevice device;
private final Rectangle screenRectangle;
private final DirectRobot robot;
private int[] screen;
public static void main(String[] args) {
Benchmark benchmark;
try {
benchmark = new DirectRobotBenchmark(24);
benchmark.start();
} catch (HeadlessException | AWTException e) {
e.printStackTrace();
}
}
public DirectRobotBenchmark(int iterations) throws HeadlessException, AWTException {
super(iterations);
device = DirectRobot.getDefaultScreenDevice();
screenRectangle = new Rectangle(1920, 1080);
robot = new DirectRobot(device);
screen = new int[screenRectangle.width * screenRectangle.height];
}
@Override
public void logic() {
screen = robot.getRGBPixels(screenRectangle);
}
}
_
import java.awt.AWTException;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.peer.RobotPeer;
import sun.awt.SunToolkit;
@SuppressWarnings("restriction")
public class RobotPeerBenchmark extends Benchmark {
private final SunToolkit toolkit;
private final RobotPeer peer;
private final Rectangle screenRectangle;
private int[] screen;
public static void main(String[] args) {
try {
Benchmark robotPeerBenchmark = new RobotPeerBenchmark(24);
robotPeerBenchmark.start();
} catch (AWTException e) {
e.printStackTrace();
}
}
public RobotPeerBenchmark(int iterations) throws AWTException {
super(iterations);
toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
peer = toolkit.createRobot(new Robot(), GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice());
screenRectangle = new Rectangle(toolkit.getScreenSize());
screen = new int[screenRectangle.width * screenRectangle.height];
}
@Override
public void logic() {
screen = peer.getRGBPixels(screenRectangle);
}
}
答案 0 :(得分:2)
唯一的方法是通过JNI或JNA。我做了一些基准测试和原生屏幕捕获API,它能够维持大约45 FPS与机器人8 FPS。我可能会在JNI项目上开始在不久的将来解决这个问题。如果需要,我会用项目URL更新这篇文章。
答案 1 :(得分:0)
我目前正在设置一个使用VLCJ然后使用DirectMediaPlayer(https://github.com/caprica/vlcj/blob/master/src/test/java/uk/co/caprica/vlcj/test/direct/DirectTestPlayer.java)来获取BufferedImage的工作示例。
JFrame无需正常工作。
我知道这是一个老问题,但今天仍然存在问题,所以我想我会分享。
VLCJ是LibVLC的Java绑定。
示例代码:
private BufferedImage image;
private MediaPlayerFactory factory;
private DirectMediaPlayer mediaPlayer;
public void start() {
image = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(width, height);
image.setAccelerationPriority(1.0f);
String mrl = "screen://";
String[] options = {
":screen-fps=30",
":live-caching=0",
":screen-width=1920",
":screen-height=1080",
":screen-left=0",
":screen-top=0"
};
factory = new MediaPlayerFactory();
mediaPlayer = factory.newDirectMediaPlayer(new TestBufferFormatCallback(), new TestRenderCallback());
mediaPlayer.playMedia(mrl, options);
}
// Callbacks are required.
private final class TestRenderCallback extends RenderCallbackAdapter {
public TestRenderCallback() {
super(((DataBufferInt) image.getRaster().getDataBuffer()).getData());
}
@Override
public void onDisplay(DirectMediaPlayer mediaPlayer, int[] data) {
// The image data could be manipulated here...
/* RGB to GRAYScale conversion example */
// for(int i=0; i < data.length; i++){
// int argb = data[i];
// int b = (argb & 0xFF);
// int g = ((argb >> 8 ) & 0xFF);
// int r = ((argb >> 16 ) & 0xFF);
// int grey = (r + g + b + g) >> 2 ; //performance optimized - not real grey!
// data[i] = (grey << 16) + (grey << 8) + grey;
// }
// imagePane.repaint();
}
}
private final class TestBufferFormatCallback implements BufferFormatCallback {
@Override
public BufferFormat getBufferFormat(int sourceWidth, int sourceHeight) {
return new RV32BufferFormat(width, height);
}
}
答案 2 :(得分:0)
使用纯Java java.awt.Robot
可以并行使用纯Java达到30FPS的帧速率。可以在GitHub