How to convert PowerPoint (.ppt) to PDF in Java - itext

Only last slide is getting convert means last slide overlapping every slides. Can anyone suggest how to combine it in one PDF?
I have tried with different approach but they are first creating image and then PDF.
FileInputStream inputStream = new FileInputStream(in);
SlideShow ppt = new SlideShow(inputStream);
inputStream.close();
Dimension pgsize = ppt.getPageSize();
Document document = new Document();
PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(out));
document.setPageSize(new Rectangle(
(float)pgsize.getWidth(), (float)pgsize.getHeight()));
document.open();
PdfGraphics2D graphics= null;
for (int i = 0; i < ppt.getSlides().length; i++) {
Slide slide = ppt.getSlides()[i];
graphics = (PdfGraphics2D) pdfWriter.getDirectContent()
.createGraphics((float)pgsize.getWidth(), (float)pgsize.getHeight());
slide.draw(graphics);
}
graphics.dispose();
document.close();

Related

Copying annotations with PdfWriter instead of PdfCopy

I need to copy annotations using PdfWriter instead of PdfCopy because at the time of the copy I need to resize/rotate the page. Can anyone tell me how to do this?
You think you need to use a plain PdfWriter instead of a PdfCopy for copying PDFs because you need to resize/rotate the page and iText in Action, 2nd Ed, says doing so is not possible with the PdfCopy class. Thus, you look for a way to copy annotations in such a context.
What you should look for instead is a way to rotate or resize pages and at the same time use PdfCopy nonetheless!
While it is true that the PdfCopy class itself does not allow resizing or rotating pages, you can manipulate a PDF loaded into a PdfReader and resize and/or rotate its pages before using the PdfCopy class. If you then copy the pages from this manipulated PdfReader into a PdfCopy, you get a result with resized or rotated pages (due to the manipulated PdfReader) and all the annotations present (due to the use of a PdfCopy).
E.g. you can resize all the pages in a PdfReader like this:
void resize(PdfReader pdfReader, float width, float height) {
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
boolean switched = pdfReader.getPageRotation(i) % 180 != 0;
float widthHere = switched ? height : width;
float heightHere = switched ? width : height;
Rectangle cropBox = pdfReader.getCropBox(i);
float halfWidthGain = (widthHere - cropBox.getWidth()) / 2;
float halfHeightGain = (heightHere - cropBox.getHeight()) / 2;
Rectangle newCropBox = new Rectangle(cropBox.getLeft() - halfWidthGain, cropBox.getBottom() - halfHeightGain,
cropBox.getRight() + halfWidthGain, cropBox.getTop() + halfHeightGain);
Rectangle mediaBox = pdfReader.getPageSize(i);
Rectangle newMediaBox = new Rectangle(Math.min(newCropBox.getLeft(), mediaBox.getLeft()),
Math.min(newCropBox.getBottom(), mediaBox.getBottom()),
Math.max(newCropBox.getRight(), mediaBox.getRight()),
Math.max(newCropBox.getTop(), mediaBox.getTop()));
PdfDictionary pageDictionary = pdfReader.getPageN(i);
pageDictionary.put(PdfName.MEDIABOX, new PdfArray(new float[] {newMediaBox.getLeft(), newMediaBox.getBottom(),
newMediaBox.getRight(), newMediaBox.getTop()}));
pageDictionary.put(PdfName.CROPBOX, new PdfArray(new float[] {newCropBox.getLeft(), newCropBox.getBottom(),
newCropBox.getRight(), newCropBox.getTop()}));
}
}
(CopyWithResizeRotate helper method)
and you can rotate all the pages in a PdfReader like this:
void rotate(PdfReader pdfReader) {
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
int rotation = pdfReader.getPageRotation(i);
int newRotation = rotation + 90 % 360;
PdfDictionary pageDictionary = pdfReader.getPageN(i);
if (newRotation == 0)
pageDictionary.remove(PdfName.ROTATE);
else
pageDictionary.put(PdfName.ROTATE, new PdfNumber(newRotation));
}
}
(CopyWithResizeRotate helper method)
Using these helpers, you can e.g. create a PDF from the rotated and/or resized pages of some source PDF and copy them like this:
byte[] wildPdf = RETRIEVE_SOURCE_PDF;
PdfReader pdfReaderOriginal = new PdfReader(wildPdf);
PdfReader pdfReaderRotate = new PdfReader(wildPdf);
rotate(pdfReaderRotate);
PdfReader pdfReaderResize = new PdfReader(wildPdf);
resize(pdfReaderResize, PageSize.LETTER.getWidth(), PageSize.LETTER.getHeight());
PdfReader pdfReaderRotateResize = new PdfReader(wildPdf);
rotate(pdfReaderRotateResize);
resize(pdfReaderRotateResize, PageSize.LETTER.getWidth(), PageSize.LETTER.getHeight());
try ( OutputStream os = new FileOutputStream(new File(RESULT_FOLDER, "wild-rotated-resized.pdf"))) {
Document document = new Document();
PdfCopy pdfCopy = new PdfCopy(document, os);
document.open();
pdfCopy.addDocument(pdfReaderOriginal);
pdfCopy.addDocument(pdfReaderRotate);
pdfCopy.addDocument(pdfReaderResize);
pdfCopy.addDocument(pdfReaderRotateResize);
document.close();
}
(CopyWithResizeRotate test method testRotateResizeAndCopy)
The result can look as follows, the first row the original pages (#1 A4, #2 HALFLETTER, #3 A5, #4 A5 rotated, #5 500x700), the second row the rotated ones, the third row the resized ones (to LETTER), and the fourth row the rotated and resized ones (to LETTER). The Adobe Reader thumbnails unfortunately are not at all to scale:
Manipulating a single PDF only
If you actually only want to resize/rotate pages of a single input PDF, you should not use a PdfCopy instance but instead a PdfStamper:
PdfReader pdfReader = new PdfReader(SOURCE);
[...manipulate properties of the pdfReader like above...]
new PdfStamper(pdfReader, TARGET_STREAM).close();
The advantage here is that not only page-level data but also document-level data of the original document are retained.
Special annotations
There is one type of annotations which will behave in an unexpected manner with the code above: annotations with the NoRotate flag set. Such annotations will behave like this when their host page is rotated:
(ISO 32000-2 section 12.5.3 — Annotation flags)

adding a textbox to the right corner of the existing pdf using ITextSharp in C#

I tiied to add a TextBox to the right corner of the existing pdf using c#, but im unable to get it done. I have wrote the following code,but it is not helping in solving the problem, can any body please suggest me
using (MemoryStream stream = new MemoryStream())
{
PdfReader reader = new PdfReader(bytes);
PdfReader.unethicalreading = true;
Paragraph p = new Paragraph();
Document doc = new Document();
using (PdfStamper stamper = new PdfStamper(reader, stream))
{
PdfContentByte canvas = stamper.GetOverContent(1);
iTextSharp.text.Rectangle size = reader.GetPageSizeWithRotation(1);
//PdfContentByte cb = null;
//PdfImportedPage page;
int pages = reader.NumberOfPages;
for (int i = 1; i <= pages; i++)
{
var size1 = reader.GetPageSize(i);
w = size1.Width;
h = size1.Height;
stamper.FormFlattening = true;
TextField tf = new TextField(stamper.Writer, new iTextSharp.text.Rectangle(0, 0, 300, 100), displaytext);
//Change the orientation of the text
tf.Rotation = 0;
stamper.AddAnnotation(tf.GetTextField(), i);
}
}
bytes = stream.ToArray();
}
File.WriteAllBytes(str, bytes);
As the OP clarified in comments to the question, he wants
to add the text as a page content in the right bottom corner of the page and
the page content previously existing there to be removed.
A simple implementation of this would include
first covering the existing page content with a filled rectangle and
then writing text there.
These tasks can be achieved with these helper methods:
void EmptyTextBoxSimple(PdfStamper stamper, int pageNumber, Rectangle boxArea, BaseColor fillColor)
{
PdfContentByte canvas = stamper.GetOverContent(pageNumber);
canvas.SaveState();
canvas.SetColorFill(fillColor);
canvas.Rectangle(boxArea.Left, boxArea.Bottom, boxArea.Width, boxArea.Height);
canvas.Fill();
canvas.RestoreState();
}
and
ColumnText GenerateTextBox(PdfStamper stamper, int pageNumber, Rectangle boxArea)
{
PdfContentByte canvas = stamper.GetOverContent(pageNumber);
ColumnText columnText = new ColumnText(canvas);
columnText.SetSimpleColumn(boxArea);
return columnText;
}
E.g. like this:
using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create)))
{
Rectangle cropBox = reader.GetCropBox(1);
Rectangle bottomRight = new Rectangle(cropBox.GetRight(216), cropBox.Bottom, cropBox.Right, cropBox.GetBottom(146));
EmptyTextBoxSimple(stamper, 1, bottomRight, BaseColor.WHITE);
ColumnText columnText = GenerateTextBox(stamper, 1, bottomRight);
columnText.AddText(new Phrase("Some test text to draw into a text box in the lower right corner of the first page"));
columnText.Go();
}
For this source page
the sample code generates this
Addendum
In a comment the OP indicated
it is working for all files but for some pdf files it is displaying in the middle
Eventually he supplied a sample file for which the issue occurs. And indeed, with this file the issue could be reproduced.
The cause for the issue is that the pages in the sample file use page rotation, something that iText (only) partially allows users to ignore. In particular iText automatically rotates text to be upright after rotation and transforms coordinates, but when retrieving the cropbox of a page, one still has to apply rotation before making use of it coordinates. Thus, a more complete example would be like this:
using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create)))
{
Rectangle cropBox = reader.GetCropBox(1);
int rotation = reader.GetPageRotation(1);
while (rotation > 0)
{
cropBox = cropBox.Rotate();
rotation -= 90;
}
Rectangle bottomRight = new Rectangle(cropBox.GetRight(216), cropBox.Bottom, cropBox.Right, cropBox.GetBottom(146));
EmptyTextBoxSimple(stamper, 1, bottomRight, BaseColor.WHITE);
ColumnText columnText = GenerateTextBox(stamper, 1, bottomRight);
columnText.AddText(new Phrase("Some test text to draw into a text box in the lower right corner of the first page"));
columnText.Go();
}

