Component with transparent background to BufferedImage? - java

I have a component extends JPanel. It saves itself as bufferedimage on every call of paintComponent method. Component is not completely transparent, only its background. Problem is background is not transparent. I am using setOpaque(false);
Here is my relevant code;
private BufferedImage bufImage = null;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// if first time call
if (bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
bufImage = (BufferedImage)this.createImage(w, h);
}
g2.drawImage(bufImage, null, 0, 0);
// draw sth
g2.draw(sth);
}
--
I also tried
bufImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
instead of
bufImage = (BufferedImage)this.createImage(w, h);
When i do that; background transperancy works but i can only draw with white color. I have no idea what causes that.
Note:
I used that code to check if it is working;
File outputfile = new File("saved.png");
ImageIO.write(bufImage, "png", outputfile);
saved.png had transparent background but drawings were only white.
This is the component, only lets drawing rectangle with mouse;
class PaintPanel extends JPanel implements MouseListener, MouseMotionListener {
private BufferedImage _bufImage = null;
private boolean dragging = false;
private Point _start = null, _end = null;
public PaintPanel() {
setOpaque(false);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
if (_bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
_bufImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
//_bufImage = (BufferedImage)this.createImage(w, h);
}
g2.drawImage(_bufImage, null, 0, 0);
if (dragging) {
drawCurrentShape(g2);
}
}
private void drawCurrentShape(Graphics2D g2) {
int startx = (int) _start.getX();
int starty = (int) _start.getY();
int stopx = (int) _end.getX();
int stopy = (int) _end.getY();
int width = Math.abs(startx - stopx);
int height = Math.abs(starty - stopy);
int x = startx, y = starty;
if(x > stopx)
x = stopx;
if(y > stopy)
y = stopy;
Rectangle r = new Rectangle(x, y, width, height);
g2.draw(r);
}
public void mousePressed(MouseEvent e) {
dragging = true;
_start = e.getPoint();
_end = _start;
}
public void mouseDragged(MouseEvent e) {
_end = e.getPoint();
this.repaint();
}
public void mouseReleased(MouseEvent e) {
_end = e.getPoint();
if (dragging) {
dragging = false;
drawCurrentShape(_bufImage.createGraphics());
this.repaint();
}
}
public void mouseMoved (MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited (MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
}

try this:
bufImage = new BufferedImage(w,h,java.awt.image.BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufImage.createGraphics();
this.print(graphics);
graphics.dispose();
The key is to use print()
Edit: I tried the following and transparency works like a charm:
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test2 {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel p = new JPanel();
p.setPreferredSize(new Dimension(400, 400));
p.setOpaque(false);
JButton button = new JButton("Hello world");
p.add(button);
frame.add(p);
frame.pack();
frame.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
BufferedImage bufImage = new BufferedImage(p.getWidth(), p.getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufImage.createGraphics();
p.print(graphics);
graphics.dispose();
try {
ImageIO.write(bufImage, "png", new File("d:/tmp/tmp.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}

createImage(w, h) will create a "blank" image with the specified width and height. That being said, what you'll need to do is invoke createGraphics on the BufferedImage instance and draw directly to the returned Graphics object.

Related

Applying colour to the transparent area of a JButton image - but not that of its container

I have a circular JButton constructed using a circular PNG image with a transparent area.
I want to fill the transparent area of the JButton image with a given colour - but something other than the opaque background colour of the JPanel which contains the JButton. I want to do this programmatically in Java rather than providing pre-coloured images from a graphics package.
I've got as far as the code below, which simply allows the orange background of the opaque panel to colour the transparent area. I can't figure out, though, how to keep the panel background as orange but fill the image transparency with, say, blue (or another colour for rollover and pressed effects).
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Insets;
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.net.URL;
import javax.imageio.ImageIO;
import javax.swing.DefaultButtonModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class App extends JFrame implements ActionListener
{
public App()
{
super();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(makeContentPane());
}
private final JPanel makeContentPane()
{
JPanel contentPane = new JPanel();
BufferedImage bi = null;
try
{
bi = ImageIO.read(new URL("http://features.advisorwebsites.com/sites/default/files/users/AdvisorWebsitesFeatures/icones/1384148625_twitter_circle_gray.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
ImageIcon icon = new ImageIcon(bi);
MyButton myButton = new MyButton(icon);
myButton.addActionListener(this);
contentPane.add(myButton);
contentPane.setBackground(Color.ORANGE);
contentPane.setOpaque(true);
return contentPane;
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
App app = new App();
app.pack();
app.setVisible(true);
}
});
}
class MyButton extends JButton
{
public MyButton(ImageIcon icon)
{
super(icon);
setMargin(new Insets(0, 0, 0, 0));
setFocusable(false);
setContentAreaFilled(false);
setBorderPainted(false);
setModel(new DefaultButtonModel());
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
#Override
public void actionPerformed(ActionEvent arg0)
{
System.out.println("You clicked me");
}
}
I'm guessing I might need to apply Graphics2D transformations to my transparent image to create a set of three new images (for the normal, rollover and pressed states of my JButton). Is this the appropriate way forward and, if so, can you provide me with a code example for the bit I'm missing ?
Thanks
try to override paintComponent() in your custom JButton
Here's what I tried
class MyButton extends JButton {
public MyButton(ImageIcon icon) {
super(icon);
setMargin(new Insets(0, 0, 0, 0));
setFocusable(false);
setContentAreaFilled(false);
setBorderPainted(false);
setModel(new DefaultButtonModel());
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
public void paintComponent(Graphics g) {
g.setColor(Color.green);
g.fillOval(0, 0, this.getWidth(), this.getHeight());
super.paintComponent(g);
}
}
And here's the result:
EDIT:
To get it to change color depending on mouse movement, you need to add a MouseListener to the JButton and add a Color attribute to the class, when a MouseEvent is fired you change the color. Also don't forget to set the graphics to that color in paintComponent()
class MyButton extends JButton {
Color color = Color.GREEN;
public MyButton(ImageIcon icon) {
super(icon);
setMargin(new Insets(0, 0, 0, 0));
setFocusable(false);
setContentAreaFilled(false);
setBorderPainted(false);
setModel(new DefaultButtonModel());
setCursor(new Cursor(Cursor.HAND_CURSOR));
this.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
color=Color.RED;
}
#Override
public void mouseReleased(MouseEvent e) {
color=Color.BLUE;
}
#Override
public void mouseEntered(MouseEvent e) {
color=Color.BLUE;
}
#Override
public void mouseExited(MouseEvent e) {
color=Color.GREEN;
}
});
}
#Override
public void paintComponent(Graphics g) {
g.setColor(color);
g.fillOval(0, 0, this.getWidth(), this.getHeight());
super.paintComponent(g);
}
}
Okay, this is little more then you're asking for, but it demonstrates a means by which you can generate a shape which matches the shape of a image, based on its alpha, all through the magic of AlphaComposite...
So, basically, we're going to take the original image on the left and turn into the image on the right...
First, we load the original image
Next, we create a mask of the shape we want to achieve (a circle in this case)
Next, we mask the two images together, so that the original image is cropped into the mask (the second)
Then we create a new mask, which is filled with the color we want to be used as the outline
We then mask the first masked image with the "outline" image, this basically acts as a cookie cutter, cutting the shape of the first masked imaged with the "block" image.
We take this "outlined" shape and then scale it up slightly
And finally, we combine them.
This example generates two images, a "normal" and a "roll over" which is easily applied to a JButton, for example...
Normal...
Roll over...
Now, if for some reason, you wanted to know when the button was "rolled over", you could simply add a ChangeListener to the ButtonModel, for example...
JButton btn = new JButton(new ImageIcon(normal));
btn.setRolloverIcon(new ImageIcon(rollOver));
btn.setRolloverEnabled(true);
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
System.out.println("Change: " + model.isRollover());
}
});
And the runnable example...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ButtonModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class JavaApplication24 {
public static void main(String[] args) {
new JavaApplication24();
}
public JavaApplication24() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
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);
} catch (IOException ex) {
Logger.getLogger(JavaApplication24.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws IOException {
setLayout(new GridBagLayout());
BufferedImage source = ImageIO.read(...));
// This the shape we want the source to be clipped to
int size = Math.min(source.getWidth(), source.getHeight());
BufferedImage mask = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D maskg = mask.createGraphics();
applyQualityRenderingHints(maskg);
maskg.setColor(Color.WHITE);
maskg.fillOval((source.getWidth() - size) / 2, (source.getHeight() - size) / 2, size, size);
maskg.dispose();
// This will mask the source to the shape we've defined
BufferedImage masked = applyMask(source, mask, AlphaComposite.DST_ATOP);
BufferedImage normal = makeOutline(masked, Color.BLACK);
BufferedImage rollOver = makeOutline(masked, Color.RED);
JButton btn = new JButton(new ImageIcon(normal));
btn.setRolloverIcon(new ImageIcon(rollOver));
btn.setRolloverEnabled(true);
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
System.out.println("Change: " + model.isRollover());
}
});
add(btn);
}
protected BufferedImage makeOutline(BufferedImage original, Color color) {
// This generates a image which is completely filled with the provided color
BufferedImage outline = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D outlineg = outline.createGraphics();
applyQualityRenderingHints(outlineg);
outlineg.setColor(color);
outlineg.fillRect(0, 0, outline.getWidth(), outline.getHeight());
outlineg.dispose();
// This applies a AlphaComposite to mask the outline with the shape
// of the original image
outline = applyMask(original, outline, AlphaComposite.SRC_ATOP);
// Now we make it slightly larger...
double scale = 1.05;
outline = getScaledInstanceToFit(outline, scale);
// And we combine the images
outlineg = outline.createGraphics();
int x = (outline.getWidth() - original.getWidth()) / 2;
int y = (outline.getHeight() - original.getHeight()) / 2;
outlineg.drawImage(original, x, y, this);
outlineg.dispose();
return outline;
}
public BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage) {
return applyMask(sourceImage, maskImage, AlphaComposite.DST_IN);
}
public BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
BufferedImage maskedImage = null;
if (sourceImage != null) {
int width = maskImage.getWidth(null);
int height = maskImage.getHeight(null);
maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D mg = maskedImage.createGraphics();
applyQualityRenderingHints(mg);
int x = (width - sourceImage.getWidth(null)) / 2;
int y = (height - sourceImage.getHeight(null)) / 2;
mg.drawImage(sourceImage, x, y, null);
mg.setComposite(AlphaComposite.getInstance(method));
mg.drawImage(maskImage, 0, 0, null);
mg.dispose();
}
return maskedImage;
}
public void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
// g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
public BufferedImage getScaledInstanceToFit(BufferedImage img, double scale) {
int width = (int)(img.getWidth() * scale);
int height = (int)(img.getHeight()* scale);
return getScaledInstanceToFit(img, new Dimension(width, height));
}
public BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) {
double scaleFactor = getScaleFactorToFit(new Dimension(img.getWidth(), img.getHeight()), size);
return getScaledInstance(img, scaleFactor);
}
public double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
public double getScaleFactor(int iMasterSize, int iTargetSize) {
return (double) iTargetSize / (double) iMasterSize;
}
public BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {
return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
}
protected BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) {
BufferedImage imgScale = img;
int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);
if (dScaleFactor <= 1.0d) {
imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);
} else {
imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);
}
return imgScale;
}
protected BufferedImage getScaledDownInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint,
boolean higherQuality) {
int type = (img.getTransparency() == Transparency.OPAQUE)
? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage) img;
if (targetHeight > 0 || targetWidth > 0) {
int w, h;
if (higherQuality) {
w = img.getWidth();
h = img.getHeight();
} else {
w = targetWidth;
h = targetHeight;
}
do {
if (higherQuality && w > targetWidth) {
w /= 2;
if (w < targetWidth) {
w = targetWidth;
}
}
if (higherQuality && h > targetHeight) {
h /= 2;
if (h < targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != targetWidth || h != targetHeight);
} else {
ret = new BufferedImage(1, 1, type);
}
return ret;
}
protected BufferedImage getScaledUpInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint,
boolean higherQuality) {
int type = BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage) img;
int w, h;
if (higherQuality) {
w = img.getWidth();
h = img.getHeight();
} else {
w = targetWidth;
h = targetHeight;
}
do {
if (higherQuality && w < targetWidth) {
w *= 2;
if (w > targetWidth) {
w = targetWidth;
}
}
if (higherQuality && h < targetHeight) {
h *= 2;
if (h > targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
tmp = null;
} while (w != targetWidth || h != targetHeight);
return ret;
}
}
}
This code borrows heavily from my personal library code, so it might be a little convoluted ;)

