java - 通过java中的套接字发送屏幕截图(bufferedImage)

标签 java sockets bufferedimage

我正在通过套接字发送 bufferedImage,并且使用 this 中找到的示例帖子:

发件人

   BufferedImage image = ....;
   ImageIO.write(image, "PNG", socket.getOutputStream());

接收者

   BufferedImage image = ImageIO.read(socket.getInputStream());

它有效 - 如果且仅当我在此行之后关闭发送者的输出流:

 ImageIO.write(image, "PNG", socket.getOutputStream());

除了关闭outputStream之外,我还能做些什么吗?

此外,我还能做些什么来完全避免使用 ImageIO 吗?做任何事情似乎都需要很长时间。 另请注意,由于性能问题,应不惜一切代价避免以任何方式读取或写入硬盘。我需要尽可能快地进行此传输,(我正在试验并尝试创建一个类似于 VNC 的客户端,并将每个屏幕截图保存到硬盘会大大减慢一切速度)..

@乔恩斯基特

编辑3:

发件人:(请注意,我发送的是 JPG 图像,而不是 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()); //Send filesize
                    out.write(new String("#<IM> \n").getBytes());        //Notify start of image

                    out.write(imgByte); //Write file
                    System.out.println("Finished");                                 

接收器:(其中 input 是套接字输入流)

尝试#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());

(失败:getWidth() 行出现空指针异常) 我理解这个错误的意思是“图像损坏”,因为它无法初始化它。正确吗?

尝试#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());

(失败:getWidth() 行出现空指针异常)

尝试#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();

(失败:接收器给出:空指针异常)

尝试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());

(失败:发送方给出:java.net.SocketException:对等方重置连接:套接字写入错误)

尝试#5:

使用 Jon skeet 的代码片段,图像到达了,但只是部分。我将其保存到文件 (1.jpg) 中以查看发生了什么,它实际上发送了 80% 的图像,而文件的其余部分则填充了空格。这会导致图像部分损坏。这是我尝试的代码:(注意captureImg()没有错,直接保存文件就可以了)

发件人:

    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);

接收者:

    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");

发送方仍然给出 Connection Reset by Peer: socket write 错误。 Click here for full sized image Problem

最佳答案

一种选择是将图像写入ByteArrayOutputStream,以便您可以确定长度,然后先将该长度写入输出流。

然后在接收端,您可以读取长度,然后将那么多字节读入字节数组,然后创建一个 ByteArrayInputStream 来包装该数组并传递ImageIO.read()

我并不完全惊讶它在输出套接字正常关闭之前不起作用 - 毕竟,一个包含有效 PNG 文件然后是其他内容的文件实际上并不是一个PNG 文件本身有效,是吗?因此,读取器需要先读取到流的末尾,然后才能完成 - 并且网络流的“结束”仅在连接关闭时出现。

编辑:这是一种将给定数量的字节读入新字节数组的方法。作为单独的“实用”方法很方便。

public static byte[] readExactly(InputStream input, int size) throws IOException
{
    byte[] data = new byte[size];
    int index = 0;
    while (index < size)
    {
        int bytesRead = input.read(data, index, size - index);
        if (bytesRead < 0)
        {
            throw new IOException("Insufficient data in stream");
        }
        index += bytesRead;
    }
    return data;
}

关于java - 通过java中的套接字发送屏幕截图(bufferedImage),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14984335/

相关文章:

Java Float 添加到 ArrayList<T> 后变为 0.0

java - 如何查找列表中每个单词的字符数? ( java )

java - 如何在 Android map 中显示不同颜色的图钉?

android - 套接字对象在绑定(bind)到服务的 Activity 中返回 null

java - 使用 gwtwiki 创建 MediaWiki 页面

c# - UdpClient 构造函数抛出 SocketException

sockets - 大量连接使用 TCP 还是 UDP?

java - 将 YUV 网络摄像头图像转换为 java 字节数组

java - 在 Java 中绘制像素最快的方法是什么

java - 在JPanel上绘制,然后保存到文件,但保存的文件全是白色