So, I built an application that has two parts, the client and the server. The client takes a screenshot, converts that to a byte array, sends that to the server, and then waits for a response to repeat all that. The server takes the byte array, turns that into a screenshot, displays the screenshot, and then tells the client it's done.
Everything works beautifully, but the problem is it takes about 200-350ms for the whole process to go down, which means at the most I'm getting five fps. This obviously isn't satisfactory, and so I'm wondering what I can do to speed up this process. Is there a faster way to take screenshots? Does having a 1080x1920 monitor rather than a smaller resolution make that much of a difference? Is the long amount of time due to the image having to resize to the size of the box? etc..
Here's the client:
// Capture the image
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture = robot.createScreenCapture(screenRect);
// Convert the image to a byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(capture, "jpg", baos);
byte[] bytes = baos.toByteArray();
// Send byte array over socket connection
Socket socket = new Socket("machine", 2282);
DataOutputStream outputData = new DataOutputStream(socket.getOutputStream());
DataInputStream inputData = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
outputData.write(bytes);
outputData.close();
// Wait for response
String incomingData = inputData.readUTF();
inputData.close();
if (incomingData.equals("1"))
break;
And the server:
long startTime = System.nanoTime();
// Get client and receive byte array
ServerSocket server = new ServerSocket(2282);
Socket socket = server.accept();
DataInputStream inputData = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
DataOutputStream outputData = new DataOutputStream(socket.getOutputStream());
// Read bytes to byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buffer[] = new byte[1024];
for (int s; (s = inputData.read(buffer)) != -1;) {
baos.write(buffer, 0, s);
}
byte result[] = baos.toByteArray();
// Create bufferedImage from byte array
BufferedImage bufferedImage = null;
ByteArrayInputStream bais = new ByteArrayInputStream(result);
bufferedImage = ImageIO.read(bais);
// Update image box
imageBox.setBounds(10, 11, (frame.getWidth() - 40), (frame.getHeight()) - 50);
BufferedImage resizedImage = resize(bufferedImage, imageBox.getHeight(), imageBox.getWidth());
imageBox.setIcon(new ImageIcon(resizedImage));
outputData.writeUTF("1");
// Close everything
outputData.close();
server.close();
socket.close();
inputData.close();
baos.close();
bais.close();
long endTime = System.nanoTime();
long totalTime = (endTime - startTime) / 1000000;
System.out.println(totalTime);
And then the resize method:
public static BufferedImage resize(BufferedImage img, int height, int width) {
Image image = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2d = resized.createGraphics();
graphics2d.drawImage(image, 0, 0, null);
graphics2d.dispose();
return resized;
}
When running this, the server takes up about 20% of the CPU (3.20 GHz) and 40% of the RAM (8GB). It isn't being limited to this, but it doesn't usually exceed that.