我想使用java来使用FFMPEG或其他解决方案截取我的机器的屏幕截图.我知道linux可以在没有JNI的情况下使用ffmpeg,但是在Windows中运行它不起作用并且可能需要(JNI?)是否有一些简单的java类(以及其他任何必要的)的示例来捕获在Windows环境中可运行的屏幕截图? FFMPEG有替代品吗?我想以比Java Robot API更快的速度截取屏幕截图,我发现它可以用于截取屏幕截图,但速度比我想要的慢.

我知道在Linux中它的工作速度非常快:

import com.googlecode.javacv.*;

public class ScreenGrabber {
    public static void main(String[] args) throws Exception {
        int x = 0,y = 0,w = 1024,h = 768;
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(":0.0+" + x + "," + y);
        grabber.setFormat("x11grab");
        grabber.setimageWidth(w);
        grabber.setimageHeight(h);
        grabber.start();

        CanvasFrame frame = new CanvasFrame("Screen Capture");
        while (frame.isVisible()) {
            frame.showImage(grabber.grab());
        }
        frame.dispose();
        grabber.stop();
    }

这在Windows环境中不起作用.我不确定是否有某种方法可以使用相同的代码,但使用javacpp实际上可以使其工作而无需更改上述代码.

目标是快速截取屏幕截图,但在截取“不同”的屏幕截图后停止.屏幕因某些事件而改变,例如窗口关闭等等.

使用内置的Robots类比其他Java库更容易,并且应该可以满足您的需求.

如果您需要一个平滑的视频,其中> = 30fps(每秒超过30个屏幕截图),您应首先尝试使用机器人方法以及使用异步存储屏幕截图的性能改进.

如果它不适合你,尝试使用JNA,即使它更复杂,几乎可以保证平滑的屏幕捕获.

机器人的方法

机器人类确实能够做你想做的事情,机器人大多数屏幕捕获方法的问题是节省了截图.一种方法可能如下所示:循环使用captureScreen()方法,将屏幕抓取到BufferedImage中,将其转换为字节数组,并在将图像的未来引用添加到目标文件后将其与异步文件编写器一起保存到目标文件中. ArrayList能够在存储图像数据的同时继续前进.

// Pseudo code
while (capturing)
{
    grab bufferedImage (screenCapture) from screen
    convert bufferImage to byte array
    start asynchronous file channel to write to the output file
      and add the future reference (return value) to the ArrayList
}

与JNA的方法

原始问题:
How to take screenshots fast in Java?

由于链接是不好的做法,我将在此处发布示例:

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferushort;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.W32API;
import com.sun.jna.win32.W32APIOptions;

public class JNAScreenShot
{

    public static BufferedImage getScreenshot(Rectangle bounds)
    {
        W32API.HDC windowDC = GDI.GetDC(USER.GetDesktopWindow());
        W32API.HBITMAP outputBitmap = GDI.CreateCompatibleBitmap(windowDC,bounds.width,bounds.height);
        try
        {
            W32API.HDC blitDC = GDI.CreateCompatibleDC(windowDC);
            try
            {
                W32API.HANDLE oldBitmap = GDI.SelectObject(blitDC,outputBitmap);
                try
                {
                    GDI.BitBlt(blitDC,bounds.height,windowDC,bounds.x,bounds.y,GDI32.SRCcopY);
                }
                finally
                {
                    GDI.SelectObject(blitDC,oldBitmap);
                }
                GDI32.BITMAPINFO bi = new GDI32.BITMAPINFO(40);
                bi.bmiHeader.biSize = 40;
                boolean ok = GDI.GetDIBits(blitDC,outputBitmap,(byte[]) null,bi,GDI32.DIB_RGB_COLORS);
                if (ok)
                {
                    GDI32.BITMAPINFOHEADER bih = bi.bmiHeader;
                    bih.biHeight = -Math.abs(bih.biHeight);
                    bi.bmiHeader.biCompression = 0;
                    return bufferedImageFromBitmap(blitDC,bi);
                }
                else
                {
                    return null;
                }
            }
            finally
            {
                GDI.DeleteObject(blitDC);
            }
        }
        finally
        {
            GDI.DeleteObject(outputBitmap);
        }
    }