JLabel goes out of alignment (aka funky) when overlaying a rectangle on it

I have a GUI I am making for the popular software ImageMagick in Java SWING.
Now, I am implementing the Crop feature into it and was trying to implement a drawable box to denote the region to be cropped.
The issue is that although I have gotten the rectangle to draw on the JLabel, the JLabel itself starts to move around once I finish painting the graphics on it.
As an example, here is a screenshot of the app before and after the selection is made.
Here is the code for the MouseReleased() event listener
private void input_showerMouseReleased(java.awt.event.MouseEvent evt) {
end_x = evt.getX();
end_y = evt.getY();
paint(input_shower.getGraphics());
input_shower.revalidate();
}
Here is the code for the paint() method
public void paint(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(5));
Rectangle2D.Double rectangle = new Rectangle2D.Double(start_x, start_y, (end_x - start_x), (end_y - start_y));
g2.draw(rectangle);
}
Are there any ideas as to why this is happening and any possible solutions?
This is dangerous code:
private void input_showerMouseReleased(java.awt.event.MouseEvent evt) {
end_x = evt.getX();
end_y = evt.getY();
paint(input_shower.getGraphics());
input_shower.revalidate();
}
since you're painting directly to a component with a Graphics object that was not given to you by the JVM. Just don't do this, and instead paint passively.
Instead use end_x and end_y in your listened to jcomponent's paintComponent method and draw with that.
e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
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 PaintComponentCorrect extends JPanel {
public static final String BULL_FIGHT = "https://duke.kenai.com/misc/Bullfight.jpg";
private static final Color RECT_COLOR = new Color(150, 150, 255);
private int startX;
private int startY;
private int endX;
private int endY;
private BufferedImage img;
public PaintComponentCorrect() throws IOException {
URL url = new URL(BULL_FIGHT);
img = ImageIO.read(url);
MyMouseAdapt myMouseAdapt = new MyMouseAdapt();
addMouseListener(myMouseAdapt);
addMouseMotionListener(myMouseAdapt);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, null);
}
g.setColor(RECT_COLOR);
int x = Math.min(startX, endX);
int y = Math.min(startY, endY);
int width = Math.abs(startX - endX);
int height = Math.abs(startY - endY);
g.drawRect(x, y, width, height);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
return new Dimension(img.getWidth(), img.getHeight());
}
private class MyMouseAdapt extends MouseAdapter {
private BufferedImage subImg;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
startX = e.getX();
startY = e.getY();
endX = startX;
endY = startY;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
endX = e.getX();
endY = e.getY();
repaint();
int x = Math.min(startX, endX);
int y = Math.min(startY, endY);
int w = Math.abs(startX - endX);
int h = Math.abs(startY - endY);
subImg = img.getSubimage(x, y, w, h);
ImageIcon icon = new ImageIcon(subImg);
JOptionPane.showMessageDialog(PaintComponentCorrect.this, icon);
}
#Override
public void mouseDragged(MouseEvent e) {
endX = e.getX();
endY = e.getY();
repaint();
}
}
private static void createAndShowGui() {
PaintComponentCorrect mainPanel = null;
try {
mainPanel = new PaintComponentCorrect();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("PaintComponent Correct");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
public void paint(Graphics g) {
super.paintComponents(g);
Custom painting is done by overriding the paintComponent() method.
You then invoke super.paintComponent(), not "paintComponents" with an "s"
For example check out Custom Painting Approaches. The code isn't designed to do what you want, but it does show how to draw a Rectangle on a component using the above suggestion.

Select, Copy and Paste Images

What I want my app to do:
1 - Select an area of Image and get the coordinates. This code below should do this:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class ScreenCaptureRectangle {
Rectangle captureRect;
ScreenCaptureRectangle(final BufferedImage screen) {
final BufferedImage screenCopy = new BufferedImage(
screen.getWidth(),
screen.getHeight(),
screen.getType());
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int)(screen.getWidth()/3),
(int)(screen.getHeight()/3)));
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(screen, screenCopy);
screenLabel.repaint();
screenLabel.addMouseMotionListener(new MouseMotionAdapter() {
Point start = new Point();
#Override
public void mouseMoved(MouseEvent me) {
start = me.getPoint();
repaint(screen, 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(screen, 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 {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ScreenCaptureRectangle(screen);
}
});
}
}
2 - get the coordinates and use it on getSubimage method.
double w = captureRect.getWidth();
double h = captureRect.getHeight();
double x = captureRect.getX();
double y = captureRect.getY();
int W = (int) w;
int H = (int) h;
int X = (int) x;
int Y = (int) y;
BufferedImage selectImg = screen.getSubimage(x, y, w, h);
3 - this code create a new image file and copy the imageselected.
BufferedImage img = new BufferedImage ( 5000, 5000, BufferedImage.TYPE_INT_RGB );
img.createGraphics().drawImage(selectImg, 0, 0, null);
File final_image = new File("C:/Final.jpg");
ImageIO.write(img, "jpeg", final_image);
The idea of app is:
- Select an area of the image.
- Copy that image and paste in other file. ( when I pressed any button )
- The program will continue run until I press another button.
- Every image that I copy the program will paste it beside the last one.
I think I am near to the solution. Can any one help me to "connect the parts" ?
Start by taking a look at:
How to Write a Mouse Listener
How to Use Buttons, Check Boxes, and Radio Buttons
How to Write an Action Listeners
Performing Custom Painting
Writing/Saving an Image
You need to take the concepts you have and rework them into a coherent workable solution. That is, provide functionality between the areas you need (selecting a region and saving the file) so that they work cleanly together...
The following example takes a screenshot, allows you to select an area, click save and the file will be saved. The example checks to see how many files are already in the current directory and increments the count by 1 so you are not overwriting the existing files...
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
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.FileFilter;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScreenImage {
public static void main(String[] args) {
new ScreenImage();
}
public ScreenImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final BufferedImage screen = robot.createScreenCapture(new Rectangle(screenSize));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane(screen));
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (AWTException exp) {
exp.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage master;
public TestPane(BufferedImage image) {
this.master = image;
setLayout(new BorderLayout());
final ImagePane imagePane = new ImagePane(image);
add(new JScrollPane(imagePane));
JButton btnSave = new JButton("Save");
add(btnSave, BorderLayout.SOUTH);
btnSave.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
BufferedImage img = imagePane.getSubImage();
master = append(master, img);
File save = new File("Capture.png");
ImageIO.write(master, "png", save);
imagePane.clearSelection();
JOptionPane.showMessageDialog(TestPane.this, save.getName() + " was saved", "Saved", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(TestPane.this, "Failed to save capture", "Error", JOptionPane.ERROR_MESSAGE);
}
}
public BufferedImage append(BufferedImage master, BufferedImage sub) {
// Create a new image which can hold both background and the
// new image...
BufferedImage newImage = new BufferedImage(
master.getWidth() + sub.getWidth(),
Math.max(master.getHeight(), sub.getHeight()),
BufferedImage.TYPE_INT_ARGB);
// Get new image's Graphics context
Graphics2D g2d = newImage.createGraphics();
// Draw the old background
g2d.drawImage(master, 0, 0, null);
// Position and paint the new sub image...
int y = (newImage.getHeight() - sub.getHeight()) / 2;
g2d.drawImage(sub, master.getWidth(), y, null);
g2d.dispose();
return newImage;
}
});
}
}
public class ImagePane extends JPanel {
private BufferedImage background;
private Rectangle selection;
public ImagePane(BufferedImage img) {
background = img;
MouseAdapter ma = new MouseAdapter() {
private Point clickPoint;
#Override
public void mousePressed(MouseEvent e) {
clickPoint = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e) {
Point dragPoint = e.getPoint();
int x = Math.min(clickPoint.x, dragPoint.x);
int y = Math.min(clickPoint.y, dragPoint.y);
int width = Math.abs(clickPoint.x - dragPoint.x);
int height = Math.abs(clickPoint.y - dragPoint.y);
selection = new Rectangle(x, y, width, height);
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public void clearSelection() {
selection = null;
repaint();
}
public BufferedImage getSubImage() {
BufferedImage img = null;
if (selection != null) {
img = background.getSubimage(selection.x, selection.y, selection.width, selection.height);
}
return img;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
if (selection != null) {
Color stroke = UIManager.getColor("List.selectionBackground");
Color fill = new Color(stroke.getRed(), stroke.getGreen(), stroke.getBlue(), 128);
g2d.setColor(fill);
g2d.fill(selection);
g2d.setColor(stroke);
g2d.draw(selection);
}
g2d.dispose();
}
}
}
So apart from rendering the selection the hardest part would be generating the resulting image...
Basically, this done by creating a new BufferedImage and painting the old image and the new, sub, image together.
public BufferedImage append(BufferedImage master, BufferedImage sub) {
// Create a new image which can hold both background and the
// new image...
BufferedImage newImage = new BufferedImage(
master.getWidth() + sub.getWidth(),
Math.max(master.getHeight(), sub.getHeight()),
BufferedImage.TYPE_INT_ARGB);
// Get new image's Graphics context
Graphics2D g2d = newImage.createGraphics();
// Draw the old background
g2d.drawImage(master, 0, 0, null);
// Position and paint the new sub image...
int y = (newImage.getHeight() - sub.getHeight()) / 2;
g2d.drawImage(sub, master.getWidth(), y, null);
g2d.dispose();
return newImage;
}
The example replaces the previous (master) image with the one created here, so it will constantly be appending new images to the end of it...
You need more listeners for button pressed and released.. some lines in the mouseMoved also better placed in mousePressed.
You would want to update your captureRect when you release the mouse (in mouseReleased method).
Then you just write it to the file. You may adjust other things according to your needs.
And for clarity maybe it's better to add a save button into your UI.
public class ScreenCaptureRectangle {
Rectangle captureRect;
Point start = new Point();
SimpleDateFormat sdf;
ScreenCaptureRectangle(final BufferedImage screen) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
final BufferedImage screenCopy = new BufferedImage(
screen.getWidth(),
screen.getHeight(),
screen.getType());
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int) (screen.getWidth() / 3),
(int) (screen.getHeight() / 3)));
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
JButton btnSave = new JButton("SAVE");
btnSave.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
double w = captureRect.getWidth();
double h = captureRect.getHeight();
double x = captureRect.getX();
double y = captureRect.getY();
int W = (int) w;
int H = (int) h;
int X = (int) x;
int Y = (int) y;
BufferedImage selectImg = screen.getSubimage(X, Y, W, H);
try {
String fName = generateFileName();
if (fName != null) {
File f = new File(fName);
if (f.createNewFile()) {
ImageIO.write(selectImg, "jpg", f);
}
}
} catch (IOException ex) {
Logger.getLogger(ScreenCaptureRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
panel.add(btnSave, BorderLayout.AFTER_LAST_LINE);
final JLabel selectionLabel = new JLabel(
"Drag a rectangle in the screen shot!");
panel.add(selectionLabel, BorderLayout.SOUTH);
repaint(screen, screenCopy);
screenLabel.repaint();
screenLabel.addMouseMotionListener(new MouseMotionAdapter() {
#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(screen, screenCopy);
screenLabel.repaint();
selectionLabel.setText("Rectangle: " + captureRect);
}
});
screenLabel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
start = me.getPoint();
repaint(screen, screenCopy);
selectionLabel.setText("Start Point: " + start);
screenLabel.repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
int endX = me.getX();
int endY = me.getY();
if (endX > start.x && endY > start.y) {
captureRect = new Rectangle(start.x, start.y, endX-start.x, endY-start.y);
System.out.println("Rectangle of interest: " + captureRect);
}
}
});
JOptionPane.showMessageDialog(null, panel);
}
private String generateFileName() {
return new StringBuilder("screencrop_").append(sdf.format(new Date())).append(".jpg").toString();
}
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 {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ScreenCaptureRectangle(screen);
}
});
}
}

