You are here:Home » Java 2D » Images in Java 2D

Images in Java 2D

Images in Java 2D

In this part of the Java 2D tutorial, we will work with images. Images are really a complex topic. Here we can only scratch the surface.
BufferedImage plays a crucial role when we work with images in Java 2D. It is used to manipulate with images. It is created in memory for efficiency. The process is as follows. We copy the image pixels into the BufferedImage, manipulate the pixels and draw the result on the panel.

Displaying an Image

In the first example, we simply display an image on the panel.
DisplayImage.java
package com.zetcode;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DisplayImage extends JPanel {

Image castle;
Dimension size;

public DisplayImage() {
size = new Dimension();
castle = new ImageIcon(this.getClass().getResource("redrock.png")).getImage();
size.width = castle.getWidth(null);
size.height = castle.getHeight(null);
setPreferredSize(size);
}

public void paint(Graphics g) {

Graphics2D g2d = (Graphics2D) g;

g2d.drawImage(castle, 0, 0, null);
}

public static void main(String[] args) {

JFrame frame = new JFrame("Red Rock");
frame.add(new DisplayImage());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
In our example, we show the Red Rock castle on the panel. It is a beautiful medieval castle located in the west part of Slovakia.
castle = new ImageIcon(this.getClass().getResource("redrock.png")).getImage();
We use the ImageIcon class to load the image.
g2d.drawImage(castle, 0, 0, null);
The drawImage() method draws the image on the panel at the specified position. The last parameter is the ImageObserver class. It is sometimes used for asynchronous loading. When we do not need asynchronous loading of our images, we can just put null there.
Red Rock
Figure: Red Rock

Grayscale image

In computing, a grayscale digital image is an image in which the value of each pixel is a single sample, that is, it carries the full (and only) information about its intensity. Images of this sort are composed exclusively of shades of neutral gray, varying from black at the weakest intensity to white at the strongest. (wikipedia)
In the next example, we will create a grayscale image with Java 2D tools.
GrayImage.java
package com.zetcode;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class GrayImage extends JPanel {

Image castle;
BufferedImage bufferedImage;
Dimension size;

public GrayImage() {

size = new Dimension();
castle = new ImageIcon("slanec.jpg").getImage();
size = new Dimension();
size.width = castle.getWidth(null);
size.height = castle.getHeight(null);
setPreferredSize(size);


bufferedImage = new BufferedImage(size.width, size.height,
BufferedImage.TYPE_BYTE_GRAY);

Graphics g = bufferedImage.getGraphics();
g.drawImage(castle, 0, 0, null);
g.dispose();
}

public void paint(Graphics g) {

Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(bufferedImage, null, 0, 0);
}

public static void main(String[] args) {

JFrame frame = new JFrame("Grayscale");
frame.add(new GrayImage());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Creating a grayscale image is very easy in Java 2D.
bufferedImage = new BufferedImage(size.width, size.height, 
BufferedImage.TYPE_BYTE_GRAY);
All we have to do is create a BufferedImage class of type BufferedImage.TYPE_BYTE_GRAY.
Graphics g = bufferedImage.getGraphics();
g.drawImage(castle, 0, 0, null);
Here we draw the image of the castle into the buffered image.
g.dispose();
Resources are released.
Grayscale
Figure: Grayscale

Flipped image

Next we are going to flip an image. We are going to filter the image. There is a filter()method, which is transforming images.
ImageFlip.java
package com.zetcode;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class ImageFlip extends JPanel {

Image castle;
BufferedImage bufferedImage;

public ImageFlip() {
castle = new ImageIcon("slanec.jpg").getImage();
bufferedImage = new BufferedImage(castle.getWidth(null),
castle.getHeight(null), BufferedImage.TYPE_INT_RGB);
}

public void paint(Graphics g) {

Graphics2D g2d = (Graphics2D) g;

Graphics gb = bufferedImage.getGraphics();
gb.drawImage(castle, 0, 0, null);
gb.dispose();

AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-castle.getWidth(null), 0);
AffineTransformOp op = new AffineTransformOp(tx,
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null);

g2d.drawImage(castle, 10, 10, null);
g2d.drawImage(bufferedImage, null, 290, 10);
}

public static void main(String[] args) {

JFrame frame = new JFrame("Flip image");
frame.add(new ImageFlip());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(570, 230);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
In our code example, we horizontally flip our image.
AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-castle.getWidth(null), 0);
Flipping an image means scaling it and translating it. So we do an AffineTransform operation.
AffineTransformOp op = new AffineTransformOp(tx, 
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null)
This is one of the filtering operations available. This could be also done by pixel manipulation. But Java 2D provides high level classes, that make it easier to manipulate images. In our case, the AffineTransformOp class performs scaling and translation on the image pixels.
g2d.drawImage(castle, 10, 10, null);
g2d.drawImage(bufferedImage, null, 290, 10);
Finally, we draw both images to see the difference.
Flipped image
Figure: Flipped image

Blurred image

The next code example will blur our image. Blur means an unfocused image. To blur an image, we use the convolution operation. It is a mathematical operations. It is also used in edge detection or noise elimination. Blur operations can be used in various graphical effects. For example creating speed illusion, showing an unfocused vision of a human being etc.
The blur filter operation replaces each pixel in image with an average of the pixel and its neighbours.
BlurredImage.java
package com.zetcode;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import java.io.IOException;

import javax.imageio.ImageIO;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class BlurredImage extends JPanel {

BufferedImage castle;
BufferedImage filteredImage;
Dimension size;

public BlurredImage() {

try {
castle = ImageIO.read(this.getClass().getResource("redrock.png"));
} catch (IOException e) {
System.out.println("cannot read image");
}

filteredImage = new BufferedImage(castle.getWidth(null),
castle.getHeight(null),
BufferedImage.TYPE_BYTE_GRAY);

size = new Dimension();
size.width = castle.getWidth(null);
size.height = castle.getHeight(null);
setPreferredSize(size);

Graphics g = filteredImage.getGraphics();
g.drawImage(castle, 455, 255, null);

float[] blurKernel = {
1/9f, 1/9f, 1/9f,
1/9f, 1/9f, 1/9f,
1/9f, 1/9f, 1/9f
};

BufferedImageOp blur = new ConvolveOp(new Kernel(3, 3, blurKernel));
castle = blur.filter(castle, new BufferedImage(castle.getWidth(),
castle.getHeight(),castle.getType()));
g.dispose();
}

@Override
public void paint(Graphics g) {

Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(castle, null, 3, 3);
}

public static void main(String[] args) {

JFrame frame = new JFrame("Blurred Image");
frame.add(new BlurredImage());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Blur.
try {
castle = ImageIO.read(this.getClass().getResource("redrock.png"));
} catch (IOException e) {
System.out.println("cannot read image");
}
Here we use an alternative method of loading an image in Java 2D. We use the read() method of the ImageIO class. This way we directly have a BufferedImage class.
float[] blurKernel = {
1/9f, 1/9f, 1/9f,
1/9f, 1/9f, 1/9f,
1/9f, 1/9f, 1/9f
};
This matrix is called a kernel. The values are weights that are applied to the neighbouring values of the pixel being changed.
BufferedImageOp blur = new ConvolveOp(new Kernel(3, 3, blurKernel));
castle = blur.filter(castle, new BufferedImage(castle.getWidth(),
castle.getHeight(),castle.getType()));
Here we apply the blur filter to the image.
Blurred image
Figure: Blurred image

Reflection

In the next example we show a reflected image. This beautiful effect makes an illusion as if the image was reflected in water.
Reflection.java
package com.zetcode;

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;


public class Reflection extends JComponent {

private BufferedImage image;

public Reflection() {
try {
image = ImageIO.read(new File("slanec.jpg"));
} catch (Exception e) {
e.printStackTrace();
}
}

public void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D)g;
int width = getWidth();
int height = getHeight();
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
int gap = 20;
float opacity = 0.4f;
float fadeHeight = 0.3f;

g2d.setPaint(new GradientPaint(0, 0, Color.black, 0, height,
Color.darkGray));
g2d.fillRect(0, 0, width, height);
g2d.translate((width - imageWidth) / 2, height / 2 - imageHeight);
g2d.drawRenderedImage(image, null);
g2d.translate(0, 2 * imageHeight + gap);
g2d.scale(1, -1);

BufferedImage reflection =
new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D rg = reflection.createGraphics();
rg.drawRenderedImage(image, null);
rg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
rg.setPaint(new GradientPaint(0, imageHeight * fadeHeight,
new Color(0.0f, 0.0f, 0.0f, 0.0f), 0,
imageHeight,
new Color(0.0f, 0.0f, 0.0f, opacity)));

rg.fillRect(0, 0, imageWidth, imageHeight);
rg.dispose();
g2d.drawRenderedImage(reflection, null);
}

public Dimension getPreferredSize() {
return new Dimension(320, 390);
}

public static void main(String[] args) {
JFrame frame = new JFrame("Reflection");
Reflection r = new Reflection();
frame.add(new Reflection());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Credit goes to jhlabs.com.
g2d.setPaint(new GradientPaint(0, 0, Color.black, 0, height,
Color.darkGray));
g2d.fillRect(0, 0, width, height);
The background is filled with a gradient paint. The paint is a smooth blending from black to dark gray.
g2d.translate(0, 2 * imageHeight + gap);
g2d.scale(1, -1);
This code flips the image and translates it below the original image. The translation operation is necessary, because the scaling operation makes the image upside down and translates the image up. To understand what happens, simply take a photograph and place it on the table. Now flip it.
rg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
rg.setPaint(new GradientPaint(0, imageHeight * fadeHeight,
new Color(0.0f, 0.0f, 0.0f, 0.0f), 0,
imageHeight,
new Color(0.0f, 0.0f, 0.0f, opacity)));
This is the most important part of the code. We make the second image transparent. But the transparency is not constant. The image gradually fades out. This is achieved with the GradientPaint.
Reflection
Figure: Reflection
In this part of the Java2D tutorial we have worked with images.

0 comments:

Post a Comment