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()
);
Related
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();
Using iText 7.1.9 java edition, I am attempting to add an image to a PDF at a fixed/absolute location, if the PDF is not landscape then I rotate it 90 degrees, however, once the page is rotated the origin point (was bottom left corner) also rotates (now at the top left corner and rotated 90 degrees), so when I insert the image it ends up rotated and uses the wrong origin point. See the two example PDF linked below for a visual of what is happening.
Is there any way to change a page origin point to the bottom left corner after a page is rotated? Is there a better way to rotate a page than using PdfDocument.getPage(p).setRotation?
Should I simply rotate the image and do some math to work out the new location for any additional elements? I have attempted rotating the image using imageData.setRotation(90) but it appears to do nothing.
The following are the inputs using the PDF attached at the bottom of this question:
//String pdfPath = "before_expected.pdf";
//String pdfDest = "after_expected.pdf";
//Or
String pdfPath = "before_unexpected.pdf";
String pdfDest = "after_unexpected.pdf";
The following is my code to rotate pages and add the image:
//Open existing PDF
FileInputStream inputStream = new FileInputStream(pdfPath);
PdfReader reader = new PdfReader(inputStream).setUnethicalReading(true);
//Create new PDF
FileOutputStream outputStream = new FileOutputStream(pdfDest);
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDocument = new PdfDocument(reader, writer);
//Load sample image
ImageData imageData = ImageDataFactory.create("C:/sample_image.png");
Image image = new Image(imageData);
//Get root element of PDF
Document document = new Document(pdfDocument);
//Get orientation
Rectangle pageSize = pdfDocument.getPage(1).getPageSize();
System.out.println("Original rotation " + pdfDocument.getPage(1).getRotation() + System.lineSeparator() + pageSize.toString());
//Rotate 90 if page is not landscape - placeholder
if (pageSize.getHeight() > pageSize.getWidth())
{
pdfDocument.getPage(1).setRotation(pdfDocument.getPage(1).getRotation() + 90);
}
//Find page size
Rectangle currentPageSize = pdfDocument.getPage(1).getPageSizeWithRotation();
//Locate image 40% across page and 20% up page
float absoluteXpos = currentPageSize.getWidth() * 0.4f;
float absoluteYpos = currentPageSize.getHeight() * 0.2f;
System.out.println("Image location from origin: " + absoluteXpos + ", "+absoluteYpos);
//Add image
image.setFixedPosition(absoluteXpos, absoluteYpos);
document.add(image);
//Removed code to close any tidy up
document.close();
The output from the second PDF (before_unexpected.pdf) shows that it is rotated, but as mentioned above, rotating the page further appears to make no difference for adding additional content:
Original rotation 90
Rectangle: 842.0x1191.0
Image location from origin: 336.80002, 238.2
Here are the PDF files I used for testing:
The first two images show expected/desired behaviour, the last two show how the image is inserted in the wrong spot (based on the incorrect origin/rotation).
Click here for the original file for the first pdf
Click here for the processed file for the first pdf
Click here for the original file for the second pdf
Click here for the processed file for the second pdf
First of all, when determining whether the current page is not landscape (if (pageSize.getHeight() > pageSize.getWidth())) you should already use getPageSizeWithRotation() instead of simply getPageSize(). You use this method later on in the code and you should have used it at an earlier point as well.
Secondly, if you want to add some content to the fixed position independent of the page rotation, you can use the following instruction before adding the content:
pdfDocument.getPage(1).setIgnorePageRotationForContent(true);
The complete code:
//Open existing PDF
FileInputStream inputStream = new FileInputStream("C:/in.pdf");
PdfReader reader = new PdfReader(inputStream).setUnethicalReading(true);
//Create new PDF
FileOutputStream outputStream = new FileOutputStream("C:/Users/Alexey/Desktop/exp.pdf");
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDocument = new PdfDocument(reader, writer);
//Load sample image
ImageData imageData = ImageDataFactory.create("C:/sample_image.png");
Image image = new Image(imageData);
//Get root element of PDF
pdfDocument.getPage(1).setIgnorePageRotationForContent(true);
Document document = new Document(pdfDocument);
//Get orientation
Rectangle pageSize = pdfDocument.getPage(1).getPageSizeWithRotation();
System.out.println("Original rotation " + pdfDocument.getPage(1).getRotation() + System.lineSeparator() + pageSize.toString());
//Rotate 90 if page is not landscape - placeholder
if (pageSize.getHeight() > pageSize.getWidth())
{
pdfDocument.getPage(1).setRotation(pdfDocument.getPage(1).getRotation() + 90);
}
//Find page size
Rectangle currentPageSize = pdfDocument.getPage(1).getPageSizeWithRotation();
//Locate image 40% across page and 20% up page
float absoluteXpos = currentPageSize.getWidth() * 0.4f;
float absoluteYpos = currentPageSize.getHeight() * 0.2f;
System.out.println("Image location from origin: " + absoluteXpos + ", "+absoluteYpos);
//Add image
image.setFixedPosition(absoluteXpos, absoluteYpos);
document.add(image);
//Removed code to close any tidy up
document.close();
It gives me same result for both input files:
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();
}
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();
I'm developing a System in which I have to add some images to an existing PDF Document.
This works great with iText 5.1.3, but for some reason in a PDF that contains a scanned image it won't add any of the images.
Here's the link to the PDF Document that can't be modified with PdfStamper
and here's the code
PdfReader reader = new PdfReader("Registro celular_OR.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("DocStamped.pdf"));
Image img = Image.getInstance("someImage.jpg");
img.setAbsolutePosition(0, 0);
img.scaleAbsolute(50f, 50f);
PdfContentByte over = null;
int total = reader.getNumberOfPages() + 1;
for(int i = 1; i < total; i++) {
System.out.println("Procesando Pagina: " + i);
over = stamper.getOverContent(i);
over.addImage(img);
over.beginText();
BaseFont bf_times = BaseFont.createFont(BaseFont.TIMES_ROMAN, "Cp1252", false);
over.setFontAndSize(bf_times, 8);
over.showTextAligned(PdfContentByte.ALIGN_CENTER, "TEXTO PRUEBA", 50, 50, 0);
over.endText();
}
stamper.close();
A PDF page does not need to have its lower left corner at (0, 0). It can be anywhere in the coordinate system. So an A4 page can be (0, 0, 595, 842), but it might as well be (1000, 2000, 1595, 2842).
You are positioning the image at (0, 0):
img.setAbsolutePosition(0, 0);
But the page of this document is defined as (0, 15366, 469, 15728). The image is actually added to the output document, but it's outside the visible area of the page.
You have to get the coordinates of the page to position the image. Inside the loop, do this:
img.setAbsolutePosition(reader.getPageSize(i).getLeft(), reader.getPageSize(i).getBottom());