How to Fade an Image in Swing

How do I fade an image in swing?

You can do the threading yourself, but it might be easier to use the Trident library to handle it. If you create a setter on your class called (say, setOpacity), you can ask trident to interpolate the "opacity" field from 1.0 to 0.0 over a specific period of time (here's some of the docs on how to use Trident).

When you're painting the image, you can do the transparency with an AlphaComposite, using the updated "opacity" value for the composite's alpha parameter. There is a Sun tutorial that includes an alpha composite example.

Java fade in and out of images

Basically, what this does is use the same alpha value, fading in from 0-1 and then using the same alpha, going from 1-0, allowing the two images to cross fade over each other...

Fading

The magic basically, happens in the paintComponent, where the image coming in using the alpha value and the outgoing image uses 1f - alpha.

Switching between the two images is actually a the same process, expect the inImage is swapped for the outImage

The timing is little different. Instead of a straight move from 0-1 using a standard delta (ie 0.01 for example), this uses a time based algorithm.

That is, I use a timer which ticks every 40 milliseconds or so, it then does a calculation based on the amount of time the timer has being running and calculates the alpha value accordingly...

This allows you to change the amount of time the animation will take, but also provides a slightly better algorithm that takes into account the passive nature of Swings rendering engine...

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FadeImage {

public static void main(String[] args) {
new FadeImage();
}

public FadeImage() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public static class TestPane extends JPanel {

public static final long RUNNING_TIME = 2000;

private BufferedImage inImage;
private BufferedImage outImage;

private float alpha = 0f;
private long startTime = -1;

public TestPane() {
try {
inImage = ImageIO.read(new File("/path/to/inImage"));
outImage = ImageIO.read(new File("/path/to/outImage"));
} catch (IOException exp) {
exp.printStackTrace();
}

final Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (startTime < 0) {
startTime = System.currentTimeMillis();
} else {

long time = System.currentTimeMillis();
long duration = time - startTime;
if (duration >= RUNNING_TIME) {
startTime = -1;
((Timer) e.getSource()).stop();
alpha = 0f;
} else {
alpha = 1f - ((float) duration / (float) RUNNING_TIME);
}
repaint();
}
}
});
addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
alpha = 0f;
BufferedImage tmp = inImage;
inImage = outImage;
outImage = tmp;
timer.start();
}

});
}

@Override
public Dimension getPreferredSize() {
return new Dimension(
Math.max(inImage.getWidth(), outImage.getWidth()),
Math.max(inImage.getHeight(), outImage.getHeight()));
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
int x = (getWidth() - inImage.getWidth()) / 2;
int y = (getHeight() - inImage.getHeight()) / 2;
g2d.drawImage(inImage, x, y, this);

g2d.setComposite(AlphaComposite.SrcOver.derive(1f - alpha));
x = (getWidth() - outImage.getWidth()) / 2;
y = (getHeight() - outImage.getHeight()) / 2;
g2d.drawImage(outImage, x, y, this);
g2d.dispose();
}

}

}

How do I fade out one image and fade in another (Java)?

You can use Trident to interpolate a property you define in your class. Then during painting you can use this property as alpha in AlphaComposite. Here you can find some examples for AlphaComposite.

EDIT:
May be this can help you:

//define a property to animate
float opacity;

//define timeline for animation
Timeline timeline = new Timeline(this);
timeline.addPropertyToInterpolate("opacity", 1.0f, 0.0f);
timeline.play();

//inside painting
...
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(this.opacity));
g2d.drawImage(img1...);

g2d.setComposite(AlphaComposite.SrcOver.derive(1.0 - this.opacity));
g2d.drawImage(img1...);

g2d.dispose();
...

How do I fade the edges of an image in Java? (example given)

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
}

}


And, when I ran this code:

Sample Image

Remember, you can always change the effect by changing the scale variable in the code above.

How to add Transitions (Fade, dissolve etc ) in Java GUI

You should use a CardLayout to swap views (JPanels) in your GUI. To get a fade effect is not the most simple thing to do, but it can be done with a little work. I've done it successfully here where I create a special class called SwappingImgPanel that extends JPanel, and that fades one image into another using a Swing Timer. Specifically, the program does this:

  • The program adds all the swapping components to the CardLayout using JPanel.
  • It also adds a single SwappingImgPanel, a JPanel created to draw two images, one of the component that is fading out, and one of the component that is fading in.
  • When you swap components, you create images of the two components, the one currently visible, and the one that will next be visible.
  • You send the images to the SwappingImgPanel instance
  • You call swap() on the SwappingImgPanel instance.
  • The SwappingImgPanel will then draw both images but uses a Swing Timer to change the Graphic object's composite value. This is what causes an image to be partially visible.
  • When the SwappingImgPanel's Timer is done, a done() method is called which sets the SwappingImgPanel's State to State.DONE.
  • The main GUI is listening to the SwappingImgPanel's state value, and when it achieves State.DONE, the main GUI shows the actual next component (and not an image of it).


Related Topics



Leave a reply



Submit