Converting an int array into an image

How can a int array be converted into an Image?
Well, that depends on the format in which the image is stored inside the int array. I will assume that each pixel is stored into a single int in aRGB format (1st byte – alpha, 2nd byte – red, 3rd byte – green, 4th byte – blue), and that the array contains the pixel values row by row (meaning that first the array contains the upper most row of the image, then the 2nd row, then the 3rd etc.) If you have it stored in a different format, convert to this one first.
Here’s code that does the trick:

/**
 * Creates an Image object from the given array of pixels.
 *
 * @param pixels The pixels array.
 * @param width The width of the Image.
 * @param height The height of the Image.
 *
 * @return An Image object representing the image stored
 * in the given int array.
 */

public static Image createImage(int [] pixels, int width, int height){
  MemoryImageSource imageSource = new MemoryImageSource(width,height,pixels,
                                                        0,width);
  return Toolkit.getDefaultToolkit().createImage(imageSource);
}

How can an image be displayed as fast as possible
Well, obviously we are drawing images using one of the various Graphics.drawImage() methods, so apparently there’s nothing we can do to speed up the drawing… The tricky part here is to know that images created with an ImageProducer such as ones we’ve created in the first question (and ones you usually create with the getImage() methods) draw much slower than images created with the Component.createImage(width,height) method. So how do we obtain such a fast drawing image? Simple – let’s draw the slow drawing image on the fast drawing image once and then draw the fast drawing image on the screen every time.
Here’s code that does this:


/**
 * Creates a new offscreen Image that will contain the same
 * data as the given image. The given Image must be preloaded.
 *
 * @param img The source image.
 * @param component Any onscreen component (one that has a peer).
 *
 * @return An offscreen copy of the given image.
 */
 
public static Image toOffscreenImage(Image img, Component comp){
  int width = img.getWidth(null);
  int height = img.getHeight(null);
  Image offScreenImage = comp.createImage(width,height);
  offScreenImage.getGraphics().drawImage(img,0,0,null);
  return offScreenImage;
}

It is important that the Component you give to the above method is onscreen (has a peer), meaning it’s inside a toplevel container (Window, Frame, Dialog) whose setVisible(true) method has been called.

Changing the outline thickness of a shape in Swing

Main.java:

import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      BasicStroke bs = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                                       10, null, 0);
      g2d.setStroke(bs);
      QuadCurve2D.Float qc = new QuadCurve2D.Float(20, 50, 100, 50, 100, 170);
      g2d.draw(qc);
 
      bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                           10, null, 0);
      g2d.setStroke(bs);
      Ellipse2D.Float e = new Ellipse2D.Float(140, 50, 80, 120);
      g2d.draw(e);
 
      bs = new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                           10, null, 0);
      g2d.setStroke(bs);
      g2d.drawRect(260, 50, 80, 120);
 
      GradientPaint gp = new GradientPaint(380, 50, Color.red, 460, 170, Color.blue);
      g2d.setPaint(gp);
      bs = new BasicStroke(15, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                           10, null, 0);
      g2d.setStroke(bs);
      g2d.drawRect(380, 50, 80, 120);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(480, 200);
      main.setVisible(true);
   }
}

Drawing a strikethrough string in Swing

Use the class AttributedString as shown in following example.

Main.java:

import java.awt.event.*;
import java.awt.font.*;
import javax.swing.*;
import java.text.*;
import java.awt.*;
 
public class Main extends JFrame {
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      AttributedString as = new AttributedString("Easter Island");
      as.addAttribute(TextAttribute.FONT, new Font("Helvetica", Font.PLAIN, 36));
      as.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, 7, 13);
     
      g2d.drawString(as.getIterator(), 50, 100);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 150);
      main.setVisible(true);
   }
}

Converting a color image to a black and white one in Swing

Use the ColorConvertOp class. Its filter() method does a pixel-by-pixel color conversion of the original image.
Following example captures the screen, converts it to gray-scale and displays it in a window:

import java.awt.event.*;
import java.awt.image.*;
import java.awt.color.*;
import javax.swing.*;
import java.awt.*;
  