Call JDialog from JDialog

I'm trying to build an application, in which allows calling JDialog from JDialog. I've tried it, but at the time of the call dialog B of A, B dialog appears and then immediately disappears. Is there a solution to these problems?
My code :
I have a class A which extends javax.swing.JDialog. Then there is a label that has the action to call dialog from class PadAndZoom as below:
private void lblSuratRekomendasiMouseClicked(java.awt.event.MouseEvent evt) {
try {
PadAndZoom app = new PadAndZoom();
BufferedImage img = ImageIO.read(PadAndZoom.class.getResource("/tampilan/background5.jpg"));
app.tes(img);
} catch (IOException ex) {
Logger.getLogger(RincianBukuBesar.class.getName()).log(Level.SEVERE, null, ex);
}
}
then I have one more class to be invoked by the method lblSuratRekomendasiMouseClicked (java.awt.event.MouseEvent evt) of class A
package dispertasih;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class PadAndZoom implements ChangeListener {
BufferedImage image;
PanPanelX label;
public void stateChanged(ChangeEvent e) {
int value = ((JSlider) e.getSource()).getValue();
double scale = value / 200.0;
BufferedImage scaled = getScaledImage(scale);
label.setImage(scaled);
}
public BufferedImage getScaledImage(double scale) {
int w = (int)(scale*image.getWidth());
int h = (int)(scale*image.getHeight());
BufferedImage bi = new BufferedImage(w, h, image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
g2.drawRenderedImage(image, at);
g2.dispose();
return bi;
}
public PanPanelX getContent() {
// createAnImage();
label = new PanPanelX(image);
//label.setHorizontalAlignment(JLabel.CENTER);
return label;
}
public void createAnImage(BufferedImage imgbuf) {
int w = 500;
int h = 500;
int type = BufferedImage.TYPE_INT_RGB; // many options
image = imgbuf;
}
public JSlider getControl() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 50, 200, 50);
slider.setMajorTickSpacing(50);
slider.setMinorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(this);
return slider;
}
public void tes(BufferedImage img) {
PadAndZoom app = new PadAndZoom();
JDialog f = new JDialog();
JButton b = new JButton();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { }
app.createAnImage(img);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.getContentPane().add(new JScrollPane(app.getContent()));
//f.getContentPane().add(new JButton("tessss"));
f.getContentPane().add(app.getControl(), "Last");
f.setSize(400, 400);
f.setLocation(200,200);
f.setVisible(true);
}
}
class PanPanelX extends JPanel {
public int x, y;
public int width = 800, height = 800;
BufferedImage img;
public final static RenderingHints textRenderHints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
public final static RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
public final static RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
static int startX, startY;
public void setImage(BufferedImage img) {
this.img = img;
revalidate();
repaint();
}
public PanPanelX(BufferedImage img) {
x = 20;
y = 20;
this.img = img;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
startX = me.getX();
startY = me.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
if (me.getX() < startX) {//moving image to right
x -= 2;
} else if (me.getX() > startX) {//moving image to left
x += 2;
}
if (me.getY() < startY) {//moving image up
y -= 2;
} else if (me.getY() > startY) {//moving image to down
y += 2;
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
//turn on some nice effects
applyRenderHints(g2d);
g2d.drawImage(img, x, y, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public static void applyRenderHints(Graphics2D g2d) {
g2d.setRenderingHints(textRenderHints);
g2d.setRenderingHints(imageRenderHints);
g2d.setRenderingHints(renderHints);
}
}
thanks u ..

Trying to paint image to JFrame with Java BufferedImage, Graphics

I'm trying to capture the screen and then paint the image to a JFrame recursively while scaling the image (to create that effect you get when you look at a mirror in a mirror).
I'm having trouble with my code - it doesn't paint any graphics. What am I doing wrong?
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class ScreenCapture extends JFrame {
BufferedImage screenCapture;
Graphics screenCaptureGraphics;
private static int recurseCount = 0;
private static float $scale = 0.9f;
private static float scale = 1.0f;
private static int height;
private static int width;
ScreenCapture() {
try {
screenCapture = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
height = screenCapture.getHeight();
width = screenCapture.getWidth();
setSize(new Dimension(width, height));
addWindowListener(new LocalWindowListener());
Graphics g = recursiveDraw(screenCapture, getGraphics());
paint(g);
} catch (HeadlessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Graphics recursiveDraw(BufferedImage img, Graphics imgG) {
updateScale(++recurseCount);
float newWidth = scale*width;
float newHeight = scale*height;
int w = (int) newWidth;
int h = (int) newHeight;
System.out.println("W: " + w + "; H: " + h);
if (w >= 10 && h >= 10) {
//scale image
System.out.print("Creating scaled Image...");
Image scaled = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
imgG = resized.createGraphics();
imgG.drawImage(scaled, 0, 0, null);
System.out.println("...Image drawn to graphics");
//return new graphics
return recursiveDraw(resized, imgG);
} else {
//otherwise return old graphics
System.out.println("Completed.");
return imgG;
}
}
private void updateScale(int count) {
for (int i=0; i<count; i++) {
scale *= $scale;
}
System.out.println("Updated scale: " + scale + "; Recurse count: " + recurseCount);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ScreenCapture().setVisible(true);
}
});
}
private class LocalWindowListener extends WindowAdapter {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0); return;
}
}
}
EDIT:
This is what I tried after #andrew-thompson 's answer:
ScreenCapture() {
try {
screenCapture = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
height = screenCapture.getHeight();
width = screenCapture.getWidth();
setSize(new Dimension(width, height));
addWindowListener(new LocalWindowListener());
setLayout(new GridLayout());
add(new PaintPanel());
} catch (HeadlessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class PaintPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
g=recursiveDraw(screenCapture, g);
//what to do with g?
}
}
I still have the same problem where I don't know how to make the BufferedImage paint to the graphics.
would separate out your Swing code from your recursive image creation code. In fact consider creating a static method that creates and returns the BufferedImage and that has no Swing code in it. Then have your GUI call the method when it wishes, and take the image and either write it to disk or display it in a JLabel's ImageIcon.
When I did this (today in fact), I created a recursive method with this signature
private static void recursiveDraw(BufferedImage img, Graphics imgG, double scale) {
and with this method body (in pseudo-code)
start recursiveDraw method
// most important: all recursions must have a good ending condition:
get img height and width. If either <= a min, return
create a BufferedImage, smlImg, for the smaller image using the height,
width and scale factor
Get the Graphics object, smlG, from the small image
Use smlG.drawImage(...) overload to draw the big image in shrunken
form onto the little image
recursively call recursiveDraw passing in smlImg, smlG, and scale.
dispose of smlG
draw smlImg (the small image) onto the bigger one using the bigger's
Graphics object (passed into this method) and a different
overload of the drawImage method.
end recursiveDraw method
This algorithm resulted in images like:
For example:
import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class RecursiveDrawTest {
private static final Color BACKGRND_1 = Color.green;
private static final Color BACKGRND_2 = Color.MAGENTA;
private static final Color FOREGRND_1 = Color.blue;
private static final Color FOREGRND_2 = Color.RED;
private static void createAndShowGui() {
final JPanel mainPanel = new JPanel(new BorderLayout());
final JSlider slider = new JSlider(50, 90, 65);
slider.setMajorTickSpacing(10);
slider.setMinorTickSpacing(5);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
JPanel southPanel = new JPanel();
southPanel.add(new JLabel("Percent Size Reduction:"));
southPanel.add(slider);
southPanel.add(new JButton(new AbstractAction("Create Recursive Image") {
#Override
public void actionPerformed(ActionEvent arg0) {
try {
double scale = slider.getValue() / 100.0;
BufferedImage img = createRecursiveImg(scale);
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
Window win = SwingUtilities.getWindowAncestor(mainPanel);
JDialog dialog = new JDialog(win, "Image", ModalityType.MODELESS);
dialog.getContentPane().add(label);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
} catch (AWTException e) {
e.printStackTrace();
}
}
}));
mainPanel.add(new JScrollPane(new JLabel(new ImageIcon(createLabelImg()))),
BorderLayout.CENTER);
mainPanel.add(southPanel, BorderLayout.PAGE_END);
JFrame frame = new JFrame("RecursiveDrawTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
// create a background image to display in a JLabel so that the GUI
// won't be boring.
private static BufferedImage createLabelImg() {
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int width = (5 * d.width) / 6;
int height = (5 * d.height) / 6;
BufferedImage img = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0, 0, BACKGRND_1, 40, 40, BACKGRND_2, true));
g2.fillRect(0, 0, width, height);
g2.setPaint(new GradientPaint(0, height, FOREGRND_1, 40, height - 40, FOREGRND_2, true));
g2.fillOval(0, 0, 2 * width, 2 * height);
g2.dispose();
return img;
}
// non-recursive image to get the initial image that will be drawn recursively
public static BufferedImage createRecursiveImg(double scale) throws AWTException {
Robot robot = new Robot();
Dimension screenSz = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRect = new Rectangle(screenSz);
BufferedImage img = robot.createScreenCapture(screenRect);
Graphics g = img.getGraphics();
recursiveDraw(img, g, scale); // call recursive method
g.dispose();
return img;
}
// recursive method to draw image inside of image
private static void recursiveDraw(BufferedImage img, Graphics g, double scale) {
int w = img.getWidth();
int h = img.getHeight();
int smlW = (int)(w * scale);
int smlH = (int)(h * scale);
// criteria to end recursion
if (smlW <= 1 || smlH <= 1) {
return;
}
BufferedImage smlImg = new BufferedImage(smlW, smlH, BufferedImage.TYPE_INT_ARGB);
Graphics smlG = smlImg.getGraphics();
// draw big image in little image, scaled to little image
smlG.drawImage(img, 0, 0, smlW, smlH, null);
// recursive call
recursiveDraw(smlImg, smlG, scale);
smlG.dispose(); // clear resources when done with them
// these guys center the smaller img on the bigger
int smlX = (w - smlW) / 2;
int smlY = (h - smlH) / 2;
// draw small img on big img
g.drawImage(smlImg, smlX, smlY, smlW, smlH, null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Graphics g = recursiveDraw(screenCapture, getGraphics());
Don't call getGraphics(). Override paint(Graphics)1 & use the supplied Graphics instance.
When using Swing, it is actually best to override the paintComponent(Graphics) method of a JComponent or JPanel. Then add that to the top-level container.
Is this what you are hoping for :
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
public class CaptureScreen extends JPanel
{
private BufferedImage screenShot;
private JLabel imageLabel;
private BufferedImage secondScreenShot;
public void createAndDisplayGUI()
{
JFrame frame = new JFrame("CAPTURE SCREEN");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
//imageLabel = new JLabel();
//getImageForLabel();
//add(imageLabel);
frame.getContentPane().add(this);
frame.setSize(600, 600);
frame.setVisible(true);
}
private void getImageForLabel()
{
Robot robot = null;
try
{
robot = new Robot();
}
catch(Exception e)
{
e.printStackTrace();
}
screenShot = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIcon icon = new ImageIcon(screenShot);
imageLabel.setIcon(icon);
}
public void paintComponent(Graphics g)
{
Robot robot = null;
try
{
robot = new Robot();
}
catch(Exception e)
{
e.printStackTrace();
}
screenShot = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
secondScreenShot = getScaledImage((Image) screenShot, 300, 300);
g.drawImage(screenShot, 0, 0, null);
g.drawImage(secondScreenShot, 150, 150, null);
}
private BufferedImage getScaledImage(Image srcImg, int w, int h)
{
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new CaptureScreen().createAndDisplayGUI();
}
});
}
}
Here is the output :
Get rid of the recursion. Create a single buffered image of the correct size and create a Graphics object for it. Just use a loop to draw progressively smaller scaled images down to whatever threshold you choose. Finally use g.drawImage() inside paintComponent() to draw your image to the screen. If you keep the recursion you need to pass the image and continually overlay the scaled down image. You do not need to return anything from the method.

Categories

Resources