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;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.
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);
}
}
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. 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;Creating a grayscale image is very easy in Java 2D.
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);
}
}
bufferedImage = new BufferedImage(size.width, size.height,All we have to do is create a
BufferedImage.TYPE_BYTE_GRAY);
BufferedImage
class of type BufferedImage.TYPE_BYTE_GRAY
. Graphics g = bufferedImage.getGraphics();Here we draw the image of the castle into the buffered image.
g.drawImage(castle, 0, 0, null);
g.dispose();Resources are released.
Figure: Grayscale
Flipped image
Next we are going to flip an image. We are going to filter the image. There is afilter()
method, which is transforming images. ImageFlip.java
package com.zetcode;In our code example, we horizontally flip our image.
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);
}
}
AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);Flipping an image means scaling it and translating it. So we do an
tx.translate(-castle.getWidth(null), 0);
AffineTransform
operation. AffineTransformOp op = new AffineTransformOp(tx,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.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null)
AffineTransformOp
class performs scaling and translation on the image pixels. g2d.drawImage(castle, 10, 10, null);Finally, we draw both images to see the difference.
g2d.drawImage(bufferedImage, null, 290, 10);
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;Blur.
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);
}
}
try {Here we use an alternative method of loading an image in Java 2D. We use the
castle = ImageIO.read(this.getClass().getResource("redrock.png"));
} catch (IOException e) {
System.out.println("cannot read image");
}
read()
method of the ImageIO
class. This way we directly have a BufferedImage
class. float[] blurKernel = {This matrix is called a kernel. The values are weights that are applied to the neighbouring values of the pixel being changed.
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));Here we apply the blur filter to the image.
castle = blur.filter(castle, new BufferedImage(castle.getWidth(),
castle.getHeight(),castle.getType()));
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;Credit goes to jhlabs.com.
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);
}
}
g2d.setPaint(new GradientPaint(0, 0, Color.black, 0, height,The background is filled with a gradient paint. The paint is a smooth blending from black to dark gray.
Color.darkGray));
g2d.fillRect(0, 0, width, height);
g2d.translate(0, 2 * imageHeight + gap);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.
g2d.scale(1, -1);
rg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));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
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)));
GradientPaint
. Figure: Reflection
In this part of the Java2D tutorial we have worked with images.
0 comments:
Post a Comment