javajava-8bufferedimagejavax.imageio

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


In order to get image's height we can use ImageIO.read(new URL("…")).getHeight().

My questions:

  1. Do I understand correctly that this method downloads the image to the local computer prior size calculation?

  2. If yes, to where exactly the image is downloaded — to some JVM's cache on HDD or directly to the RAM?

  3. Is there any way to take image's height without transfer or download? But with some kind of request to server?


Solution

  • First, your questions:

    1. Kind of. First of all, the ImageIO.read(...) methods, are convenience methods that will decode the first image in a file, using all default parameters for decoding. As all ImageIO.read(...) operations are delegated to format specific plugins or ImageReader instances (like JPEGImageReader), this may be plugin specific. But the general case, is that the image data is transferred and decoded "on the fly". Note that there's no "size calculation" here, rather the entire image is decoded to a BufferedImage in this case. As much data as is needed to decode the first image in the file has to be transferred, but not necessarily stored anywhere on the computer, other than the decoded pixel values.

    2. It depends. There's a setting ImageIO.setUseCache(boolean), that controls whether the data is cached on disk or in RAM.

    1. No, not unless your server has a special API to give you this data, and you perform specific requests against this API. However, the ImageIO API does have a lot more granular methods that allows you to get the image dimensions a lot faster, and without downloading/decoding the entire image up front.

    The faster way of obtaining the image dimensions is:

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

    Again, depending on image format, the above code should only read as much of the header/meta data as is needed to determine the image dimensions. Most ImageReader implementations will read all header data for this, but still, it's much faster and involves a lot less data (and memory) than decoding the entire image.

    It's hard to make any assumptions as to how much data is or needs to be downloaded, because different formats have headers of varying size, the underlying transport (ie. HTTP) may transfer data in "chunks" etc.