Reputation: 3
I am currently in the middle of a project in which I have to grayscale, blue filter, red filter, green filter, and fade the edges of a picture of a cat at the press of a JButton. grayscale and color filtering the picture was easy, but I can't seem to figure out how to fade the image's edges to black.
What I mean by this, is I have this picture of the cat I need to change:
and I need to change it into something like this one:
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class GUIKittenPicJC {
public static class KittenChanger extends JPanel {
BufferedImage img = null;
File Kitten = null;
ImageIcon imagetransformed = null;
JButton grayscale = new JButton("Grayscale Image");
JButton rgbB = new JButton("Blue filter this image");
JButton rgbR = new JButton("Red filter this image");
JButton rgbG = new JButton("Green filter this image");
JButton fader = new JButton("Fade this image");
{
try
{
Kitten = new File("C:\\Users\\Jarrod\\Desktop\\Lab 3\\Lab 3\\kitten.bmp");
img = ImageIO.read(Kitten);
}
catch(IOException e)
{
System.out.println(e);
}
ImageIcon image = new ImageIcon(img);
JLabel imageLabel = new JLabel(image);
add(imageLabel);
grayscale.addActionListener(e->{
imagetransformed = new ImageIcon(Grayscale(img));
imageLabel.setIcon(imagetransformed);
imgReset();
});
rgbB.addActionListener(e->{
imagetransformed = new ImageIcon(Bluify(img));
imageLabel.setIcon(imagetransformed);
imgReset();
});
rgbG.addActionListener(e->{
imagetransformed = new ImageIcon(Greenify(img));
imageLabel.setIcon(imagetransformed);
imgReset();
});
rgbR.addActionListener(e->{
imagetransformed = new ImageIcon(Redify(img));
imageLabel.setIcon(imagetransformed);
imgReset();
});
add(grayscale);
add(rgbB);
add(rgbG);
add(rgbR);
}
private void imgReset() {
try {
img = ImageIO.read(Kitten);
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
}
public static void main(String[] args)
{
createGUI();
}
private static void createGUI() {
JFrame frame = new JFrame("Kitten Changer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
KittenChanger newContentPane = new KittenChanger();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.setSize(400, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//Grayscale and rgb filter methods follow, not important to question
}
How would I create a method for this sort of filter and properly apply it to a button like the others?
Upvotes: 0
Views: 327
Reputation: 473
You would have to edit each of the pixels individually. The main idea of this solution is that you have the center of an image, and each pixel is changed as a function of the distance to the center.
More simply put, pixels farther from the center will be made darker.
This is what your code would look like:
BufferedImage cat; //assuming it is assigned
for(int i = 0; i < cat.getWidth(); i++) { // i is the x coord
for(int j = 0; j < cat.getHeight(); j++) { // j is the y coord
int color = cat.getRGB(i, j);
int r = (color >> 16) & 0xff; //extract red value
int g = (color >> 8) & 0xff;
int b = color & 0xff;
double scale = 0.75; /**** Change this to change the resulting effect ****/
//pixel's distance from center
double dist = Math.sqrt( Math.pow(i - cat.getWidth()/2, 2) + Math.pow(j - cat.getHeight()/2, 2) );
r = (int) Math.max(0, r - dist*scale); //r - dist*scale makes px darker
g = (int) Math.max(0, g - dist*scale); //Math.max makes sure r is always >= 0
b = (int) Math.max(0, b - dist*scale);
int newRGB = (r << 16) + (g << 8) + b; //convert r,g,b to single int
cat.setRGB(i, j, newRGB); //finally, update rgb value
}
}
Remember, you can always change the effect by changing the scale
variable in the code above.
Upvotes: 1