Copyright Derek O'Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.
ConvolveOp applies a filter to a BufferedImages, to give various efects, as seen in the example below.
Using a ConvolveOp is similar the various other BufferedImageOp classes. In all cases, we can apply a filter to a source to generate a destination. The other BufferedImageOp classes are explained in further detail in these other sections of the notes (AffineTransformOp, ColorConvertOp, LookupOp & RescaleOp).
ConvolveDemo Example (Run Applet)
import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; public class ConvolveDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel implements ItemListener { private final float noConvolveMatrix[] = { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }; private final float sharpenMatrix[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f, -1.0f }; // adds up to 1 private final float blurMatrix[] = { 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f }; // each element is 1/9 private final float edgeDetectMatrix[] = { -0.5f, -0.5f, -0.5f, -0.5f, 4.0f, -0.5f, -0.5f, -0.5f, -0.5f }; // adds up to 0 private final float lightMatrix[] = { 0.1f, 0.1f, 0.1f, 0.1f, 1.0f, 0.1f, 0.1f, 0.1f, 0.1f }; // adds to greater than 0 private final float darkMatrix[] = { 0.01f, 0.01f, 0.01f, 0.01f, 0.5f, 0.01f, 0.01f, 0.01f, 0.01f }; // adds to less than 0 private final float convolveMatrices[][] = { this.noConvolveMatrix, this.sharpenMatrix, this.blurMatrix, this.edgeDetectMatrix, this.lightMatrix, this.darkMatrix }; private final String convolveNames[] = { "Normal", "Sharpen", "Blur", "Edge Detection", "Lighten", "Darken" }; private final JComboBox convolveList = new JComboBox(convolveNames); private final Image image = new ImageIcon(getClass().getClassLoader().getResource("images/koala.jpg")).getImage(); private float convolveMatrix[] = this.noConvolveMatrix; // initialise to have no convolution public View() { super(); this.add(this.convolveList); this.convolveList.addItemListener(this); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // place the original file image into a buffered image final BufferedImage srcBufferedImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); final Graphics2D SrcG = srcBufferedImg.createGraphics(); SrcG.drawImage(this.image, 0, 0, getWidth(), getHeight(), this); // Do the convolution Kernel kernel = new Kernel(3, 3, this.convolveMatrix); final ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); final BufferedImage destBufferedImg = convolve.filter(srcBufferedImg, null); // draw the destination buffered image onto the applet's panel g.drawImage(destBufferedImg, 0, 0, getWidth(), getHeight(), this); } @Override public void itemStateChanged(ItemEvent e) { this.convolveMatrix = this.convolveMatrices[this.convolveList.getSelectedIndex()]; this.repaint(); } } }
We can use the ConvolveOp to blur a mirrored image, to make it more realistic. This is shown in the example below.
Convolve_MirrorImage_Demo Example (Run Applet)
import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import javax.swing.*; public class Convolve_MirrorImage_Demo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { private final int blurFactor = 20; // change this value to adjust the amout of bluring private final float blurMatrix[] = { 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f }; private final Image image = new ImageIcon(getClass().getClassLoader().getResource("images/koala.jpg")).getImage(); public View() { super(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); // place the original file image into buffered image final BufferedImage srcBufferedImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D SrcG = srcBufferedImg.createGraphics(); SrcG.drawImage(this.image, 0, 0, getWidth(), getHeight(), this); final AffineTransform affineTransform = new AffineTransform(); affineTransform.translate(0, getHeight()); // need to translate because we are scaling y by a factor of -1 affineTransform.scale(1.0, -1.0); final AffineTransformOp affineTransformOp = new AffineTransformOp(affineTransform, null); BufferedImage invertedBufferedImg = affineTransformOp.filter(srcBufferedImg, null); // blur the reflected image final Kernel kernel = new Kernel(3, 3, this.blurMatrix); final ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); for (int i = 0; i < this.blurFactor; i++) { invertedBufferedImg = convolve.filter(invertedBufferedImg, null); } // draw the original image and the inverted image g.drawImage(this.image, 0, 0, getWidth(), getHeight() / 2, this); g.drawImage(invertedBufferedImg, 0, getHeight() / 2, getWidth(), getHeight() / 2, this); } } }
We can use the ConvolveOp to blur a mirrored image and a linear gradient to fade the image, to make it even more realistic. This is shown in the example below.
Convolve_MirrorImageWithFade_Demo Example (Run Applet)
import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import javax.swing.*; public class Convolve_MirrorImageWithFade_Demo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { private final int blurFactor = 20; // change this value to adjust the amout of bluring private final float blurMatrix[] = { 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f }; private final Image image = new ImageIcon(getClass().getClassLoader().getResource("images/koala.jpg")).getImage(); public View() { super(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); final Graphics2D g2 = (Graphics2D)g; // place the original file image into a buffered image final BufferedImage originalBufferedImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D originalBufferedG = originalBufferedImg.createGraphics(); originalBufferedG.drawImage(this.image, 0, 0, getWidth(), getHeight(), this); // copy and invert the original image to make invertedBufferedImg final AffineTransform affineTransform = new AffineTransform(); affineTransform.translate(0, getHeight()); // need to translate because we are scaling y by a factor of -1 affineTransform.scale(1.0, -1.0); final AffineTransformOp affineTransformOp = new AffineTransformOp(affineTransform, null); BufferedImage invertedBufferedImg = affineTransformOp.filter(originalBufferedImg, null); // blur invertedBufferedImg final Kernel kernel = new Kernel(3, 3, this.blurMatrix); final ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); for (int i = 0; i < this.blurFactor; i++) { invertedBufferedImg = convolve.filter(invertedBufferedImg, null); } // fade the inverted, blurred image final BufferedImage fadedBufferedImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D fadedG = fadedBufferedImg.createGraphics(); final GradientPaint gradient = new GradientPaint(0, 0, new Color(255, 255, 255, 255), 0, getHeight(), new Color(255, 255, 255, 0)); fadedG.setPaint(gradient); fadedG.fillRect(0, 0, getWidth(), getHeight()); fadedG.setComposite(AlphaComposite.SrcIn); fadedG.drawImage(invertedBufferedImg, 0, 0, getWidth(), getHeight(), this); // draw the original image and the fadedImage onto the applet's surface g2.drawImage(this.image, 0, 0, getWidth(), getHeight() / 2, this); g.drawImage(fadedBufferedImg, 0, getHeight() / 2, getWidth(), getHeight() / 2, this); } } }
We can use the ConvolveOp to blur a shadow. This is shown in the example below.
Convolve_BlurredDropShadow_Demo Example (Run Applet)
import java.awt.*; import java.awt.image.*; import javax.swing.*; public class Convolve_BlurredDropShadow_Demo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { private final Image image = new ImageIcon(getClass().getClassLoader().getResource("images/koala.jpg")).getImage(); private final Color shadowColour = Color.black; private final Color backgroundColour = Color.white; private final int shadowOffset = 15; private final int blurFactor = 40; // the number of times the blur is called. High value is more blurred private final int blurFade = 10; // the width of background used in the blur. High value is smoother private final int margin = 5; // put a border around the image to show up the drop shadow better private final float blurMatrix[] = { 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f }; public View() { super(); // put a border around the image to show up the drop shadow better this.setBorder(BorderFactory.createLineBorder(this.backgroundColour, this.margin)); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); final BufferedImage dropShadowBufferedImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D dropShadowG = dropShadowBufferedImg.createGraphics(); // make the drop shadow dropShadowG.setColor(Color.yellow); dropShadowG.drawImage(this.image, 0, 0, getWidth(), getHeight(), this); dropShadowG.setComposite(AlphaComposite.SrcIn); dropShadowG.setColor(this.shadowColour); dropShadowG.fillRect(0, 0, getWidth(), getHeight()); BufferedImage blurredBufferedImg = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D blurredBufferedG = blurredBufferedImg.createGraphics(); // blur the shadow into white blurredBufferedG.setColor(this.backgroundColour); blurredBufferedG.fillRect(0, 0, getWidth(), getHeight()); blurredBufferedG.drawImage(dropShadowBufferedImg, this.shadowOffset, this.shadowOffset, getWidth() - this.shadowOffset - this.blurFade, // this.blurFade is needed so that the blur will getHeight() - this.shadowOffset - this.blurFade, // have some background colour to blur into this); // the larger the value, the smoother the shadow final Kernel kernel = new Kernel(3, 3, this.blurMatrix); final ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); for (int i = 0; i < this.blurFactor; i++) { blurredBufferedImg = convolve.filter(blurredBufferedImg, null); } // draw the blurred drop shadow and then draw the image over it g.drawImage(blurredBufferedImg, 0, 0, getWidth(), getHeight(), this); g.drawImage(this.image, 0, 0, getWidth() - this.shadowOffset, getHeight() - this.shadowOffset, this); } } }
Copyright Derek O' Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.