How do I load an enormous image to Java via BufferedImage?

时光怂恿深爱的人放手 提交于 2019-12-04 05:26:35

You can read and display fragments of the image using ImageReadParam from ImageIO package. Here is a basic example that illustrates how to read a single fragment using ImageReadParam without reading the whole image:

import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;

public class TestImageChunks {
    private static void createAndShowUI() {
        try {
            URL url = new URL(
                    "http://duke.kenai.com/wave/.Midsize/Wave.png.png");
            Image chunk = readFragment(url.openStream(), new Rectangle(150,
                    150, 300, 250));
            JOptionPane.showMessageDialog(null, new ImageIcon(chunk), "Duke", 
                    JOptionPane.INFORMATION_MESSAGE);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
                    JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }

    public static BufferedImage readFragment(InputStream stream, Rectangle rect)
            throws IOException {
        ImageInputStream imageStream = ImageIO.createImageInputStream(stream);
        ImageReader reader = ImageIO.getImageReaders(imageStream).next();
        ImageReadParam param = reader.getDefaultReadParam();

        param.setSourceRegion(rect);
        reader.setInput(imageStream, true, true);
        BufferedImage image = reader.read(0, param);

        reader.dispose();
        imageStream.close();

        return image;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

The result looks like this:

Generally, you'd need to do something like this:

  • Break the image into manageable size image files and store them on disk with your application.
  • When displaying a particular part of this image, only the load and display image fragments that overlap your viewport.
  • As you pan around the image, update the loaded and displayed image fragments appropriately.
  • Either let the unnecessary image fragments get collected by the GC or load new ones in such a way that they overwrite older ones. (This last argues for identically-sized image fragments that load into pooled memory buffers.)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!