How to change text height in pdfbox - pdfbox

PDFBOX / JSF
Im trying to change the font height of a given text. I know how to change the fontsize only.
PDPageContentStream contentStreambc = new PDPageContentStream(doc1, page, true, true);
contentStreambc.setFont( fonta, 16 );
contentStreambc.beginText();
contentStreambc.moveTextPositionByAmount(200, 320);
contentStreambc.drawString( "abcdef");
contentStreambc.endText();
contentStreambc.close();
The code works fine. But How I change the font height ?
thanks in advance stack members.

If you need something like this
you can create it with this code:
PDRectangle rec = new PDRectangle(220, 70);
PDDocument document = null;
document = new PDDocument();
PDPage page = new PDPage(rec);
document.addPage(page);
PDPageContentStream content = new PDPageContentStream(document, page, true, true);
content.beginText();
content.moveTextPositionByAmount(7, 55);
content.setFont(PDType1Font.HELVETICA, 12);
content.drawString("Normal text (size 12)");
content.setTextMatrix(1, 0, 0, 1.5f, 7, 30);
content.drawString("Stretched text (size 12, factor 1.5)");
content.setTextMatrix(1, 0, 0, 2f, 7, 5);
content.drawString("Stretched text (size 12, factor 2)");
content.endText();
content.close();
document.save("SimplePdfStretchedText.pdf");
The code stretches the text by setting the text matrix accordingly; for details cf. chapter 9 of the PDF specification ISO 32000-1.
PS: As you mention bar codes in a comment to another answer, this should indeed allow you to make higher bar codes while keeping the distances.

Related

Unable to rotate image in PDFBox

I am trying to change the angle of the image by using matrix.Its a needle image which points the value in a chart.
If i am giving "at.rotate(Math.toRadians(45));" , then its looking like it went inside the page, but i need it in the page.
Here is the code i m trying
//Retrieving the pages of the document
PDPage page = document.getPage(0);
//Creating PDImageXObject object
PDImageXObject needle = PDImageXObject.createFromFile("SpeedometerNeedle-300dpi-ActualSize.png"
,document);
PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true, true);
//Drawing the image in the PDF document
// draw 90° rotated, placed on the right of the first image
Matrix at = new Matrix(needle.getHeight() / 4, 0, 0, needle.getWidth() / 4,120, 565);
at.rotate(Math.toRadians(45));
// contentStream.drawImage(needle, 100, 565, needle.getWidth() / 4, needle.getHeight() / 4);
contentStream.drawImage(needle,at);
contentStream.close();
I am using org.apache.pdfbox:pdfbox:2.0.1 version ,So if i am trying to use
AffineTransform at = new AffineTransform(ximage.getHeight() / 2, 0, 0, ximage.getWidth() / 2, x + ximage1.getWidth(), y);
at.rotate(Math.toRadians(90));
contentStream.drawXObject(ximage, at);
Then drawXObject method is shown as deprecated.
So suggest me how to use it.

Unable to add margins in iTextSharp document having images

