如何在Java中快速截图?
我正在实现一个简单的眼动仪,它需要快速截屏屏幕上发生的事情,同时从networking摄像头捕捉video。
事情是这样做的机器人,在这里提到: https : //stackoverflow.com/questions/2475303/java-library-for-capturing-active-window-screenshot是非常缓慢的。
顺便说一下,从networking摄像头检索video的速度更快,并返回字节数组,这是非常快的处理。
有人知道更快的解决scheme吗? 可以链接到Java来执行此操作的C ++库也可能有所帮助。
谢谢!
更新:决定切换到OpenCV,现在寻找的方式来使它的截图:)
你一定要给OpenCV一个镜头
这是一个使用JNA的Windows特定版本,我正在使用我的一个项目。
我发现它比Robot
更快一个数量级,即使是本地通话开销也是如此。
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, 0, 0, bounds.width, 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, 0, bounds.height, (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, outputBitmap, 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, bih.biWidth, height, strideElementsAligned, ((DirectColorModel) cm).getMasks(), 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, outputBitmap, 0, raster.getHeight(), pixels, bi, 0); } break; case DataBuffer.TYPE_USHORT: { short[] pixels = ((DataBufferUShort) buffer).getData(); ok = GDI.GetDIBits(blitDC, outputBitmap, 0, raster.getHeight(), pixels, bi, 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, HBITMAP bmp, int startScan, int scanLines, short[] pixels, BITMAPINFO bi, int usage); boolean GetDIBits(HDC dc, HBITMAP bmp, int startScan, int scanLines, int[] pixels, BITMAPINFO bi, 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(); }
robot.createScreenCapture(captureSize);
通话大概需要20ms。
可能是你可以使用JMF ..检查屏幕抓取代码@ Oracle的网站 。 我认为这会帮助你解决你的问题。