Not able to add icon on desired coordinates on PDF using ApachePdfBox [duplicate] - pdfbox

I am drawing an image on one of the PDF page.. when I use PDPageContentStream stream = new PDPageContentStream(doc, page); to draw image, everything works fine.. see below image.
but when I use constructor PDPageContentStream(doc, page, true, true); to create PDPageContentStream and draw image, the newly added image gets inverted upside down..
not getting what's going wrong here..
PS. I am using library PdfBox-Android

Use the constructor that has a fifth parameter, so to reset the graphic context.
public PDPageContentStream(PDDocument document, PDPage sourcePage, boolean appendContent,
boolean compress, boolean resetContext) throws IOException
alternatively, save and restore the graphics state in the first content stream by calling
saveGraphicsState();
// ...
restoreGraphicsState();

Related

Text is reverse in generated pdf

I am using pdfbox to add a line to pdf file. but the text i am adding is reversed.
File file = new File(filePath);
PDDocument document = PDDocument.load(file);
PDPage page = document.getPage(0);
PDPageContentStream contentStream = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,true);
int stampFontSize = grailsApplication.config.pdfStamp.stampFontSize ? grailsApplication.config.pdfStamp.stampFontSize : 20
contentStream.beginText();
contentStream.setFont(PDType1Font.TIMES_ROMAN, stampFontSize);
int leftOffset = grailsApplication.config.pdfStamp.leftOffset ? grailsApplication.config.pdfStamp.leftOffset : 10
int bottomOffset = grailsApplication.config.pdfStamp.bottomOffset ? grailsApplication.config.pdfStamp.bottomOffset : 20
contentStream.moveTextPositionByAmount(grailsApplication.config.xMove,grailsApplication.config.yMove)
contentStream.newLineAtOffset(leftOffset, bottomOffset)
String text = "i have added this line...!!!!";
contentStream.showText(text);
contentStream.endText();
contentStream.close();
document.save(new File(filePath));
document.close();
byte[] pdfData;
pdfData = Files.readAllBytes(file.toPath());
return pdfData;
i tried using moveTextPositionByAmount method but this does not seem to have any effect on text. why is my text reversed and how can i set it to correct orientation.
Your code is not causing the mirrored output by itself, so the cause must be inside the PDF you are stamping. Unfortunately you did not provide the PDF in question, so we have to guess here.
Most likely the issue is caused by the pre-existing page content having set the current transformation matrix to a mirroring affine transformation without resetting it at the end.
If that indeed is the case, PDFBox provides an easy work-around:
You construct your PDPageContentStream like this:
PDPageContentStream contentStream = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,true);
There is another constructor accepting an additional boolean argument. If you use that constructor setting the additional argument to true, PDFBox attempts to reset the graphics state of the content:
PDPageContentStream contentStream = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,true,true);
Beware: If this indeed fixes the issue, the coordinates and offsets you currently use rely on the transformation matrix being changed as it is. In that case you will have to update them accordingly.
Alternatively introducing a counter-mirroring may help, e.g. by setting the text matrix like this at the start of each of your text objects:
contentStream.beginText();
contentStream.setTextMatrix(new Matrix(1f, 0f, 0f, -1f, 0f, 0f));
Thereafter all y coordinate changes need to be negated, in particular the second argument of contentStream.moveTextPositionByAmount and contentStream.newLineAtOffset.
(By the way, moveTextPositionByAmount and newLineAtOffset do the same, the former merely is the deprecated variant, so you might want to use the latter in both cases.)

Why is flying saucer always printing PDF on A4 paper?

