使用 ImageIO 发送图像流?

2024-04-20

我设置了一个 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");
        }

我的客户代码:

        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
        }

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 and 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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ImageIO 发送图像流? 的相关文章

随机推荐

  • if (flag==0) 和 if (0==flag) 哪一个执行得更快?

    面试问题 哪一个执行得更快 if flag 0 or if 0 flag Why 我还没有看到任何正确答案 已经有一些了 警告 纳瓦兹确实指出了用户定义的陷阱 我很遗憾我仓促地对 最愚蠢的问题 投了赞成票 因为似乎很多人都没有得到正确的答案
  • 如何查找当前选定 DOM 对象的所有兄弟姐妹

    在 JavaScript 中查找所有 nextSiblings 和 previousSiblings 的完美方法是什么 我尝试了几种方法但没有得到准确的解决方案 如果选择任何元素 我需要获取所有下一个同级元素的长度 不包括空格 任何空格或换
  • CKContainer accountStatusWithCompletionHandler 返回错误值

    accountStatusWithCompletionHandler方法返回 NoAccount价值 知道为什么返回值不是 Available 我已登录 iCloud 并连接到互联网 医生说 NoAccount means 用户的 iClo
  • 有没有办法像“举手发言”功能一样监控用户的 iPhone 移动情况?

    我想在用户将 iPhone 举到脸上时收到通知 就像 Siri 一样 是否可以 添加更具体的要求 当用户将手机放在耳朵附近时 我想使屏幕变暗 我知道可以启用接近传感器来实现这一点 但令人烦恼的是 当用户在传感器上移动手指时 屏幕会时不时变暗
  • 为什么有些对象属性是 UnaryExpression,而另一些对象属性是 MemberExpression?

    根据我的答案采取行动使用 lambda 而不是字符串属性名称选择模型属性 https stackoverflow com questions 3558974 select a model property using a lambda an
  • 删除记录时找不到元素

    JqG rid 4 6 一切正常 唯一的问题是 当我打开 Firefox 调试器并转到控制台时 如果我删除一条记录 单击垃圾桶图标 然后弹出删除对话框 单击删除按钮并刷新页面等 调试器会警告我 没有找到元素 可能的脚本是 gridSelec
  • Python 中 Comet 的最新推荐? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 对 numpy 屏蔽数组的操作给出屏蔽的无效值

    来自 numpy 中屏蔽数组的文档numpy 数组上的操作 https docs scipy org doc numpy reference maskedarray generic html operations on masked arr
  • Java 中的内存管理

    如何在Java中手动删除对象 有没有类似的方法obj delete or obj kill 没有真正的办法 Java有一个特殊的垃圾收集器这会为你做到这一点 一旦您的对象没有任何对它的引用 它就会在某个时候被垃圾收集器拾取并销毁 From
  • 带有多个 webapp 的 tomcat ajp 连接器

    我有一个 tomcat 服务器 带有 webapps ROOT 应用程序 以 Apache 为前端 LoadModule proxy ajp module modules mod proxy ajp so and ProxyPass ajp
  • 如何在 Swift 中返回序列?

    我正在尝试编写一个扩展Matrix书中的例子 稍微调整为通用的 https stackoverflow com q 24136604 458193 我正在尝试编写一个名为的方法getRow返回给定行的值序列 在 C 中 我会这样写 IEnu
  • 迭代 JSON 数据? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有一个如下所示的 JSON 数据
  • 数据源中 String 类型的给定值无法转换为指定目标列的 bigint 类型

    这是我的代码 protected void SendToServer Click object sender EventArgs e DataTable Values Session valuesdt as DataTable if Val
  • 必须在创建 QCoreApplication 之前设置属性 Qt::AA_UseSoftwareOpenGL

    所以我的环境是 Windows 10 截至 2019 年 11 月 8 日更新 通过 miniconda 安装了 Python 3 6 Spyder 4 运行 miniconda shell 激活虚拟环境 运行 Spyder 我得到以下信息
  • .PO 到 .MO - 程序转换 (PHP)

    我计划允许用户通过 PHP 用户界面生成 POT 文件 PO 文件 作为 CMS 解决方案的一部分 一旦生成这些文件 简单一点 我希望允许我的系统自动将这些文件转换为 MO 文件以响应用户 POST 请求 我在SO上看到了以下问题 php
  • InvalidArgumentError:ConcatOp:输入的维度应该匹配

    Tensorflow 1 7使用dynamic rnn时 一开始运行良好 但在第32步 当我运行代码时它发生变化 时 出现错误 当我使用较小的批次时 代码似乎可以运行更长时间 但是错误仍然弹出 只是无法弄清楚出了什么问题 from mapp
  • 一个带有一个等号的 php if 语句...?这是什么意思?

    我正在尝试解决问题 并且需要理解这个 if 语句的含义 if confirmation payment modules gt confirmation 我能找到的所有资源只显示带有双等号的 if 语句 而不是单等号 这是 php if 的简
  • 错误:没有运算符 << 与这些操作数匹配?

    我正在练习一些 C 试图离开 Java 我偶然发现了这个恼人的错误 错误 没有操作符 这个错误在我的 cpp 文件中 还有其他错误 但我现在不关心它们 void NamedStorm displayOutput NamedStorm sto
  • 是否可以在 Android Wear 上显示 Google 地图视图?

    是否可以在 Android Wear 上显示 Google 地图视图 我想在地图上向用户显示特定位置 您可以设法在您的 Activity 中嵌入 MapView 但是这是行不通的因为 Android Wear 无法直接访问网络 然而 你能做
  • 使用 ImageIO 发送图像流?

    我设置了一个 ServerSocket 和一个 Socket 因此 ServerSocket 使用 ImageIO write 发送图像流 并且 Socket 尝试读取它们并用它们更新 JFrame 所以我想知道 ImageIO 是否可以检