I am writing a program to capture a screenshot of the screen when I press a particular button on my keyboard. The problem that I have is that the program won't take my screenshot if its in the background. The screenshot will only capture if my program is in the foreground.
I'm using the robot class to capture and save the screenshot. I have my program below...
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.awt.AWTException;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.KeyEventDispatcher;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
public class FullScreenCaptureExample{
private static int num = 1;
public static void main(String[] args) throws AWTException{
final File file = new File("C:\\screenshots");
final Robot rbt = new Robot();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setBounds(100, 100, 190, 73);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
if(!file.exists()){
file.mkdir();
}
KeyEventDispatcher dispatcher = new KeyEventDispatcher(){
public boolean dispatchKeyEvent(KeyEvent e){
if (e.getKeyCode() == KeyEvent.VK_5){
try {
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage screenshot = rbt.createScreenCapture(screenRect);
ImageIO.write(screenshot, "jpg", new File(file + "/" + num + ".jpg"));
num++;
System.out.println("screenshot taken");
} catch (Exception e1) {
e1.printStackTrace();
}
}
return false;
}
};
DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(dispatcher);
}
}
I'm wondering if there is a java class or some other way to get user input without having the program run in the foreground.
Thank you
Related
My Java code below places a image on a label.The button when triggered should export the image. There are no runtime error but nothing is being exported. I assume the issue is during the conversion from image icon to buffered image which occurs in b3.addActionListener(new ActionListener() {. I am not seeing anything exported at all not even a blank image.
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ren {
Frame f;
JLabel b2 = new JLabel("");
ren() throws IOException {
f = new JFrame();
b2.setIcon(new ImageIcon("/Users/johnzalubski/Desktop/dropIn/Complete-Audi-Buying-Guide-gear-patrol-lead-full.jpg"));
JButton b3 = new JButton("Exported");
File file = new File("aa.png");
f.add(b2, BorderLayout.CENTER);
f.add(b3, BorderLayout.SOUTH);
f.setSize(400, 500);
f.setVisible(true);
b3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Icon ico = b2.getIcon();
// Create a buffered image
BufferedImage bimg = new BufferedImage(ico.getIconWidth(), ico.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
// Create the graphics context
Graphics g = bimg.createGraphics();
// Now paint the icon
ico.paintIcon(null, g, 0, 0);
g.dispose();
BufferedImage scaledButtonImage =
new BufferedImage(400, 1000, bimg.getType());
Graphics g1 = scaledButtonImage.createGraphics();
g1.drawImage(scaledButtonImage, 0, 0, 400, 1000, null);
//
g1.dispose();
b2.setIcon(new ImageIcon(bimg));
try {
ImageIO.write(bimg, "png", file);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
}
public static void main(String[] args) throws IOException {
new ren();
}
}
today I kinda fiddled around with image opening/scaling/displaying in Java and wrote a bit of code to open an Image File, scale it randomly and display it for a short time.
The problem is: After displaying it for like 100-1000 times, the used memory of my "javaw.exe" grows and grows, it even reached 1 GB of memory space.
I dont know where the memory leak in my code is since the only memory eating things are my picures and there are only 2 (the original image and the one who is getting scaled, which is always assigned to the same variable(temp) so the "older" ones should be picked off by the GC), maybe you guys could have a look over it, its pretty simple.
1) You choose an image from your hard drive
2) It gets scaled randomly
3) Its displayed for a short amount of time and then disappears
4) go to 2)
To scale the image I used this library: http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.imgscalr.Scalr;
public static void main(String[] args) throws IOException, InterruptedException {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(null);
BufferedImage originalImage = ImageIO.read(chooser.getSelectedFile());
BufferedImage temp;
while(true){
int width = (int) ((Math.random()*1000)+1);
int height = (int) ((Math.random()*1000)+1);
Thread.sleep(1000);
temp = Scalr.resize(originalImage,Scalr.Mode.FIT_EXACT, width, height);
showImage(temp, 800);
}
}
static void showImage(BufferedImage v,long length) throws InterruptedException {
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(v)));
frame.setSize(v.getWidth(), v.getHeight());
frame.setVisible(true);
Thread.sleep(length);
frame.setVisible(false);
}
This is my first time posting here, so please ask questions if I am unclear
thanks in advance!
EDIT: I monitored the memory javaw.exe is needing
1 picture displayed: 75M
100 pictures displayed: 330M
1000 pictures displayed: 2,4G
EDIT 2:
I now have applied your helpful advice but I still have a growing amount of memory and my Images arent displayed anymore.. The JFrames are empty.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import org.imgscalr.Scalr;
public class App {
public static void main(String[] args) throws IOException, InterruptedException {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(null);
BufferedImage originalImage = ImageIO.read(chooser.getSelectedFile());
BufferedImage temp;
JFrame frame = new JFrame();
while(true){
int width = (int) ((Math.random()*1000)+1);
int height = (int) ((Math.random()*1000)+1);
Thread.sleep(1000);
temp = Scalr.resize(originalImage,Scalr.Mode.FIT_EXACT, width, height);
showImage(temp, 500, frame);
}
}
static void showImage(BufferedImage v,long length, JFrame frame) throws InterruptedException {
SwingUtilities.invokeLater(
() -> {
frame.removeAll();
frame.revalidate();
frame.repaint();
frame.add(new JLabel(new ImageIcon(v)));
frame.setSize(v.getWidth(), v.getHeight());
frame.setVisible(true);
try {
Thread.sleep(length);
} catch (Exception e) {}
frame.setVisible(false);
frame.dispose();
});
}
}
Maybe I put your advice in the wrong places in my code.
The code below should do what you want. I used a Timer instead of Thread.sleep. You're tying up the EDT. I also just draw the image in the container. You should probably use a JPanel instead (add it to the JFrame and override its paintComponent method). I also cleaned up the methods a little.
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Graphics;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import org.imgscalr.Scalr;
public class App extends JFrame implements ActionListener{
BufferedImage originalImage = null;
BufferedImage temp = null;
JFileChooser chooser = null;
public App(){
setVisible(true);
}
public static void main(String[] args) throws IOException, InterruptedException {
SwingUtilities.invokeLater(
() -> {
App app = new App();
Timer timer = new Timer(1000, app);
timer.start();
});
}
#Override
public void actionPerformed(ActionEvent ae){
if(null == chooser){
chooser = new JFileChooser();
chooser.showOpenDialog(this);
loadImage();
}
showImage();
repaint();
}
#Override
public void paint(Graphics g){
super.paint(g);
if(null == temp){
return;
}
g.drawImage(temp, 0, 0, null);
}
public void loadImage(){
try{
originalImage = ImageIO.read(chooser.getSelectedFile());
} catch(IOException ioe){
ioe.printStackTrace();
}
}
public void showImage() {
int width = (int) ((Math.random()*1000)+1);
int height = (int) ((Math.random()*1000)+1);
temp = Scalr.resize(originalImage,Scalr.Mode.BEST_FIT_BOTH, width, height);
setSize(width, height);
}
}
You might want to try
originalImage.flush();
originalImage = null;
temp.flush();
temp = null;
but there is no guarantee when your image will get garbage collected
Apart from that you should also consider clearing and reusing the same JFrame.
removeAll();//or remove the previous JLabel
revalidate();
repaint();
Also the proper way to display a JFrame is by using the SwingUtilities invokeLater method to make sure this "job" is placed on the Event Dispatch Thread (EDT).
// schedule this for the event dispatch thread (edt)
SwingUtilities.invokeLater(yourJFrame);
I am looking to build a program to show pictures to friends and family. With the regular Windows Image Viewer there is a lot of unused screen space and it does not react on the USB presenter that I use for PPT presentations.
My idea is to have the user select a folder (easy), all images in that folder will be selected and the JFrame will display the first image in full screen mode (easy). On right arrow (easy) the presentation will jump to the next picture from the selection (difficult). Sounds simple, but I can't solve it.
Here is my code so far after Andrews suggestion:
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
class ArrowAction extends AbstractAction {
private String cmd;
public ArrowAction(String cmd) {
this.cmd = cmd;
}
#Override
public void actionPerformed(ActionEvent e) {
if (cmd.equalsIgnoreCase("Backward")) {
System.out.println("Previous picture!");
} else if (cmd.equalsIgnoreCase("Forward")) {
System.out.println("Next Picture!");
}
}
}
class TestKeyBinding {
public TestKeyBinding() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = panel.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "Forward");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Backward");
am.put("Forward", new ArrowAction("Forward"));
am.put("Backward", new ArrowAction("Backward"));
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
gs.setFullScreenWindow(frame);
BufferedImage myPicture;
try {
myPicture = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/commons/1/13/Vancouver_ib.jpg"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
panel.add(picLabel);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
frame.add(panel);
frame.validate();
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestKeyBinding kb = new TestKeyBinding();
}
}
Any idea how to do the onKeyEvent and have the next image displayed? And any other best practices that I should get used to?
Thanks,
Florian
So, I know that images can be cropped, shrunk, and expanded, but can you adapt an image into the shape of a parallelogram? I'm using Java Swing to draw images. I was thinking maybe some class or some method of BufferedImage might do the trick, but I couldn't find anything. I have also searched Google for a while, but I cannot find an answer. Does anyone know of a way I could do this, or a webpage that explains it? Thanks in advance.
You could use AffineTransform.getShearInstance.
This example uses a AffineTransformOp to "filter" the original image
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SkewImage {
public static void main(String[] args) {
new SkewImage();
}
public SkewImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(1, 2));
try {
BufferedImage original = ImageIO.read(new File("C:\\hold\\thumbnails\\Megatokyo_707___Torn_by_crusaderky.jpg"));
BufferedImage skew = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB);
// Adjust the image width if we use a negative skew...
double skewX = 0.3d;
double x = (skewX < 0) ? -skewX * original.getHeight() : 0;
AffineTransform at = AffineTransform.getTranslateInstance(x, 0);
at.shear(skewX, 0);
AffineTransformOp op = new AffineTransformOp(at,
new RenderingHints(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC));
skew = op.filter(original, null);
add(new JLabel(new ImageIcon(original)));
add(new JLabel(new ImageIcon(skew)));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Just an example using a Java image processing framework.
Output:
public class SkewExample extends JFrame{
MarvinImagePlugin skew = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.transform.skew");
public SkewExample(){
super("Skew Example");
// Layout
setLayout(new GridLayout(6,1));
// Load Image
MarvinImage image = MarvinImageIO.loadImage("./res/chamaleon.jpg");
skew.setAttribute("skew", "Horizontal");
// Process the image multiple times with different angle.
for(int i=1; i<=6; i++){
add(new JLabel(new ImageIcon(skew(image, i*7).getBufferedImage())));
}
setSize(340,880);
setVisible(true);
}
private MarvinImage skew(MarvinImage imageIn, int angle){
skew.setAttribute("SkewAngle", angle);
MarvinImage ret = new MarvinImage(imageIn.getWidth(),imageIn.getHeight());
ret.fillRect(0, 0,imageIn.getWidth(),imageIn.getHeight(), new Color(238,238,238));
ret.update();
skew.process(imageIn, ret);
ret.update();
return ret;
}
public static void main(String[] args) {
new SkewExample().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I'm trying to set up face detection with JavaCV. I've got working code with cvLoadImage but when I try to load an image via Highgui.imread there's an error: 'Highgui cannot be resolved' and 'Highgui' has red wavy underlining. For some reason Eclipse cannot deal properly with imported com.googlecode.javacv.cpp.opencv_highgui or ...?
Problem here:
CvMat myImg = Highgui.imread(myFileName);
Full code:
import java.awt.EventQueue;
import java.awt.Insets;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import com.googlecode.javacv.cpp.opencv_core.CvMemStorage;
import com.googlecode.javacv.cpp.opencv_core.CvRect;
import com.googlecode.javacv.cpp.opencv_core.CvScalar;
import com.googlecode.javacv.cpp.opencv_core.CvSeq;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.googlecode.javacv.cpp.opencv_objdetect.CvHaarClassifierCascade;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import java.awt.Button;
import java.io.File;
import javax.swing.SwingConstants;
import javax.swing.JLabel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import com.googlecode.javacv.cpp.opencv_core.CvMat;
import com.googlecode.javacv.cpp.opencv_highgui;
//import opencv_highgui;
public class Form1 {
static private final String newline = "\n";
JButton openButton, saveButton;
JTextArea log;
JFileChooser fc;
String myFileName = "";
//Load haar classifier XML file
public static final String XML_FILE =
"resources/!--master--haarcascade_frontalface_alt_tree.xml";
private JFrame frame;
//Detect for face using classifier XML file
public static void detect(IplImage src){
//Define classifier
CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad(XML_FILE));
CvMemStorage storage = CvMemStorage.create();
//Detect objects
CvSeq sign = cvHaarDetectObjects(
src,
cascade,
storage,
1.1,
3,
0);
cvClearMemStorage(storage);
int total_Faces = sign.total();
//Draw rectangles around detected objects
for(int i = 0; i < total_Faces; i++){
CvRect r = new CvRect(cvGetSeqElem(sign, i));
cvRectangle (
src,
cvPoint(r.x(), r.y()),
cvPoint(r.width() + r.x(), r.height() + r.y()),
CvScalar.RED,
2,
CV_AA,
0);
}
//Display result
cvShowImage("Result", src);
cvWaitKey(0);
}
/**
* Create the application.
*/
public Form1() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
JLabel Label1 = new JLabel(" ");
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 301, 222);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDetect = new JButton("Detect");
btnDetect.setVerticalAlignment(SwingConstants.TOP);
btnDetect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//IplImage img = cvLoadImage("resources/lena.jpg");
IplImage img = cvLoadImage(myFileName);
CvMat myImg = Highgui.imread(myFileName);
detect(img);
}
});
frame.getContentPane().add(btnDetect, BorderLayout.SOUTH);
Label1.setHorizontalAlignment(SwingConstants.CENTER);
frame.getContentPane().add(Label1, BorderLayout.CENTER);
JButton btnNewButton = new JButton("Open");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JFileChooser fileopen = new JFileChooser();
int ret = fileopen.showDialog(null, "Открыть файл");
if (ret == JFileChooser.APPROVE_OPTION) {
File file = fileopen.getSelectedFile();
myFileName = file.getAbsolutePath();
Label1.setText(myFileName);
}
}
});
frame.getContentPane().add(btnNewButton, BorderLayout.NORTH);
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Form1 window = new Form1();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
//Load image
//IplImage img = cvLoadImage("resources/lena.jpg");
//detect(img);
}
}
External JARs: http://pasteboard.co/jwqNHC9.png
Full project in ZIP
I've also followed all steps from here: http://opencvlover.blogspot.in/2012/04/javacv-setup-with-eclipse-on-windows-7.html
Any help will be appreciated.
Mat m = Highgui.imread(myFileName); is from the builtin opencv java wrappers , not from javacv ( which is a independant, 3rd party wrapper ).
unfortunately, both concurrent apis are pretty incompatible, as javacv is wrapping the outdated c-api, and the opencv ones are wrapping the more modern c++ api.