java.awt.Robot.createScreenCapture的更快替代方案?

java.awt.Robot.createScreenCapture的更快替代方案?,java,image,performance,screenshot,awtrobot,Java,Image,Performance,Screenshot,Awtrobot,我正在制作一个程序,需要每秒至少捕获24个屏幕截图。目前,对于下面的代码,我每94毫秒只能得到1个,所以大约每秒10个 我不喜欢使用任何第三方库,因为我正试图使它尽可能小,但如果我能获得显著的性能提升,我愿意。我也在努力保持这个平台的独立性,但再次强调,如果它真的能显著提高性能,我愿意将其限制在Windows上 编辑:我现在也尝试了两种不同的方法;使用oracles网站上的片段和下面评论中指出的片段。所有这三个过程都花费了大约相同的时间,210-220万纳秒,这是相当他妈的低效 public a

我正在制作一个程序,需要每秒至少捕获24个屏幕截图。目前,对于下面的代码,我每94毫秒只能得到1个,所以大约每秒10个

我不喜欢使用任何第三方库,因为我正试图使它尽可能小,但如果我能获得显著的性能提升,我愿意。我也在努力保持这个平台的独立性,但再次强调,如果它真的能显著提高性能,我愿意将其限制在Windows上

编辑:我现在也尝试了两种不同的方法;使用oracles网站上的片段和下面评论中指出的片段。所有这三个过程都花费了大约相同的时间,210-220万纳秒,这是相当他妈的低效

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));
    }
}
_

_


实现这一点的唯一方法是通过JNI或JNA。我做了一些基准测试和本机屏幕捕获API,它能够维持约45 FPS与机器人8 FPS的速度。我可能会在不久的将来开始一个JNI项目来解决这个问题。如果继续的话,我会用项目URL更新这篇文章。

我目前已经建立了一个使用VLCJ然后使用DirectMediaPlayer()获取BuffereImage的工作示例

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);
        }

    }
私有缓冲区图像;
私营MediaPlayerFactory工厂;
私有DirectMediaPlayer;
公开作废开始(){
image=GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(宽度、高度);
image.setAccelerationPriority(1.0f);
String mrl=“屏幕:/”;
字符串[]选项={
“:屏幕fps=30”,
“:实时缓存=0”,
“:屏幕宽度=1920”,
“:屏幕高度=1080”,
“:屏幕左侧=0”,
“:屏幕顶部=0”
};
工厂=新的MediaPlayerFactory();
mediaPlayer=factory.newDirectMediaPlayer(新的TestBufferFormatCallback(),新的TestRenderCallback());
playMedia(mrl,选项);
}
//需要回调。
私有最终类TestRenderCallback扩展了RenderCallbackAdapter{
公共TestRenderCallback(){
超级(((DataBufferInt)image.getRaster().getDataBuffer()).getData());
}
@凌驾
public void onDisplay(DirectMediaPlayer,int[]数据){
//图像数据可以在这里操作。。。
/*RGB到灰度转换示例*/
//对于(int i=0;i>8)和0xFF);
//int r=((argb>>16)和0xFF);
//int grey=(r+g+b+g)>>2;//性能优化-不是真正的灰色!

//数据[i]=(灰色纯Java的帧速率约为30FPS,可以使用multiple
Java.awt.Robot
并行实现。可以在

上找到一个示例实现,听起来像是您正在尝试捕获屏幕视频。您可以看一看,我没有使用过它,也没有在测试台上标记它though@JimGarrison我是一个程序员那个论坛上的活跃用户,这是我将其与哈哈进行比较的第一件事。不过,遗憾的是,我得到了一个非常小的性能提升,比如2-4毫秒。我做了第二个基准测试,可以确认任何性能提升都是可以忽略不计的。这方面有什么新闻吗?我们有没有其他选择,可以将JNI/JNA用于screen capture?我也想看看这个。是的,我一直在这个项目上懈怠。我正在将原始库导入maven,然后我将开始进行开发。听起来不错,我做了一些研究,并得出了以下链接:。我还创建了一个简单的ThreadPoolExecutor实现,以帮助美国用户编写图像s谁需要将图像写入文件。如果您认为这有助于您的工作,我可以提供代码。因此,我在过去几天中进行了一些编码,下面是事情的分解方式。对于X11目标,我可以使用XShm扩展在10-15毫秒内获得一个单帧。使用XImage,每帧的长度约为5毫秒。在OSX上使用核心基础,我可以做大约42-55毫秒每帧。在我的Windows VM使用BITBLT,我看到大约60-75毫秒每帧。X11号码几乎不可在大约60 FPS。OSX号码等于20 FPS和Windows得到了15 fps。我将更新有关本机Windows测试,如果我能提高性能。是的,这是一个共同的合作伙伴。多线程-如果你的机器有多个CPU(对当前的计算机来说是可以的,但并不总是有保证)-这是个好主意。但是想法是让原始代码工作得更快-上面这个家伙开始谈论JNA,然后改成objective-C和其他废话-我想看看JNA方法!!
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);
    }
}
    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);
        }

    }