Requirement:
A large image (dynamic) needs to be split and shown in PDF pages. If image can't be accomodated in one page then we need to add another page and try to fit the remaining portion and so on.
So far I am able to split the image in multiple pages, however it appears that they are completely ignoring the margin values and so images are shown without any margins.
Please see below code:
string fileStringReplace = imageByteArray.Replace("data:image/jpeg;base64,", "");
Byte[] imageByte = Convert.FromBase64String(fileStringReplace);
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageByte);
float w = image.ScaledWidth;
float h = image.ScaledHeight;
float cropHeight = 1500f;
iTextSharp.text.Rectangle page = new iTextSharp.text.Rectangle(1150f, cropHeight);
var x = page.Height;
Byte[] created;
iTextSharp.text.Document document = new iTextSharp.text.Document(page, 20f, 20f, 20f, 40f); --This has no impact
using (var outputMemoryStream = new MemoryStream())
{
PdfWriter writer = PdfWriter.GetInstance(document, outputMemoryStream);
writer.CloseStream = false;
document.Open();
PdfContentByte canvas = writer.DirectContentUnder;
float usedHeights = h;
while (usedHeights >= 0)
{
usedHeights -= cropHeight;
document.SetPageSize(new iTextSharp.text.Rectangle(1150f, cropHeight));
canvas.AddImage(image, w, 0, 0, h, 0, -usedHeights);
document.NewPage();
}
document.Close();
created = outputMemoryStream.ToArray();
outputMemoryStream.Write(created, 0, created.Length);
outputMemoryStream.Position = 0;
}
return created;
I also tried to set margin in the loop by document.SetMargins() - but that's not working.
You are mixing different things.
When you create margins, be it while constructing the Document instance or by using the setMargins() method, you create margins for when you let iText(Sharp) decide on the layout. That is: the margins will be respected when you do something like document.Add(image).
However, you do not allow iText to create the layout. You create a PdfContentByte named canvas and you decide to add the image to that canvas using a transformation matrix. This means that you will calculate the a, b, c, d, e, and f value needed for the AddImage() method.
You are supposed to do that Math. If you want to see a margin, then the values w, 0, 0, h, 0, and -usedHeights are wrong, and you shouldn't blame iTextSharp, you should blame your lack of insight in analytical geometrics (that's the stuff you learn in high school at the age of 16).
This might be easier for you:
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageByte);
float w = image.ScaledWidth;
float h = image.ScaledHeight;
// For the sake of simplicity, I don't crop the image, I just add 20 user units
iTextSharp.text.Rectangle page = new iTextSharp.text.Rectangle(w + 20, h + 20);
iTextSharp.text.Document document = new iTextSharp.text.Document(page);
PdfWriter writer = PdfWriter.GetInstance(document, outputMemoryStream);
// Please drop the line that prevents closing the output stream!
// Why are so many people making this mistake?
// Who told you you shouldn't close the output stream???
document.Open();
// We define an absolute position for the image
// it will leave a margin of 10 to the left and to the bottom
// as we created a page that is 20 user units to wide and to high,
// we will also have a margin of 10 to the right and to the top
img.SetAbsolutePosition(10, 10);
document.Add(Image);
document.Close();
Note that SetAbsolutePosition() also lets you take control, regardless of the margins, as an alternative, you could use:
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageByte);
float w = image.ScaledWidth;
float h = image.ScaledHeight;
// For the sake of simplicity, I don't crop the image, I just add 20 user units
iTextSharp.text.Rectangle page = new iTextSharp.text.Rectangle(w + 20, h + 20);
iTextSharp.text.Document document = new iTextSharp.text.Document(page, 10, 10, 10, 10);
PdfWriter writer = PdfWriter.GetInstance(document, outputMemoryStream);
// Please drop the line that prevents closing the output stream!
// Why are so many people making this mistake?
// Who told you you shouldn't close the output stream???
document.Open();
// We add the image to the document, and we let iTextSharp decide where to put it
// As there is just sufficient space to fit the image inside the page, it should fit,
// But be aware of the existence of a leading; that could create side-effects
// such as forwarding the image to the next page because it doesn't fit vertically
document.Add(Image);
document.Close();

table header in pdf getting displayed using itextpdf5.1.1 but not in itextpdf5.5.3

We have generated a pdf in landscape mode with header and footer as part of the pdf. The header table and footer display fine in pdf using itextpdf5.1.1 jar. However when we update the jar to 5.5.3, the header table does not show only the footer shows. Below is the code snippet.
document = new Document(PageSize.A4.rotate(), 20, 20, 75, 20);
PdfCopy copy = new PdfCopy(document, new FileOutputStream(strPDFFile));
document.open();
PdfReader pdfReaderIntermediate =
new PdfReader(strIntermediatePDFFile);
numberOfPages = pdfReaderIntermediate.getNumberOfPages();
Font ffont = new Font(Font.FontFamily.UNDEFINED, 7, Font.NORMAL);
System.out.println("###### No. of Pages: " + numberOfPages);
for (int j = 0; j < numberOfPages; ) {
page = copy.getImportedPage(pdfReaderIntermediate, ++j);
stamp = copy.createPageStamp(page);
Phrase footer =
new Phrase(String.format("%d of %d", j, numberOfPages), ffont);
ColumnText.showTextAligned(stamp.getUnderContent(),
Element.ALIGN_CENTER, footer,
(document.right() - document.left()) /
2 + document.leftMargin(),
document.bottom() - 10, 0);
if (j != 1) {
headerTable = new PdfPTable(2);
headerTable.setTotalWidth(700);
headerTable.getDefaultCell().setFixedHeight(10);
headerTable.getDefaultCell().setBorder(Rectangle.NO_BORDER);
headerTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
headerTable.addCell(new Phrase(String.format(header1), ffont));
headerTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
headerTable.addCell(new Phrase(String.format(header2), ffont));
headerTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
headerTable.addCell(new Phrase(String.format(header3), ffont));
headerTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
headerTable.addCell(new Phrase(String.format(header5, j),
ffont));
headerTable.completeRow();
headerTable.writeSelectedRows(0, 5, 60.5f, 550,
stamp.getUnderContent());
}
stamp.alterContents();
copy.addPage(page);
}
document.close();
When we change the jar from 5.1.1 to 5.5.3 the header is lost. May be a change is needed in the way we call the header for the new jar.
Any inputs will be well appreciated.
Thanks.
You have cells with default padding (i.e. 2) and height 10, and you try to insert text at height 7. But 2 (top margin) + 7 (text height) + 2 (bottom margin) = 11, i.e. more than fits into your cell height 10. Thus, the text does not fit and is not displayed.
You can fix this by either
using a smaller font, e.g. 6, or
using a heigher cell, e.g. 11, or
using a smaller padding, e.g. 1:
headerTable.getDefaultCell().setPadding(1);
With any of these changes, your header shows.
I don't know in which way iText 5.1.1 handled this differently, but the behavior of current iText versions makes sense.