public class Main extends JFrame
{
   public Main() throws Exception {
      Robot robot = new Robot();
      int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
      int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
 
      // capture the whole screen
      BufferedImage image = robot.createScreenCapture(new Rectangle(0, 0, width, height));
  
      // convert to black and white
      BufferedImage bwimage = convert2bw(image);
 
      // add the image inside a JLabel component to the window
      getContentPane().add(new JLabel(new ImageIcon(bwimage)));
      pack();
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   // converts an image to a black and white one
   public BufferedImage convert2bw(BufferedImage image) {
      ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
      ColorConvertOp ccop = new ColorConvertOp(cs, null);

      return ccop.filter(image, null);
   }
  
   public static void main(String args[]) throws Exception {
      Main main = new Main();
      main.show();
   }
}

Blurring an Image in Swing

Use the class ConvolveOp and apply a blur filter.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         Kernel kernel = new Kernel(3, 3, new float[] 
                                            {  1f/9f, 1f/9f, 1f/9f,
                                               1f/9f, 1f/9f, 1f/9f,
                                               1f/9f, 1f/9f, 1f/9f });
         ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
         cOp.filter(sourceBi, destBi);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

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

Get notified when the user has moved the JSplitPane divider

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.awt.*;
 
public class Main extends JFrame
{
   JSplitPane splitPane;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      final JLabel label = new JLabel();
      splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 
                                 label, new JPanel());
      splitPane.setDividerSize(20);
      splitPane.setOneTouchExpandable(true);
 
      createMainMenuBar();
 
      getContentPane().add(splitPane);
 
      addComponentListener(new ComponentAdapter() {
         public void componentShown(ComponentEvent event) {
            splitPane.setDividerLocation(0.5);  
            label.setText("Divider location: " + splitPane.getDividerLocation());
                
            removeComponentListener(this);
         }
      });
 
      splitPane.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent pce) {
            if (pce.getPropertyName().equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) {
               label.setText("Divider location: " + splitPane.getDividerLocation());
            }
         }
      });
   }
 
   public void createMainMenuBar() {
      JMenuBar mainBar = new JMenuBar();
      JMenu menu = new JMenu("JSplitPane");
      JMenuItem item1 = new JMenuItem("HORIZONTAL_SPLIT");
      JMenuItem item2 = new JMenuItem("VERTICAL_SPLIT");
      menu.add(item1);
      menu.add(item2);
      mainBar.add(menu);
      setJMenuBar(mainBar);
 
      item1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
         }
      });
 
      item2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}

Changing the background color of the main panel in a JTabbedPane

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
 
public class Main extends JFrame implements ActionListener {
   JTabbedPane tabbedPane;
   int ntabs = 0;
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
      tabbedPane = new JTabbedPane();
      createTab();
 
      getContentPane().add(BorderLayout.CENTER, tabbedPane);
      setJMenuBar(createMenuBar());
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   
      setTitle("JTabbedPane Color Demonstration");
      setSize(new Dimension(400, 400));
   }
 
   protected JMenuBar createMenuBar() {
      JMenuBar menuBar = new JMenuBar();
 
      JMenu menu1 = new JMenu("JTabbedPane");
      JMenuItem menuItem1 = new JMenuItem("Create new tab");
      menuItem1.addActionListener(this);
      menu1.add(menuItem1);
      JMenu menu2 = new JMenu("Change orientation");
      JMenuItem menuItem2 = new JMenuItem("TOP");
      menuItem2.addActionListener(this);
      menu2.add(menuItem2);
      JMenuItem menuItem3 = new JMenuItem("BOTTOM");
      menuItem3.addActionListener(this);
      menu2.add(menuItem3);
      JMenuItem menuItem4 = new JMenuItem("LEFT");
      menuItem4.addActionListener(this);
      menu2.add(menuItem4);
      JMenuItem menuItem5 = new JMenuItem("RIGHT");
      menuItem5.addActionListener(this);
      menu2.add(menuItem5);
      menuBar.add(menu1);
      menuBar.add(menu2);
 
      return menuBar;
   }
  
   public void actionPerformed(ActionEvent e) {
      if (e.getActionCommand().equals("Create new tab")) {
         createTab();
      }
      else if (e.getActionCommand().equals("TOP")) {
         tabbedPane.setTabPlacement(JTabbedPane.TOP);
      }
      else if (e.getActionCommand().equals("BOTTOM")) {
         tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
      }
      else if (e.getActionCommand().equals("LEFT")) {
         tabbedPane.setTabPlacement(JTabbedPane.LEFT);
      }
      else if (e.getActionCommand().equals("RIGHT")) {
         tabbedPane.setTabPlacement(JTabbedPane.RIGHT);
      }
   }
 
   protected void createTab() {
      ntabs++;
      JPanel panel = new JPanel();
      panel.setBackground(new Color((float) Math.random(), 
                                    (float) Math.random(), 
                                    (float) Math.random()));
      panel.setLayout(new BorderLayout());
      panel.add(BorderLayout.SOUTH, new JLabel("Tab #" + ntabs));
      tabbedPane.addTab("Tab #" + ntabs, panel);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}