Capture screenshot of all the elements present on a page - selenium

I'm trying to capture the screenshot of all the elements present on a webpage and want to store it in my disk for which i have written the below code.
The only issue is this piece of code is working only for the first iteration and after which some unexpected thing is happening.
List<WebElement> eleId = driver.findElements(By.xpath("//*[#id]")); //fetch all the elements with ID attribute
System.out.println(eleId.size());
for (int i = 0;i < eleId.size();i++) {
// Get entire page screenshot
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
// Get the location of element on the page
Point point = eleId.get(i).getLocation();
// Get width and height of the element
int eleWidth = eleId.get(i).getSize().getWidth();
int eleHeight = eleId.get(i).getSize().getHeight();
// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot = fullImg.getSubimage(point.getX(), point.getY(), eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);
// Creating variables name for image to be stores in the disk
String fileName = eleId.get(i).getAttribute("id");
String imageLocation = "D:\\" + fileName + ".png";
// System.out.println(imageLocation);
// Copy the element screenshot to disk
File screenshotLocation = new File(imageLocation);
FileUtils.copyFile(screenshot, screenshotLocation);
System.out.println("Screenshot has been stored.");
}

Hi Sandeep try below code. It is working for me. I just added one "if" condition to check the image height and width.
#Test(enabled=true)
public void getIndividualElementScreenShot() throws IOException{
WebDriver driver = new FirefoxDriver();
driver.get("http://www.google.com/");
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
List<WebElement> eles = driver.findElements(By.xpath("//*[#id]"));
System.out.println(eles.size());
for(WebElement ele : eles){
//Get Entire page screen shot
File screenShot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImage = ImageIO.read(screenShot);
//Get the location on the page
Point point = ele.getLocation();
//Get width and height of an element
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();
//Cropping the entire page screen shot to have only element screen shot
if(eleWidth != 0 && eleHeight != 0){
BufferedImage eleScreenShot = fullImage.getSubimage(point.getX(), point.getY(), eleWidth, eleHeight);
ImageIO.write(eleScreenShot, "png", screenShot);
//Creating variable name for image to be store in disk
String fileName = ele.getAttribute("id");
String imageLocation = "F:\\ElementImage\\"+fileName+".png";
System.out.println(imageLocation);
//Copy the element screenshot to disk
File screenShotLocation = new File(imageLocation);
org.apache.commons.io.FileUtils.copyFile(screenShot, screenShotLocation);
System.out.println("Screen shot has beed stored");
}
}
driver.close();
driver.quit();
}

Your code is doing fine. But you are overwriting the file in each iteration. Did you get it? Change file name in each iteration by assigning new file name in fileName variable. Use the code below:
List<WebElement> eleId = driver.findElements(By.xpath("//*[#id]")); //fetch all the elements with ID attribute
System.out.println(eleId.size());
for (int i = 0;i < eleId.size();i++) {
// Get entire page screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
// Get the location of element on the page
Point point = eleId.get(i).getLocation();
// Get width and height of the element
int eleWidth = eleId.get(i).getSize().getWidth();
int eleHeight = eleId.get(i).getSize().getHeight();
// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot = fullImg.getSubimage(point.getX(), point.getY(), eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);
// Creating variables name for image to be stores in the disk
String fileName = eleId.get(i).getAttribute("id");
String imageLocation = "D:/" + fileName + i + ".png";
// System.out.println(imageLocation);
// Copy the element screenshot to disk
File screenshotLocation = new File(imageLocation);
FileUtils.copyFile(screenshot, screenshotLocation);
System.out.println("Screenshot has been stored.");
}

Related

itext7 html2pdf is not able to render vector images