How to make PdfLayer.SetPrint work with PdfStamper?

I'm adding watermarks on existing PDF using the iText PdfStamper class. And I want these watermarks to be switched to on or off, so I'm using the class PdfLayer.
But I also want these watermarks to be always visible when the file is printed : I'm using the function PdfLayer.setPrint() then.
This is this last step that unfortunately doesn't work as expected.
Here's my code :
PdfReader reader = new PdfReader("C:/Temp/input.pdf");
PdfStamper stamp = new PdfStamper(reader, new FileOutputStream("C:/Temp/output.pdf"));
PdfWriter writer = stamp.getWriter();
PdfLayer layer = new PdfLayer("Watermarks", writer);
layer.setOn(true);
layer.setPrint("Watermarks", true);
BaseFont bf = BaseFont.createFont();
PdfContentByte cb = stamp.getOverContent(1);
cb.beginText();
cb.setFontAndSize(bf, 18);
cb.beginLayer(layer);
cb.showTextAligned(Element.ALIGN_LEFT, "Watermark line 1", 50, 55, 0);
cb.showTextAligned(Element.ALIGN_LEFT, "Watermark line 2", 50, 40, 0);
cb.endLayer();
cb.endText();
stamp.close();
reader.close();
When I check the layer properties from Adobe Reader (version 10), I see that the "Initial State : Print" property stays at "Prints When Visible" while it should be "Always Print".
I also tried creating layers on a new PDF document and there the setPrint() works.
What am I doing wrong ?
I have the same issue. My code want to add a image as watermark on every page of original pdf. And the watermark can only be viewed, not allow to print. I use PdfStamper and PdfLayer.setPrint() too. But it did not work. I read the itext java source and found a way to make it work. Here is code :
PdfWriter writer = stamp.getWriter();
PdfLayer layer = new PdfLayer("Watermarks", writer);
layer.setOn(true);
layer.setOnPanel(false);
layer.setPrint("watermark", false);
writer.addToBody(layer.getPdfObject(), layer.getRef());
It call addToBody after setPrint. This works well.
I have the same problem. As a workaround, you can use new Document and getImportedPage instead of pdfStamper.
Unfortunately, you loose the hyperlink because all pages are converted to images. I tried to use PdfCopy but I reproduced the same issue. I am really interested in a solution allowing me to add a watermark without changing the source file.
Degraded sample solution :
PdfReader pdfReaderS = new PdfReader(filepathS);
Document document = new Document(pdfReaderS.getPageSizeWithRotation(1));
PdfWriter pdfWriterD = PdfWriter.getInstance(document, new FileOutputStream(filepathD));
document.open();
PdfContentByte pdfContentByteD = pdfWriterD.getDirectContent();
BaseFont baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
int n = pdfReaderS.getNumberOfPages();
PdfLayer pdfLayer = new PdfLayer("Watermark", pdfWriterD);
pdfLayer.setPrint("Print", true);
pdfLayer.setView(visibleScreen);
for (int i = 1; i <= n; i++) {
Rectangle pageSizeS =pdfReaderS.getPageSizeWithRotation(i);
float pageWidth = pageSizeS.getWidth() / 2;
float pageheight = pageSizeS.getHeight() / 2;
float degree = (float)(Math.toDegrees(Math.atan(pageSizeS.getHeight()/pageSizeS.getWidth())));
document.setPageSize(pageSizeS);
document.newPage();
PdfImportedPage pdfImportedPage = pdfWriterD.getImportedPage(pdfReaderS, i);
int rotation = pdfReaderS.getPageRotation(i); //This value can be 0, 90, 180 or 270.
if (rotation == 0)
pdfContentByteD.addTemplate(page, 1, 0, 0, 1, 0, 0);
else if (rotation == 90)
pdfContentByteD.addTemplate(page, 0, -1, 1, 0, 0, pageSizeS.getHeight());
else if (rotation == 180)
pdfContentByteD.addTemplate(page, -1, 0, 0, -1, pageSizeS.getHeight(), pageSizeS.getWidth());
else if (rotation == 270)
pdfContentByteD.addTemplate(page, 0, 1, -1, 0, pageSizeS.getWidth(), 0);
pdfContentByteD.beginLayer(pdfLayer);
pdfContentByteD.beginText();
pdfContentByteD.setFontAndSize(baseFont, policeSize);
pdfContentByteD.setColorFill(col);
pdfContentByteD.showTextAligned(PdfContentByte.ALIGN_CENTER, text, pageWidth, pageheight, degree);
pdfContentByteD.endText();
pdfContentByteD.endLayer();
}
document.close();
pdfReaderS.close();

