Dan*_*mes 5 java streaming networking image
我有一个ServerSocket和一个Socket设置,所以ServerSocket使用ImageIO.write(....)发送图像流,Socket尝试读取它们并用它们更新JFrame.所以我想知道ImageIO是否可以检测到图像的结束.(我完全不了解JPEG格式,所以我测试了它)
显然不是.
在服务器端,我通过循环使用ImageIO.write(...)连续发送图像,其间有一些睡眠.在客户端,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");
}
Run Code Online (Sandbox Code Playgroud)
我的客户代码:
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
}
Run Code Online (Sandbox Code Playgroud)
ImageIO.read(InputStream)创建ImageInputStream并在内部调用read(ImageInputStream)。后一种方法被记录为在读取图像完成后关闭流。
因此,理论上,您可以获取ImageReader,自己创建一个ImageInputStream,然后重复ImageReader读取ImageInputStream。
除此之外,它似乎ImageInputStream被设计用于处理一张且仅一张图像(可能包含也可能不包含多个帧)。ImageReader.read(0)如果您多次 调用,它每次都会倒回到(缓存的)流数据的开头,一遍又一遍地为您提供相同的图像。ImageReader.read(1)会在多帧图像中寻找第二帧,这对于 JPEG 来说当然没有意义。
那么,也许我们可以创建一个 ImageInputStream,让 ImageReader 从中读取,然后创建一个新的 ImageInputStream 来处理流中的后续图像数据,对吗?除此之外,它似乎ImageInputStream执行了各种缓存、预读和推回操作,这使得很难知道包装的 InputStream 的读取位置。下一个 ImageInputStream 将开始从某处读取数据,但它并不像我们期望的那样位于第一个图像数据的末尾。
确定基础流位置的唯一方法是使用mark和reset。由于图像可能很大,因此您可能需要一个BufferedInputStream允许较大的readLimit.
这对我有用:
private static final int MAX_IMAGE_SIZE = 50 * 1024 * 1024;
static void readImages(InputStream stream)
throws IOException {
stream = new BufferedInputStream(stream);
while (true) {
stream.mark(MAX_IMAGE_SIZE);
ImageInputStream imgStream =
ImageIO.createImageInputStream(stream);
Iterator<ImageReader> i =
ImageIO.getImageReaders(imgStream);
if (!i.hasNext()) {
logger.log(Level.FINE, "No ImageReaders found, exiting.");
break;
}
ImageReader reader = i.next();
reader.setInput(imgStream);
BufferedImage image = reader.read(0);
if (image == null) {
logger.log(Level.FINE, "No more images to read, exiting.");
break;
}
logger.log(Level.INFO,
"Read {0,number}\u00d7{1,number} image",
new Object[] { image.getWidth(), image.getHeight() });
long bytesRead = imgStream.getStreamPosition();
stream.reset();
stream.skip(bytesRead);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5379 次 |
| 最近记录: |