I'm trying to save an html document to PDF using flyingsaucer but the generated document always ends up having an A4 dimension when I look at the Document Properties from Adobe Reader (Page Size: 8.26 x 11.69 in).
I did read the documentation and I'm passing the css #page {size: letter;} style. And while it does have an effect on the output, the page size always remains 8.26 x 11.69 in Adobe Reader. For example, if I set the page size to legal, my PDF is still the size of a A4 but the top of the document is missing as if it had fell off the "paper".
I'm not sure if the problem falls on the itext side or the flying saucer side. I was using a fairly old version so my first step was to upgrade to the latest 9.1.6 version of flying saucer. I also moved from itext 2.0.8 to openPDF 1.0.1 but I'm still getting the same behavior.
I also traced in the debugger up to the com.lowagie.text.Document creation in ITextRenderer and at this point the document size passed is correct. That makes me think that the issue might be in openPDF / iText but I can't find what I'm doing wrong.
It turns out the PDF generation was correctly using the #page size declaration and the problem was occurring later in our software. What I had not noticed is that after the generation of the PDF another method was called to merge multiple PDFs into one. This method should probably not have been called, but that's another story.
The bottom line is this method created a new com.lowagie.text.Document(), which by default creates an A4 sized document, and then was iterating over all pages of the pdf, adding the pages to the new document using pdfWriter.getImportedPage(pdfReader, currentPage++). These imported pages did not retain their original size.
I fixed it by passing the page size of the fist page when creating the merged document object:
document = new Document(pdfReader.getPageSize(1));
The real problem is that you're (unwittingly) using software that is no longer supported. Anything that still has the namespace lowagie (the founder and CTO of iText) is really outdated.
If you simply want to convert HTML to pdf, why not use iText directly and cut out the middle-man?
We have multiple options for you.
XMLWorker (iText5 based code that converts HTML to pdf)
pdfHTML (iText7 based add-on that converts HTML5/CSS3 to pdf)
This is a rather extensive code-sample for using pdfHTML:
public void createPdf(String src, String dest, String resources) throws IOException {
try {
FileOutputStream outputStream = new FileOutputStream(dest);
WriterProperties writerProperties = new WriterProperties();
//Add metadata
writerProperties.addXmpMetadata();
PdfWriter pdfWriter = new PdfWriter(outputStream, writerProperties);
PdfDocument pdfDoc = new PdfDocument(pdfWriter);
pdfDoc.getCatalog().setLang(new PdfString("en-US"));
//Set the document to be tagged
pdfDoc.setTagged();
pdfDoc.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));
//Set meta tags
PdfDocumentInfo pdfMetaData = pdfDoc.getDocumentInfo();
pdfMetaData.setAuthor("Joris Schellekens");
pdfMetaData.addCreationDate();
pdfMetaData.getProducer();
pdfMetaData.setCreator("iText Software");
pdfMetaData.setKeywords("example, accessibility");
pdfMetaData.setSubject("PDF accessibility");
//Title is derived from html
// pdf conversion
ConverterProperties props = new ConverterProperties();
FontProvider fp = new FontProvider();
fp.addStandardPdfFonts();
fp.addDirectory(resources);//The noto-nashk font file (.ttf extension) is placed in the resources
props.setFontProvider(fp);
props.setBaseUri(resources);
//Setup custom tagworker factory for better tagging of headers
DefaultTagWorkerFactory tagWorkerFactory = new AccessibilityTagWorkerFactory();
props.setTagWorkerFactory(tagWorkerFactory);
HtmlConverter.convertToPdf(new FileInputStream(src), pdfDoc, props);
pdfDoc.close();
} catch (Exception e) {
e.printStackTrace();
}
}
You can find more information at http://itextpdf.com/itext7/pdfHTML

How can I draw a text into a buffered image with different font affects in Java 2d?

I am trying to convert Multi-line Text to image but couldn't found a way to draw it with different Font format's is there any way to do it.Thanks in Advance.
What you could do is simply loading an image, and then setting it as the default graphics context, and then drawing text with a Graphics2D object using different fonts. Here's how you could do this :
BufferedImage image = ImageIO.load(new File("test.png"));
Graphics2D g2d = image.createGraphics();
g2d.setFont(new Font("TimesRoman", Font.PLAIN, fontSize));
g2d.drawString("test", posx, posy, etc.)
If you want simply to draw to a blank image and then save it, just create a BufferedImage using the default constructor. Then, to save the image :
File output = new File("test.png");
ImageIO.write(image, "png", output);
If you want to know more about this, here's a link to Oracle's Java2D tutorials : https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
(from where these examples are).

iTextSharp rotated PDF page reverts orientation when file is rasterized at print house

