iText : How does add image to top of PDF page - java

I going to convert tiff to pdf file, but image displayed bottom of page, how to start image from top of the pdf page.
private static String convertTiff2Pdf(String tiff) {
// target path PDF
String pdf = null;
try {
pdf = tiff.substring(0, tiff.lastIndexOf('.') + 1) + "pdf";
// New document A4 standard (LETTER)
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdf));
document.setMarginMirroring(true);
int pages = 0;
document.open();
PdfContentByte cb = writer.getDirectContent();
RandomAccessFileOrArray ra = null;
int comps = 0;
ra = new RandomAccessFileOrArray(tiff);
comps = TiffImage.getNumberOfPages(ra);
// Convertion statement
for (int c = 0; c < comps; ++c) {
Image img = TiffImage.getTiffImage(ra, c+1);
if (img != null) {
img.scalePercent(7200f / img.getDpiX(), 7200f / img.getDpiY());
img.setAbsolutePosition(0, 0);
img.scaleAbsolute(600, 250);
cb.addImage(img);
document.newPage();
++pages;
}
}
ra.close();
document.close();
} catch (Exception e) {
System.out.println(e);
pdf = null;
}
System.out.println("[" + tiff + "] -> [" + pdf + "] OK");
return pdf;
}

You are creating a new document with A4 pages (as opposed to using the LETTER format). These pages have a width of 595 pt and a height of 842 pt. The origin of the coordinate system (0, 0) is in the lower-left corner, which is exactly where you're adding the image using the method setAbsolutePosition(0, 0);
Surprisingly, you don't adapt the size of the page to the size of the image. Instead you want to add the image at the top of the page. In this case, you need to change the coordinates of the absolute position like this:
img.setAbsolutePosition(0, PageSize.A4.getHeight() - img.getScaledHeight());
If img.getScaledHeight() exceeds PageSize.A4.getHeight() (which is equal to 842), your image will be clipped at the bottom. The image will be clipped on the right if img.getScaledWidth() exceeds PageSize.A4.getWidth() (which is equal to 595).

Based in the answer, this code center any size image.
image.setAbsolutePosition((PageSize.A4.getWidth() - img.getScaledWidth())/2, (PageSize.A4.getHeight() - img.getScaledHeight())/2 );

Related

PDFBox why is the image not appearing in the PDF output?

