java使用ImageIO发送图像流?
我设置了一个ServerSocket和一个socket,以便ServerSocket使用ImageIO发送图像流。写(…)socket尝试读取它们并用它们更新JFrame。所以我想知道ImageIO是否能检测到图像的结尾。(我完全不知道JPEG格式,所以我测试了它)
显然不是
在服务器端,我使用ImageIO连续发送图像。写(…)在循环中,中间有一些睡眠。在客户端,ImageIO读取第一个图像没有问题,但在下一个图像上返回null。这令人困惑。我希望它要么在读取第一个图像时阻塞(因为它认为下一个图像仍然是同一个图像的一部分),要么在读取所有图像时成功(因为它可以工作)。怎么回事?看起来ImageIO检测到了第一张图像的结尾,但没有检测到第二张图像。(顺便问一下,这些图像彼此大致相似)有没有一种简单的方法可以像这样流式传输图像,还是我必须自己制作一种机制,将字节读入缓冲区,直到它达到指定的字节或字节序列,然后从缓冲区中读取图像
这是我的服务器代码中有用的部分:
while(true){
Socket sock=s.accept();
System.out.println("Connection");
OutputStream out=sock.getOutputStream();
while(!socket.isClosed()){
BufferedImage img=//get image
ImageIO.write(img, "jpg", out);
Thread.sleep(100);
}
System.out.println("Closed");
}
我的客户代码:
Socket s=new Socket(InetAddress.getByName("localhost"), 1998);
InputStream in=s.getInputStream();
while(!s.isClosed()){
BufferedImage img=ImageIO.read(in);
if(img==null)//this is what happens on the SECOND image
else // do something useful with the image
}
# 1 楼答案
ImageIO.read(InputStream)
创建一个ImageInputStream
并在内部调用read(ImageInputStream)
。后一种方法是在完成图像读取后关闭流因此,从理论上讲,您只需获取
ImageReader
,自己创建一个ImageInputStream
,然后让ImageReader
从ImageInputStream
重复读取除此之外,
ImageInputStream
似乎被设计为只处理一个图像(可能包含也可能不包含多个帧)。如果你多次调用ImageReader.read(0)
,它每次都会倒回(缓存的)流数据的开头,一遍又一遍地给你相同的图像ImageReader.read(1)
将在多帧图像中查找第二帧,这对于JPEG来说毫无意义所以,也许我们可以创建一个ImageInputStream,让ImageReader从中读取,然后创建一个新的ImageInputStream来处理流中的后续图像数据,对吗?除此之外,
ImageInputStream
似乎进行了各种缓存、预读和回写,这使得很难知道包装输入流的读取位置。下一个ImageInputStream将开始从某处读取数据,但它并不像我们预期的那样位于第一个图像数据的末尾确定底层流位置的唯一方法是使用
mark
和reset
。因为图像可能很大,所以可能需要一个BufferedInputStream
来允许一个大的readLimit
这对我很有用: