Image Capture in BufferedImage - java

I am new here and also quite new to Java.
I am making an app where one can select an area of image and it simply returns the selected coordinates. The problem is that, instead of displaying the image, it displays a black area instead of the image.
Also tried with BufferedImage.TYPE_INT_ARGB and now it shows a blank area.
Here is the code. Please help.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ScreenCaptureRectangle {
Rectangle captureRect;
ScreenCaptureRectangle(final Image im) {
final BufferedImage screenCopy = new BufferedImage(
im.getWidth(null),
im.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
final BufferedImage screenCopy1 = new BufferedImage(
im.getWidth(null),
im.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int)(im.getWidth(null)),
(int)(im.getHeight(null))));
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
final JLabel selectionLabel = new JLabel(
"Drag a rectangle in the screen shot!");
panel.add(selectionLabel, BorderLayout.SOUTH);
repaint(screenCopy1, screenCopy);
screenLabel.repaint();
screenLabel.addMouseMotionListener(new MouseMotionAdapter() {
Point start = new Point();
#Override
public void mouseMoved(MouseEvent me) {
start = me.getPoint();
repaint(screenCopy1, screenCopy);
selectionLabel.setText("Start Point: " + start);
screenLabel.repaint();
}
#Override
public void mouseDragged(MouseEvent me) {
Point end = me.getPoint();
captureRect = new Rectangle(start,
new Dimension(end.x-start.x, end.y-start.y));
repaint(screenCopy1, screenCopy);
screenLabel.repaint();
selectionLabel.setText("Rectangle: " + captureRect);
}
});
JOptionPane.showMessageDialog(null, panel);
System.out.println("Rectangle of interest: " + captureRect);
}
public void repaint(BufferedImage orig, BufferedImage copy) {
Graphics2D g = copy.createGraphics();
g.drawImage(orig,0,0, null);
if (captureRect!=null) {
g.setColor(Color.RED);
g.draw(captureRect);
g.setColor(new Color(255,255,255,150));
g.fill(captureRect);
}
g.dispose();
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new ScreenCaptureRectangle(ImageIO.read(new File("Desert.jpg")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}

Your problem is that you never paint the original image (im, read from "Desert.jpg") into any of your screenCopy or screenCopy1 images, you only create empty BufferedImages of the same size. These "copies" will always stay blank.

Related

Displaying image over image Java

How do I display an image over another image on either applet or jframe?
I know for one image in applet is this:
Image Bendy;
Bendy = getImage(getDocumentBase(), "Bendy Icon.PNG");
g.drawImage(Bendy, 20, 20, this);
And for jframe:
ImageIcon kh = new ImageIcon("KH3.gif");
JLabel lab = new JLabel(kh);
add(lab);
So how do I add an image over the other for either one?
As mentioned in comments, (Java) Applets are indeed dead and not worth pursuing. The ImagePanel in this answer extends JPanel and could theoretically be displayed in any Java Swing based top-level container (e.g. JFrame, JWindow, JOptionPane..) or in another container like a JPanel.
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.Random;
import javax.imageio.ImageIO;
import java.net.URL;
public class StackedImages {
private JComponent ui = null;
String path1 = "https://i.stack.imgur.com/F0JHK.png";
String path2 = "https://i.stack.imgur.com/gJmeJ.png";
class ImagePanel extends JPanel {
private final BufferedImage[] images;
private final Random rand = new Random();
private final Dimension prefeSize = new Dimension(400, 400);
ImagePanel(BufferedImage[] images) {
this.images = images;
setBackground(Color.WHITE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int ii = 0; ii < 200; ii++) {
int x = rand.nextInt(prefeSize.width);
int y = rand.nextInt(prefeSize.height);
int ind = rand.nextInt(images.length);
g.drawImage(images[ind], x, y, this);
}
}
#Override
public Dimension getPreferredSize() {
return prefeSize;
}
}
StackedImages() {
try {
initUI();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public final void initUI() throws Exception {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
BufferedImage[] bi = new BufferedImage[2];
bi[0] = ImageIO.read(new URL(path1));
bi[1] = ImageIO.read(new URL(path2));
ui.add(new ImagePanel(bi));
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
StackedImages o = new StackedImages();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
As said by people in comments, Applets are dead, you don't actually need them to learn GUI programs.
But still, if you want there are some ways you can do so, like using drawImage() method. Maybe something like this:
try
{
BufferedImage background = ImageIO.read(new File("..."));
BufferedImage logo = ImageIO.read(new File("..."));
Graphics g = background.getGraphics();
g.drawImage(logo, 0, 0, null);
}
catch (Exception e)
{
e.printStackTrace();
}

Why is the rectangle not showing?

I checked this code for hours, but the rectangle is not showing, can anyone tell me why it is not showing?:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
int resx = 700,resy = 500;
frame.setSize(resx,resy);
frame.setLocationRelativeTo(null);
frame.setTitle("Game");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
try {
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\ivans\\Pictures\\Cookies.png")))));
} catch (IOException e) {
}
frame.repaint();
frame.setLayout(new FlowLayout());
frame.add(new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(50,50,450,650);
}
}, BorderLayout.CENTER);
frame.repaint();
frame.setVisible(true);
}
}
Every time I try to activate the background, the rectangle is not shown, and every time I activate the rectangle, the background is not shown. Please help!
You're setting the JFrame's contentPane to a JLabel, a container that uses no layout, and so adding a component to it will not allow that component to be displayed unless you fully specify that component's size and position, i.e., its bounds. This is one reason I avoid using JLabels for contentPanes (also that it will not set its preferred size based on the components it holds) and instead in general prefer to do my drawing in a background JPanel's paintComponent method.
Side recommendations:
You've too much going on in the main method -- unless this program is not for anything other than demonstration purposes
You set the JFrame's original contentPane (a JPanel) to FlowLayout, but understand that this is meaningless once you change the contentPane.
Despite your assuming that the contentPane uses FlowLayout, you're trying to add the drawing JPanel into a BorderLayout position, something that doesn't make sense.
You have an empty catch block, something that almost never should be done.
Get your images as resources, not files.
Avoid using absolute file paths and prefer use of relative paths to resources.
Don't set sizes of things if you can avoid it.
Avoid so-called "magic numbers", e.g., g.fillRect(50,50,450,650); as this makes your code hard to debug and enhance.
For example, something like:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class ShowRectangle extends JPanel {
private static final int RECT_X = 50;
private static final int RECT_Y = RECT_X;
private static final int RECT_W = 200;
private static final int RECT_H = 200;
private static final String URL_SPEC = "https://duke.kenai.com/guitar/DukeAsKeith-daylightSmall.png";
private BufferedImage img;
public ShowRectangle(BufferedImage img) {
this.img = img;
}
// have same JPanel draw image and graphic element
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
// avoid magic numbers
// g.fillRect(50,50,450,650);
g.fillRect(RECT_X, RECT_Y, RECT_W, RECT_H);
}
// Size the JPanel to the image size
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
return new Dimension(img.getWidth(), img.getHeight());
}
private static void createAndShowGui(BufferedImage image) {
ShowRectangle mainPanel = new ShowRectangle(image);
JFrame frame = new JFrame("ShowRectangle");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
try {
URL imageUrl = new URL(URL_SPEC);
BufferedImage img = ImageIO.read(imageUrl);
SwingUtilities.invokeLater(() -> createAndShowGui(img));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
}
If you avoid using "magic" numbers for instance, it's easy to make the black rectangle draggable, since it is now be drawn by variable values, values that you can change inside of a MouseAdapter (MouseListener and MouseMotionListener combined). For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class ShowRectangle extends JPanel {
private static final int RECT_X = 50;
private static final int RECT_Y = RECT_X;
private static final int RECT_W = 200;
private static final int RECT_H = 200;
private static final String URL_SPEC = "https://duke.kenai.com/guitar/DukeAsKeith-daylightSmall.png";
private int rectX = RECT_X;
private int rectY = RECT_Y;
private BufferedImage img;
public ShowRectangle(BufferedImage img) {
this.img = img;
MouseAdapter myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
// have same JPanel draw image and graphic element
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
// avoid magic numbers
// g.fillRect(50,50,450,650);
g.fillRect(rectX, rectY, RECT_W, RECT_H);
}
// Size the JPanel to the image size
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
return new Dimension(img.getWidth(), img.getHeight());
}
private class MyMouse extends MouseAdapter {
private Point p1;
private Point rectP = null;
#Override
public void mousePressed(MouseEvent e) {
p1 = e.getPoint();
if (new Rectangle(rectX, rectY, RECT_W, RECT_H).contains(p1)) {
rectP = new Point(rectX, rectY);
}
}
#Override
public void mouseDragged(MouseEvent e) {
moveRect(e.getPoint());
}
#Override
public void mouseReleased(MouseEvent e) {
moveRect(e.getPoint());
rectP = null;
}
private void moveRect(Point p2) {
if (rectP == null) {
return;
}
rectX = rectP.x + p2.x - p1.x;
rectY = rectP.y + p2.y - p1.y;
repaint();
}
}
private static void createAndShowGui(BufferedImage image) {
ShowRectangle mainPanel = new ShowRectangle(image);
JFrame frame = new JFrame("ShowRectangle");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
try {
URL imageUrl = new URL(URL_SPEC);
BufferedImage img = ImageIO.read(imageUrl);
SwingUtilities.invokeLater(() -> createAndShowGui(img));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
}
Its there just it was going out of boundary and hence not visible.
replace these two lines and check
g.setColor(Color.BLACK);
g.fillRect(0,0,250,250);
Try this,
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Rectangle clipBounds = g.getClipBounds();
System.out.println(clipBounds.getX() +" "+ clipBounds.getY() + " "+ clipBounds.getHeight() + " " + clipBounds.getWidth());
g.setColor(Color.BLACK);
g.fillRect(0,0,450,450);
}
You will get 0.0 0.0 10.0 10.0
as output meaning the fill reactangle container is starting from 0,0 till 10,10 and hence it was not shown
Change the layout to GridLayout() will solve your problem,
frame.setLayout(new GridLayout());
frame.add(new JPanel(new GridLayout()){
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Rectangle clipBounds = g.getClipBounds();
System.out.println(clipBounds.getX() +" "+ clipBounds.getY() + " "+ clipBounds.getHeight() + " " + clipBounds.getWidth());
g.setColor(Color.BLACK);
g.fillRect(frame.getWidth()/2,0,frame.getWidth(),frame.getWidth());
}
}, BorderLayout.CENTER);
As per doc,
void java.awt.Graphics.fillRect(int x, int y, int width, int height)
Fills the specified rectangle. The left and right edges of the rectangle are at x and x + width - 1. The top and bottom edges are at y and y + height - 1. The resulting rectangle covers an area width pixels wide by height pixels tall. The rectangle is filled using the graphics context's current color.
Parameters:
x the x coordinate of the rectangle to be filled.
y the y coordinate of the rectangle to be filled.
width the width of the rectangle to be filled.
height the height of the rectangle to be filled.
So that's the issue

How to set imageicon fix on jlabel

I am trying to make a java desktop application. I have a JLabel where I am shuffling image but all image sizes are different so I want to fix size of the image on JLabel.
How can I do this?
Here is my code :
public class ImageShuffle1 extends JPanel {
private List<Icon> list = new ArrayList<Icon>();
private List<Icon> shuffled;
private JLabel label = new JLabel();
private Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
public ImageShuffle1() {
this.setLayout(new GridLayout(1, 0));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\e.jpg"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\d.jpg"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\yellow.png"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\f.jpg"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\l.jpg"));
//label.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
for(Icon icon: list){
Image img = icon.getImage() ;
// put here the size properties
Image newimg = img.getScaledInstance( 45, 34, java.awt.Image.SCALE_SMOOTH ) ;
icon = new ImageIcon(newimg);
}
shuffled = new ArrayList<Icon>(list);
Collections.shuffle(shuffled);
timer.start();
}
private void update() {
if (shuffled.isEmpty()) {
shuffled = new ArrayList<Icon>(list);
Collections.shuffle(shuffled);
}
Icon icon = shuffled.remove(0);
label.setIcon(icon);
}
private void display() {
JFrame f = new JFrame("ImageShuffle");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(label);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageShuffle1().display();
}
});
}
}
I am getting error herein this.
line/variable getimage can not found mage img = icon.getImage() ;
Thanks in advance
Use BufferedImage in place of Icon that has a functionality to re size it.
Here is the code
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageShuffle1 extends JPanel {
private List<BufferedImage> list = new ArrayList<BufferedImage>();
private List<BufferedImage> shuffled;
private JLabel label = new JLabel();
private int width = 50;
private int height = 100;
private Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
public ImageShuffle1() {
try {
list.add(resizeImage(ImageIO.read(new File("resources/1.png"))));
list.add(resizeImage(ImageIO.read(new File("resources/2.png"))));
list.add(resizeImage(ImageIO.read(new File("resources/6.png"))));
list.add(resizeImage(ImageIO.read(new File("resources/Tulips.jpg"))));
} catch (IOException e) {
e.printStackTrace();
}
shuffled = new ArrayList<BufferedImage>(list);
Collections.shuffle(shuffled);
timer.start();
}
private BufferedImage resizeImage(BufferedImage originalImage) throws IOException {
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
private void update() {
if (shuffled.isEmpty()) {
shuffled = new ArrayList<BufferedImage>(list);
Collections.shuffle(shuffled);
}
BufferedImage icon = shuffled.remove(0);
label.setIcon(new ImageIcon(icon));
}
private void display() {
JFrame f = new JFrame("ImageShuffle");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(label);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageShuffle1().display();
}
});
}
}
Lets start with this...
for(Icon icon: list){
Image img = icon.getImage() ;
Icon does not have a method getImage, there is actually no way to get the "image" data maintained by the Icon class without first rendering it to something (like a BufferedImage)
A better solution might be to load the images into a List that supports BufferedImage. BufferedImage is a more versatile starting point and because it extends from Image, it can be used with ImageIcon. For example...
private List<BufferedImage> list = new ArrayList<BufferedImage>();
//...
list.add(ImageIO.read("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\e.jpg"));
Take a look at Reading/Loading an Image
For scaling you might like to take a look at
The Perils of Image.getScaledInstance
Java: maintaining aspect ratio of JPanel background image
Quality of Image after resize very low -- Java
First you resize every image to a fixed size and it must be fit in JLabel
public static Boolean resizeImage(String sourceImage, String destinationImage, Integer Width, Integer Height) {
BufferedImage origImage;
try {
origImage = ImageIO.read(new File(sourceImage));
int type = origImage.getType() == 0? BufferedImage.TYPE_INT_ARGB : origImage.getType();
//*Special* if the width or height is 0 use image src dimensions
if (Width == 0) {
Width = origImage.getWidth();
}
if (Height == 0) {
Height = origImage.getHeight();
}
int fHeight = Height;
int fWidth = Width;
//Work out the resized width/height
if (origImage.getHeight() > Height || origImage.getWidth() > Width) {
fHeight = Height;
int wid = Width;
float sum = (float)origImage.getWidth() / (float)origImage.getHeight();
fWidth = Math.round(fHeight * sum);
if (fWidth > wid) {
//rezise again for the width this time
fHeight = Math.round(wid/sum);
fWidth = wid;
}
}
BufferedImage resizedImage = new BufferedImage(fWidth, fHeight, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(origImage, 0, 0, fWidth, fHeight, null);
g.dispose();
ImageIO.write(resizedImage, "png", new File(destinationImage));
...

Use of setIcon on jLabel repeats old image

I'm attempting to display an image that was downloaded from a website, with the use of setIcon and a jLabel
jLabel5.setIcon(new ImageIcon("image.png"));
At the start of the program, the image doesn't exist, it gets downloaded, and after that displayed, with no problems. But if it changes, even if it downloads a newer version of the image, it will display the old one, as if it had a cache of it or something.
Does someone know why this happens? How to get a workaround with or without this method?
I have also tried to do the following to see if it could help, with no success:
jLabel5.setIcon(null);
jLabel5.setIcon(new ImageIcon("image.png"));
It would display nothing and then the same old image again.
it will display the old one, as if it had a cache of it or something.
Yep, caching is the problem. Here are a couple of options:
// This works using ImageIO
imageLabel.setIcon( new ImageIcon(ImageIO.read( new File(imageName) ) ) );
// Or you can flush the image
ImageIcon icon = new ImageIcon(imageName);
icon.getImage().flush();
imageLabel.setIcon( icon );
Have you tried to use the SwingUtilities.invokeLater() method, similar to this:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//JLabel myLabel = new JLabel("Old Text");
jLabel5.setIcon(new ImageIcon("image.png"));
}
});
Taken from here.
If the problem is about caching, try downloading the image with a query string. For example, http://abc.co.th/image.png?t=149534274 The number is obtained from System.currentTimeMillis()
for example
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;
public class LabelsIcon extends JFrame implements Runnable {
private static final long serialVersionUID = 1L;
private JLabel label = new JLabel();
private Random random = new Random();
private boolean runProcess = true;
public LabelsIcon() {
label.setLayout(new BorderLayout());
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
label.setPreferredSize(new Dimension(d.width / 3, d.height / 3));
add(label, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
new Thread(this).start();
}
#Override
public void run() {
while (runProcess) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setIcon(new ImageIcon(getImage()));
}
});
try {
Thread.sleep(300);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public BufferedImage getImage() {
int w = label.getWidth();
int h = label.getHeight();
GradientPaint gp = new GradientPaint(0f, 0f, new Color(
127 + random.nextInt(128),
127 + random.nextInt(128),
127 + random.nextInt(128)),
w, w,
new Color(random.nextInt(128), random.nextInt(128), random.nextInt(128)));
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
g2d.setColor(Color.BLACK);
return bi;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
LabelsIcon t = new LabelsIcon();
}
});
}
}