PDF Watermark for printing only, programmatically

I can watermark any PDF already, and the images inside, everything ok, but now I need the watermark only showing up when the PDF is printed... Is this possible? How?
I need to do this programmatically of course.
For future readers, this is possible to do by wrapping the watermark in a PDF layer (Optional Content Group), then configuring the Usage attribute of this layer as Print-Only. See the PDF Reference Document, Chapter 4-Graphics, part 4.10-Optional Content for more details.
Specifically, using itextsharp, I was able to get it working with the following, specifically - pdf version 1.7, and SetPrint("Watermark",true)
string oldfile = #"c:\temp\oldfile.pdf";
string newFile = #"c:\temp\newfile.pdf";
PdfReader pdfReaderS = new PdfReader(oldfile);
Document document = new Document(pdfReaderS.GetPageSizeWithRotation(1));
PdfWriter pdfWriterD = PdfWriter.GetInstance(document, new FileStream(newFile, FileMode.Create, FileAccess.Write));
pdfWriterD.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
document.Open();
PdfContentByte pdfContentByteD = pdfWriterD.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
int n = pdfReaderS.NumberOfPages;
string text = "UNCONTROLLED";
for (int i = 1; i <= n; i++)
{
iTextSharp.text.Rectangle pageSizeS = pdfReaderS.GetPageSizeWithRotation(i);
float pageWidth = pageSizeS.Width / 2;
float pageheight = pageSizeS.Height / 2;
document.SetPageSize(pageSizeS);
document.NewPage();
PdfImportedPage pdfImportedPage = pdfWriterD.GetImportedPage(pdfReaderS, i);
PdfLayer layer1 = new PdfLayer("Watermark", pdfWriterD);
layer1.SetPrint("Watermark", true);
layer1.View = false;
layer1.On = false;
layer1.OnPanel = false;
pdfContentByteD.BeginLayer(layer1);
pdfContentByteD.SetColorFill(BaseColor.RED);
pdfContentByteD.SetFontAndSize(bf, 30);
ColumnText.ShowTextAligned(pdfContentByteD, Element.ALIGN_CENTER, new Phrase(text), 300, 700, 0);
pdfContentByteD.EndLayer();
pdfContentByteD.AddTemplate(pdfImportedPage, 0, 0);//, 0, 1, 0, 0);
}
document.Close();
pdfReaderS.Close();
You should probably make use of the fact that the screen uses RGB and the printer CMYK. You should be able to create two colors in CMYK that map to the same RGB value. This is of course not enough against a determined specialist.
The bOnScreen parameter determines whether the watermark will be displayed when the PDF is viewed on the computer screen, and bOnPrint determines whether it will be displayed when the PDF is printed.
-- https://acrobatusers.com/tutorials/watermarking-a-pdf-with-javascript