We have .net Web API to generate pdf based on certain parameters, this pdf will have images in .eps and .ai (vector images). We are using itext7 html2pdf and passing html as string to the method ConvertToPdf but it's not able to recognize those vector images.
Need help to add vector image in pdf to retain the image quality in pdf and the file size should not increase more than 2MB.
Please find code snippet:
public string GenerateHtmlToPdf(string html , string fileName)
{
//generate pdf from html using iText7
try
{
string filePath = WebConfigurationManager.AppSettings["filePath"];
FileStream finalPdfPath = new FileStream(filePath + "\\" + fileName + ".pdf", FileMode.Create);
string finalPath = filePath + fileName + ".pdf";
PdfFontFactory.RegisterDirectory(FONTDIR);
var NewTransportBold = PdfFontFactory.CreateRegisteredFont("NewTransport-Bold", PdfEncodings.IDENTITY_H);
var NewTransportNormal = PdfFontFactory.CreateRegisteredFont("NewTransport-Regular", PdfEncodings.IDENTITY_H);
var NewTransportLight = PdfFontFactory.CreateRegisteredFont("NewTransport-Light", PdfEncodings.IDENTITY_H);
HtmlConverter.ConvertToPdf(html, finalPdfPath);
return finalPath;
}
catch (IOException ex)
{
var exists = File.Exists("File already exist on desktop");
return "file exist";
}
//end
}
As for pdfs, it is not possible to add svg formats.Hence the svg image would have to be added to the document where the html was set separately.For this a NuGet package named Svg is used.
public void AddSVG(string resourceLocator, float x, float y, int page, int scalePresent = 100)
{
var webClient = new WebClient();
MemoryStream memoryFile = new MemoryStream(webClient.DownloadData(resourceLocator));
SvgDocument memorySVGFile = SvgDocument.Open<SvgDocument>(memoryFile);//get the img as svg doc
var imgconv = memorySVGFile.Draw(3000, 3000);
MemoryStream imgStream = new MemoryStream();
imgconv.Save(imgStream, ImageFormat.Png);//convert svg doc in to a png and save in a mem stream
Image img = new Image(ImageDataFactory.Create(imgStream.ToArray())); //create itext image object from byte array
img.SetFixedPosition(page,x, y, 550);
doc.Add(img);
memoryFile.Close();
}
here the string resourceLocator is the path to the svg. And "doc." is the pdf document where the html was converter to a pdf document.

Selenium Marionette getLocation nullpointer

I'm encountering:
Exception in thread "main" java.lang.NullPointerException at org.openqa.selenium.remote.RemoteWebElement.getLocation(RemoteWebElement.java:338)
while trying to get a BufferedImage of the captcha at https://signup.live.com/:
public BufferedImage getCaptchaBufferedImage() throws IOException, InterruptedException {
System.out.println("Looking for captcha image");
this.wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("hipTemplateContainer")));
System.out.println("Found image");
WebElement element = this.driver.findElement(By.id("hipTemplateContainer"));
System.out.println(element.getAttribute("outerHTML"));
List<WebElement> childs = element.findElements(By.xpath(".//*"));
WebElement firstChild = childs.get(0);
System.out.println(firstChild.getAttribute("outerHTML"));
List<WebElement> childs2 = firstChild.findElements(By.xpath(".//*"));
WebElement imageChild = childs2.get(0);
System.out.println(imageChild.getAttribute("outerHTML"));
((JavascriptExecutor) this.driver).executeScript("arguments[0].scrollIntoView(true);", imageChild);
String id = imageChild.getAttribute("id");
this.wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(id)));
**Point point = firstChild.getLocation();**
byte[] img_bytes = ((TakesScreenshot) this.driver).getScreenshotAs(OutputType.BYTES);
BufferedImage imageScreen = ImageIO.read(new ByteArrayInputStream(img_bytes));
System.out.println("Downloaded image");
double d = Double.parseDouble(firstChild.getCssValue("height").split("px")[0]);
int height = (int) d;
double e = Double.parseDouble(firstChild.getCssValue("width").split("px")[0]);
int width = (int) e;
BufferedImage captcha = imageScreen.getSubimage(point.getX(), point.getY(), width, height);
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(new JLabel(new ImageIcon(captcha)));
frame.pack();
frame.setVisible(true);
return captcha;
}
I've looked all over the net, can't figure this one out.. Possible bug in Selenium 3.0? This code works if I skip getting the offset of the image and just hardcode the values in getSubImage()..
I tried for more than 2 hours and guess what? I found the issue.
Issue:
It is because getScreenshotAs is taking only the visible part of the page (after scrolling to the captcha) but not complete the page, hence resulting in all the issues. It resulted in the Y coordinate returned by the Point (1041), is relative to the complete web page, but the screenshot image has different Y-coordinate for the captcha (300) relative to the partial page. hence resulted in the following exception:
java.awt.image.RasterFormatException: (y + height) is outside of Raster
X-coordinate is the same value in both complete web page and partial
web page.
so, hardcoding the Y-coordinate to 300 solved the issue temporararliy. BUt the actual issue is that why screenshot is not taken for the complete page instead of jus visible page. may be the bug in the latest geckodriver (firefox driver). tried in Firefox 49 version with Selenium 3 version, geckodriver v0.1.11 and Java 1.8.
Following is the code. please try and let me know:
driver.get("https://signup.live.com/");
driver.manage().window().maximize();
System.out.println("Looking for captcha image");
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("hipTemplateContainer")));
System.out.println("Found image");
WebElement element = driver.findElement(By.id("hipTemplateContainer"));
System.out.println(element.getAttribute("outerHTML"));
List<WebElement> childs = element.findElements(By.xpath(".//*"));
WebElement firstChild = childs.get(0);
System.out.println(firstChild.getAttribute("outerHTML"));
List<WebElement> childs2 = firstChild.findElements(By.xpath(".//*"));
WebElement imageChild = childs2.get(0);
System.out.println(imageChild.getAttribute("outerHTML"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", imageChild);
String id = imageChild.getAttribute("id");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(id)));
Point point = imageChild.getLocation();
int width = imageChild.getSize().getWidth();
int height = imageChild.getSize().getHeight();
System.out.println("height: " + height + "\t weight : " + width);
System.out.println("X co-ordinate: " + point.getX());
System.out.println("Y co-ordinate: " + point.getY());
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshot, new File("G:\\naveen\\screenshot.png"));
BufferedImage imageScreen = ImageIO.read(screenshot);
System.out.println("Downloaded image");
BufferedImage captcha = imageScreen.getSubimage(245, 300, width, height);
ImageIO.write(captcha, "png", screenshot);
FileUtils.copyFile(screenshot, new File("G:\\naveen\\screenshot1.png"));
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(new JLabel(new ImageIcon(captcha)));
frame.pack();
frame.setVisible(true);
Following are screenshots saved:
Only visible web page is saved.
sub image - captcha image:

JAVA Selenium Webdriver Capturing wrong region in the screenshot

I am using selenium Web Driver(Java) to automate our web application.
I need to capture and compare the each icon of the application in all browsers.
For that first I've opened the application in Firefox and captured icons images with its xpath and then saving them at a particular path.
Later comparing the saved images when the application opened in another browser.
For this I have used the below code to capture the images, but the element image is not capturing, some unknown region in the screen is saving.
Please help, how to get the correct image of the element.
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
Point point = x.getLocation();
//Get width and height of the element
int eleWidth = x.getSize().getWidth();
int eleHeight = x.getSize().getHeight();
Rectangle rect = new Rectangle(point.getX(),point.getY(),eleWidth, eleHeight);
//Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(), rect.width, rect.height);
ImageIO.write(eleScreenshot, "png", screenshot);
//Copy the element screenshot to disk
FileUtils.copyFile(screenshot, new File("E:\\ICONS\\Icon1.jpg"));
driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(By.xpath("//*[#id='CWinBtn']")));
WebElement ele =driver.findElement(By.xpath("//*[#id='CCDLinkedformToolbar_cmdPrint']"));
try{
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);
Point point = ele.getLocation();
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX()+30, 95, eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);
FileUtils.copyFile(screenshot, new File("E:\\ ICONS\\Icon1.png"));
}
catch(Exception e){
e.printStackTrace();
}
Changes that i have made to my previous code are, added value to X coordinate and passed static value to Y coordinate, as per my application resolution.

Accessing saved image on a Windows Phone

I am creating a camera app for the Windows Phone but when I want to retrieve my saved photo as a BitmapImage, nothing seems to work. I am using IsolatedStorageSettings to save the path of the images as shown below:
Picture p = mediaLibrary.SavePictureToCameraRoll(fileName, e.ImageStream);
if (!settings.Contains("lastImageTaken"))
{
//GetPath() requires using Microsoft.Xna.Framework.Media.PhoneExtensions;
settings.Add("lastImageTaken", p.GetPath());
}
else
{
settings["lastImageTaken"] = p.GetPath();
}
settings.Save();
then once the app starts up, I try to retrieve that last photo taken as shown below:
lastImageTaken = IsolatedStorageSettings.ApplicationSettings["lastImageTaken"] as string;
Uri uri = new System.Uri(lastImageTaken, UriKind.RelativeOrAbsolute);
BitmapImage image = new BitmapImage(uri);
previouseImage.Source = image;
if (image.PixelWidth < 1)
debugText.Text += " FAILED";
I have also tried something like this:
Uri uri = new System.Uri("file:///" + lastImageTaken.Replace("\\", "/"), UriKind.RelativeOrAbsolute);
BitmapImage image = new BitmapImage(uri);
but nothing seems to display the image. The width of to image always is shown as 0 which displays a "FAILED" text on a debug text. lastImageTaken is shown as C:\Data\Users\Public\Camera Roll\SMCA_jpg.jpg
I have also added the capabilities of ID_CAP_MEDIALIB_PHOTO
It seems that you are saving the image to CameraRoll, but trying to retrieve image from IsolatedStorage. Those are two different storage areas, and they are accessed differently.
In order to save an image to IsolatedStorage you need to replace this :
library.SavePictureToCameraRoll(fileName, e.ImageStream);
with this :
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to the local folder.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
Then access the image the same way you've described in your original post.
Source : http://msdn.microsoft.com/en-us/library/windows/apps/hh202956(v=vs.105).aspx#BKMK_SavingToTheMediaLibraryAndIsolatedStorage

Add links to PDF programmatically

