我知道在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实际上可以使其工作而无需更改上述代码.
目标是快速截取屏幕截图,但在截取“不同”的屏幕截图后停止.屏幕因某些事件而改变,例如窗口关闭等等.
如果您需要一个平滑的视频,其中> = 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