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.