Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Out of the box, webdriver only takes a screenshot of the visible page area.
Following on from this post, I would like to ask how to take a full page screenshot in Selenium using Java, when the page length is greater than the viewport?
The posts describing how to do this are either unanswered (such as this one) or point towards the AShot library (such as this one) which provides the functionality, but it has some issues which means I do not want to use it. Specifically, when using a remote driver on e.g. Browserstack, it only renders the left-hand half of the screenshot. In addition it is no longer maintained by the original author and so it seems more appropriate to write a new function for what is essentially a fairly simple problem.
Prerequisite: access to an instance of WebDriver. Mine is instantiated with the class the code lives in.
The main function that coordinates the size of the screenshot and the scrolling down the page is as follows. Note that the image format is to make it compatible with pdiff :
public void takeFullScreenshot(String outputFile) throws IOException {
JavascriptExecutor js = ((JavascriptExecutor) webDriver);
// Scroll right to the top
js.executeScript("window.scrollTo(0,0)");
// Get the height of the screen
int windowHeight = ((Number) js.executeScript("return window.innerHeight")).intValue();
// Get the total height of the page
int pageHeight = ((Number) js.executeScript("return document.body.scrollHeight")).intValue();
// Calculate the number of full screen shots
double fullFraction = pageHeight / windowHeight;
int fullShots = (int) fullFraction; // this simply removes the decimals
// Initialise ouput image
int imageWidth = webDriver.manage().window().getSize().width;
BufferedImage fullScreenshot = new BufferedImage(imageWidth, pageHeight, BufferedImage.TYPE_4BYTE_ABGR);
// Get the graphics
Graphics2D fullGraphics = fullScreenshot.createGraphics();
// Calculate our scroll script
String script = "window.scrollBy(0," + String.valueOf(windowHeight) + ")";
// Loop - for the required number of full screenshots
for (int aShot = 0; aShot < fullShots; aShot ++) {
// Sort out the screenshot and paste it in the correct place
pasteScreenshot(fullGraphics, aShot * windowHeight);
// scroll
js.executeScript(script);
}
// Final phase - scroll to the bottom
js.executeScript(script); // we know this goes too far down, but should be OK.
// Take final screenshot and paste at the bottom
pasteScreenshot(fullGraphics, pageHeight - windowHeight);
// Save the whole thing to output file.
ImageIO.write(fullScreenshot, "PNG", new File(outputFile));
}
The little function that pastes the screenshot into the correct place in the output graphics is as follows:
private void pasteScreenshot (Graphics2D outputGraphics, int yCoordinate) throws IOException {
// Take screenshot and hold it as an image
File tmpFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
BufferedImage tmpImage = ImageIO.read(tmpFile);
// Draw it on the graphics of the final output image
outputGraphics.drawImage(tmpImage, null, 0, yCoordinate);
}
Hope this is useful.
Related
I am using PdfExplicitDestination as a page number, for titles by reading the existing pdf content from the page,
but I need to point the focus on specific text content while click on the bookmark.
for (int page = 1; page <= pdf.getNumberOfPages(); page++) {
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
String currentText = PdfTextExtractor.getTextFromPage(pdf.getPage(page), strategy);
if (currentText.contains("title")) {
k.addDestination(PdfExplicitDestination.createXYZ(pdf.getPage(page), pdf.getPage(page).getPageSize().getLeft(), pdf.getPage(page).getPageSize().getTop(), 0));
//System.out.println(currentText);
}
}
I need to find the position of the title in the pdf page to set "float top" value.
PdfExplicitDestination.createXYZ(pageNum, left, top, zoom)
Can any one please help to get it from the existing content in the pdf.
This task can be approached in a number of ways. One of the way is to go over page content in "stripes" (rectangles with small height), and only consider content from such a small rectangle at a time. If you find a text piece in such rectangle then you know that somewhere between upper and lower bound of Y position given by the rectangle coordinates lies the desired text content. You can e.g. create the destination to point to the topmost coordinate in that case - it might be a bit above the desired text but the difference will be small depending on the rectangle height you select.
The following code snipped contains example implementation of the presented idea. There are two parameters - windowHeight which must be tall enough to fit a piece of content you are looking for, but the smaller this variable is the better accuracy you get in the result. Parameter step defines how many such rectangles of height windowHeight we will try on each page. The smaller the parameter is the better accuracy you get, but bigger parameter values optimize performance. Up to a specific use case to tweak those trade-offs.
final float windowHeight = 30;
final float step = 10;
for (int page = 1; page <= pdf.getNumberOfPages(); page++) {
Rectangle pageSize = pdf.getPage(page).getPageSize();
for (float upperPoint = pageSize.getHeight(); upperPoint > 0; upperPoint -= step) {
IEventFilter filter = new TextRegionEventFilter(new Rectangle(0, upperPoint - windowHeight, pageSize.getWidth(), windowHeight));
LocationTextExtractionStrategy strategy = new LocationTextExtractionStrategy();
FilteredTextEventListener listener = new FilteredTextEventListener(strategy, filter);
new PdfCanvasProcessor(listener).processPageContent(pdf.getPage(page));
if (strategy.getResultantText().contains("title")) {
float top = upperPoint; // This is the topmost point of the rectangle
break; // Break here not to capture same text twice
}
}
}
scrolling is working fine in normal pages in android application.But if i click on any element it will open as a new page over existing page,there scrolling is not working in appium automation using touchaction.here is my code to scrolldown
public void scrollDown(AppiumDriver driver){
try {
int height = driver.manage().window().getSize().getHeight();
TouchAction touchAction = new TouchAction(driver);
touchAction.longPress(5, height * 2 / 3).moveTo(5, height /
3).release().perform();
}
catch(Exception e) {
e.getMessage();
}}
You are likely not starting your swipe within the boundaries of the swipe view. A good way to debug if this is the case is to activate the Pointer location option within androids developer options then watch where the automation is touching.
Now if this is the issue like I expect it is then you need to do a little bit of math around where a valid point is. I would recommend looking at the following functions
MobileElement el = myElement; // Pretend this is a real element :D
el.getSize(); // This has a getHeight() and getWidth() function
el.getLocation; // This has a getX() and getY() function
Now what you can do (assuming you are swiping in a rectangular field is find out what the smallest and largest x and y positions are.
To get the Y positions is easy simply:
int smallestY = el.getLocation.getY();
int largestY = smallestYPosition + el.getSize().getHeight();
Now to get the X positions:
int smallestX = el.getLocation.getX();
int largestX = smallestX + el.getSize().getHeight();
Now use these points when swiping.
This will work in basic cases but to my understanding if the element is wider than the screen size issues will appear so you will have to handle that.
Hopefully this helps you develop a way that works for your given case. Unfortunately with the currently given information I cannot provide an answer that will work out of the box for you.
Currently I am developing a project and it is a requirement that I screenshot the current active window on the screen (Assuming one monitor) and save it as an image.
I have worked at the following code which screenshots the entire screen:
int x = 0,y = 0;
Color suit = new Robot().getPixelColor(x, y);
Rectangle fs = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage rank = new Robot().createScreenCapture(fs);
ImageIO.write(rank, "bmp", new File("hi.bmp"));
and I am of the understanding that to get the size of the current active window one must use a method as such:
public static long getHWnd(Frame f) {
return f.getPeer() != null ? ((WComponentPeer) f.getPeer()).getHWnd() : 0;
}
however I am having trouble implementing this method into my code, and I have no previous experience working with frames or rectangles.
Could I be pointed in the right direction in terms of where to go next!
Thanks.
I use SVG Salamander to display and manipulate SVG images in Java. I managed to change fill, stroke or text of elements and display the changes.
Now I want to rotate an element. So I tried to manipulate the transformation matrix:
SVGElement e = diagram.getElement("path4150");
System.out.println(e.getPresAbsolute("transform").getStringValue());
StyleAttribute t = e.getPresAbsolute("transform");
double[] d = t.getDoubleList();
d[0] = -0.39394618;
d[1] = -0.91913346;
d[2] = 0.91913357;
d[3] = -0.39394618;
d[4] = -429.42706;
d[5] = 1513.019;
t.setStringValue("matrix(" + Joiner.on(",").join(Doubles.asList(d)) + ")");
System.out.println(e.getPresAbsolute("transform").getStringValue());
diagram.render(graphics);
Output:
matrix(0.87615346,0.48203226,-0.48203232,0.87615346,468.09264,-25.725313)
matrix(-0.39394618,-0.91913346,0.91913357,-0.39394618,-429.42706,1513.019)
As I can see in the output, the matrix is changed. But the element is not rotating in the picture.
I just started learning about this - but the SVGSalamander doc mentioned one needs to call updateTime() on a container of the element that is modified (or maybe just the root element?), to force it to redraw. If you're not using animation, then any value (0.0?) as an argument to updateTime() would do...
I've been looking for a solution for the last several days.
I've seen an example of composite images with Java Advanced Imaging. But that seems to be restricted by the smallest width and height of either image files. So it outputs a file with the height and width of the header file.
Preferably, I'd like to have the header not covering any part of the body image. But it's not a requirement. Sometimes the body image's width is smaller than the header and that's fine as the main content of the header file will be in the middle.
Using JDK 1.6.0_41, I need to take the first two images:
And have the result be:
Whether it is using Java or Javscript is fine. The entire process is as follows:
I take a canvas object of a map using OpenLayers, then use a POST to send it to a Java Servlet to be processed and stored. Then later retrieved the image if the user desires.
The long blue header needs to be at the top of an image or just above it. The header image will have content from the user that created it, etc. That I can do. But manipulating multiple images is not something I am familiar with.
In Java, you can do this:
public BufferedImage prependImage(BufferedImage image1, BufferedImage image2) {
Dimension d1 = new Dimension(image1.getWidth(null),
image1.getHeight(null));
Dimension d2 = new Dimension(image2.getWidth(null),
image2.getHeight(null));
Dimension dt = new Dimension(d1.width, d1.height + d2.height);
BufferedImage image = new BufferedImage(dt.width, dt.height,
BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
int x = 0;
int y = 0;
g.drawImage(image1, x, y, d1.width, d1.height, null);
y += d1.height;
g.drawImage(image2, x, y, d2.width, d2.height, null);
g.dispose();
return image;
}