I have the below sample code which generates a PDF file using iText.
The question I have is when I create the base64Binary by DatatypeConverter.printBase64Binary method..
I tried to copy the Sysem.out.println of "base64Binary".
Used a online base64 online decoder tool to decode the content and save it output as sample.pdf and
when I try to open the sample.pdf it shows empty. I am not sure why its behaving this way and help would be much appreciated.
But when I directly decode using java and write it to a disk file it shows the context.
Can someone help me understand why it shows blank when I try to save "base64Binary" output as sample.pdf.
Thanks.
Below is the code snippet:
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.bind.DatatypeConverter;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
/**
* Creates a PDF file in memory.
*/
public class HelloWorldMemory {
/** Path to the resulting PDF file. */
public static final String RESULT = "C:////hello_memory.pdf";
public static void main(final String[] args) throws DocumentException, IOException {
// step 1
final Document document = new Document();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PdfWriter writer = PdfWriter.getInstance(document, baos);
document.open();
final PdfContentByte cb = writer.getDirectContent();
cb.beginText();
cb.setFontAndSize(getBaseFont(Font.NORMAL), 24);
final float exPosition = (PageSize.A4.getWidth()) / 2;
cb.showTextAligned(Element.ALIGN_CENTER, "Test No", exPosition, 670, 0);
cb.endText();
document.add(new Paragraph("Hello World!"));
document.close();
System.out.println("baos.toByteArray():" + baos.toByteArray());
final String base64Binary = DatatypeConverter.printBase64Binary(baos.toByteArray());
System.out.println("base64Binary:" + base64Binary);
final byte[] txt = DatatypeConverter.parseBase64Binary(base64Binary);
final FileOutputStream fos = new FileOutputStream(RESULT);
fos.write(txt);
fos.close();
}
private static BaseFont getBaseFont(final int fontType) {
final Font f = new Font(FontFamily.HELVETICA, 0, fontType);
final BaseFont baseFont = f.getCalculatedBaseFont(true);
return baseFont;
}
}
This question is not really related to iText or PDF. You'll have the same problem with any binary data that is base64 encoded. When using the online base64 decoder, your binary data gets corrupted somehow. Bruno already explained in his answer why this does not completely invalidate a file in case of a PDF.
The data is probably corrupted because of encoding issues. Maybe the online base64 decoder displayed the decoded data in a textarea or something and you copy/pasted it into a file? If you use a decoder that offers you a binary file for download, the result should be fine.
I tested with http://www.opinionatedgeek.com/dotnet/tools/base64decode/ (the first hit of a Google search). When I save the .bin file and rename it to .pdf, it displays as expected in a PDF viewer.
PDF is a binary file format based on the Carousel Object System (COS) syntax and the AIM (Adobe Imaging Model). The COS objects use ASCII for the file structures, but the streams for images and AIM syntax are usually binary. When you copy a PDF file without respecting the binary aspect of the file, a PDF viewer can render the document structure (the pages) based on the ASCII COS objects, but not the content (what's on the pages). This is probably what happens in your case: you're corrupting the bytes in the content streams.
Related
How to convert PDDocument (the pdf document contains words and images, if it is possible) to Base64 String? Is there any suggestion of code. Please.
The answer assumes that you are using jdk8 or higher, if not, please see here.
import java.util.Base64;
...
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.save(baos);
String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
doc.close(); // don't forget to close your document
Here, I am trying to send a SVG image to local server and in output I want to download that image in PNG / JPEG format.
While I have found some solutions but those are done by BATIK libraries, but in my Eclipse BATIK libraries are not supported , so I can't use the batik libraries.
Use batik library. Below is the code.
import java.io.*;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import java.nio.file.Paths;
import java.nio.file.Path;
public class svg2png {
public static void main(String[] args) throws Exception {
//Step -1: We read the input SVG document into Transcoder Input
//We use Java NIO for this purpose
String svg_URI_input = Paths.get("chessboard.svg").toUri().toURL().toString();
TranscoderInput input_svg_image = new TranscoderInput(svg_URI_input);
//Step-2: Define OutputStream to PNG Image and attach to TranscoderOutput
OutputStream png_ostream = new FileOutputStream("chessboard.png");
TranscoderOutput output_png_image = new TranscoderOutput(png_ostream);
// Step-3: Create PNGTranscoder and define hints if required
PNGTranscoder my_converter = new PNGTranscoder();
// Step-4: Convert and Write output
my_converter.transcode(input_svg_image, output_png_image);
// Step 5- close / flush Output Stream
png_ostream.flush();
png_ostream.close();
}
}
Hope it will help you.
Refer this: http://thinktibits.blogspot.com/2012/12/Batik-Convert-SVG-PNG-Java-Program-Example.html
You can also convert svg to png format without the use of Batik Transcoder.
BufferedImage input_image = null;
input_image = ImageIO.read(new File("Convert_to_PNG.svg")); //read svginto input_image object
File outputfile = new File("imageio_png_output.png"); //create new outputfile object
ImageIO.write(input_image, "PNG", outputfile);
By simply using the ImageIO library. Hope this will help!
I'm am trying to get the Icon from a .lnk file, put it into a javafx Image and then save it as a .png file (to ensure it's working).
My current code compiles but does not work:
import java.io.*;
import java.util.*;
import javax.swing.filechooser.FileSystemView;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javafx.embed.swing.SwingFXUtils;
import java.awt.image.BufferedImage;
import java.awt.Graphics;
import javafx.scene.image.Image;
import javax.imageio.ImageIO;
class Iconic {
public static void main(String[] args) throws IOException{
File origin = new File("C:\\Users\\00001\\OneDrive.lnk");
Icon icn = FileSystemView.getFileSystemView().getSystemIcon(origin);
ImageIcon ico = ((ImageIcon) icn);
BufferedImage bi = new BufferedImage(
ico.getIconWidth(),
ico.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
ico.paintIcon(null,g,0,0);
g.dispose();
Image img = SwingFXUtils.toFXImage(bi,null);
File output = new File("C:\\Users\\00001\\");
BufferedImage bim = SwingFXUtils.fromFXImage(img,null);
ImageIO.write(bim,".png",output);
}
}
You are almost there, however, there are two issues in your code. Both are related to the ImageIO.write(...) method.
From the API doc of ImageIO.write(RenderedImage, String, File):
Writes an image using an arbitrary ImageWriter that supports the given format to a File. If there is already a File present, its contents are discarded.
Parameters:
im - a RenderedImage to be written.
formatName - a String containg the informal name of the format.
output - a File to be written to.
The second parameter is the format name, not the file extension. So, the second argument should be "PNG", not ".png". Because ImageIO does not find any plugins that can write ".png" format, the write(...) invocation will just silently return false. I recommend always checking the return value of ImageIO.write(...).
The third parameter is the destination file to write. The path of this file has to point to a file, however yours point only to a directory. If you fix only the format name above, you'll see that most likely you get an IOException.
So, a fixed version of your writing code would like like:
File output = new File(origin.getParentFile(), origin.getName().replace(".lnk", ".png"));
if (!ImageIO.write(bi, "PNG", output)) {
System.err.println("Could not write icon");
}
I deliberately left the conversion from FX Image out. You should be able to write bi directly, without conversion to and from FX Image(unless, of course, you manipulate the image in FX).
I have to add text to pdf documents where there are many scanned pdf documents so the inserted text is inserted back to the scanned image and not over the image. how to add text over the scanned image inside the pdf.
package editExistingPDF;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import org.apache.commons.io.FilenameUtils;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
public class AddPragraphToPdf {
public static void main(String[] args) throws IOException, DocumentException, BiffException {
String tan = "no tan";
File inputWorkbook = new File("lars.xls");
Workbook w;
w = Workbook.getWorkbook(inputWorkbook);
// Get the first sheet
Sheet sheet = w.getSheet(0);
Cell[] tnas =sheet.getColumn(0);
File ArticleFolder = new File("C:\\Documents and Settings\\sathishkumarkk\\My Documents\\article");
File[] listOfArticles = ArticleFolder.listFiles();
for (int ArticleInList = 0; ArticleInList < listOfArticles.length; ArticleInList++)
{
Document document = new Document(PageSize.A4);
// System.out.println(listOfArticles[ArticleInList].toString());
PdfReader pdfArticle = new PdfReader(listOfArticles[ArticleInList].toString());
if(listOfArticles[ArticleInList].getName().contains(".si."))
{continue;}
int noPgs=pdfArticle.getNumberOfPages();
String ArticleNoWithOutExt = FilenameUtils.removeExtension(listOfArticles[ArticleInList].getName());
String TanNo=ArticleNoWithOutExt.substring(0,ArticleNoWithOutExt.indexOf('.'));
// Create output PDF
PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream("C:\\Documents and Settings\\sathishkumarkk\\My Documents\\toPrint\\"+ArticleNoWithOutExt+".pdf"));
document.open();
PdfContentByte cb = writer.getDirectContent();
//get tan form excel sheet
System.out.println(TanNo);
for(Cell content : tnas){
if(content.getContents().contains(TanNo)){
tan=content.getContents();
System.out.println(tan);
}else{
continue;
}
}
// Load existing PDF
//PdfReader reader = new PdfReader(new FileInputStream("1.pdf"));
for (int i = 1; i <= noPgs; i++) {
PdfImportedPage page = writer.getImportedPage(pdfArticle, i);
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your TAN here
Paragraph p= new Paragraph(tan);
Font font = new Font();
font.setSize(1.0f);
p.setLeading(12.0f, 1.0f);
p.setFont(font);
document.add(p);
}
document.close();
}
}
}
NOTE: The problem is that when there is a pdf create with only text I have no problem but when a pdf is with full of scanned document and when I try to add text; it gets added to the back of the scanned document. so while I print those pdf I will not get those text I added.
From this iText Example (which is the reverse of what you want, but switch getUnderContent with getOverContent and you'll be fine) :
Blockquote
Each PDF page has two extra layers; one that sits on top of all text / graphics and one that goes to the bottom. All user added content gets in-between these two. If we get into this bottommost content, we can write anything under that we want. To get into this bottommost layer, we can use the " getUnderContent" method of PdfStamper object.
This is documented in iText API Reference as shown below:
public PdfContentByte getUnderContent(int pageNum)
Gets a PdfContentByte to write under the page of the original document.
Parameters:
pageNum - the page number where the extra content is written
Returns:
a PdfContentByte to write under the page of the original document
To do this, you will need to first read in the PDF document, extract the elements and then add text to the document and resave it as a PDF document. This of course assumes that you can read the PDF document in the first place.
I'd recommend iText (see Example Code iText) to help you do this.
I have the following code:
ImageIO.write(originalImage, OUTPUT_TYPE, resultOutput);
This is an invocation of the following javax.imageio.ImageIO method:
public static boolean write(RenderedImage im,
String formatName,
File output)
throws IOException
This turns an original BMP image into a JGP output. Is it possible to also store DPI and Paper Size information in the JPEG to aid in printing operations?
I found this post for setting DPI on PNG Files. It pointed out that you should use 'metadata.mergeTree' to properly save your metadata.
With that in mind, here is some working groovy code that takes a BMP file and creates a JPG file at arbitrary DPI:
import java.awt.image.BufferedImage
import java.io.File
import java.util.Hashtable
import java.util.Map
import javax.imageio.*
import javax.imageio.stream.*
import javax.imageio.metadata.*
import javax.imageio.plugins.jpeg.*
import org.w3c.dom.*
File sourceFile = new File("sample.bmp")
File destinationFile = new File("sample.jpg")
dpi = 100
BufferedImage sourceImage = ImageIO.read(sourceFile)
ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(destinationFile);
imageWriter.setOutput(ios);
def jpegParams = imageWriter.getDefaultWriteParam();
IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(sourceImage), jpegParams);
Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0");
Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0);
jfif.setAttribute("Xdensity", Integer.toString(dpi));
jfif.setAttribute("Ydensity", Integer.toString(dpi));
jfif.setAttribute("resUnits", "1"); // density is dots per inch
data.mergeTree("javax_imageio_jpeg_image_1.0",tree)
// Write and clean up
imageWriter.write(data, new IIOImage(sourceImage, null, data), jpegParams);
ios.close();
imageWriter.dispose();
Worked fine for me in that OSX's Preview app and Gimp both reported that the resulting image was 100 DPI. As to Paper Size...I imagine this is directly determined by DPI? I couldn't find any JPEG property that would set that particular value.
You may consider using Commons Sanselan, instead of ImageIO for this task.
See http://commons.apache.org/sanselan/whysanselan.html for more info.