This question already has an answer here:
How to save a high DPI snapshot of a JavaFX Canvas
(1 answer)
Closed 7 years ago.
I'm trying to save a snapshot of my application to disk using JavaFX 2, which should be easy considering FX comes with a built-in snapshot function. It does work, however, the image is fuzzy. The application I'm building relies greatly on getting these images to save clear and crisp. Anyone know why this happens? Or how to fix it so it saves what I'm actually seeing when the app runs?
The top image is what saved to disk, the bottom is my app running:
My code for saving the scene is below:
try
{
WritableImage wi = new WritableImage((int) scene.getWidth(), (int) scene.getHeight());
WritableImage snapshot = scene.snapshot(wi);
File output = new File("Full.png");
ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", output);
} catch (IOException ex) {
ex.printStackTrace();
}
It looks as if you are running your code on a Mac with Retina display. If that is the case, the answer is here:
How to save a high DPI snapshot of a JavaFX Canvas
Related
For some reason, my application is not showing JPG files within a JavaFX window. It does not matter if I'm trying to display the image inside an ImageViewer node or setting it as a background with the CSS -fx-background-image: url(...); property.
I have tried with different jpg files. It did not work.
I have tried with different image extensions (png, gif). It did work.
I'm using OpenJDK 16+36 (I tested with Hotspot and OpenJ9 JVM), JavaFX 16, my operating system is Linux 5.11.16 and my window manager is GNOME Shell 3.38.4.
PS: Needless to say, the operating system handles JPG images without any problems.
What could be causing this behavior?
Edit 1:
For me, nothing that involves jpeg is working on JavaFX. Wether I try to use jpeg as an background-image, like this very Oracle's sample, or within an ImageViewer, the result is the same (the window opens normally, as if I hadn't put any image). If I replace the file with a different extension, it works perfectly. The funny thing is that jpeg is working without issues in Swing.
Here's one sample of the possible situations in which the issue happens:
/**
* JavaFX Application
*/
#Override
public void start(Stage primaryStage) throws Exception {
// opens a window with the image without issue and prints true
var fileUrl = getClass().getResource("/freemind.png");
var image = new Image(fileUrl.toExternalForm());
var imageViewer = new ImageView(image);
var vbox = new VBox(imageViewer);
var scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
System.out.println(new File(fileUrl.getFile()).exists());
}
But when I replace the fileUrl with another existing jpg file, in the same directory, it opens a blank window, and prints true.
Edit 2:
I found the -Dprism.verbose=true -Djavafx.verbose=true debug flags, which were unknown to me, and they print the problem:
Stack trace here
Some JPEG library, which I am not sure whether it comes embedded in the JavaFX SDK or is related to the operating system is in a different version than the expected. Now, which library is that, I don't know!
rpm -qa | grep -P jpe?g returns:
libjpeg-turbo-2.0.5-5.fc33.i686
libjpeg-turbo-2.0.5-5.fc33.x86_64
libjpeg-turbo-devel-2.0.5-5.fc33.x86_64
mjpegtools-libs-2.1.0-20.fc33.x86_64
openjpeg2-2.3.1-10.fc33.x86_64
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm automating our organization's supply ordering system. Under the current (paper) system, we need to attach a printout of the web page displaying the requested item if we're ordering off of a web site. The system I'm writing has a method to upload scanned documents, but I'd like to make it one-click operation instead of printing the web page, scanning it, then uploading the file of the scan.
I found this code to convert the page into an image, and it does work, but the image created is based off of the html (which makes sense), but not what is displayed in browser.
For example, I'm viewing this item:
When I run the url through the code, this is the returned image:
The project is Java web using a servlet. The servlet code:
try {
if (request.getParameter("formType").equalsIgnoreCase("addReference")) {
String url = request.getParameter("url");
BufferedImage bi = WebImage.create(url, 800, 600);
File tmpFile = new File("c:/testimages/url2img.png");
ImageIO.write(bi, "png", tmpFile);
} catch (Exception e) {
e.printStackTrace();
}
The code from the link above:
public abstract class WebImage {
static class Kit extends HTMLEditorKit {
#Override
public Document createDefaultDocument() {
HTMLDocument doc
= (HTMLDocument) super.createDefaultDocument();
doc.setTokenThreshold(Integer.MAX_VALUE);
doc.setAsynchronousLoadPriority(-1);
return doc;
}
}
public static BufferedImage create(String src, int width, int height) {
BufferedImage image = null;
JEditorPane pane = new JEditorPane();
Kit kit = new Kit();
pane.setEditorKit(kit);
pane.setEditable(false);
pane.setMargin(new Insets(0, 0, 0, 0));
try {
pane.setPage(src);
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
Container c = new Container();
SwingUtilities.paintComponent(g, pane, c, 0, 0, width, height);
g.dispose();
} catch (Exception e) {
System.out.println(e);
}
return image;
}
}
Is there any way to return an image of the url as displayed by the browser?
You're using Java, so there's actually a really simple solution. Browser automation is a (mostly) solved problem with Selenium.
Here is some sample code, just note that it's not particularly robust if the page takes longer than usual to load but it should suffice to demonstrate the steps necessary to do what you want. Also note, that if this needs to run headlessly you might want to look into JBrowserDriver instead of the FireFox driver.
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("https://www.amazon.com/I-Robot-Isaac-Asimov/dp/055338256X/ref=sr_1_2?ie=UTF8&qid=1496161782&sr=8-2&keywords=Asimov");
// This move is necessary, the original file is temporary and gets deleted after java exists
File resultingScreenshot = new File(System.getProperty("user.home"), "screenshot.png");
Files.move(screenshotFile, resultingScreenshot);
driver.quit();
System.out.println("The screenshot is found here: " + resultingScreenshot);
You need a fully fledged browser with all of its support for tonnes of web standards (HTML, CSS, JS) in order to achieve what you want. Otherwise you will often be capturing badly rendered images by a substandard web browser.
Have a look at Selenium as suggested by BCqrstoO.
Additionally there are also Headless Chrome which comes with Chrome 59 (yet to come for Windows)
or PhantomJS which unfortunately is no longer maintained, and therefore the ability to render latest and greatest pages will diminish over time.
I'm doing a program to create a die (cube) with different image textures based on the input of the user (user choose images on a SWT GUI).
Once the user choose the images, it can visualize the dice on a separate dialog, and perform some rotate operations over it (see, after perform a small rotation to see three faces in the screenshots).
See screenshots: http://pastebin.com/XqJfXL6i
And my problem starts here: I want to save the content of the canvas (the dice with the background in its current form, after being rotated). I've been searching for several codes and I think that my problem is because my current canvas is an "on-screen" canvas and I need an off-screen canvas, which will allow to save the content.
My current code is the following:
http://pastebin.com/ZAv0ATJN
And.. here starts the problem. It throws this exception:
java.lang.IllegalStateException: Canvas3D: Not in off-screen mode
Concretely it fails in this line:
ImageComponent2D ic2d = canvas.getOffScreenBuffer();
As you can see there are several lines commented that I tried before, but they didn't work neither.
Any clue about how to do it?
Thanks!
Based on the comment provided by gouessej (thanks!) finally I use this code, which works fine for my doubt:
private void saveImage(String img) throws Exception {
FileOutputStream fileOut = new FileOutputStream(img);
Robot r = new Robot();
BufferedImage bi = r.createScreenCapture(new java.awt.Rectangle(
(int) frame.getLocationOnScreen().getX(), (int) frame
.getLocationOnScreen().getY(), frame.getBounds().width,
frame.getBounds().height));
ImageIO.write(bi, "jpeg", fileOut);
fileOut.flush();
fileOut.close();
}
Is it possible to take a screen capture of a specific application/exe launched on Windows in Java?
I tried this code but it does not take a capture of the application itself and return a black picture:
try {
...
Robot robot = new Robot();
Rectangle captureSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage bufferedImage = robot.createScreenCapture(captureSize);
ImageIO.write(bufferedImage,"png",myFile);
...
} catch(AWTException e) {
System.err.println("call a doc!");
}
This is why I think that forcing a screenshot linked with the process launched may solve the problem.
Or maybe they are other ways to take a capture of the displayed screen? (if yes could you please show me some working code?)
There are a few questions here on SO about capturing screenshots of an android application. However, I haven't found a solid solution on how to take a screenshot programatically using the android SDK or any other method.
So I thought I would ask this question again in the hopes that I can find a good solution, hopefully one that will allow capturing full length images that I can save to the SD card or somewhere similar.
I appreicate any help
This is not possible directly on the device/emulator, unless it is rooted.
to honest all I need it for is the emulator as this is for a testing application on a PC
This sounds like a job for monkeyrunner.
monkeyrunner tool can do the job for you with bit of adb command, [python script]
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
//waits for connection
device = MonkeyRunner.waitForConnection()
//take the current snapshot
device.takeSnapshot()
//stores the current snapshot in current dir in pc
device.writeToFile('current.png')\
//copy it to the sd card of device
os.subprocess.call('adb push current.png /sdcard/android/com.test.myapp/current.png')
Note: call this jython script file
monkeyrunner.bat <file name>
You will most likely not be happy with this answer, but the only ones that I have seen involve using native code, or executing native commands.
Edit:
I hadn't seen this one before. Have you tried it?:
http://code.google.com/p/android-screenshot-library/
Edit2: Checked that library, and it also is a bad solution. Requires that you start the service from a pc. So my initial answer still holds :)
Edit3: You should be able to save a view as an image by doing something similar to this. You might need to tweek it a bit so that you get the width/height of the view. (I'm inflating layouts, and specify the width/height when I layout the code)
View content = getView();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
File file = new File(pathAndFilename);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
You can look at http://codaset.com/jens-riboe/droidatscreen/wiki (with a write up at http://blog.ribomation.com/2010/01/droidscreen/): this is a Java library that uses adb to capture a screen shots. I've been able to (with a lot of elbow grease) modify the source to let me automatically capture a timed series of screen shots (which I use for demo videos).
You can see the class structure at http://pastebin.com/hX5rQsSR
EDIT: You'd invoke it (after bundling all the requirements) like this:
java -cp DroidScreen.jar --adb "" --device "" --prefix "" --interval