How to rotate elements with SVG Salamander - java

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...

Related

itext7 Java Create PdfExplicitDestination for titles in existing pdf

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
}
}
}

Selenium / Java - taking a full page screenshot [closed]

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.

How to check if 2 images are similar with respect to a reference object?

In my application I want to check whether an image taken has the same reference object that a previous image had.
For eg. I capture an image having a pole besides an open land and say after few months I capture standing at the same position and I now get an image of the pole and some building coming up. I want to check if the images are similar in this respect.
We cannot check object , but other way is that we can save our image to the drawable and then we can check the bytes of the image , if bytes are same then image is same
Try to compare with bytes or pixel is the only way that generally works.
drawable1.bytesEqualTo(drawable2)
drawable1.pixelsEqualTo(drawable2)
bitmap1.bytesEqualTo(bitmap1)
bitmap1.pixelsEqualTo(bitmap2)
Option A: Calculate a simplified histogram (8 bits). Sort your images by histogram similarity.
I used this in a image-processing class. It's a pretty forgiving way to compare images. Small changes in lighting or orientation won't break the comparison. You can even flip the image 90° or 180°.
I still have the code, even if it was matlab, it may be helpful:
// image to compare:
QueryPicture = imread(strcat('E:\Users\user98\Images\',num2str(floor(result/10)),num2str(mod(result,10)),'.jpg'));
sums = zeros(50,2);
h = zeros(64,50);
// do a simpified histogram:
for n=1:50
img=double(imread(strcat('E:\Users\user98\Images\',num2str(floor(n/10)),num2str(mod(n,10)),'.jpg')));
for i=1:200
for j=1:200
x1 = bitshift(img(i,j,1), -6);
x2 = bitshift(img(i,j,2), -6) * 4;
x3 = bitshift(img(i,j,3), -6) * 16;
x = x1 + x2 + x3;
h(x+1, n) = (h(x+1, n) + 1);
end
end
end
// compare histograms:
for n=1:50
tmpVec = zeros(64,1);
for i=1:64
tmpVec(i) = abs(h(i,n) - h(i,result));
end
for j=1:64
sums(n,1) = sums(n,1)+tmpVec(j);
end
sums(n,2) = n;
end
sortedImages = sortrows(sums,1)
// Show compare-image:
subplot(2,3,1); image(uint8(QueryPicture));
// show 3 best matches for compare-image:
sortedImages(1);
sortedImages(2);
sortedImages(3);
img1=double(imread(strcat('E:\Users\user98\Images\',num2str(floor(sortedImages(2,2)/10)),num2str(mod(sortedImages(2,2),10)),'.jpg')));
img2=double(imread(strcat('E:\Users\user98\Images\',num2str(floor(sortedImages(3,2)/10)),num2str(mod(sortedImages(3,2),10)),'.jpg')));
img3=double(imread(strcat('E:\Users\user98\Images\',num2str(floor(sortedImages(4,2)/10)),num2str(mod(sortedImages(4,2),10)),'.jpg')));
subplot(2,3,4); image(uint8(img1));
subplot(2,3,5); image(uint8(img2));
subplot(2,3,6); image(uint8(img3));
Option B::
Use the gps data from the image (exif) if available.
Option C::
Google Lens is an app that can classify images and detect objects.

MPAndroidChart Display Label Over Horizontal Line on Graph

Is it possible to display custom text centered between 2 points on the graph?
I've got MPAndroidChart setup to display a step function type graph (representing hours spent doing a specific task) with horizontal and vertical lines only. What I would like to be able to do is show a label over the horizontal sections indicating the size of the section (aka the time spent calculated by taking the difference between the x values). Is there a way to do this? I've been look into modifying the library but I can't seem to figure out where would be the correct place to do so.
My best guess would be some changes in BarLineChartBase onDraw() method or maybe in the LineChartRenderer drawLinear() method.
Here is what I am able to produce:
Here is an example of what I am trying to produce:
Figured it out! Just add a new method drawTime() to the LineChart class at the end of onDraw() right after drawDescription(). Since each horizontal line is described by 2 Entry points I simply loop through 2 entries at a time for my single data set and calculate the difference:
protected void drawTime(Canvas c)
{
Paint timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
timePaint.setTextSize(Utils.convertDpToPixel(16));
timePaint.setColor(Color.BLUE);
timePaint.setTextAlign(Paint.Align.CENTER);
MPPointD position;
LineData data = this.getLineData();
ILineDataSet dataSet = data.getDataSetByIndex(0);
for (int i = 1; i < dataSet.getEntryCount(); i+=2)
{
Entry e1 = dataSet.getEntryForIndex(i-1);
Entry e2 = dataSet.getEntryForIndex(i);
float time = e2.getX() - e1.getX();
position = getPixelForValues(e1.getX() + time/2, e1.getY() - 0.05f, YAxis.AxisDependency.LEFT);
c.drawText(String.valueOf(time), (float)position.x, (float)position.y, timePaint);
}
}
The resulting graph looks like this

PDFbox to iText coordinate conversions using AffineTransform

Question:
I can't seem to get one coordinate format to work with another format. I think I'm just not using the right matrix, but I don't know enough about them to be certain. I was hoping to get some help figuring out if I'm making an assumption on what my transform should be.
iText uses the bottom left as origin per ISO standard, but the pdfbox code and the program that gives me the coordinates to scrape from the pdf both use the upper left as the origin.
What transform should I be doing to adapt the coordinates so that iText can consume them in a way that will work?
Background
I've got some code that uses pdfbox to manipulate a pdf and strip out some data and now I need to inject the modified data back on the page. PDFBox's writer keeps corrupting the pdf so we have decided to go with iText to do the injection.
The trick is that the coordinates I used with pdfbox (and the ones we get from the system generating the pdf) don't seem to match up with iText's.
What I've done so far
I checked, and both the iText page and cropbox seem to be accurate:
PdfReader splitPDFDocumentReader = new PdfReader(splitPDFdocumentName);
com.lowagie.text.Rectangle theCropBox = splitPDFDocumentReader.getCropBox(1);
com.lowagie.text.Rectangle thePageSize = splitPDFDocumentReader.getPageSize(1);
consolePrintln("Cropbox: " + theCropBox.toString());
consolePrintln("\tBottom " + theCropBox.getBottom());
consolePrintln("\tLeft " + theCropBox.getLeft());
consolePrintln("\tTop " + theCropBox.getTop());
consolePrintln("\tRight " + theCropBox.getRight());
consolePrintln("PageSize: " + thePageSize.toString());
consolePrintln("\tBottom " + thePageSize.getBottom());
consolePrintln("\tLeft " + thePageSize.getLeft());
consolePrintln("\tTop " + thePageSize.getTop());
consolePrintln("\tRight " + thePageSize.getRight());
Outputs:
Cropbox: Rectangle: 612.0x792.0 (rot: 0 degrees)
Bottom 0.0
Left 0.0
Top 792.0
Right 612.0
PageSize: Rectangle: 612.0x792.0 (rot: 0 degrees)
Bottom 0.0
Left 0.0
Top 792.0
Right 612.0
Which would lead me to believe its just a matter of flipping the y coordinate since pdfbox's origin is in the top left, whereas iTexts is in the bottom left.
Where I run into trouble
When I apply the transform:
// matrix data example:
// [m00, m01, m02,
// m10, m11, m12,
// 0 , 0 , 1 ] // this bit is implied as part of affineTransform docs
content.saveState();
int m00 = 1;
int m01 = 0;
int m02 = 0;
int m10 = 0;
int m11 = -1;
int m12 = 0;
content.concatCTM(m00, m10, m01, m11, m02, m12);
content.setColorStroke(Color.RED);
content.setColorFill(Color.white);
content.rectangle(x, y, x + height, y + width);
content.fillStroke();
content.restoreState();
It doesn't seem to do what I would expect. It seems that the data is completely outside the page.
Misc notes
To be honest, i'm not very good with matrixes, perhaps I need to do some translation work and not just filp the y as I've tried to do?
The concatCTM function seems to take the same format as awt.geom.affinetransform, and I am going by this example and tutorial for using the transforms.
I figured it out. When I was fipping the y coordinate, I was assuming it would flip over the middle of the document and just invert everything. However it actually flips over the line y=0;
After it flips over y=0, you would need to shift the entire page back up.
I ended up using affineTransform directly to get it done, then just feed the resulting matrix into concatCTM.
content.saveState();
AffineTransform transform = new AffineTransform();
transform.scale(1, -1); // flip along the line y=0
transform.translate(0, -pageHeight); // move the page conet back up
/* the version of iText used in Jasper iReport doesn't seem to use affineTransform directly */
double[] transformMatrix = new double[6];
transform.getMatrix(transformMatrix);
content.concatCTM((float) transformMatrix[0], (float) transformMatrix[1], (float) transformMatrix[2], (float) transformMatrix[3], (float) transformMatrix[4], (float) transformMatrix[5]);
// drawing and printing code here (stamping?)
content.restoreState();

Categories

Resources