Java – How To Overlay One Image Over Another Using Graphics2D [Tutorial]

Image overlay is a process of laying one image over another one.You can use Java Graphics2d and easily place one image over another one.In the following tutorial, I am demonstrating how easily this can be achieved.

Here is what we will do:

  • Read the foreground image from file.
  • Read the background image from file.
  • Call the overlayImages method to place foreground image over the background image.
  • Write the overlayed image back to file.

Overlaying logic is simple.

  • First you will create a Graphics2D Object from the background image (BufferedImage)
  • In an optional step, you will set the anti aliasing render to the graphics so that you output image quality does not look bad.
  • Then you will write the background image on the graphics starting from co-ordinate (0,0).
  • Finally you will write the foreground image on the same graphics starting from co-ordinate (0,0). You can alter the co-ordinates to change the location of the overlapped image.

I am also doing some preliminary validations. In the following tutorial I am checking

  • If the height of the foreground image is greater than the background image and
  • If the width of the foreground image is greater than the background image

If one of the conditions is satisfied, I am prompting the user to enter an image of smaller dimension.

Although not a necessary step, this will insure that the overlapped forgeround image lies within the background image.

Source Code:

package com.kushal.graphics;
/**
 * @Author Kushal Paudyal
 * www.sanjaal.com/java
 * Last Modified On: 2009-11-20
 *
 * ImageOverLay.java
 *
 * Overlays one image over another image.
 */
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JOptionPane;

public class ImageOverlay {

	public static void main(String args[]) {

		/**
		 * Read a background image
		 */
		BufferedImage bgImage = readImage("C:/temp/myBGImage.jpg");

		/**
		 * Read a foreground image
		 */
		BufferedImage fgImage = readImage("C:/temp/myFGImage.jpg");

		/**
		 * Do the overlay of foreground image on background image
		 */
		BufferedImage overlayedImage = overlayImages(bgImage, fgImage);

		/**
		 * Write the overlayed image back to file
		 */
		if (overlayedImage != null){
			writeImage(overlayedImage, "C:/temp/overLayedImage.jpg", "JPG");
			System.out.println("Overlay Completed...");
		}else
			System.out.println("Problem With Overlay...");

	}

	/**
	 * Method to overlay Images
	 *
	 * @param bgImage --> The background Image
	 * @param fgImage --> The foreground Image
	 * @return --> overlayed image (fgImage over bgImage)
	 */
	public static BufferedImage overlayImages(BufferedImage bgImage,
			BufferedImage fgImage) {

		/**
		 * Doing some preliminary validations.
		 * Foreground image height cannot be greater than background image height.
		 * Foreground image width cannot be greater than background image width.
		 *
		 * returning a null value if such condition exists.
		 */
		if (fgImage.getHeight() > bgImage.getHeight()
				|| fgImage.getWidth() > fgImage.getWidth()) {
			JOptionPane.showMessageDialog(null,
					"Foreground Image Is Bigger In One or Both Dimensions"
							+ "nCannot proceed with overlay."
							+ "nn Please use smaller Image for foreground");
			return null;
		}

		/**Create a Graphics  from the background image**/
		Graphics2D g = bgImage.createGraphics();
		/**Set Antialias Rendering**/
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		/**
		 * Draw background image at location (0,0)
		 * You can change the (x,y) value as required
		 */
		g.drawImage(bgImage, 0, 0, null);

		/**
		 * Draw foreground image at location (0,0)
		 * Change (x,y) value as required.
		 */
		g.drawImage(fgImage, 0, 0, null);

		g.dispose();
		return bgImage;
	}

	/**
	 * This method reads an image from the file
	 * @param fileLocation -- > eg. "C:/testImage.jpg"
	 * @return BufferedImage of the file read
	 */
	public static BufferedImage readImage(String fileLocation) {
		BufferedImage img = null;
		try {
			img = ImageIO.read(new File(fileLocation));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return img;
	}

	/**
	 * This method writes a buffered image to a file
	 * @param img -- > BufferedImage
	 * @param fileLocation --> e.g. "C:/testImage.jpg"
	 * @param extension --> e.g. "jpg","gif","png"
	 */
	public static void writeImage(BufferedImage img, String fileLocation,
			String extension) {
		try {
			BufferedImage bi = img;
			File outputfile = new File(fileLocation);
			ImageIO.write(bi, extension, outputfile);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/*
	 * SANJAAL CORPS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
	 * THE SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
	 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
	 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SANJAAL CORPS SHALL NOT BE LIABLE FOR
	 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
	 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
	 *
	 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
	 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
	 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
	 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
	 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
	 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
	 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SANJAAL CORPS
	 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
	 * HIGH RISK ACTIVITIES.
	 */
}

Here are the images:

[Background Image]

[Foreground Image]

[Image After Overlrlay]