Animated Swing effect to display full-resolution image

I've got an editor with lots of image thumbnails. I'd like a double-click on an image to display the full resolution image using a modal undecorated dialog. Ideally, this would be animated, to show the image zooming up to full resolution on the center of the screen, then any click would make the image go away, either zooming back out or fading away.
I'm not concerned with establishing an exact behavior, I just want something slick. I've found plenty of JavaScript examples for this, but is there anything built for Swing?
This piece of code does more or less the trick...
There is still a problem in the way I'm setting the dialog's location...
Hope it helps.
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class OpenImageZooming {
private static final int NB_STEPS = 30;
private static final long OPENING_TOTAL_DURATION = 3000;
public static void main(String[] args) {
OpenImageZooming me = new OpenImageZooming();
me.openImage(args[0]);
}
private JFrame frame;
private JDialog dialog;
private JPanelZooming panelZooming;
private void openImage(final String imagePath) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame = new JFrame();
frame.setTitle("Open image with zoom");
JPanel p = new JPanel(new BorderLayout());
p.add(new JLabel("click on button to display image"), BorderLayout.CENTER);
JButton button = new JButton("Display!");
frame.setContentPane(p);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread t = new Thread() {
#Override
public void run() {
displayImaggeWithProgressiveZoom(imagePath);
}
};
t.start();
}
});
p.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected void displayImaggeWithProgressiveZoom(String imagePath) {
try {
final BufferedImage image = ImageIO.read(new File(imagePath));
for (int i = 0; i < NB_STEPS; i++) {
displayDialog(i, NB_STEPS, image);
Thread.sleep(OPENING_TOTAL_DURATION / NB_STEPS);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void displayDialog(final int i, final int nbSteps, final BufferedImage image) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
if (dialog == null) {
dialog = new JDialog(frame);
dialog.setUndecorated(true);
dialog.setModal(false);
panelZooming = new JPanelZooming(image);
dialog.setContentPane(panelZooming);
dialog.setSize(0, 0);
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
int w = (i + 1) * image.getWidth() / nbSteps;
int h = (i + 1) * image.getHeight() / nbSteps;
panelZooming.setScale((double) (i + 1) / nbSteps);
dialog.setSize(w, h);
dialog.setLocationRelativeTo(null);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#SuppressWarnings("serial")
public static class JPanelZooming extends JPanel {
private BufferedImage image;
private double scale = 1.0d;
public JPanelZooming(BufferedImage image) {
this.image = image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform at = g2.getTransform();
AffineTransform oldTransform = (AffineTransform) at.clone();
at.scale(scale, scale);
g2.setTransform(at);
g2.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
g2.setTransform(oldTransform);
}
public void setScale(double scale) {
this.scale = scale;
}
}
}
You can create a custom control that displays the image at the scale you want.
1) Create a BufferedImage from the image file you want using ImageIO.read(file) (you can also create it from an InputStream)
2) Extend the JComponent or Canvas class and overload the paint function to draw the animated image using Graphics.DrawImage() and set the width and height based on how long the window has been open. Set a timer or use another thread to repeatedly have the component redraw itself for however long you want the animation to play.
I haven't done much with customized modal dialogs (I mostly find them annoying), but you can use a JDialog and and your component to it.

Categories