I have about 180 PDF files that are generated from a geodatabase. I would like to programmatically add links as hot spots (no text) at the top, bottom, left and right as needed to navigate to the adjoining page files. I would also like to add links over a 3x3 grid in the lower left corner of the page for additional navigation. The grid is already in the existing PDF just no links. Total there will be a possible 14 links added to each page
I am open to suggestions as to how to go about this. I am using Acrobat Pro XI, and I am familiar with various programing languages python, vb.net, C#... Just no experience working directly with PDF files.
This is very late answer. Actually I was searching for free alternative to above paid libraries. I found the following links which can be helpful to others.
Apache PDFBox is a vast java library to create pdf programmatically.
TomRoush/PdfBox-Android is it's android implementation. You can find the sample project with this implementation.
I have added the code for creating clickable links in pdf by using above android library and sample project.
public void createPdf(View v) {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.HELVETICA;
// Or a custom font
//try {
// PDType0Font font = PDType0Font.load(document, assetManager.open("MyFontFile.TTF"));
//} catch(IOException e) {
// e.printStackTrace();
//}
PDPageContentStream contentStream;
try {
// Define a content stream for adding to the PDF
contentStream = new PDPageContentStream(document, page);
String preText = "Icons made by ";
String linkText = "My_Site";
float upperRightX = page.getMediaBox().getUpperRightX();
float upperRightY = page.getMediaBox().getUpperRightY();
// Write linkText in blue text
contentStream.beginText();
contentStream.setNonStrokingColor(15, 38, 192);
contentStream.setFont(font, 18);
contentStream.moveTextPositionByAmount( 0, upperRightY-20);
contentStream.drawString(preText + linkText);
contentStream.endText();
// create a link annotation
PDAnnotationLink txtLink = new PDAnnotationLink();
// set up the markup area
float offset = (font.getStringWidth(preText) / 1000) * 18;
float textWidth = (font.getStringWidth(linkText) / 1000) * 18;
PDRectangle position = new PDRectangle();
position.setLowerLeftX(offset);
position.setLowerLeftY(upperRightY - 24f);
position.setUpperRightX(offset + textWidth);
position.setUpperRightY(upperRightY -4);
txtLink.setRectangle(position);
// add an action
PDActionURI action = new PDActionURI();
action.setURI("https://www.**********.com/");
txtLink.setAction(action);
// and that's all ;-)
page.getAnnotations().add(txtLink);
// load 'Social media' icons from 'vector' resources.
float padding = 5, startX = 5, startY = upperRightY-100, width = 25, height=25;
loadVectorIconWithLink(document, page, contentStream, R.drawable.ic_facebook,
"https://www.facebook.com/My_Name/", startX, startY, width, height);
startX += (width + padding);
loadVectorIconWithLink(document, page, contentStream, R.drawable.ic_instagram,
"https://www.instagram.com/My_Name", startX, startY, width, height);
// Make sure that the content stream is closed:
contentStream.close();
// Save the final pdf document to a file
String path = root.getAbsolutePath() + "/Download/Created.pdf";
document.save(path);
document.close();
tv.setText("Successfully wrote PDF to " + path);
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadVectorIconWithLink( PDDocument theDocument,
PDPage thePage,
PDPageContentStream theContentStream,
#DrawableRes int theDrawableId,
String theUriString,
float x, float y, float width, float height
) throws IOException
{
Bitmap alphaImage = getBitmapFromDrawable(this, theDrawableId);
PDImageXObject alphaXimage = LosslessFactory.createFromImage(theDocument, alphaImage);
theContentStream.drawImage(alphaXimage, x, y, width, height );
// create a link annotation
PDAnnotationLink iconLink = new PDAnnotationLink();
PDRectangle position = new PDRectangle( x, y, width, height );
iconLink.setRectangle(position);
// add an action
PDActionURI action1 = new PDActionURI();
action1.setURI(theUriString);
iconLink.setAction(action1);
// and that's all ;-)
thePage.getAnnotations().add(iconLink);
}
public static Bitmap getBitmapFromDrawable(Context context, #DrawableRes int drawableId) {
Drawable drawable = AppCompatResources.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawableCompat || drawable instanceof VectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} else {
throw new IllegalArgumentException("unsupported drawable type");
}
}
There are at least three types of links you might want to add: links to pages within the same document, links to pages in other PDF document, links to URLs on the web.
Docotic.Pdf library can add links of any of these types (please note that I am on of the developers of this library). Here are two relevant examples:
Create link to page
Create hyperlink
There are no examples for how to create links to pages in an other PDF document published online, but you can always contact support if you need such an example.
After continuing to search and not finding any other promising open source solutions I went with Debenu Quick PDF Library. The specific functions I used are are noted below:
AddLinkToFile
AddLinkToPage
Other annotations and hotspot links
The time that the two library functions are going to save me weekly is worth the cost alone. I am sure I will find other use for the other 900+ PDF functions