Reduce size of iText generated PDF including time series bar chart

Adding a time series bar chart for a large time span in PDF results in large file size like 50 MB or more depending on the data points. Here are the code samples:
Adding chart to PDF
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
document.open();
PdfContentByte cb = writer.getDirectContent();
float width = PageSize.A4.getWidth();
float height = PageSize.A4.getHeight() / 2;
PdfTemplate bar = cb.createTemplate(width, height);
Graphics2D g2d2 = new PdfGraphics2D(bar, width, height);
Rectangle2D r2d2 = new Rectangle2D.Double(0, 0, width, height);
getBarChart().draw(g2d2, r2d2);
g2d2.dispose();
cb.addTemplate(bar, 0, 0);
document.close();
Creating chart
JFreeChart getBarChart() {
TimeSeries series = new TimeSeries("Data");
GregorianCalendar cal = new GregorianCalendar();
for (int i=0; i<365*24; i++) {
cal.add(Calendar.HOUR, 1);
series.addOrUpdate(new Millisecond(cal.getTime()), Math.random());
}
XYPlot plot = new XYPlot();
plot.setDataset(new XYBarDataset(new TimeSeriesCollection(series), 10));
plot.setRenderer(new XYBarRenderer());
plot.setRangeAxis(new NumberAxis());
plot.setDomainAxis(new DateAxis());
return new JFreeChart(plot);
}
How can I reduce the file size?
Using itextpdf-5.4.4 and jfreechart-1.0.15.
While inspecting the PDF provided by the OP, it quickly becomes apparent that it is full of Pattern definitions and the like used for drawing pretty bars. To reduce the PDF size, therefore, simplifying the bar design is the way to go.
In the case at hand this can be done by setting a different default bar painter (using XYBarRenderer.setDefaultBarPainter()). The initial value of that attribute is a GradientXYBarPainter, but using gradients for so small bars makes the number of required drawing operations and operators explode while only making a difference at a gigantic zoom level, if at all.
As already worked out in the comments to the question, using the StandardXYBarPainter instead solves the size issues.
You can try to set full compression and compare the difference:
PdfReader reader = new PdfReader(new FileInputStream("in.pdf"));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("out.pdf"));
int total = reader.getNumberOfPages() + 1;
for ( int i=1; i<total; i++) {
reader.setPageContent(i + 1, reader.getPageContent(i + 1));
}
stamper.setFullCompression();
stamper.close();

