title: How to Speed up Frame Rate of Remote Viewer?
body: <p>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.</p>
  
  <p>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..</p>
  
  <p>Here's the client:</p>
  
  <pre><code>// 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;
  </code></pre>
  
  <p>And the server:</p>
  
  <pre><code>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);
  </code></pre>
  
  <p>And then the resize method:</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>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.</p>