在Java里使用java.awt.Robot来屏幕截图非常的慢。直接使用RobotPeer或者native JNI的函数能数倍的提高速度,实现即时截图。
- RobotPeer可以通过Toolkit直接生成。
- WRobotPeer里“private native getRGBPixels”的应用是通过reflection实现的。
下面是测试结果:
// 使用Robot
Robot.getPixelColor(1024 * 768): 3850 ms
Robot.createScreenCapture(1024 * 768): 19 ms
// 使用RobotPeer
RobotPeer.getRGBPixel(1024 * 768): 3686 ms
RobotPeer.getRGBPixels(1024 * 768): 10 ms
// 使用RobotPeer.getRGBPixels(int x, int y, int w, int h, int[] buffer) (native)
RobotPeer.getRGBPixels(1024 * 768, buffer): 7 ms
测试代码:
//
// 使用Robot
//
final Robot robot = new Robot();
long start = System.currentTimeMillis();
int x = 0;
int y = 0;
for (int i = 0; i < 1024 * 768; i++) {
robot.getPixelColor(x++, y);
if (x == 1024) {
y++;
}
}
System.out.println("Robot.getPixelColor(1024 * 768): " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
robot.createScreenCapture(new Rectangle(0, 0, 1024, 768));
System.out.println("Robot.createScreenCapture(1024 * 768): " + (System.currentTimeMillis() - start) + " ms");</code>
//
// 使用RobotPeer
//
final RobotPeer peer = ((ComponentFactory) Toolkit.getDefaultToolkit()).createRobot(null, null);
start = System.currentTimeMillis();
for (int i = 0; i < 1024 * 768; i++) {
peer.getRGBPixel(x++, y);
if (x == 1024) {
y++;
}
}
System.out.println("RobotPeer.getRGBPixel(1024 * 768): " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
peer.getRGBPixels(new Rectangle(0, 0, 1024, 768));
System.out.println("RobotPeer.getRGBPixels(1024 * 768): " + (System.currentTimeMillis() - start) + " ms");
//
// 使用RobotPeer.getRGBPixels(int x, int y, int w, int h, int[] buffer) (native)
//
final Class[] params = new Class[] { int.class, int.class, int.class, int.class, int[].class };
final Method getRGBPixelsMethod = peer.getClass().getDeclaredMethod("getRGBPixels", params);
getRGBPixelsMethod.setAccessible(true);
final int[] buffer = new int[1024 * 768];
start = System.currentTimeMillis();
getRGBPixelsMethod.invoke(peer, 0, 0, 1024, 768, buffer);
System.out.println("RobotPeer.getRGBPixels(1024 * 768, buffer): " + (System.currentTimeMillis() - start) + " ms");
如果是纯粹想在自己的电脑上提升速度。也不妨试一下binary weaving。就是覆盖rt.jar里的WRobotPeer.java文件。
测试结果:
Robot.getPixelColor(1024 * 768): 3446 ms
Robot.createScreenCapture(1024 * 768): 23 ms
RobotPeer.getRGBPixel(1024 * 768): 3387 ms
RobotPeer.getRGBPixels(1024 * 768): 10 ms
RobotPeer.getRGBPixels(1024 * 768, buffer): 8 ms
RobotPeer.getRGBPixels(1024 * 768, buffer) direct: 7 ms
WRobotPeer.java文件:
package sun.awt.windows;
import java.awt.Rectangle;
import java.awt.peer.RobotPeer;
public class WRobotPeer extends WObjectPeer
implements RobotPeer {
public WRobotPeer() {
create();
}
private synchronized native void _dispose();
protected void disposeImpl() {
_dispose();
}
public native void create();
public native void mouseMoveImpl(int paramInt1, int paramInt2);
public void mouseMove(int paramInt1, int paramInt2) {
mouseMoveImpl(paramInt1, paramInt2);
}
public native void mousePress(int paramInt);
public native void mouseRelease(int paramInt);
public native void mouseWheel(int paramInt);
public native void keyPress(int paramInt);
public native void keyRelease(int paramInt);
public int getRGBPixel(int paramInt1, int paramInt2) {
return getRGBPixelImpl(paramInt1, paramInt2);
}
public native int getRGBPixelImpl(int paramInt1, int paramInt2);
public int[] getRGBPixels(Rectangle paramRectangle) {
int[] arrayOfInt = new int[paramRectangle.width * paramRectangle.height];
getRGBPixels(paramRectangle.x, paramRectangle.y, paramRectangle.width, paramRectangle.height, arrayOfInt);
return arrayOfInt;
}
public native void getRGBPixels(int x, int y, int w, int h, int[] buffer);
}
49.484677
8.476724