I was trying to find out how to set the text position and rotation in a pdf with the "itextpdf" dependency. My current code looks like that:
//Create the pdf document
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
PdfContentByte pdfCB = new PdfContentByte(writer);
//Create the font which will be used
Font font = FontFactory.getFont(FontFactory.COURIER, 16, BaseColor.BLACK);
//Open the document
document.open();
//Get the image which was previously created (Not important for this)
Image iTextImage = Image.getInstance(pdfCB, image, 1);
//Set the position of the image (How do I do that with the text?)
iTextImage.setAbsolutePosition(0, 0);
//Create a text chunk which I want to set the position of and rotate
Chunk chunk = new Chunk("Hello World!", font);
//Add both the image and text to the pdf and save it
document.add(iTextImage);
document.add(chunk);
document.close();
//Notify the user that it was a success
System.out.println("Image added successfully and PDF file created!");
Now I was wondering how to set the position and rotation of the text. I want to create PDF's for a project which will later be printed. Now I don't want to add like a hundred whitespace's each time there is a blank spot in the page like the table of contents and then a footer at the bottom. I don't want to write the table of contents and then do \n 20 times to reach the bottom, so I can add my footer text, like page number, author, project ID, date, company logo, etc.
So how do I best position the text here? Also, I would like to rotate it, since some of the text has to be turned by 90 degrees for stuff like labels for tables and so on.
Any help would be appreciated, thank you.
PS: I already tried to set the absolute position, which just makes the text disappear.
Related
Is there a way to blur text (text is not random text but it comes from db) added with showTextAligned(PdfContentByte.ALIGN_LEFT,"Random text",297,606,rotation) to PdfContentByte ? Or any other way to blur text (it can be image but the image must be generated from input text and it's not image that you added to your project) and added it to the pdf ? I'm using itextpdf:5.5.12 (on android)
Small example what i have in mind:
PdfWriter pdfWriter=PdfWriter.getInstance(document, new FileOutputStream(file));
PdfContentByte cb = pdfWriter.getDirectContent();
cb.saveState();
cb.beginText();
cb.setColorFill(baseCol);
cb.setFontAndSize(myBaseFontArialNarrowBold,7);
//some function that blurs the text ??
//here
cb.showTextAligned(PdfContentByte.ALIGN_LEFT,"Random text that we want to blur",297,638,rotation);
cb.endText();
cb.restoreState();
//another option would be to add generated image from canvas
Bitmap btmp=bBlur.getBitmap();
ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
btmp.compress(Bitmap.CompressFormat.PNG, 100, stream2);
byte[] byteArray2 = stream2.toByteArray();
Image img2 = Image.getInstance(byteArray2);
cb.addImage(img,250,0,0,250,290,398);
Using canvas in android (if going with option two):
//arial narrow bold
paint.setTypeface(typeface);
paint.setColor(Color.argb(190,0,0,0));
paint.setTextAlign(Paint.Align.LEFT);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setSubpixelText(true);
paint.setLinearText(true);
//paint.setMaskFilter(new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL));
paint.setTextSize(8);
canvas.rotate(-0.9876f);
canvas.drawText(textAr[0],6.8f,11.78f,paint);
paint.setTextSize(7);
canvas.drawText(textAr[1],6.8f,20,paint);
canvas.drawText(textAr[2],6.8f,45,paint);
canvas.setBitmap(bitmap);
The only problem with the second option is that generated text in canvas is very very bad and it doesn't look nice when image is added in pdf... So where could be a problem with "bad font"?
Any help or advice is very much appreciated.
Solution:
Going with second option.
Increase bitmap size (set Bitmap.Config.ARGB_8888), increase font size to something bigger then size 7 or 8 and then apply blur to it (in my case i increased the font size to 24), save image as bitmap and then add image to PdfContentByte or add image directly to document (apply scaleAbsolute to image and absolutePosition).
I am trying to read one PDF and copy its data into another PDF. The first PDF contains some text and images and I wish to write an image in the second PDF exactly where the text ends(which is basically the end of the PDF file). RIght now it just prints at the top. How can I make this change?
PdfReader reader = null;
reader = new PdfReader(Var.input);
Document document=new Document();
PdfWriter writer = null;
writer = PdfWriter.getInstance(document,new FileOutputStream(Var.output));
PdfImportedPage page = writer.getImportedPage(reader, 1);
reader.close();
document.open();
PdfContentByte cb = writer.getDirectContent();
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your new data / text here
Image image = null;
image = Image.getInstance (Var.qr);
document.add(image);
document.close();
Try this:
First get the location/co-ords of where the image needs to go, then simply add the second line from below to your code so the image is inserted at that location "X, Y"
Image image = Image.getInstance(String RESOURCE);
image.setAbsolutePosition(X, Y);
writer.getDirectContent().addImage(image);
Take a look here for some examples in iText 5: https://itextpdf.com/en/resources/examples/itext-5-legacy/chapter-3-adding-content-absolute-positions
You should use a PdfStamper instead of a PdfWriter with imported pages. Your approach throws away all interactive contents. You can use sorifiend's idea there, too.
To determine where the text on the given page ends, have a look at the iText in Action, 2nd edition example ShowTextMargins which parses a PDF and ads a rectangle showing the text margin.
I want to move text with iText7. I have a source bounding box, that can be somewhere on the page and I have a target bounding box, that has a fixed position (incl. width and height). I'll stay on the same page. The source and target boxes can overlap. The source bounding box can also be larger than the target box. In this case I have to reduce the font size. The text should retain font, color and so on.
There is a cut and paste example on the iText website . But in the result pdf file you can select the text at the new and old position (tried it only with a normal pdf reader). I don't want the text to be selectable at the old position.
I thought, that maybe I could select the text and just place it at the new position and remove it from the old position. For the latter i would need pdfSweep, but this is ok. Adding the text at the new position should be no problem. Even if the text has different fonts, sizes and so on. There are plenty of examples on the iText website. The only way I know to select the text is like shown in this example. This gives me only the text. But to place it at the target position with the same font, color and so on, I need all those informations, too.
I know, that pdf is not meant for editing. This is often mention in answers on StackOverflow.
Is there a way to do this with iText7?
There is no high level API in iText allowing you to move page content, in particular not all content from some rectangle. One reason may be that in general this is no mere moving. PDFs often contain structures influencing larger areas, and such structures would not simply have to be moved but instead copied, and each copy restricted to its area.
It is indeed possible, though, to combine the cut and paste example the OP found with the pdfSweep module already considered by the OP to a solution which prevents the text from being selectable at the old position, e.g. like this:
public void moveCleanSection(PdfReader pdfReader, String targetFile, int page, Rectangle from, Rectangle to) throws IOException
{
LicenseKey.loadLicenseFile("itextkey-multiple-products.xml");
ByteArrayOutputStream interimMain = new ByteArrayOutputStream();
ByteArrayOutputStream interimPage = new ByteArrayOutputStream();
ByteArrayOutputStream interimSection = new ByteArrayOutputStream();
try ( PdfDocument pdfMainDocument = new PdfDocument(pdfReader);
PdfDocument pdfPageDocument = new PdfDocument(new PdfWriter(interimPage)) )
{
pdfMainDocument.setCloseReader(false);
pdfMainDocument.copyPagesTo(page, page, pdfPageDocument);
}
try ( PdfDocument pdfMainDocument = new PdfDocument(pdfReader, new PdfWriter(interimMain));
PdfDocument pdfSectionDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(interimPage.toByteArray())),
new PdfWriter(interimSection)) )
{
List<PdfCleanUpLocation> cleanUpLocations = new ArrayList<PdfCleanUpLocation>();
cleanUpLocations.add(new PdfCleanUpLocation(page, from, null));
cleanUpLocations.add(new PdfCleanUpLocation(page, to, null));
PdfCleanUpTool cleaner = new PdfCleanUpTool(pdfMainDocument, cleanUpLocations);
cleaner.cleanUp();
cleanUpLocations = new ArrayList<PdfCleanUpLocation>();
Rectangle mediaBox = pdfSectionDocument.getPage(1).getMediaBox();
if (from.getTop() < mediaBox.getTop())
cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(mediaBox.getLeft(), from.getTop(), mediaBox.getWidth(), mediaBox.getTop() - from.getTop()), null));
if (from.getBottom() > mediaBox.getBottom())
cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(mediaBox.getLeft(), mediaBox.getBottom(), mediaBox.getWidth(), from.getBottom() - mediaBox.getBottom()), null));
if (from.getLeft() > mediaBox.getLeft())
cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(mediaBox.getLeft(), mediaBox.getBottom(), from.getLeft() - mediaBox.getLeft(), mediaBox.getHeight()), null));
if (from.getRight() < mediaBox.getRight())
cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(from.getRight(), mediaBox.getBottom(), mediaBox.getRight() - from.getRight(), mediaBox.getHeight()), null));
cleaner = new PdfCleanUpTool(pdfSectionDocument, cleanUpLocations);
cleaner.cleanUp();
}
try ( PdfDocument pdfSectionDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(interimSection.toByteArray())));
PdfDocument pdfMainDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(interimMain.toByteArray())), new PdfWriter(targetFile)) )
{
float scale = Math.min(to.getHeight() / from.getHeight(), to.getWidth() / from.getWidth());
pdfSectionDocument.getPage(1).setMediaBox(from);
PdfFormXObject pageXObject = pdfSectionDocument.getFirstPage().copyAsFormXObject(pdfMainDocument);
PdfPage pdfPage = pdfMainDocument.getPage(page);
PdfCanvas pdfCanvas = new PdfCanvas(pdfPage);
pdfCanvas.addXObject(pageXObject, scale, 0, 0, scale, (to.getLeft() - from.getLeft() * scale), (to.getBottom() - from.getBottom() * scale));
}
}
(From MoveSectionCleanly.java)
Beware: Due to the nature of pdfSweep, text being on the border of the source area is removed both from the source and the copy of it.
I was wondering if it was possible to mark strings in pdf with different color or underline them while looping through the pdf document ?
It's possible on creating a document. Just use different chunks to set the style. Here's an example:
Document document = new Document();
PdfWriter.getInstance(document, outputStream);
document.open();
document.add(new Chunk("This word is "));
Chunk underlined = new Chunk("underlined");
underlined.setUnderline(1.0f, -1.0f); //We can customize thickness and position of underline
document.add(underlined);
document.add(new Chunk(". And this phrase has "));
Chunk background = new Chunk("yellow background.");
background.setBackground(BaseColor.YELLOW);
document.add(background);
document.add(Chunk.NEWLINE);
document.close();
However, it's almost impossible to edit an existing PDF document. The author of iText writes in his book:
In a PDF document, every character or glyph on a PDF page has its
fixed position, regardless of the application that’s used to view the
document. This is an advantage, but it also comes with a disadvantage.
Suppose you want to replace the word “edit” with the word “manipulate”
in a sentence, you’d have to reflow the text. You’d have to reposition
all the characters that follow that word. Maybe you’d even have to
move a portion of the text to the next page. That’s not trivial, if
not impossible.
If you want to “edit” a PDF, it’s advised that you change the original
source of the document and remake the PDF.
Aspose.PDF APIs support to create new PDF document and manipulate existing PDF documents without Adobe Acrobat dependency. You can search and add Highlight Annotation to mark PDF text.
REST API Solution using Aspose.PDF Cloud SDK for Java:
// For complete examples and data files, please go to https://github.com/aspose-pdf-cloud/aspose-pdf-cloud-java
String name = "02_pages.pdf";
String folder="Temp";
String remotePath=folder+"/"+name;
// File to upload
File file = new File("C:/Temp/"+name);
// Storage name is default storage
String storage = null;
// Get App Key and App SID from https://dashboard.aspose.cloud/
PdfApi pdfApi = new PdfApi("xxxxxxxxxxxxxxxxxxxx", "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxx");
//Upload file to cloud storage
pdfApi.uploadFile(remotePath,file,storage);
//Text Position
Rectangle rect = new Rectangle().LLX(259.27580539703365).LLY(743.4707997894287).URX(332.26148873138425).URY(765.5148007965088);
List<AnnotationFlags> flags = new ArrayList<>();
flags.add(AnnotationFlags.DEFAULT);
HighlightAnnotation annotation = new HighlightAnnotation();
annotation.setName("Name Updated");
annotation.rect(rect);
annotation.setFlags(flags);
annotation.setHorizontalAlignment(HorizontalAlignment.CENTER);
annotation.setRichText("Rich Text Updated");
annotation.setSubject("Subj Updated");
annotation.setPageIndex(1);
annotation.setZindex(1);
annotation.setTitle("Title Updated");
annotation.setModified("02/02/2018 00:00:00.000 AM");
List<HighlightAnnotation> annotations = new ArrayList<>();
annotations.add(annotation);
//Add Highlight Annotation to the PDF document
AsposeResponse response = pdfApi.postPageHighlightAnnotations(name,1, annotations, storage, folder);
//Download annotated PDF file from Cloud Storage
File downloadResponse = pdfApi.downloadFile(remotePath, null, null);
File dest = new File("C:/Temp/HighlightAnnotation.pdf");
Files.copy(downloadResponse.toPath(), dest.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
System.out.println("Completed......");
On-Premise Solution using Aspose.PDF for Java:
// For complete examples and data files, please go to https://github.com/aspose-pdf/Aspose.Pdf-for-Java
// Instantiate Document object
Document document = new Document("C:/Temp/Test.pdf");
// Create TextFragment Absorber instance to search particular text fragment
TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber("Estoque");
// Iterate through pages of PDF document
for (int i = 1; i <= document.getPages().size(); i++) {
// Get first page of PDF document
Page page = document.getPages().get_Item(i);
page.accept(textFragmentAbsorber);
}
// Create a collection of Absorbed text
TextFragmentCollection textFragmentCollection = textFragmentAbsorber.getTextFragments();
// Iterate on above collection
for (int j = 1; j <= textFragmentCollection.size(); j++) {
TextFragment textFragment = textFragmentCollection.get_Item(j);
// Get rectangular dimensions of TextFragment object
Rectangle rect = new Rectangle((float) textFragment.getPosition().getXIndent(), (float) textFragment.getPosition().getYIndent(), (float) textFragment.getPosition().getXIndent() + (float) textFragment.getRectangle().getWidth(), (float) textFragment.getPosition().getYIndent() + (float) textFragment.getRectangle().getHeight());
// Instantiate HighLight Annotation instance
HighlightAnnotation highLight = new HighlightAnnotation(textFragment.getPage(), rect);
// Set opacity for annotation
highLight.setOpacity(.80);
// Set the color of annotation
highLight.setColor(Color.getYellow());
// Add annotation to annotations collection of TextFragment
textFragment.getPage().getAnnotations().add(highLight);
}
// Save updated document
document.save("C:/Temp/HighLight.pdf");
P.S: I work as support/evangelist developer at Aspose.
I am trying to read one PDF and copy its data into another PDF. The first PDF contains some text and images and I wish to write an image in the second PDF exactly where the text ends(which is basically the end of the PDF file). RIght now it just prints at the top. How can I make this change?
PdfReader reader = null;
reader = new PdfReader(Var.input);
Document document=new Document();
PdfWriter writer = null;
writer = PdfWriter.getInstance(document,new FileOutputStream(Var.output));
PdfImportedPage page = writer.getImportedPage(reader, 1);
reader.close();
document.open();
PdfContentByte cb = writer.getDirectContent();
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your new data / text here
Image image = null;
image = Image.getInstance (Var.qr);
document.add(image);
document.close();
Try this:
First get the location/co-ords of where the image needs to go, then simply add the second line from below to your code so the image is inserted at that location "X, Y"
Image image = Image.getInstance(String RESOURCE);
image.setAbsolutePosition(X, Y);
writer.getDirectContent().addImage(image);
Take a look here for some examples in iText 5: https://itextpdf.com/en/resources/examples/itext-5-legacy/chapter-3-adding-content-absolute-positions
You should use a PdfStamper instead of a PdfWriter with imported pages. Your approach throws away all interactive contents. You can use sorifiend's idea there, too.
To determine where the text on the given page ends, have a look at the iText in Action, 2nd edition example ShowTextMargins which parses a PDF and ads a rectangle showing the text margin.