There is a web site developed entirely in PHP with GD library that mainly deals with printing text over a random image.
The text has to be printed in any of about 100 prescribed TTF fonts (residing in a directory near the .php files) in a dozen of prescribed colors and there is a requirement to specify location of the text according to any of several prescribed algorithms.
This is solved by using imagettfbox() which returns geometry of the text, which is then mapped onto the image using imagettftext().
What can I use in Java to achieve the same functionality with servlets/beans?
I can put the TTF fonts anywhere I have to. Registering them in Windows is undesirable, but if that's the only option we'd go for it (currently they are not).
#LexLythius:
From your link and some other resources I pieced together a working solution to drawing text over graphics:
// file is pointed at the image
BufferedImage loadedImage = ImageIO.read(file);
// file is pointed at the TTF font
Font font = Font.createFont(Font.TRUETYPE_FONT, file);
Font drawFont = font.deriveFont(20); // use actual size in real life
Graphics graphics = loadedImage.getGraphics();
FontMetrics metrics = graphics.getFontMetrics(drawFont);
Dimension size = new Dimension(metrics.getHeight(), metrics.stringWidth("Hello, world!"));
graphics.setFont(drawFont);
graphics.setColor(new Color(128, 128, 128); // use actual RGB values in real life
graphics.drawString("Hello, world!", 10,10); // use Dimension to calculate position in real life
What is remaining is displaying that image in a servlet and deciding what functionality goes where - to a servlet or bean.
You can get an OutputStream from the servlet response, and pass that OutputStream to ImageIO.write. Example based on the code from here (not my code):
http://www.avajava.com/tutorials/lessons/how-do-i-return-an-image-from-a-servlet-using-imageio.html
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ImageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("image/jpeg"); // change this if you are returning PNG
File f = new File( /* path to your file */ );
BufferedImage bi = ImageIO.read(f);
// INSERT YOUR IMAGE MANIPULATION HERE
OutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out); // or "png" if you prefer
out.close(); // may not be necessary; containers should do this for you
}
Depending on how much memory you have, pre-loading the fonts and keeping a pool of them may save a bit of time.
Related
While trying to add an SVG image to XSSFWorkbook, I noticed there is no option to set the PictureType to SVG.
FileInputStream in = new FileInputStream("testWorkbook.xlsx");
XSSFWorkbook wb = (XSSFWorkbook)WorkbookFactory.create(in);
InputStream inputStream = new FileInputStream("/home/test/test1.svg");
//Get the contents of an InputStream as a byte[].
byte[] imageData = IOUtils.toByteArray(inputStream);
// XSSFWorkbook.PICTURE_TYPE_SVG is not supported yet.
int pictureIndex = wb.addPicture(imageData, XSSFWorkbook.PICTURE_TYPE_SVG); // Preferred support
However, I noticed there is support for adding SVG images to XSLF.
Is there any way of adding an SVG image to a XSSFWorkbook?
Support for SVG is a new feature of Microsoft Office 365. That's why it is not fully supported by apache poi until now (May 2021, apache poi 5.0.0).
To implement that support in Excel one needs to know how Excel inserts SVG images. It converts the images to PNG for backwards compatibility. And it puts both, the SVG image as well as the PNG image, into the workbook. Then it shows the PNG image as a shape in the drawing. That shape has an additional reference to the SVG image, so if Excel 365 is used, the SVG image can be got too.
To implement that support in apache poi following is needed:
A SVG to PNG converter. There Apache Batik Transcoder can be used.
An extended XSSFWorkbook which provides either a separate addSVGPicture method or provides support for SVG in addPicture method. But extending XSSF... classes is not as simple as it could be, because of some weird decisions to make members or methods private.
A XSSFRelation.IMAGE_SVG to provide creating relations while creating pictures and shapes. But XSSFRelation is not extendable at all. So extending the low level POIXMLRelation is needed.
An extended XSSFPictureData to provide support for needed picture constructors for the new POIXMLRelation.
Following code provides all that. It is commented where needed.
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class CreateExcelXSSFPictureSVG {
// use org.apache.batik.transcoder to convert SVG to PNG
static byte[] svgToPng(InputStream svg) throws Exception {
org.apache.batik.transcoder.image.PNGTranscoder t = new org.apache.batik.transcoder.image.PNGTranscoder();
org.apache.batik.transcoder.TranscoderInput input = new org.apache.batik.transcoder.TranscoderInput(svg);
java.io.ByteArrayOutputStream ostream = new java.io.ByteArrayOutputStream();
org.apache.batik.transcoder.TranscoderOutput output = new org.apache.batik.transcoder.TranscoderOutput(ostream);
t.transcode(input, output);
ostream.flush();
return ostream.toByteArray();
}
public static void main(String[] args) throws Exception {
String svgFilePath = "./Freesample.svg";
MyXSSFWorkbook workbook = new MyXSSFWorkbook(); // see MyXSSFWorkbook.java
// add SVG Image to workbook
FileInputStream is = new FileInputStream(svgFilePath);
int svgPictureIdx = workbook.addSVGPicture(is);
is.close();
// add PNG image to workbook
is = new FileInputStream(svgFilePath);
int pngPictureIdx = workbook.addPicture(svgToPng(is), Workbook.PICTURE_TYPE_PNG);
is.close();
// create sheet and get drawing
XSSFSheet sheet = workbook.createSheet("Sheet1");
XSSFDrawing drawing = sheet.createDrawingPatriarch();
// add SVG Image relation to drawing
XSSFPictureData pictureData = workbook.getAllPictures().get(svgPictureIdx);
org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart rp = drawing.addRelation(null, XSSFRelation.IMAGES, pictureData);
String svgRId = rp.getRelationship().getId();
// create anchor for picture shape
XSSFCreationHelper helper = workbook.getCreationHelper();
XSSFClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(1);
anchor.setRow1(1);
// create PNG picture shape
XSSFPicture pngPicture = drawing.createPicture(anchor, pngPictureIdx);
pngPicture.resize();
// set SVG extension to PNG picture shape
org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension ext = pngPicture.getCTPicture().getBlipFill().getBlip().addNewExtLst().addNewExt();
ext.setUri("{96DAC541-7B7A-43D3-8B79-37D633B846F1}");
org.apache.xmlbeans.XmlCursor cursor = ext.newCursor();
cursor.toNextToken();
cursor.toNextToken();
cursor.beginElement(new javax.xml.namespace.QName("http://schemas.microsoft.com/office/drawing/2016/SVG/main", "svgBlip", "asvg"));
cursor.insertNamespace("asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main");
cursor.insertAttributeWithValue(new javax.xml.namespace.QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "embed", "r"), svgRId);
cursor.dispose();
FileOutputStream out = new FileOutputStream("CreateExcelXSSFPictureSVG.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
Used extended classes:
MyXSSFWorkbook.java
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFFactory;
import org.apache.poi.util.IOUtils;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.lang.reflect.Field;
public class MyXSSFWorkbook extends XSSFWorkbook {
public int addSVGPicture(InputStream is) throws Exception {
Field _xssfFactory = XSSFWorkbook.class.getDeclaredField("xssfFactory");
_xssfFactory.setAccessible(true);
XSSFFactory xssfFactory = (XSSFFactory)_xssfFactory.get(this);
int imageNumber = getAllPictures().size() + 1;
Field _pictures = XSSFWorkbook.class.getDeclaredField("pictures");
_pictures.setAccessible(true);
#SuppressWarnings("unchecked")
List<XSSFPictureData> pictures = (List<XSSFPictureData>)_pictures.get(this);
MyXSSFPictureData img = createRelationship(MyXSSFRelation.IMAGE_SVG, xssfFactory, imageNumber, true).getDocumentPart(); // see MyXSSFPictureData.java and MyXSSFRelation.java
try (OutputStream out = img.getPackagePart().getOutputStream()) {
IOUtils.copy(is, out);
}
pictures.add(img);
return imageNumber - 1;
}
}
MyXSSFRelation.java
import org.apache.poi.ooxml.POIXMLRelation;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
public final class MyXSSFRelation extends POIXMLRelation {
public static final MyXSSFRelation IMAGE_SVG = new MyXSSFRelation(
"image/svg",
PackageRelationshipTypes.IMAGE_PART,
"/xl/media/image#.svg",
MyXSSFPictureData::new, MyXSSFPictureData::new // see MyXSSFPictureData.java
);
private MyXSSFRelation(String type, String rel, String defaultName,
NoArgConstructor noArgConstructor,
PackagePartConstructor packagePartConstructor) {
super(type, rel, defaultName, noArgConstructor, packagePartConstructor, null);
}
}
MyXSSFPictureData.java
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
public class MyXSSFPictureData extends XSSFPictureData {
protected MyXSSFPictureData() {
super();
}
protected MyXSSFPictureData(PackagePart part) {
super(part);
}
}
I need to create a rectangle with a horizontal or vertical gradient fill in a PowerPoint presentation I'm creating with the Apache POI API.
I'm using XSLFFreeformShape for the rectangle:
XSLFGroupShape currentGroup = ...;
XSLFFreeformShape ppShape = currentGroup.createFreeform();
ppShape.setPath( ... );
Setting a single, flat color is easy:
ppShape.setFillColor( myColor );
And there's a mechanism to get details of the gradient fill, via superclass method XSLFSimpleShape.getFillStyle().
But there's no corresponding setFillStyle(), and I don't see any other easy public way to specify a gradient.
Question: Can I create a rectangle with a gradient, and if so, how?
When defining the current API, I was mainly focused on giving the image renderer enough information and left out probably a lot of write access properties.
So currently you need to use the XmlObjects to set the gradient:
package org.apache.poi.xslf;
import java.awt.geom.Rectangle2D;
import java.io.FileOutputStream;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFAutoShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStopList;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TestGradientFill {
#Test
public void fill() throws Exception {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide sl = ppt.createSlide();
XSLFAutoShape as = sl.createAutoShape();
as.setShapeType(ShapeType.STAR_12);
as.setAnchor(new Rectangle2D.Double(100, 100, 100, 100));
CTShape cs = (CTShape)as.getXmlObject();
CTGradientFillProperties gFill = cs.getSpPr().addNewGradFill();
gFill.addNewLin().setAng(1800000);
CTGradientStopList list = gFill.addNewGsLst();
// set the start pos
CTGradientStop stop = list.addNewGs();
stop.setPos(0);
stop.addNewSrgbClr().setVal(new byte[]{ (byte)0x94, (byte)0xbd, (byte)0x5e });
// set the end pos (100000 = 100%)
stop = list.addNewGs();
stop.setPos(100000);
stop.addNewSrgbClr().setVal(new byte[]{ 0,0,0 });
FileOutputStream fos = new FileOutputStream("gradient.pptx");
ppt.write(fos);
fos.close();
}
}
I am trying to create a pdf using itext java library like:
Where I create highlighter icon(the arrow sign) like:
Phrase ph=new Phrase("รค", FontFactory.getFont(FontFactory.ZAPFDINGBATS, 14f));
Now I want that all the text of the advertisement ie.
Now own a Farm Plot nr Jigani in 5yrs installment option #INR450/sqft
with 5acre Club House.www.goldeneraproperty.com M-9999999999
should automatically wrap around the icon which I created above using FontFactory.ZAPFDINGBATS.
However I am stuck here.Please could anyone help me resolve it.
I tried creating a table of one column and one cell and put the icon in that cell but it did not help as the text did not wrap around the table.
Please suggest how could i create a pdf where the text would automatically wrap around the icon.Thanks in Advance!!!
I have designed it to a similar state. Please use you own alignment, fonts, sizes, etc. inside you PDF file.
PFB the code for above design:
package com.itext_dummy;
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
public class Hello {
/** Path to the resulting PDF file. */
public static final String RESULT
= "src/hello.pdf";
public static void main(String[] args)
throws DocumentException, IOException {
new Hello().createPdf(RESULT);
}
public void createPdf(String filename)
throws DocumentException, IOException {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(filename));
document.open();
Image img = Image.getInstance("src/Arrow.png");
img.scaleAbsolute(50f, 50f);
img.setAlignment(Image.LEFT | Image.TEXTWRAP);
document.add(img);
Paragraph para = new Paragraph();
para.add("Now own a Farm Plot nr Jigani in 5yrs installment option #INR450/sqft with 5acre Club House.www.goldeneraproperty.com M-99999999994444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
document.add(para);
document.close();
}
}
Please do your own alignment on image size and paragraph text sizes and alignments.
Also PFB the icon image that I used:
I used the image since, that is the only way the wrapping could be done.
PFB my result screenshot:
Is there any way to convert generated .ppt file using apache poi to .pdf file?
OR
Any way to convert PPT file to PDF file using JAVA?
Gagravarr, thanks you for your comment with following approach: PPT -> images -> PDF. It gave me clues for further solutions.
Recently, I've faced the same task: convert PPT reports into PDF reports using Java facilities. PPT reports are generated via Apache POI lib, and I intended to reuse ready created PPT structure.
I developed two solutions, each has its own advantages/disadvantages. And both of them using iText library with version 2.1.7.(which is free to use, and which is great)). Both of them do support Japanese symbols after additional enhancement.
1. Apache POI Slide -> image -> PDF
Demonstration code example:
package com.test.pdf;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.usermodel.SlideShow;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfWriter;
public class PPTtoImageToPDFexample {
public static void main(String[] args) throws IOException, DocumentException {
//load any ppt file
FileInputStream inputStream = new FileInputStream("d:/temp/initialPPT.ppt");
SlideShow ppt = new SlideShow(inputStream);
inputStream.close();
Dimension pgsize = ppt.getPageSize();
//take first slide and save it as an image
Slide slide = ppt.getSlides()[0];
BufferedImage img = new BufferedImage(pgsize.width, pgsize.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width,
pgsize.height));
slide.draw(graphics);
FileOutputStream out = new FileOutputStream("d:/temp/slideImage.png");
javax.imageio.ImageIO.write(img, "png", out);
out.close();
//get saved slide-image and save it into pdf
Image slideImage = Image.getInstance("d:/temp/slideImage.png");
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("d:/temp/PPTtoImageTest.pdf"));
document.setPageSize(new Rectangle(slideImage.getWidth(), slideImage.getHeight()));
document.open();
slideImage.setAbsolutePosition(0, 0);
document.add(slideImage);
document.close();
}
}
2. This approach works on-fly: take Apache POI Slide -> get awt.Graphics2 instance from it -> pass this interface to the iText
draw engine.
Demonstration code example:
package com.test.pdf;
import java.awt.Dimension;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.usermodel.SlideShow;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfGraphics2D;
import com.lowagie.text.pdf.PdfWriter;
public class PPTtoPDFdirectly {
public static void main(String[] args) throws IOException, DocumentException {
//load any ppt file
FileInputStream inputStream = new FileInputStream("d:/temp/initialPPT.ppt");
SlideShow ppt = new SlideShow(inputStream);
inputStream.close();
Dimension pgsize = ppt.getPageSize();
//take first slide and draw it directly into PDF via awt.Graphics2D interface.
Slide slide = ppt.getSlides()[0];
Document document = new Document();
PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream("d:/temp/PPTtoPDF.pdf"));
document.setPageSize(new Rectangle((float)pgsize.getWidth(), (float) pgsize.getHeight()));
document.open();
PdfGraphics2D graphics = (PdfGraphics2D) pdfWriter.getDirectContent().createGraphics((float)pgsize.getWidth(), (float)pgsize.getHeight());
slide.draw(graphics);
graphics.dispose();
document.close();
}
}
One option is to use POI to convert each slide into an image, then use something like Apache PDFBox to place each image onto it's own PDF page. This should work well for simpler PPT files, but the code to render slides is still a WIP. So, if you have a very complex slide, you may find some bits missing/incorrect, do send in patches if you fix any of these gaps!
Otherwise, your other option is to use the Java bindings for OpenOffice, and have that do the conversion for you
I have to build a Java servlet that receives an image and returns that image converted to PNG format. How can I achieve this?
By converting I don't mean changing the file extension, like some examples suggest.
Thanks in advance!
Try this out:
package demo;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main( String [] args ) throws IOException {
File input = new File("input.gif");
File output = new File("output.png");
ImageIO.write( ImageIO.read( input ), "png", ouput);
}
}
Read ImageIO.
Of course, you may want to read and write from an stream instead.
ImageIO.write(ImageIO.read(new File("img.gif")), "png", new File("img.png"));
Use ImageIo to save an Image in any format your want.