Using iTextSharp I am creating a PDF composed of a collection of existing PDFs, some of the included PDFs are landscape orientation and need to be rotated. So, I do the following:
private static void AdjustRotationIfNeeded(PdfImportedPage pdfImportedPage, PdfReader reader, int documentPage)
{
float width = pdfImportedPage.Width;
float height = pdfImportedPage.Height;
if (pdfImportedPage.Rotation != 0)
{
PdfDictionary pageDict = reader.GetPageN(documentPage);
pageDict.Put(PdfName.ROTATE, new PdfNumber(0));
}
if (width > height)
{
PdfDictionary pageDict = reader.GetPageN(documentPage);
pageDict.Put(PdfName.ROTATE, new PdfNumber(270));
}
}
This works great. The included PDFs rotated to portrait orientation if needed. The PDF prints correctly on my local printer.
This file is sent to a fulfillment house, and unfortunately, the landscape included files do not print properly when going through their printer and rasterization process. They use Kodak (Creo) NexRip 11.01 or Kodak (Creo) Prinergy 6.1. machines. The fulfillment house's suggestion is to: "generate a new PDF file after we rotate pages or make any changes to a PDF. It is as easy as exporting out to a PostScript and distilling back to a PDF."
I know iTextSharp doesn't support PostScript. Is there another way iTextSharp can rotate included PDFs to hold the orientation when rasterized?
First let me assure you that changing the rotation in the page dictionary is the correct procedure to achieve what you want. As far as I can see your code, there's nothing wrong with it. You are doing the right thing.
Unfortunately, you are faced with a third party product over which you have no control that is not doing the right thing. How to solve this?
I have written an example called IncorrectExample. I have named it that way because I don't want it to be used in a context that is different from yours. You can safely ignore all the warnings I added: they are not meant for you. This example is very specific to your problem.
Please try the following code:
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
// Creating a reader
PdfReader reader = new PdfReader(src);
// step 1
Rectangle pagesize = getPageSize(reader, 1);
Document document = new Document(pagesize);
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
PdfContentByte cb = writer.getDirectContent();
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
pagesize = getPageSize(reader, i);
document.setPageSize(pagesize);
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
if (isPortrait(reader, i)) {
cb.addTemplate(page, 0, 0);
}
else {
cb.addTemplate(page, 0, 1, -1, 0, pagesize.getWidth(), 0);
}
}
// step 4
document.close();
reader.close();
}
public Rectangle getPageSize(PdfReader reader, int pagenumber) {
Rectangle pagesize = reader.getPageSizeWithRotation(pagenumber);
return new Rectangle(
Math.min(pagesize.getWidth(), pagesize.getHeight()),
Math.max(pagesize.getWidth(), pagesize.getHeight()));
}
public boolean isPortrait(PdfReader reader, int pagenumber) {
Rectangle pagesize = reader.getPageSize(pagenumber);
return pagesize.getHeight() > pagesize.getWidth();
}
I have taken the pages.pdf file as an example. This file is special in the sense that it has two pages in landscape that are created in a different way:
one page is a page of which the width is smaller than the height (sounds like it's a page in portrait), but as there's a /Rotate value of 90 added to the page dictionary, it is shown in landscape.
the other page isn't rotated, but it has a height that is smaller than the width.
In my example, I am using the classes Document and PdfWriter to create a copy of the original document. This is wrong in general because it throws away all interaction. I should use PdfStamper or PdfCopy instead, but it is right in your specific case because you don't need the interactivity: the final purpose of the PDF is to be printed.
With Document, I create new pages using a new Rectangle that uses the lowest value of the dimensions of the existing page as the width and the highest value as the height. This way, the page will always be in portrait. Note that I use the method getPageSizeWithRotation() to make sure I get the correct width and height, taking into account any possible rotation.
I then add a PdfImportedPage to the direct content of the writer. I use the isPortrait() method to find out if I need to rotate the page or not. Observe that the isPortrait() method looks at the page size without taking into account the rotation. If we did take into account the rotation, we'd rotate pages that don't need rotating.
The resulting PDF can be found here: pages_changed.pdf
As you can see, some information got lost: there was an annotation on the final page: it's gone. There were specific viewer preferences defined for the original document: they're gone. But that shouldn't matter in your specific case, because all that matters for you is that the pages are printed correctly.

How to set Background of a Button without flicker?

I am trying to change the Background of a button to an image source. I want to load that image in memory when we navigate to the page so that it doesn't flicker the first time it shows.
On Windows Phone, I was able to create the image source as such:
StreamResourceInfo resourceInfo = Application.GetResourceStream(uri);
BitmapImage bitmapSource = new BitmapImage();
// Avoid flicker by not delay-loading.
bitmapSource.CreateOptions = BitmapCreateOptions.None;
bitmapSource.SetSource(resourceInfo.Stream);
imageSource = bitmapSource;
I tried something similar in my Windows 8 Store app:
BitmapImage bitmapSource = new BitmapImage();
bitmapSource.CreateOptions = BitmapCreateOptions.None;
bitmapSource.UriSource = uri;
imageSource = bitmapSource;
but the same problem occurs. The button already has a different image as the Background, and on a certain event I would like it to change to the new background. But when I change the source, a noticeable flicker is observed. I'm assuming this is because the image is not yet in memory, as the issue goes away the second time the image source is modified.
Anyone know a solution? I need to somehow force the loading of this image.
Thanks!
If you use the SetSourceAsync method on the BitmapImage and await it before you attach it to the image source you should not see the flicker:-
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
imageSource = bitmapImage;
}
The MSDN docs have some more info on this
Thanks Ross, but what I ended up doing instead is I preloaded the half dozen or so bitmaps I needed by using similar code to what you had above, except from resource of course. I did this asynchronously when the page loaded, and then when I set the ImageSource on the button background, I used the already preloaded bitmaps. That way I know I'm not allocated a new chunk of memory for every instance of the bitmap.