I have (I think) correctly followed the instructions from: https://memorynotfound.com/apache-pdfbox-add-image-pdf-document/
I am attempting to insert an image logo.png. The code runs and doesn't throw up any errors, but the resulting PDF does not contain an image! The text does appear as expected. Does anybody know why this is and how to fix it?
I'm using Java 8 in Apache NetBeans 11.
Thanks. Here's the code:
public void generate(File samplefile) throws IOException {
PDDocument document = new PDDocument();
//Adding the blank page to the document
//Repeat this next line for further pages
PDPage page = new PDPage();
document.addPage(page);
File dir = new File(ArdenRecord.sadd + "/Sample Reports");
if (!dir.exists()) {
dir.mkdir();
}
String fname = samplefile.toString().split("\\.")[0].split("\\\\")[2];
File f = new File(ArdenRecord.sadd + "/Sample Reports/" + fname + ".pdf");
File imfile = new File(ArdenRecord.sadd + "/logo.png");
PDImageXObject pdImage = PDImageXObject.createFromFile(imfile.toString(), document);
PDPageContentStream contents = new PDPageContentStream(document, page);
PDRectangle mediaBox = page.getMediaBox();
float startX = (mediaBox.getWidth() - pdImage.getWidth()) / 2;
float startY = (mediaBox.getHeight() - pdImage.getHeight()) / 2;
contents.drawImage(pdImage, startX, startY);
contents.beginText();
contents.newLineAtOffset(25, 700);
contents.setFont(PDType1Font.TIMES_ROMAN, 12);
BufferedReader br = new BufferedReader(new FileReader(samplefile));
String st;
int n = 0;
while ((st = br.readLine()) != null) {
if (n < 4 || n > 20 && n < 30) {
contents.showText(st);
contents.newLineAtOffset(0, -18);
}
n++;
}
contents.endText();
contents.close();
document.save(f);
document.close();
Desktop.getDesktop().open(f);
}
}```
Maybe there's nothing wrong with your code. I copy-pasted (removed .split("\\\\")[2] to get path right), compiled and tested it with PDFBox 2.0.17, OpenJDK 8, this PNG file and the first chapter of Lorem Ipsum in a text file. See the result below (Adobe Reader screenshot).
At least you should try with a different PNG file.

Detecting text field overflow

Assuming I have a PDF document with a text field with some font and size defined, is there a way to determine if some text will fit inside the field rectangle using PDFBox?
I'm trying to avoid cases where text is not fully displayed inside the field, so in case the text overflows given the font and size, I would like to change the font size to Auto (0).
This code recreates the appearance stream to be sure that it exists so that there is a bbox (which can be a little bit smaller than the rectangle).
public static void main(String[] args) throws IOException
{
// file can be found at https://issues.apache.org/jira/browse/PDFBOX-142
// https://issues.apache.org/jira/secure/attachment/12742551/Testformular1.pdf
try (PDDocument doc = PDDocument.load(new File("Testformular1.pdf")))
{
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
PDTextField field = (PDTextField) acroForm.getField("Name");
PDAnnotationWidget widget = field.getWidgets().get(0);
// force generation of appearance stream
field.setValue(field.getValue());
PDRectangle rectangle = widget.getRectangle();
PDAppearanceEntry ap = widget.getAppearance().getNormalAppearance();
PDAppearanceStream appearanceStream = ap.getAppearanceStream();
PDRectangle bbox = appearanceStream.getBBox();
float fieldWidth = Math.min(bbox.getWidth(), rectangle.getWidth());
String defaultAppearance = field.getDefaultAppearance();
System.out.println(defaultAppearance);
// Pattern must be improved, font may have numbers
// /Helv 12 Tf 0 g
final Pattern p = Pattern.compile("\\/([A-z]+) (\\d+).+");
Matcher m = p.matcher(defaultAppearance);
if (!m.find() || m.groupCount() != 2)
{
System.out.println("oh-oh");
System.exit(-1);
}
String fontName = m.group(1);
int fontSize = Integer.parseInt(m.group(2));
PDResources resources = appearanceStream.getResources();
if (resources == null)
{
resources = acroForm.getDefaultResources();
}
PDFont font = resources.getFont(COSName.getPDFName(fontName));
float stringWidth = font.getStringWidth("Tilman Hausherr Tilman Hausherr");
System.out.println("stringWidth: " + stringWidth * fontSize / 1000);
System.out.println("field width: " + fieldWidth);
}
}
The output is:
/Helv 12 Tf 0 g
stringWidth: 180.7207
field width: 169.29082

PDFBox: put two A4 pages on one A3

I have a pdf document with one or more pages A4 paper.
The resulting pdf document should be A3 paper where each page contains two from the first one (odd on the left, even on the right side).
I already got it to render the A4 pages into images and the odd pages are successfully placed on the first parts of a new A3 pages but I cannot get the even pages to be placed.
public class CreateLandscapePDF {
public void renderPDF(File inputFile, String output) {
PDDocument docIn = null;
PDDocument docOut = null;
float width = 0;
float height = 0;
float posX = 0;
float posY = 0;
try {
docIn = PDDocument.load(inputFile);
PDFRenderer pdfRenderer = new PDFRenderer(docIn);
docOut = new PDDocument();
int pageCounter = 0;
for(PDPage pageIn : docIn.getPages()) {
pageIn.setRotation(270);
BufferedImage bufferedImage = pdfRenderer.renderImage(pageCounter);
width = bufferedImage.getHeight();
height = bufferedImage.getWidth();
PDPage pageOut = new PDPage(PDRectangle.A3);
PDImageXObject image = LosslessFactory.createFromImage(docOut, bufferedImage);
PDPageContentStream contentStream = new PDPageContentStream(docOut, pageOut, AppendMode.APPEND, true, true);
if((pageCounter & 1) == 0) {
pageOut.setRotation(90);
docOut.addPage(pageOut);
posX = 0;
posY = 0;
} else {
posX = 0;
posY = width;
}
contentStream.drawImage(image, posX, posY);
contentStream.close();
bufferedImage.flush();
pageCounter++;
}
docOut.save(output + "\\LandscapeTest.pdf");
docOut.close();
docIn.close();
} catch(IOException io) {
io.printStackTrace();
}
}
}
I'm using Apache PDFBox 2.0.2 (pdfbox-app-2.0.2.jar)
Thank you very much for your help and the link to the other question - I think I already read it but wasn't able to use in in my code yet.
But finally the PDFClown made the job, though I think it's not very nice to use PDFBox and PDFClown in the same program.
Anyway here's my working code to combine A4 pages on A3 paper.
public class CombinePages {
public void run(String input, String output) {
try {
Document source = new File(input).getDocument();
Pages sourcePages = source.getPages();
Document target = new File().getDocument();
Page targetPage = null;
int pageCounter = 0;
double moveByX = .0;
for(Page sourcePage : source.getPages()) {
if((pageCounter & 1) == 0) {
//even page gets a blank page
targetPage = new Page(target);
target.setPageSize(PageFormat.getSize(PageFormat.SizeEnum.A3, PageFormat.OrientationEnum.Landscape));
target.getPages().add(targetPage);
moveByX = .0;
} else {
moveByX = .50;
}
//get content from source page
XObject xObject = sourcePages.get(pageCounter).toXObject(target);
PrimitiveComposer composer = new PrimitiveComposer(targetPage);
Dimension2D targetSize = targetPage.getSize();
Dimension2D sourceSize = xObject.getSize();
composer.showXObject(xObject, new Point2D.Double(targetSize.getWidth() * moveByX, targetSize.getHeight() * .0), new Dimension(sourceSize.getWidth(), sourceSize.getHeight()), XAlignmentEnum.Left, YAlignmentEnum.Top, 0);
composer.flush();
pageCounter++;
}
target.getFile().save(output + "\\CombinePages.pdf", SerializationModeEnum.Standard);
source.getFile().close();
} catch (FileNotFoundException fnf) {
log.error(fnf);
} catch (IOException io) {
log.error(io);
}
}
}

Locating a cell image

I have inserted an image in an Excel table successfully; but now I have a huge trouble, I want the images to be centered in a single cell, since when I export the file with the images, they seems to be inside one cell., but when I look closely the image is some millimeters our of the cell which makes difficult to work. The image doesn't recognize which cell it belong to. using the library of Apache POI.
I hope you can help me, thanks.
here I send you part of the code,
int posReporte = 1;
int posRow = 1;
for (List<Object> dr : datosReportes) {
Row filaReporte = hojaReporte.createRow(posReporte);
for (int a = 0; a < dr.size(); a++) {
Cell celdaD = filaReporte.createCell(angel);*
celdaD.setCellStyle(estiloDatos);
Object obj = dr.get(angel);
if (a == 0) {
hojaReporte.setColumnWidth(a, 180 * 38);
filaReporte.setHeight(Short.valueOf("1500"));
//Add image data to the book
try {
if (directorio("S:\\", dr.get(1) + "_mini")) {
InputStream is = new FileInputStream("S:\\" + dr.get(1) + "_mini.jpg");
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
is.close();
CreationHelper helper = wb.getCreationHelper();
Drawing drawing = hojaReporte.createDrawingPatriarch();
//Add image
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(o);
anchor.setRow1(posRow);
anchor.setAnchorType(o);
Picture pict = drawing.createPicture(anchor, pictureIdx);
pict.resize();
}
} catch (Exception e) {
continue;
}
}
}
}

Implement Batch Export in the Jasper reports server to get the landscape and portrait in a single report

I am trying to implement a batch export similar to one here (as in the link) in jasper reports.
Please give pointers.
What I have:
1. A Portrait Template
2. A Landscape Template
3. Order in which I need to generate the reports
4. Same Bean Datasource with filter queries for each template to fill
What I need:
Generate the reports separately and merge all the generated JasperPrint objects and tweak the Page Nos
Since you are generating the reports and then merging it, current page number and total pages are available only during the export, based on the number of reports you merge. We solved a similar issue using generic elements. You need to write your custom logic to handle the page number inside the handler you create.
My report page 1 (jr1) is portrait and page 2 (jr2) landscape.
JasperReport jr1 = (JasperReport) JRLoader.loadObject(...);
JasperReport jr2 = (JasperReport) JRLoader.loadObject(...);
JREmptyDataSource ds = new JREmptyDataSource(1);
JasperPrint print1 = JasperFillManager.fillReport(jr1, new HashMap(), ds);
ds.moveFirst();
JasperPrint print2 = JasperFillManager.fillReport(jr2, new HashMap(), ds);
List l = new ArrayList();
l.add(print1);
l.add(print2);
JRPdfExporter exp = new JRPdfExporter();
exp.setParameter(JRExporterParameter.JASPER_PRINT_LIST, l);
exp.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, SAVE_LOCATION);
exp.exportReport();
This might work for page number issue:
private static void mergeAndNumber() throws IOException, DocumentException
{
PdfReader readerOne = new PdfReader("c:\file_one.pdf"«»);
// we retrieve the total number of pages
int nOne = readerOne.getNumberOfPages();
PdfReader readerTwo = new PdfReader("c:\file_two.pdf"«»);
// we retrieve the total number of pages
int nTwo = readerTwo.getNumberOfPages();
int totalPages = (nOne + nTwo);
System.out.println("Total number of pages: " + (nOne + nTwo));
Rectangle psize = readerOne.getPageSize(1);
float widthPort = psize.width();
float heightPort = psize.height();
// step 1: creation of a document-object
Document document = new Document(psize, 50, 50, 50, 50);
// step 2: we create a writer that listens to the document
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("c:\file_combined.pdf"«»));
document.open();
// step 4: we add content
PdfContentByte cb = writer.getDirectContent();
PdfImportedPage importPage = null;
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
float pageNumXPos = widthPort;
float pageNumYPos = heightPort;
for (int i = 1; i <= nOne; i++) {
document.newPage();
importPage = writer.getImportedPage(readerOne, i);
cb.addTemplate(importPage, 0,0);
cb.moveTo(400, 40);
cb.beginText();
cb.setFontAndSize(bf, 10);
//cb.showText("Page " + i + " of " + totalPages);
cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "Page " + i + " of " + totalPages, pageNumXPos - 45, pageNumYPos - 55, 0);
cb.endText();
}
document.setPageSize(PageSize.A4.rotate());
for (int i = 1; i <= nTwo; i++) {
document.newPage();
importPage = writer.getImportedPage(readerTwo, i);
cb.addTemplate(importPage, 0,0);
cb.moveTo(400, 40);
cb.beginText();
cb.setFontAndSize(bf, 10);
cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "Page " + (nOne + i) + " of " + totalPages, pageNumYPos - 20, pageNumXPos - 60, 0);
cb.endText();
}
document.close();
}

Categories