I am sending a bufferedImage through a socket, and I am using the example found in this post:
Sender
BufferedImage image = ....; ImageIO.write(image, "PNG", socket.getOutputStream());
Receiver
BufferedImage image = ImageIO.read(socket.getInputStream());
It works - IF, and ONLY IF, I close the sender's output stream after this line:
ImageIO.write(image, "PNG", socket.getOutputStream());
Is there anything I can do except close the output stream?
Also, is there anything else not to use ImageIO at all? It seems that the time has come to do something. Also note that reading or writing to the hard drive should in any case be avoided at all costs due to performance issues. I need to make this transfer as quickly as possible (I am experimenting and trying to create a client similar to VNC, and saving each screenshot to the hard drive will greatly slow down everything).
@Jon Skeet
Edit 3:
Sender: (Please note that I am sending a JPG image, not a PNG).
int filesize; OutputStream out = c.getClientSocket().getOutputStream(); ByteArrayOutputStream bScrn = new ByteArrayOutputStream(); ImageIO.write(screenshot, "JPG", bScrn); byte[] imgByte = bScrn.toByteArray(); bScrn.flush(); bScrn.close(); filesize = bScrn.size(); out.write(new String("#FS " + filesize).getBytes());
Reciever: (where input is the input stream of the socket)
Attempt # 1:
String str = input.toString(); imageBytes = str.getBytes(); InputStream in = new ByteArrayInputStream(imageBytes); BufferedImage image = ImageIO.read(in); in.close(); System.out.println("width=" + image.getWidth());
(failed: Nullpointer exception in getWidth () line) I understand that this error means “damaged image” because it cannot initialize it. correctly?
Attempt number 2:
byte[] imageBytes = new byte[filesize]; for (int j = 0; i < filesize; i++) { imageBytes[j] = (byte) input.read(); } InputStream in = new ByteArrayInputStream(imageBytes); BufferedImage image = ImageIO.read(in); in.close(); System.out.println("width=" + image.getWidth());
(failed: Nullpointer exception on getWidth () line)
Attempt number 3:
if (filesize > 0) { int writtenBytes = 0; int bufferSize = client.getReceiveBufferSize(); imageBytes = new byte[filesize]; //Create a byte array as large as the image byte[] buffer = new byte[bufferSize];//Create buffer do { writtenBytes += input.read(buffer); //Fill up buffer System.out.println(writtenBytes + "/" + filesize); //Show progress //Copy buffer to the byte array which will contain the full image System.arraycopy(buffer, 0, imageBytes, writtenBytes, client.getReceiveBufferSize()); writtenBytes+=bufferSize; } while ((writtenBytes + bufferSize) < filesize); // Read the remaining bytes System.arraycopy(buffer, 0, imageBytes, writtenBytes-1, filesize-writtenBytes); writtenBytes += filesize-writtenBytes; System.out.println("Finished reading! Total read: " + writtenBytes + "/" + filesize); } InputStream in = new ByteArrayInputStream(imageBytes); BufferedImage image = ImageIO.read(in); in.close();
(failed: Reciever gives: null pointer exception)
Attempt 4:
int readBytes = 0; imageBytes = new byte[filesize]; //Create a byte array as large as the image while (readBytes < filesize) { readBytes += input.read(imageBytes); } InputStream in = new ByteArrayInputStream(imageBytes); BufferedImage image = ImageIO.read(in); in.close(); System.out.println("width=" + image.getWidth());
(failed: sender gives: java.net.SocketException: connection reset by error: socket write error)
Attempt number 5:
Using the Jon skeet code snippet, the image comes in, but only partially. I saved it in a file (1.jpg) to see what happens, and it actually sends 80% of the image, and the rest of the file is filled with empty space. This results in a partially damaged image. Here is the code I tried: (note that captureImg () is not wrong, saving the file directly works)
Sender:
Socket s = new Socket("127.0.0.1", 1290); OutputStream out = s.getOutputStream(); ByteArrayOutputStream bScrn = new ByteArrayOutputStream(); ImageIO.write(captureImg(), "JPG", bScrn); byte imgBytes[] = bScrn.toByteArray(); bScrn.close(); out.write((Integer.toString(imgBytes.length)).getBytes()); out.write(imgBytes,0,imgBytes.length);
Receiver:
InputStream in = clientSocket.getInputStream(); long startTime = System.currentTimeMillis(); byte[] b = new byte[30]; int len = in.read(b); int filesize = Integer.parseInt(new String(b).substring(0, len)); if (filesize > 0) { byte[] imgBytes = readExactly(in, filesize); FileOutputStream f = new FileOutputStream("C:\\Users\\Dan\\Desktop\\Pic\\1.jpg"); f.write(imgBytes); f.close(); System.out.println("done");
The sender still receives the message Connection reset by peer: socket write. Click here for full size image. 