I have a Java application which has a functionality to take a screenshot. It does it by running Powershell script:
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
$screens = [Windows.Forms.Screen]::AllScreens
$top = ($screens.Bounds.Top | Measure-Object -Minimum).Minimum
$left = ($screens.Bounds.Left | Measure-Object -Minimum).Minimum
$width = ($screens.Bounds.Right | Measure-Object -Maximum).Maximum
$height = ($screens.Bounds.Bottom | Measure-Object -Maximum).Maximum
$bounds = [Drawing.Rectangle]::FromLTRB($left, $top, $width, $height)
$bmp = New-Object System.Drawing.Bitmap ([int]$bounds.width), ([int]$bounds.height)
$graphics = [Drawing.Graphics]::FromImage($bmp)
$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
$memStream = New-Object System.IO.MemoryStream
$bmp.Save($memStream, [Drawing.Imaging.ImageFormat]::Jpeg)
Write-Host $memStream.ToArray()
$graphics.Dispose()
$bmp.Dispose()
$memStream.Dispose()
Java application listens to the output of it and does some operations on it. The problem is that sometimes Write-Host $memStream.ToArray() takes too much time (Sometimes in 2 minutes, sometimes 3, or even 5). I'm not familiar with Powershell. Is there any analog of Write-Host which is faster? Or maybe I can take a screenshot using some other functionality faster? Thanks
You stated a solution using other functionality would be acceptable, so why not perform the screen capture directly with the Java application instead? Java is fully capable of this natively:
import java.awt.Robot;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.AWTException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
// Set up Robot and other vars
Robot robot = new Robot();
String imgFormat = "jpg";
BufferedImage screenBuffer;
Rectangle screenBounds;
// Enumerate all screens
GraphicsEnvironment graphEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = graphEnv.getScreenDevices();
// Variables only used for generating filename
String fnameFormat = "%s-%s-screencap.%s";
String dtNowString = new SimpleDateFormat("yyyyMMddHHmmss").format(Calendar.getInstance().getTime());
String filename = String.format(fnameFormat, dtNowString, "all", imgFormat);
Rectangle allScreenBounds = new Rectangle();
int num = 0;
for(GraphicsDevice screen : screens) {
screenBounds = screen.getDefaultConfiguration().getBounds();
allScreenBounds.x = Math.min(allScreenBounds.x, screenBounds.x);
allScreenBounds.y = Math.min(allScreenBounds.y, screenBounds.y);
// Make sure we only add extra pixels to the total width and height, subtracting overlapping dimensions
// Does not take into account non-continuous display area, normally impossible on Windows
allScreenBounds.width += Math.abs(allScreenBounds.width - (screenBounds.width + screenBounds.x));
allScreenBounds.height += Math.abs(allScreenBounds.height - (screenBounds.height + screenBounds.y));
System.out.println(String.format("Display %d: X=%d, Y=%d, Height=%d, Width=%d", num++, screenBounds.x, screenBounds.y, screenBounds.height, screenBounds.width));
}
System.out.println(String.format("Screen Area: X=%d, Y=%d, Height=%d, Width=%d", allScreenBounds.x, allScreenBounds.y, allScreenBounds.height, allScreenBounds.width));
screenBuffer = robot.createScreenCapture(allScreenBounds);
// Save the screencap to file
ImageIO.write(screenBuffer, imgFormat, new File(filename));
There is file-writing code there for testing but if this is performed by your application you can remove the filename variables, import javax.imageio.ImageIO, and the ImageIO.write call as you'll have the screenshot data in screenBuffer instead.
Related
I have a scheduled job and I want to get fixedRate dynamically but couldn't solve how to do it.
FixedRate gets value as milliseconds but I want to give time as hours. And I also tried read parameter from property file and multiply it but I did not work. How can I make this?
package com.ipera.communicationsuite.scheduleds;
import com.ipera.communicationsuite.models.FreeDbSize;
import com.ipera.communicationsuite.repositories.interfaces.IFreeDbSizeRepository;
import com.ipera.communicationsuite.repositories.interfaces.settings.IPropertiesRepository;
import com.ipera.communicationsuite.utilities.mail.SMTPConnection;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
#Component
#AllArgsConstructor
#PropertySource("classpath:scheduled.properties")
public class KeepAlive {
private static Logger logger = LoggerFactory.getLogger(KeepAlive.class);
private IFreeDbSizeRepository freeDbSizeRepository;
private SMTPConnection smtpConnection;
private IPropertiesRepository propertiesRepository;
#Scheduled(fixedRateString ="${keepAlive.timer}")
public void keepAliveMailSender() {
StringBuilder content = new StringBuilder();
ArrayList<File> files = getDrivers();
List<FreeDbSize> list = freeDbSizeRepository.getFreeDbSize();
FreeDbSize dbDiskInfo = freeDbSizeRepository.dbDiskSize();
content.append("DB file size is: ").append(list.get(0).getType().equals("mdf") ? list.get(0).getFileSize() : list.get(1).getFileSize()).append(" MB\n")
.append("DB log size is: ").append(list.get(0).getType().equals("ldf") ? list.get(0).getFileSize() : list.get(1).getFileSize()).append(" MB\n");
propertiesRepository.updateByKey("DatabaseSize", list.get(0).getType().equals("mdf") ? list.get(0).getFileSize().toString() : list.get(1).getFileSize().toString());
propertiesRepository.updateByKey("DatabaseLogSize", list.get(0).getType().equals("ldf") ? list.get(0).getFileSize().toString() : list.get(1).getFileSize().toString());
propertiesRepository.updateByKey("FreeDiskSpaceForDb", dbDiskInfo.getFreeSpace().toString());
for (int i = 0; i < files.size(); i++) {
content.append("Free size for driver ").append(files.get(i)).append(" is ").append(files.get(i).getFreeSpace() / (1024 * 1024)).append(" MB\n");
propertiesRepository.createIfNotExistOrUpdate(("FreeSpaceInDisk".concat(Character.toString(files.get(i).toString().charAt(0)))), Long.toString(files.get(i).getFreeSpace() / (1024 * 1024)));
}
if (dbDiskInfo.getName().equals("-1")) {
content.append("This application has not permission to run query for calculate free size of disk.");
} else {
content.append("Free size of disk which contains Db is: ").append(dbDiskInfo.getFreeSpace());
}
smtpConnection.sendMail(content.toString(), "Server Is Up!!!", "fkalabalikoglu#iperasolutions.com", "", "", "", "");
logger.info("KeepAlive has runned.");
}
public ArrayList<File> getDrivers() {
ArrayList<File> list = new ArrayList<>();
File[] drives = File.listRoots();
if (drives != null && drives.length > 0) {
for (File aDrive : drives) {
list.add(aDrive);
}
}
return list;
}
}
And also my propery file is here:
keepAlive.timer=86400000
You could use SpEL in your annotation like:
#Scheduled(fixedRateString ="#{new Long('${keepAlive.timer}') * 1000 * 3600}")
to have expression evaluated. So keepAlive.timer would be the amount of hours.
But in my opinion it would be an ugly solution. I would rather put it in the properties as you have it now and just add a comment like:
# 24 hours is: 1000 * 3600 * 24
keepAlive.timer=86400000
Another way to use hours would be to use attribute cron that gives you more flexibility but might need some study before using:
In your code:
#Scheduled(cron = "${keepAlive.timer}")
and the cron expression in your properties - for example - like:
keepAlive.timer="*/60 00 21 * * ?"
This would run every day # 21.00
Note this "*/60" it should accept also "0" here but in my case it did not
I want to add the polygon in the PDF at the given coordinates, I referred this link for adding the annotation of circle and rectangle, but it does not contain anything for polygon. Does anyone know how to do it? Or does anyone know where do I get all documentation about PDFBox annotation.
Here I am sharing what I'vs done until now. But I couldn't proceed further.
import java.io.IOException;
import java.io.File;
import java.io.FileReader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.json.simple.parser.ParseException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLine;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationMarkup;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationSquareCircle;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderStyleDictionary;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageFitWidthDestination;
public class Polygon{
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// Loading the PDF File
File file = new File("abc.pdf");
PDDocument document = PDDocument.load(file);
System.out.println("PDF Loaded.");
PDPage page = document.getPage(0);
List<PDAnnotation> polygon = page.getAnnotations();
// Color of polygon
PDColor color = new PDColor(new float[] {0, 0, 1}, PDDeviceRGB.INSTANCE);
// Define border thickness
PDBorderStyleDictionary thickness = new PDBorderStyleDictionary();
thickness.setWidth((float)2);
float[] vertices = {418, 110, 523, 110, 522, 132, 419, 133};
PDAnnotationSquareCircle lines = new PDAnnotationSquareCircle(PDAnnotationSquareCircle.SUB_TYPE_POLYGON);
lines.setColor(color);
lines.setBorderStyle(thickness);
/*****************
*
* ????
* *************************************/
// Save annotations
document.save(file);
// Close document
document.close();
}
}
As far I have seen, There isn't any method for adding vertices in polygon in PDAnnotation jar. So is there any way we can draw polygon here?
Thanks.
Here's some code that will soon be added to the AddAnnotations.java example from the source code download:
static final float INCH = 72;
float pw = page1.getMediaBox().getUpperRightX();
float ph = page1.getMediaBox().getUpperRightY();
PDAnnotationMarkup polygon = new PDAnnotationMarkup();
polygon.getCOSObject().setName(COSName.SUBTYPE, PDAnnotationMarkup.SUB_TYPE_POLYGON);
position = new PDRectangle();
position.setLowerLeftX(pw - INCH);
position.setLowerLeftY(ph - INCH);
position.setUpperRightX(pw - 2 * INCH);
position.setUpperRightY(ph - 2 * INCH);
polygon.setRectangle(position);
polygon.setColor(blue); // border color
polygon.getCOSObject().setItem(COSName.IC, red.toCOSArray()); // interior color
COSArray triangleVertices = new COSArray();
triangleVertices.add(new COSFloat(pw - INCH));
triangleVertices.add(new COSFloat(ph - 2 * INCH));
triangleVertices.add(new COSFloat(pw - INCH * 1.5f));
triangleVertices.add(new COSFloat(ph - INCH));
triangleVertices.add(new COSFloat(pw - 2 * INCH));
triangleVertices.add(new COSFloat(ph - 2 * INCH));
polygon.getCOSObject().setItem(COSName.VERTICES, triangleVertices);
polygon.setBorderStyle(borderThick);
annotations.add(polygon);
to adjust your own code, you need to adjust the rectangle and pass your vertices:
position.setLowerLeftX(418);
position.setLowerLeftY(110);
position.setUpperRightX(523);
position.setUpperRightY(133);
polygon.setRectangle(position);
float[] vertices = {418, 110, 523, 110, 522, 132, 419, 133};
COSArray verticesArray = new COSArray();
for (float v : vertices)
verticesArray.add(new COSFloat(v));
polygon.getCOSObject().setItem(COSName.VERTICES, verticesArray);
This is for 2.0 only. In 3.0 there will be a PDAnnotationPolygon type with appropriate methods. That version will also support the construction of appearance streams, i.e. you will be able to show the PDF with other viewers than Adobe Reader. Most viewers, e.g. PDF.js and PDFBox don't build missing appearances so you'll see nothing.
If you need the appearance for 2.0 you can try with the code in the file ShowAnnotation-6.java in https://issues.apache.org/jira/browse/PDFBOX-3353 .
To test with the 3.0 version, get the jar here:
https://repository.apache.org/content/groups/snapshots/org/apache/pdfbox/pdfbox-app/3.0.0-SNAPSHOT/
To build the appearance, call polygon.constructAppearances();
I've used the Weka GUI for training and testing a file (making predictions), but can't do the same with the API. The error I'm getting says there's a different number of attributes in the train and test files. In the GUI, this can be solved by checking "Output predictions".
How to do something similar using the API? do you know of any samples out there?
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.meta.FilteredClassifier;
import weka.classifiers.trees.J48;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.NominalToBinary;
import weka.filters.unsupervised.attribute.Remove;
public class WekaTutorial
{
public static void main(String[] args) throws Exception
{
DataSource trainSource = new DataSource("/tmp/classes - edited.arff"); // training
Instances trainData = trainSource.getDataSet();
DataSource testSource = new DataSource("/tmp/classes_testing.arff");
Instances testData = testSource.getDataSet();
if (trainData.classIndex() == -1)
{
trainData.setClassIndex(trainData.numAttributes() - 1);
}
if (testData.classIndex() == -1)
{
testData.setClassIndex(testData.numAttributes() - 1);
}
String[] options = weka.core.Utils.splitOptions("weka.filters.unsupervised.attribute.StringToWordVector -R first-last -W 1000 -prune-rate -1.0 -N 0 -stemmer weka.core.stemmers.NullStemmer -M 1 "
+ "-tokenizer \"weka.core.tokenizers.WordTokenizer -delimiters \" \\r\\n\\t.,;:\\\'\\\"()?!\"");
Remove remove = new Remove();
remove.setOptions(options);
remove.setInputFormat(trainData);
NominalToBinary filter = new NominalToBinary();
NaiveBayes nb = new NaiveBayes();
FilteredClassifier fc = new FilteredClassifier();
fc.setFilter(filter);
fc.setClassifier(nb);
// train and make predictions
fc.buildClassifier(trainData);
for (int i = 0; i < testData.numInstances(); i++)
{
double pred = fc.classifyInstance(testData.instance(i));
System.out.print("ID: " + testData.instance(i).value(0));
System.out.print(", actual: " + testData.classAttribute().value((int) testData.instance(i).classValue()));
System.out.println(", predicted: " + testData.classAttribute().value((int) pred));
}
}
}
Error:
Exception in thread "main" java.lang.IllegalArgumentException: Src and Dest differ in # of attributes: 2 != 17152
This was not an issue for the GUI.
You need to ensure that categories in train and test sets are compatible, try to
combine train and test sets
List item
preprocess them
save them as arff
open two empty files
copy the header from the top to line "#data"
copy in training set into first file and test set into second file
SOLVED
OK, I just messed with neo4j-server.properties` config file, I shouldn't have written the db path using "...".
I have created a neo4j database using java's inserter and I strive to access it with py2neo. Here's my java code:
///opt/java/64/jdk1.6.0_45/bin/javac -classpath $HOME/opt/usr/neo4j-community-1.8.2/lib/*:. neo_batch.java
///opt/java/64/jdk1.6.0_45/bin/java -classpath $HOME/opt/usr/neo4j-community-1.8.2/lib/*:. neo_batch
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.index.Index;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.lang.Long;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.helpers.collection.MapUtil;
import org.neo4j.unsafe.batchinsert.BatchInserter;
import org.neo4j.unsafe.batchinsert.BatchInserterImpl;
import org.neo4j.unsafe.batchinsert.BatchInserters;
import org.neo4j.unsafe.batchinsert.BatchInserterIndex;
import org.neo4j.unsafe.batchinsert.BatchInserterIndexProvider;
import org.neo4j.unsafe.batchinsert.LuceneBatchInserterIndexProvider;
public class neo_batch{
private static final String KEY = "id";
public static void main(String[] args) {
//create & connect 2 neo db folder
String batch_dir = "neo4j-batchinserter-store";
BatchInserter inserter = BatchInserters.inserter( batch_dir );
//set up neo index
BatchInserterIndexProvider indexProvider =
new LuceneBatchInserterIndexProvider( inserter );
BatchInserterIndex OneIndex =
indexProvider.nodeIndex( "one", MapUtil.stringMap( "type", "exact" ) );
OneIndex.setCacheCapacity( "id", 100000 );
//batchin graph, index and relationships
RelationshipType linked = DynamicRelationshipType.withName( "linked" );
for (int i=0;i<10;i++){
System.out.println(i);
long Node1 = createIndexedNode(inserter, OneIndex, i);
long Node2 = createIndexedNode(inserter, OneIndex, i+10);
inserter.createRelationship(Node1, Node2, linked, null);
}
indexProvider.shutdown();
inserter.shutdown();
}
// START SNIPPET: helperMethods
private static long createIndexedNode(BatchInserter inserter,BatchInserterIndex OneIndex,final long id)
{
Map<String, Object> properties = new HashMap<String, Object>();
properties.put( KEY, id );
long node = inserter.createNode( properties );
OneIndex.add( node, properties);
return node;
}
// END SNIPPET: helperMethods
}
Then I modify the neo4j-server.properties config file accordingly and start neo4j start.
The following python code suggests the graph is empty
from py2neo import neo4j
graph = neo4j.GraphDatabaseService("http://localhost:7474/db/data/")
graph.size()
Out[8]: 0
graph.get_indexed_node("one",'id',1)
What's wrong with my appraoch? Thanks
EDIT
Neither can I count the nodes with a cypher:
neo4j-sh (?)$ START n=node(*)
> return count(*);
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row
0 ms
EDIT 2
I can check with the java api that the indexes and nodes exist
private static void query_batched_db(){
GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( batch_dir);
IndexManager indexes = graphDb.index();
boolean oneExists = indexes.existsForNodes("one");
System.out.println("Does the 'one' index exists: "+oneExists);
System.out.println("list indexes: "+graphDb.index().nodeIndexNames());
//search index 'one'
Index<Node> oneIndex = graphDb.index().forNodes( "one" );
for (int i=0;i<25;i++){
IndexHits<Node> hits = oneIndex.get( KEY, i );
System.out.println(hits.size());
}
graphDb.shutdown();
}
Where the output is
Does the 'one' index exists: true
list indexes: [Ljava.lang.String;#26ae533a
1
1
...
1
1
0
0
0
0
0
Now if I populate the graph using python, I won't be able to access them with the previous java method (will count 20 again)
from py2neo import neo4j
graph = neo4j.GraphDatabaseService("http://localhost:7474/db/data/")
idx=graph.get_or_create_index(neo4j.Node,"idx")
for k in range(100):
graph.get_or_create_indexed_node('idx','id',k,{'id':k}
EDIT 3
Now I delete the store I created with the batchinserter, namely neo4j-test-store while the neo4j-server.properties config file continues to point to the deleted store, namely org.neo4j.server.database.location="{some_path}/neo4j-test-store".
Now if I run a cypher count, I got a 100, 100 being the number of nodes I inserted using py2neo.
I am going crazy with this stuff!
SOLVED
OK, I just messed with neo4j-server.properties` config file, I shouldn't have written the db path using "...".
I have dual head (VGA output, DVI or HDMI output) from 1 PC using this xrandr --output VGA1 --left-of LVDS1. Each having 1024x768 resolution.
When i use this using Java:
screen = Toolkit.getDefaultToolkit().getScreenSize();
I get a huge two screen width together. As a result my Width and height is huge.
Where i only need to place my application in one screen either VGA or DVI. But using Java how do i know that?
How do i tell that using Toolkit.getDefaultToolkit() ?
Example: (my application has to run where Java is labeled)
Test.java
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
public class Test {
public static void main(String[] a) throws Exception {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screenDevices = ge.getScreenDevices();
for (int i = 0; i < screenDevices.length; i++) {
System.out.println(screenDevices[i].getIDstring());
DisplayMode dm = screenDevices[i].getDisplayMode();
int screenWidth = dm.getWidth();
int screenHeight = dm.getHeight();
System.out.println("Cake: " + screenWidth + " " + screenHeight);
}
}
}
Output:
:0.0
Cake: 1024 768
:0.1
Cake: 1024 768
I think
GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()
is what you are looking for. And then from there you can iterate through the screens and get the screen dimension by getDisplayMode()