Add file with bookmark

I want to add a PDF file using iTextSharp but if PDF file contains bookmarks then they should also be added.
Currently I'm using following code
Document document = new Document();
//Step 2: we create a writer that listens to the document
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(outputFileName, FileMode.Create));
writer.ViewerPreferences = PdfWriter.PageModeUseOutlines;
//Step 3: Open the document
document.Open();
PdfContentByte cb = writer.DirectContent;
//The current file path
string filename = "D:\\rtf\\2.pdf";
// we create a reader for the document
PdfReader reader = new PdfReader(filename);
//Chapter ch = new Chapter("", 1);
for (int pageNumber = 1; pageNumber < reader.NumberOfPages + 1; pageNumber++)
{
document.SetPageSize(reader.GetPageSizeWithRotation(1));
document.NewPage();
// Insert to Destination on the first page
if (pageNumber == 1)
{
Chunk fileRef = new Chunk(" ");
fileRef.SetLocalDestination(filename);
document.Add(fileRef);
}
PdfImportedPage page = writer.GetImportedPage(reader, pageNumber);
int rotation = reader.GetPageRotation(pageNumber);
if (rotation == 90 || rotation == 270)
{
cb.Add(page);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
document.Close();
Please read Chapter 6 of my book. In table 6.1, you'll read:
Can import pages from other PDF documents. The major downside is that all interactive features of the imported page (annotations, bookmarks, fields, and so forth) are lost in the process.
This is exactly what you experience. However, if you look at the other classes listed in that table, you'll discover PdfStamper, PdfCopy, etc... which are classes that do preserve interactive features.
PdfStamper will keep the bookmarks. If you want to use PdfCopy (or PdfSmartCopy), you need to read chapter 7 to find out how to keep them. Chapter 7 isn't available for free, but you can consult the examples here: Java / C#. You need the ConcatenateBookmarks example.
Note that you're code currently looks convoluted because you're not using the correct classes. Using PdfStamper should significantly reduce the number of lines of code.

Converting ppt to png using Apache poi

Hello I am trying to use the Apache Poi framework to convert each slide of a ppt to an individual png. The problem is that some slides are deformed. For instance there is a slide where the background has a rainbow color to it. And Images that are on some slides do not appear at all on the .png file
here is the code:
FileInputStream is = new FileInputStream(args[0]);
SlideShow ppt = new SlideShow(is);
is.close();
Dimension pgsize = ppt.getPageSize();
Slide[] slide = ppt.getSlides();
for (int i = 0; i < slide.length; i++) {
BufferedImage img = new BufferedImage(pgsize.width, pgsize.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
//clear the drawing area
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
//render
slide[i].draw(graphics);
//save the output
FileOutputStream out = new FileOutputStream("C:\\Users\\Farzad\\Desktop\\slide-" + (i+1) + ".png");
javax.imageio.ImageIO.write(img, "png", out);
out.close();
}
For this to work we don't have to use:
graphics.setPaint(Color.white);
Instead use :
graphics.setPaint(
slideShow.getSlides()[0].getBackground().getFill().getForegroundColor()
);