Java有没有什么方法可以不用传输不用下载就可以获取图片的宽高?

Is there any way in Java to take image width and height without transfer or download?

为了得到图片的高度我们可以使用ImageIO.read(new URL("…")).getHeight().

我的问题:

  1. 我的理解是否正确,此方法会先将图像下载到本地计算机,然后再计算大小?
  2. 如果是,图像下载到的确切位置——HDD 上的某些 JVM 缓存或直接到 RAM?
  3. 有没有什么办法可以不传不下载就可以测高的?但是对服务器有某种请求?

答案是 read() 方法必须完成并且 return 可以调用 getHeight() 方法之前的值。

这甚至不是 ImageIO 问题,它只是基本的 Java 语法和语义。

首先,您的问题:

  1. 有点。首先,ImageIO.read(...) 方法是使用所有默认参数解码文件中的 first 图像的便捷方法。由于所有 ImageIO.read(...) 操作都委托给特定插件或 ImageReader 实例(如 JPEGImageReader),因此此 可能 是特定于插件的。但一般情况下,图像数据被传输和解码"on the fly"。请注意,这里没有 "size calculation",而是 整个图像 在这种情况下被解码为 BufferedImage。必须传输,但不一定存储在计算机上的任何地方,必须传输解码文件中的第一个图像所需的数据,除了解码后的像素值。

  2. 视情况而定。有一个设置 ImageIO.setUseCache(boolean),它控制数据是缓存在磁盘上还是缓存在 RAM 中。

    • 如果设置为 true,数据将临时存储在磁盘上,通常在默认的临时目录中(参见 java.io.tempdir 系统 属性)。
    • 如果设置为 false,则在解码图像时将数据临时存储在内存中。
  3. 不,除非你的服务器有一个特殊的 API 来给你这个数据,并且你针对这个 API 执行特定的请求。但是,ImageIO API 确实有很多更精细的方法,可以让您更快地获得图像尺寸,而无需 downloading/decoding 整个图像。

获取图像尺寸的更快方法是:

try (InputStream stream = url.openStream()) {
    // The "useCache" setting will decide whether "input" below 
    // will be disk or memory cached
    try (ImageInputStream input = ImageIO.createImageInputStream(stream)) {
         ImageReader reader = ImageIO.getImageReaders(input).next(); // TODO: Handle no reader
         try {
             reader.setInput(input);

             // Get dimensions of first image in the stream, without decoding pixel values
             int width = reader.getWidth(0);
             int height = reader.getHeight(0);
         }
         finally {
             reader.dispose();
         }
    }
 }

同样,根据图像格式,上述代码应仅读取确定图像尺寸所需的 header/meta 数据。大多数 ImageReader 实现将为此读取所有 header 数据,但与解码整个图像相比,它仍然更快并且涉及的数据(和内存)少得多。

很难对下载或需要下载多少数据做出任何假设,因为不同的格式有不同大小的 header,底层传输(即 HTTP)可能以 "chunks"等