    private static BufferedImage bufferedImageFromBitmap(GDI32.HDC blitDC,GDI32.HBITMAP outputBitmap,GDI32.BITMAPINFO bi)
    {
        GDI32.BITMAPINFOHEADER bih = bi.bmiHeader;
        int height = Math.abs(bih.biHeight);
        final ColorModel cm;
        final DataBuffer buffer;
        final WritableRaster raster;
        int strideBits = (bih.biWidth * bih.biBitCount);
        int strideBytesAligned = (((strideBits - 1) | 0x1F) + 1) >> 3;
        final int strideElementsAligned;
        switch (bih.biBitCount)
        {
            case 16:
                strideElementsAligned = strideBytesAligned / 2;
                cm = new DirectColorModel(16,0x7C00,0x3E0,0x1F);
                buffer = new DataBufferushort(strideElementsAligned * height);
                raster = Raster.createPackedRaster(buffer,bih.biWidth,height,strideElementsAligned,((DirectColorModel) cm).getMasks(),null);
                break;
            case 32:
                strideElementsAligned = strideBytesAligned / 4;
                cm = new DirectColorModel(32,0xFF0000,0xFF00,0xFF);
                buffer = new DataBufferInt(strideElementsAligned * height);
                raster = Raster.createPackedRaster(buffer,null);
                break;
            default:
                throw new IllegalArgumentException("Unsupported bit count: " + bih.biBitCount);
        }
        final boolean ok;
        switch (buffer.getDataType())
        {
            case DataBuffer.TYPE_INT:
            {
                int[] pixels = ((DataBufferInt) buffer).getData();
                ok = GDI.GetDIBits(blitDC,raster.getHeight(),pixels,0);
            }
                break;
            case DataBuffer.TYPE_USHORT:
            {
                short[] pixels = ((DataBufferushort) buffer).getData();
                ok = GDI.GetDIBits(blitDC,0);
            }
                break;
            default:
                throw new AssertionError("Unexpected buffer element type: " + buffer.getDataType());
        }
        if (ok)
        {
            return new BufferedImage(cm,raster,false,null);
        }
        else
        {
            return null;
        }
    }

    private static final User32 USER = User32.INSTANCE;

    private static final GDI32 GDI = GDI32.INSTANCE;

}

interface GDI32 extends com.sun.jna.platform.win32.GDI32
{
    GDI32 INSTANCE = (GDI32) Native.loadLibrary(GDI32.class);

    boolean BitBlt(HDC hdcDest,int nXDest,int nYDest,int nWidth,int nHeight,HDC hdcSrc,int nXSrc,int nYSrc,int dwRop);

    HDC GetDC(HWND hWnd);

    boolean GetDIBits(HDC dc,HBITMAP bmp,int startScan,int scanLines,byte[] pixels,BITMAPINFO bi,int usage);

    boolean GetDIBits(HDC dc,short[] pixels,int[] pixels,int usage);

    int SRCcopY = 0xCC0020;
}

interface User32 extends com.sun.jna.platform.win32.User32
{
    User32 INSTANCE = (User32) Native.loadLibrary(User32.class,W32APIOptions.UNICODE_OPTIONS);

    HWND GetDesktopWindow();
}

更多信息和方法

> Increasing screen capture speed when using Java and awt.Robot
> http://www.dreamincode.net/forums/topic/234896-faster-screen-capture/
> How to get over 30FPS using Java in a Screen Capture Program?
> http://ffmpeg.org

也可以看看

> http://www.thepcwizard.in/2012/12/java-screen-capturing-tutorial.html
> How to develop screen capture to video application
> http://www.javalobby.org/forums/thread.jspa?threadID=16400&tstart=0
> http://hiddensciencex.blogspot.co.at/2014/01/fast-screen-capture-in-java-example.html
> http://www.coderanch.com/t/340180/GUI/java/efficient-screenshot-Java
> http://www.javaworld.com/article/2071755/learn-java/capture-the-screen.html
> ffmpeg for screen capture?
> Java applet screen capture to a video
> Screen Capture of DirectX programs with Java

如何在Windows(ffmpeg等)中使用Java快速截取桌面?的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. Xcode:iPhone截图不再有效

