17463

How to scale down the size and quality of an BufferedImage?

Question:

I'm working on a project, a client-server application named 'remote desktop control'. What I need to do is take a screen capture of the client computer and send this screen capture to the server computer. I would probably need to send 3 to 5 images per second. But considering that sending BufferedImage directly will be too costly for the process, I need to reduce the size of the images. The image quality need not to be loss less.

How can I reduce the byte size of the image? Any suggestions?

Answer1:

You can compress it with ZIP very easily by using <a href="http://docs.oracle.com/javase/6/docs/api/java/util/zip/GZIPInputStream.html" rel="nofollow">GZIPInputStream</a> and its output counterpart on the other end of the socket.

<strong>Edit:</strong>

Also note that you can create <em>delta</em> images for transmission, you can use a "transpartent color" for example (magic pink #FF00FF) to indicate that no change was made on that part of the screen. On the other side you can draw the new image over the last one ignoring these magic pixels.

Note that if the picture already contains this color you can change the real pink pixels to #FF00FE for example. This is unnoticable.

An other option is to transmit a <strong>1-bit mask</strong> with every image (after painting the no-change pixels to an arbitrary color. For this you can change the color which is mostly used in the picture to result in the best compression ratio (optimal huffman-coding).

Answer2:

Vbence's solution of using a GZIPInputStream is a good suggestion. The way this is done in most commercial software - Windows Remote Desktop, VNC, etc. is that only changes to the screen-buffer are sent. So you keep a copy on the server of what the client 'sees', and with each consecutive capture you calculate what is different in terms of screen areas. Then you only send these screen areas to the client along with their top-left coords, width, height. And update the server copy of the client 'view' with just these new areas.

That will MASSIVELY reduce the amount of network data you use, while I have been typing this answer, only 400 or so pixels (20x20) are changing with each keystroke. This on a 1920x1080 screen is just 1/10,000th of the screen, so clearly worth thinking about.

The only expensive part is how you calculate the 'difference' between one frame and the next. There are plenty of libraries out there to do that cheaply, most of them very mathematical (discrete cosine transform type stuff, way over my head), but it can be done relatively cheaply.

Answer3:

See <a href="https://stackoverflow.com/a/5998015/418556" rel="nofollow">this thread</a> for how to encode to JPG with controllable compression/quality. The slider on the left is used to control the level.

<img width="639" height="475" class="b-lazy" data-src="https://i.stack.imgur.com/GyCaw.png" data-original="https://i.stack.imgur.com/GyCaw.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" />

Ultimately it would be better to encode the images directly to a video codec that can be streamed, but I am a little hazy on the details.

Answer4:

One way would be to use ImageIO API

ImageIO.write(buffimg, "jpg", new File("buffimg.jpg"));

As for the quality and other parameters- I'm not sure, but it should be possible, just dig deeper.

Recommend

  • Distributed Cache and performance Hadoop
  • Recognizing MSSQL Service Broker sender side error messages
  • Files are getting corrupted via FTP Client Upload
  • A simple timeout function
  • How to scale down the size and quality of an BufferedImage?
  • What are advantages of using JSON/XML over a plain string of variable format?
  • In R shiny, how to use on the UI side a value computed on the SERVER side?
  • Packing SUBFIELDS using jpos api
  • Ignoring a field without modifying the POJO class with Jackson
  • Shift operation implementation in java
  • Restrict mouse movement over a specified window handle
  • onpreviewframe byte[] to int[]
  • Wierd Results using script to find length of a string?
  • Concise R data.table syntax for modal value (most frequent) by group
  • WPF Image control clipping
  • write text on image and show it to a imageview
  • Certain Arabic text gets incorrectly shown while other Arabic text gets showed normally?
  • How to change placeholder text in an autocomplete activity of android google place?
  • cell spacing in div table
  • Ember.js model to be organised as a tree structure
  • Java color detection
  • Moving Android View and preventing onDraw to be called over and over again
  • Blackberry - Custom EditField Cursor
  • Jackson Parser: ignore deserializing for type mismatch
  • OpenGL ES texture problem, 4 duplicate columns and horizontal lines (Android)
  • Update CALayer sublayers immediately
  • What is Eclipse's Declaration View used for?
  • Validaiting emails with Net.Mail MailAddress
  • Which linear programming package should I use for high numbers of constraints and “warm starts” [clo
  • Javascript + PHP Encryption with pidCrypt
  • How can I estimate amount of memory left with calling System.gc()?
  • Jquery - Jquery Wysiwyg return html as a string
  • Calling of Constructors in a Java
  • SVN: Merging two branches together
  • Traverse Array and Display in markup
  • Transpose CSV data with awk (pivot transformation)
  • Why can't I rebase on to an ancestor of source changesets if on a different branch?
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • Append folder name and increment by 1 using batch script