如何在Windows(ffmpeg等)中使用Java快速截取桌面?
我想使用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的方法 原始问题: 由于链接是不好的做法,我将在此处发布示例: 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.thepcwizard.in/2012/12/java-screen-capturing-tutorial.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- botframework – Microsoft Bot Framework:例外:数据已更
- Windows 8 Metro开放网站/ mailto C#
- 是否有适用于Windows 7 64位的Python蓝牙模块?
- Windows Mobile:使用C#的手机摄像头
- .net – 如何判断Windows何时处于非活动状态
- 任何人都可以推荐一个.Net开源替代Windows Workflow?
- windows – 什么是rgbReserved?
- .net-4.0 – 如何学习70-511 TS:Windows应用程序开发与Mic
- 外部用户能够给Exchange通讯组发送邮件排错分析
- DLL_PROCESS_ATTACH无法在Windows 7 C上执行
- 系统管理员为Windows专家/ Lunix Noob提供Debian
- DOS批处理中%cd%和%~dp0的区别
- .net – 与Windows兼容的文件系统的文件时间分辨
- 有没有办法在Windows上获得超过Meta和Ctrl的方法
- Windows上的Python 3.4中的Tkinter在退出时不会将
- windows server 2008 r2 环境下,实现域名和IP同
- 无法启动此程序,因为计算机中丢失QtCored4.dll。
- windows – Jenkins从Bonobo Git Server中拔出
- .net – 以编程方式在Windows中重启USB设备
- windows-server-2008-r2 – 我从raid上启动了哪个