I'm trying to add a PNG image to an existing pdf, but the transparency is converted to black color.
PdfReader reader = new PdfReader(pdfPath);
File f = new File(pdfPath);
String result = f.getParent() + File.separator + UUID.randomUUID().toString() + ".pdf";
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(result));
Image image = Image.getInstance(ImageIO.read(new File(imagePath)), null);
PdfImage stream = new PdfImage(image, null, null);
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(30, 300);
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image);
stamper.close();
reader.close();
How can I keep transparency?
First this: I am violating the policy at iText Software by answering this question. You are using an old version of iText, and the policy dictates that voluntary support on iText 5 or earlier has stopped. You should either use iText 7, or you should get a support contract if you still want support for an old iText version.
However, I am curious. I want to know where you found this clunky code (or why you decided to write this code):
Image image = Image.getInstance(ImageIO.read(new File(imagePath)), null);
PdfImage stream = new PdfImage(image, null, null);
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(30, 300);
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image);
You don't need ImageIO and you don't need to create a PdfImage, nor do you need to add that image to the body of a PDF file. The code you are using is code specialists would use for a very particular purpose. If you know that particular purpose, please explain.
If adding an image at an absolute position is all you want to do (that's a general purpose, not a particular purpose), your code should be as simple as this:
Image image = Image.getInstance(imagePath);
image.setAbsolutePosition(30, 300);
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image);
In this case, you don't have to worry about the image mask; iText will take care of that for you.
Please also explain why you're using an outdated version of iText instead of iText 7. If you want your application to be future-proof, you should upgrade to iText 7 now (to avoid wasting time later).
Related
We are in the process of migrating from iText 5 to iText7. ColumnText is used in few places in our existing code. According to the following https://www.slideshare.net/iTextPDF/oops-i-broke-my-api?from_action=save
we tried to run a sample to test iText7 solution based on ColumnDocumentRenderer. Even though it is working fine, we are seeing a minor difference in the alignment. Apparently, iText5 code is aligning the text to the bottom, but iText7 is not doing that.
iText 5 code
Document document = new Document();
PdfWriter writer =
PdfWriter.getInstance(document, new FileOutputStream("D:\\Temp Files\\Test.pdf"));
document.open();
ColumnText ct = new ColumnText(writer.getDirectContent());
Font normal = new Font(FontFamily.TIMES_ROMAN, 12);
Paragraph p = new Paragraph("Text", normal);
ct.addElement(p);
int status = ColumnText.START_COLUMN;
Rectangle[] columns = {new Rectangle(36, 36, 290, 806)};
while(ColumnText.hasMoreText(status)) {
ct.setSimpleColumn(columns[0]);
status = ct.go();
}
document.close();
iText 7 code
PdfDocument pdf = new PdfDocument(new PdfWriter("D:\\Temp Files\\Test i7 ColumnText.pdf"));
Document document = new Document(pdf);
Rectangle[] columns = {new Rectangle(36, 36, 254, 770)};
document.setRenderer(new ColumnDocumentRenderer(document, columns));
BufferedReader br = new BufferedReader(new StringReader("Text"));
String line;
PdfFont normal = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
while ((line = br.readLine()) != null) {
document.add(new Paragraph(line).setFont(normal));
}
document.close();
There is no alignment or padding set in either case. Not sure if there is anything else that we need to set in iText7. We want to retain the placement of the text, which is very crucial while trying to generate dynamic PDF's. How to maintain the placement of the text between iText 5 and iText 7?
Note: Enclosed screenshot for reference.
iText5 Vs iText7
Left hand side pdf is created by 5 and right hand side is created by 7. The rectangular box was drawn to show how itext 5 is rendering Text aligned to the bottom, but itext 7 is placing the Text little bit above the base line. How to fix itext7 code to place Text similar itext 5?
I want to print the captions imported from facebook/instagram in an image and save it. I want to do this using imagick library with php as I am creating the base image using imagick. The normal text prints properly but the emojis that are imported do not get printed as emoji's. Can anyone suggest how emojis can be printed using imagick.
What I have tried:
$eachpageimg = new Imagick ();
$eachpageimg->setResolution ( 300 , 300 );
$eachpageimg->newImage (1050, 1260 , 'rgb(255,255,255)');
$eachpageimg->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH);
$eachpageimg->setImageFormat ('jpeg');
$eachpageimg->setImageCompressionQuality(100);
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'rgb(255, 255, 255)' );
$pixel->setColorValue(Imagick::COLOR_ALPHA, .8);
$draw->setStrokeColor('rgb(0,0,0)');
$draw->setFillColor ('rgb(0,0,0)');
$draw->setFont ("ROBOTO-REGULAR");
$draw->setFontSize (70);
$xpos = 10;
$ypos = 200;
$eachpageimg->annotateImage($draw, $xpos, $ypos, 0, "Gshdh😚😎😑😚🤠");
$filename = 'saved.jpg';
// SAVE FINAL page image
file_put_contents ($filename, $eachpageimg);
The font you are using needs to have the emojis in them. This can be checked by just editing a word or web page with that font set.
However:
"Gshdh😚😎😑😚🤠"
Those look very much like a mucked up character set rather than emoji. I strongly suspect that you are saving some data in a character set that doesn't support emoji (i.e. most non-UTF) character sets.
Exactly where that has happened will need to be something you discover yourself.
In order to find an added image file and replace it with another image file when I read a PDF next time, I want to use Itext to add an image file into an existing PDF, and declare a unique name for it.
My code:
final PdfName key = new PdfName("MY_SIGN_KEY");
final PdfName val = new PdfName("MY_SIGN_VAL");
Image signImage=Image.getInstance(signPngFile.getAbsolutePath());
signImage.setAlignment(1);
signImage.scaleAbsolute(newWidth, newHeight);
signImage.setAbsolutePosition(200,200);
PdfContentByte over = stamper.getOverContent(1);
PdfImage stream = new PdfImage(signImage, "", null);
stream.put(key,val);// a unique name for it.(设置唯一标识符)
//PdfIndirectObject ref=over.getPdfWriter().addToBody(stream);
//signImage.setDirectReference(ref.getIndirectReference());
over.addImage(signImage);
I have tried your code and it works for me. See the AddImageWithID example:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
Image image = Image.getInstance(IMG);
PdfImage stream = new PdfImage(image, "", null);
stream.put(new PdfName("ITXT_SpecialId"), new PdfName("123456789"));
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(36, 400);
PdfContentByte over = stamper.getOverContent(1);
over.addImage(image);
stamper.close();
reader.close();
}
In this example, I take a file named hello.pdf and I add an image named bruno.jpg with the file hello_with_image_id.pdf as result.
The image doesn't look black:
The ID is added:
Can you try the code I shared and see if the problem persists.
I can think of one reason why you'd get a black image: in our code, we assume that a single image is added. In the case of JPEG, this is always the case. In the case of PNG or GIF though, adding one source image could result in two images being added. Strictly speaking, PDF doesn't support transparent images (depending on how you interpret the concept of transparent images). Whenever you add a single source image with transparent parts, two images will be added to the PDF: one opaque image and one image mask. The combination of the opaque image and the image mask results in something that is perceived as a transparent image. Maybe this is what happens in your case.
I use different tools like processing to create vector plots. These plots are written as single or multi-page pdfs. I would like to include these plots in a single report-like pdf using pdfbox.
My current workflow includes these pdfs as images with the following pseudo code
PDDocument inFile = PDDocument.load(file);
PDPage firstPage = (PDPage) inFile.getDocumentCatalog().getAllPages().get(0);
BufferedImage image = firstPage.convertToImage(BufferedImage.TYPE_INT_RGB, 300);
PDXObjectImage ximage = new PDPixelMap(document, image);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.drawXObject(ximage, 0, 0, ximage.getWidth(), ximage.getHeight());
contentStream.close();
While this works it looses the benefits of the vector file formats, espectially file/size vs. printing qualitity.
Is it possible to use pdfbox to include other pdf pages as embedded objects within a page (Not added as a separate page)? Could I e.g. use a PDStream? I would prefer a solution like pdflatex is able to embed pdf figures into a new pdf document.
What other Java libraries can you recommend for that task?
Is it possible to use pdfbox to include other pdf pages as embedded objects within a page
It should be possible. The PDF format allows the use of so called form xobjects to serve as such embedded objects. I don't see an explicit implementation for that, though, but the procedure is similar enough to what PageExtractor or PDFMergerUtility do.
A proof of concept derived from PageExtractor using the current SNAPSHOT of the PDFBox 2.0.0 development version:
PDDocument source = PDDocument.loadNonSeq(SOURCE, null);
List<PDPage> pages = source.getDocumentCatalog().getAllPages();
PDDocument target = new PDDocument();
PDPage page = new PDPage();
PDRectangle cropBox = page.findCropBox();
page.setResources(new PDResources());
target.addPage(page);
PDFormXObject xobject = importAsXObject(target, pages.get(0));
page.getResources().addXObject(xobject, "X");
PDPageContentStream content = new PDPageContentStream(target, page);
AffineTransform transform = new AffineTransform(0, 0.5, -0.5, 0, cropBox.getWidth(), 0);
content.drawXObject(xobject, transform);
transform = new AffineTransform(0.5, 0.5, -0.5, 0.5, 0.5 * cropBox.getWidth(), 0.2 * cropBox.getHeight());
content.drawXObject(xobject, transform);
content.close();
target.save(TARGET);
target.close();
source.close();
This code imports the first page of a source document to a target document as XObject and puts it twice onto a page there with different scaling and rotation transformations, e.g. for this source
it creates this
The helper method importAsXObject actually doing the import is defined like this:
PDFormXObject importAsXObject(PDDocument target, PDPage page) throws IOException
{
final PDStream src = page.getContents();
if (src != null)
{
final PDFormXObject xobject = new PDFormXObject(target);
OutputStream os = xobject.getPDStream().createOutputStream();
InputStream is = src.createInputStream();
try
{
IOUtils.copy(is, os);
}
finally
{
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
}
xobject.setResources(page.findResources());
xobject.setBBox(page.findCropBox());
return xobject;
}
return null;
}
As mentioned above this is only a proof of concept, corner cases have not yet been taken into account.
To update this question:
There is already a helper class in org.apache.pdfbox.multipdf.LayerUtility to do the import.
Example to show superimposing a PDF page onto another PDF: SuperimposePage.
This class is part of the Apache PDFBox Examples and sample transformations as shown by #mkl were added to it.
As mkl appropriately suggested, PDFClown is among the Java libraries which provide explicit support for page embedding (so-called Form XObjects (see PDF Reference 1.7, § 4.9)).
In order to let you get a taste of the way PDFClown works, the following code represents the equivalent of mkl's PDFBox solution (NOTE: as mkl later stated, his code sample was by no means optimised, so this comparison may not correspond to the actual status of PDFBox -- comments are welcome to clarify this):
Document source = new File(SOURCE).getDocument();
Pages sourcePages = source.getPages();
Document target = new File().getDocument();
Page targetPage = new Page(target);
target.getPages().add(targetPage);
XObject xobject = sourcePages.get(0).toXObject(target);
PrimitiveComposer composer = new PrimitiveComposer(targetPage);
Dimension2D targetSize = targetPage.getSize();
Dimension2D sourceSize = xobject.getSize();
composer.showXObject(xobject, new Point2D.Double(targetSize.getWidth() * .5, targetSize.getHeight() * .35), new Dimension(sourceSize.getWidth() * .6, sourceSize.getHeight() * .6), XAlignmentEnum.Center, YAlignmentEnum.Middle, 45);
composer.showXObject(xobject, new Point2D.Double(targetSize.getWidth() * .35, targetSize.getHeight()), new Dimension(sourceSize.getWidth() * .4, sourceSize.getHeight() * .4), XAlignmentEnum.Left, YAlignmentEnum.Top, 90);
composer.flush();
target.getFile().save(TARGET, SerializationModeEnum.Standard);
source.getFile().close();
Comparing this code to PDFBox's equivalent you can notice some relevant differences which show PDFClown's neater style (it would be nice if some PDFBox expert could validate my assertions):
Page-to-FormXObject conversion: PDFClown natively supports a dedicated method (Page.toXObject()), so there's no need for additional heavy-lifting such as the helper method importAsXObject();
Resource management: PDFClown automatically (and transparently) allocates page resources, so there's no need for explicit calls such as page.getResources().addXObject(xobject, "X");
XObject drawing: PDFClown supports both high-level (explicit scale, translation and rotation anchors) and low-level (affine transformations) methods to place your FormXObject into the page, so there's no need to necessarily deal with affine transformations.
The whole point is that PDFClown features a rich architecture made up of multiple abstraction layers: according to your requirements, you can choose the most appropriate coding style (either to delve into PDF's low-level basic structures or to leverage its convenient and elegant high-level model). PDFClown lets you tweak every single byte and solve complex tasks with a ridiculously simple method call, at your will.
DISCLOSURE: I'm the lead developer of PDFClown.
Hello everybody I would like to ask how can I resize an image without losing quality?
Here is my controller method
var fileName = DateTime.Now.ToString("MM.dd.yyyy HH.mm.ss") + Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/uploads/"), fileName);
file.SaveAs(path);
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath("~/uploads/") + fileName);
System.Drawing.Image thumb = img.GetThumbnailImage(97, 114, null, IntPtr.Zero);
img.Dispose();
thumb.Save(Server.MapPath("~/uploads/") + fileName);
There are some really good image resizing libraries out there - I would use one of those. I'm using ImageResizing on one of my projects and the results have been pretty good. Bertrand LeRoy has done some benchmarking of some of the main libraries, which you might find useful.