Reading a specific region of an image file with the ImageIO APIs

With the class ImageReadParam, you have control over the decoding of the image and the region. Specify the region with a Rectangle instance and pass this to the ImageReadParam instance with setSourceRegion. Then, when you execute BufferedImage bi = reader.read(imageindex, param), the resulting BufferedImage will only contain that region. (imageindex specifies the number of the image in the image file, possible in some image formats).

It is especially useful for handling large images.

In the following example, a large image is selected as the ImageInputStream. Every 10ms, a region as small as the size of the JFrame is read, and only that region. At every step, a new window region is selected; it moves about horizontally and vertically.

Main.java:

import javax.imageio.stream.*;
import javax.swing.event.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.imageio.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.io.*;
  
public class Main extends JFrame implements Runnable
{
   BufferedImage background;
   ImageReader reader;
   ImageReadParam param;
   int imageWidth, imageHeight;
   int currentx, currenty, dx, dy;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      setResizable(false);
   }
   
   public void initImageReading() throws Exception {
      Iterator readers = ImageIO.getImageReadersByFormatName("jpg");
      reader = (ImageReader)readers.next();
 
      ImageInputStream iis = ImageIO.createImageInputStream(new File("autumn16.jpg"));
      reader.setInput(iis, true);
      param = reader.getDefaultReadParam();
 
      imageWidth = reader.getWidth(0);
      imageHeight = reader.getHeight(0);
 
      Rectangle rect = new Rectangle(0, 0, getWidth(), getHeight()); 
      param.setSourceRegion(rect);
 
      currentx = imageWidth/2;
      currenty = imageHeight/2;
      background = reader.read(0, param);
 
      dx = getWidth() / 2;
      dy = getHeight() / 2;
   }
 
   public void run() {
      while (true) {
         try {
            Thread.sleep(10);
         }
         catch(InterruptedException e) { }
 
         if (currentx+dx > imageWidth-getWidth() || currentx+dx <= 0) {
            dx *= -1;
            currenty += dy;
            if (currenty+dy > imageHeight-getHeight() || currenty+dy <= 0) {
               dy *= -1;
            }
            currenty += dy;
         }
         currentx += dx;
 
         Rectangle rect = new Rectangle(currentx, currenty, getWidth(), getHeight()); 
         param.setSourceRegion(rect);
 
         try {
            background = reader.read(0, param);
         }
         catch(IOException e) {
            e.printStackTrace();
         }
 
         repaint();
      }
   }
  
   public void paint(Graphics g) {
      if (background != null)
         g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
   }
 
   public static void main(String []args) throws Exception {
      Main main = new Main();
      main.setSize(100, 100);
      main.setVisible(true);
 
      main.initImageReading();
      new Thread(main).start();
   }
}