3

I've managed to send small (less than about 22mb) images but when sending bigger images I get errors such as shown below. I want to be able to reuse the socket and therefore not closing it.

As you maybe can see I'm trying to send a picture from client to server where it will be displayed if i type s in the console.

javax.imageio.IIOException: Error reading PNG image data

at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
at lärning5.Server.main(Server.java:55)

Caused by: java.io.EOFException: Unexpected end of ZLIB input stream

at java.base/java.util.zip.InflaterInputStream.fill(Unknown Source)
at java.base/java.util.zip.InflaterInputStream.read(Unknown Source)
at java.base/java.io.BufferedInputStream.fill(Unknown Source)
at java.base/java.io.BufferedInputStream.read1(Unknown Source)
at java.base/java.io.BufferedInputStream.read(Unknown Source)
at java.base/java.io.DataInputStream.readFully(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(Unknown Source)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(Unknown Source)
... 5 more

I have tried sending the images as an object using ObjectOutputStream which ended up requiring the socket to close. I have also tried scaling up the buffers so they can should be able to accommodate this much memory. I have tried using ByteArrayInputStream and ByteArrayOutputStream "the right way" in which I pickup exactly the size of the ByteArray and I always end up with the same error message.

Try to ignore the comments

Server code

package lärning5;

import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Server 
{

    static ServerSocket servern;
    static Socket client = new soketen();
    static OutputStream out;
    static InputStream in;
    static JFrame fön = new JFrame();
    static Panelen pan = new Panelen();
    static BufferedImage picture;
    static Scanner read = new Scanner(System.in);

    public static void main(String args[]) 
    {
        try 
        {
            servern = new ServerSocket(7777, 9999);
            client = servern.accept();
            System.out.print("conectad");


            out = client.getOutputStream();
            out.flush();
            in = client.getInputStream();

            byte[] buffer = new byte[899999];

            in.read(buffer, 0, buffer.length);
            ByteArrayInputStream bil = new ByteArrayInputStream(buffer, 0, buffer.length);
            picture = ImageIO.read(bil);

        } catch (Exception e) 
        {
            System.out.print("gg wp ");
            e.printStackTrace();
        }

        if (read.nextLine().equals("s"))
        {

            fön.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
            fön.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            fön.add(pan);
            fön.repaint();
            fön.setVisible(true);
        }
    }
}

Client code

package lärning6;

import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

public class Client 
{

    static Socket servern;
    static OutputStream out;
    static InputStream in;
    static Robot datorn;
    static BufferedImage picture;
    static ImageInputStream bil;
    static File fil = new File("src\\bilder\\ddeee.PNG");


    public static void main(String args[])
    {


        try
        {

            servern = new Socket(InetAddress.getByName("the ip address"), 7777);
            out = servern.getOutputStream();
            out.flush();
            in = servern.getInputStream();

            //byte[] buffer = new byte[90000];

            ByteArrayOutputStream bil = new ByteArrayOutputStream();
            picture = ImageIO.read(fil);//datorn.createScreenCapture(new Rectangle(0, 0, 500, 500));

            ImageIO.write(bild, "PNG", bil);


            out.write(bil.toByteArray());
            /*
            bil = ImageIO.createImageInputStream(picture);
            //bil.read(buffer, 0, buffer.length);
            ImageOutputStream bil = null;

            ImageIO.write(picture, "png", bil);
            buffer = bil.*/

        }catch(Exception e)
        {
            System.out.print("gg wr");
            e.printStackTrace();
        }

    }

}

Panel

package lärning5;

import java.awt.Graphics;

import javax.swing.JPanel;

public class Panelen extends JPanel
{

    public void paintComponent(Graphics g)
    {

        g.drawImage(Server.picture, 0, 0, this.getWidth(), this.getHeight(), null);
    }
}

THE CODE ABOVE AND THE CODE BELOW ARE TWO DIFFERENT CODES AND SHOULD NOT BE COMBINED

The code below is the codes which use bufferers that adapt to the picture size.

Server

package lärning5;

import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Server 
{

    static ServerSocket servern;
    static Socket client = new soketen();
    static OutputStream out;
    static InputStream in;
    static JFrame window = new JFrame();
    static Panelen panel = new Panelen();
    static BufferedImage bild;
    static File fil = new File("src\\bilde\\bilden.jpg");
    static Scanner läs = new Scanner(System.in);

    public static void main(String args[]) 
    {
        try 
        {
            servern = new ServerSocket(7777, 9999);
            client = servern.accept();
            System.out.print("conectad");


            out = client.getOutputStream();
            out.flush();
            in = client.getInputStream();

            byte[] buffer = new byte[4];
            //in.read(buffer);

            //ImageOutputStream bil = ImageIO.createImageOutputStream(bild);
            in.read(buffer);

            byte[] buffer2 = new byte[ByteBuffer.wrap(buffer).asIntBuffer().get()];

            in.read(buffer2);

            ImageIO.write(ImageIO.read(new ByteArrayInputStream(buffer2)), "PNG", new File("C:\\Users\\Bodi\\Desktop\\testse"));
            bild = ImageIO.read(new ByteArrayInputStream(buffer2));

        } catch (Exception e) 
        {
            System.out.print("gg wp ");
            e.printStackTrace();
        }

        if (läs.nextLine().equals("s"))
        {

            window.setSize(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.add(panel);
            window.repaint();
            window.setVisible(true);
        }
    }
}

Client


package lärning6;

import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

public class Client 
{

    static Socket servern;
    static OutputStream out;
    static InputStream in;
    static Robot datorn;
    static BufferedImage picture;
    static ImageInputStream bil;
    static File fil = new File("src\\bilder\\dddd.PNG");


    public static void main(String args[])
    {


        try
        {

            servern = new Socket(InetAddress.getByName("The ip adress"), 7777);
            out = servern.getOutputStream();
            out.flush();
            in = servern.getInputStream();

            //byte[] buffer = new byte[90000];

            ByteArrayOutputStream bil = new ByteArrayOutputStream();
            picture = ImageIO.read(fil);//datorn.createScreenCapture(new Rectangle(0, 0, 500, 500));

            ImageIO.write(picture, "PNG", bil);
            byte[] storlek = ByteBuffer.allocate(4).putInt(bil.size()).array();

            out.write(storlek);
            out.write(bil.toByteArray());
            out.flush();
            /*
            bil = ImageIO.createImageInputStream(picture);
            //bil.read(buffer, 0, buffer.length);
            ImageOutputStream bil = null;

            ImageIO.write(picture, "png", bil);
            buffer = bil.*/

        }catch(Exception e)
        {
            System.out.print("gg wr");
            e.printStackTrace();
        }

    }

}

The errors are a bit different to

Errors

conectadgg wp javax.imageio.IIOException: Error reading PNG image data
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(Unknown Source)
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(Unknown Source)
    at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
    at java.desktop/javax.imageio.ImageIO.read(Unknown Source)
    at lärning5.Server.main(Server.java:134)
Caused by: javax.imageio.IIOException: Unknown row filter type (= 148)!
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(Unknown Source)
    at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(Unknown Source)
    ... 5 more

I expect the server to turn on smoothly without any errors and the client to run smoothly without any errors ether.

But when they connect, i expect the server to receive the byte arrays but then pop up with the errors still running but doing nothing. You should still be able to press "s", and that will bring up a blank window. But this is wrong.

What i want to actually happen is that the server receives the byte array, does it's thing and then waits for you to press "s", when you press "s", a window should pop up displaying the received image.

that actually happens if i simply change to a "smaller"(less than 22 mb) pictures.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433

1 Answers1

1

I think your problem starts here:

in.read(buffer, 0, buffer.length)

When you turn to the javadoc for that method, it says:

RETURNS the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.

It is absolutely essential that you check that returned number of "bytes read". 99% of the time, you get all the bytes you want. But sometimes ... less than that! And in that case, you will have less valid bytes than expected in your buffer array.

In your case, you have to tell the server how many bytes should be read overall, and then you have to read until you really read exactly that number of bytes!

Long story short: it starts with a conceptual problem. A single read into a buffer can't be sufficient to handle variable-sized data! Your server only has

byte[] buffer = new byte[899999];

But most likely, your the client will send a different number of bytes. How is the server supposed to know how many bytes exactly will be coming over the wire?!

So: change your "protocol" to first tell the server how many bytes will follow. Then ensure that exactly that number of bytes gets read! That might include some sort of loop (when the image is larger than your buffer array!)

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • I have already tried that with some other code but it didn't fix the problem. But I made the bufferer bigger than needed anyway and it still doesn't work with pictures above aproxemetly 22mb – Mohmad Mahra Sep 08 '19 at 15:45
  • 1
    @MohmadMahra Then update your input and show us the **exact** code you are working with right now. Again: the code you have right now cant work conceptually. And you going "but I also wrote some other code" ... doesnt change anything. And worse: we can't help you with code you didnt put into your question. – GhostCat Sep 08 '19 at 15:47
  • I Uppdated it. The Errors are kinda diffrent to – Mohmad Mahra Sep 08 '19 at 15:59
  • @MohmadMahra Your other code has **different** issues. Sorry, but you have to understand: this is a Q/A site. You ask one specific question, and then you get an answer for that. This is not a free tutor service where people sit down with you and help you with the different problems you encounter while working on a project. My recommendation for you: dissect your problem in smaller parts. Start by **reading** bytes from an image into a buffer. And back to a file. Make sure that you do that correctly (by comparing the initial file with the copy you create). And so on. – GhostCat Sep 08 '19 at 16:39
  • You see, your second code is still **plain wrong**. It doesnt help to use TWO buffers. You have to do something like `int bytesRead = in.read(...)` and then use that number `bytesRead` to ensure that you end up with the exact number of bytes you need. But as said: this is not a free tutor service where people *teach* you how to do things. We give you a hint, and point out the relevant material. – GhostCat Sep 08 '19 at 16:40
  • Where do i find a tutorial about this? I have looked everywhere – Mohmad Mahra Sep 08 '19 at 17:33
  • @MohmadMahra See https://stackoverflow.com/a/1264737/1531124 for example. That shows you how to **properly** use the read method. – GhostCat Sep 08 '19 at 17:35