    解决方法我没有针对您的问题的解决方案,但这是一个解决方法:使用设备制作屏幕截图.生成的屏幕截图将保存在设备上.要将屏幕截图传输到桌面,请不要使用慢速iPhoto或iTunes进行同步.而是使用Preview.app导入图像.文件菜单中有一个命令可以在iPhone连接时从iPhone导入图像.

  3. ios – 来自Share Extension的Safari屏幕截图

    是否可以通过共享扩展程序在Safari中执行webview当前可见区域的屏幕截图?

  4. ios – 无法编辑屏幕截图,performChanges阻止失败

    我正在开发一个允许用户使用PhotoKit编辑照片的应用程序.我之前将编辑过的照片以JPEG格式保存到磁盘.我想避免转换为JPEG,并已实施修改,以便这样做.它适用于使用相机拍摄的照片,但如果您尝试编辑屏幕截图,PHPhotoLibrary.sharedPhotoLibrary().performChanges块将失败并记录操作无法完成.(可可错误-1.).我不确定为什么这会导致performCh

  5. ios – 核心图形栅格数据不从内存释放

    所以我让我的应用程序拍摄屏幕截图并将其保存到相册中,代码如下…如何释放由持有屏幕截图栅格数据的CoreGraphics分配的内存?我的项目是使用ARC进行内存管理.在测试应用程序如何分配内存时,我注意到在屏幕截图后内存没有被释放,导致应用程序随着时间的推移而变得迟缓.Instruments中的“AllocationSummary”告诉我数据类别是“CG栅格数据”,负责调用者是’CGDataProviderCreatWithcopyOfData’.CFRelease()中是否有解决方案;?解决方法您可以尝试

  6. 如何清除屏幕截图IOS

    我正在研究IOS应用程序,其中需要采取清晰的屏幕截图我已经尝试过了但是图像的质量并不好.请为我推荐一些东西.解决方法换线至

  7. ios – App Store提交的最大屏幕截图数

    我正在研究找出将应用程序提交到iOS应用商店所需的元数据要求.在没有注册Apple开发者计划的情况下,我无法找到提交时允许的屏幕截图数量的任何信息.任何人都可以开导我吗?

  8. ios – iTunes Connect的截图与错误的纵横比

    在模拟器中拍摄各种尺寸的屏幕截图,而我的4.7英寸和5.5英寸屏幕截图只出现问题….4英寸和3.5英寸没有问题上传.错误状态:一个或多个屏幕截图的纵横比不正确.有关更多信息,请参阅开发人员指南.在开发指南上说:我的屏幕截图有这些尺寸,我把它们与相应的模拟器.有人有类似的问题吗?(已经尝试重命名截图,避免奇怪的字符,什么不…还没成功)解决方法将模拟器比例设置为100%模拟器>窗口>比例>100%

  9. ios – 苹果在iPhone应用程序上要求iPad屏幕截图(在iTunes Connect中)?

    快而有希望的明显问题.我正在设置我的应用程序来提交,我正在iTunesConnect工作.它是要求我的iPhone和iPad截图.如果您的版本仅适用于iPhone,那么请放弃iPad屏幕截图?

  10. ios – ffmpeg不会在我的项目中构建,在示例应用程序中运行良好

    我已经尝试了几个小时,但我无法弄清楚这一点.我在我的项目中使用KXMOVIE.我按照指示下载并编译了ffmpeg二进制文件.示例应用程序实际上工作正常,但我不能让它在我自己的项目中构建.所有.a文件都在那里,它与示例应用程序中的文件完全相同.当我尝试为模拟器构建时,我收到此错误.我究竟做错了什么?我甚至不知道从哪里开始.解决方法您还需要与libiconv链接.假设你拥有它,请将-liconv作为链接选项.

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部