How can I add an image to a PDF at specific x-y coordinates using IText? - image

I have existing PDFs to which I need to dynamically add an image/images. The image comes from a file upload. Once I have the file uploaded, how can specify where to place the image on the PDF. One code snippet I found does not work correctly. This needs to work for PDFs with any number of pages. From what I understand, absolute positioning is set from the bottom-left corner of the last page of the PDF. If I need an image to be displayed 30 pixels from the top and 50 pixels from the left of page 1, how can I accomplish this? Or, if I need to display an image 50px from the top/100 px from the left on page 2?
I've tried using the code found at http://rip747.wordpress.com/2009/03/26/add-an-image-dynamically-to-a-pdf-with-cf-and-itext/. I've modified it for my needs below:
<cfscript>
myLeft = 30;
myTop = 50;
myPageNum = 1;
// output buffer to write PDF
fileIO = createObject("java","java.io.FileOutputStream").init(myOutputPath);
// reader to read our PDF
reader = createObject("java","com.lowagie.text.pdf.PdfReader").init(mySourcePath);
// stamper so we can modify our existing PDF
stamper = createObject("java","com.lowagie.text.pdf.PdfStamper").init(reader, fileIO);
// get the content of our existing PDF
content = stamper.getOverContent(reader.getNumberOfPages());
// create an image object so we can add our dynamic image to our PDF
image = createobject("java", "com.lowagie.text.Image");
// initalize our image
img = image.getInstance(imgPath);
x = (reader.getPageSize(1).width() - img.scaledWidth()) - myLeft;
y = (reader.getPageSize(1).height() - img.scaledHeight()) - myTop;
// now we assign the position to our image
img.setAbsolutePosition(javacast("float", x), javacast("float", y));
// add our image to the existing PDF
content.addImage(img);
// flattern our form so our values show
stamper.setFormFlattening(true);
// close the stamper and output our new PDF
stamper.close();
// close the reader
reader.close();
</cfscript>
The above code places my image at the top-right corner of page 2 - 50px form the top/30px from the left.
I know I'm close...just need a little help getting this nailed down for my needs.
I've updated my code. This gets the image to the top left corner of page 2 - correct positioning, but I want it on page 1:
x = myLeft;
y = (reader.getPageSize(1).height()) - img.scaledHeight() - myTop;
I thought maybe I needed to add the height of page 1 to get the image up to page 1, but the image completely disappears when I try either of the options below:
// I figure I'll need something like this to handle multi-page docs
y = (reader.getPageSize(1).height() * reader.getNumberOfPages()) - img.scaledHeight() - myTop;
y = reader.getPageSize(1).height() + reader.getPageSize(1).height() - img.scaledHeight() - myTop;

You're getting your "OverContent" from stamper.getOverContent(reader.getNumberOfPages());. The parameter for getOverContent() is the page number. So your code is getting a PdfContentByte for the last page, not the first.

I found my answer:
The page number has to be set in com.lowagie.text.pdf.PdfStamper.getOverContent():
content = stamper.getOverContent(myPageNum);
Knew it was easy.

are you using CF8+? You can use
<cfpdf action="addWatermark" source="myPDF.pdf" image="myImage.jpg"
position="0,0" rotation="0" showOnPrint="true" opacity="10">

Related

Would it be possible to crop image using google app script without using any third party api

I want to crop an image with Google App Script if an image outside the page frame, but as far as I checked in Google App Script documentation and I could not find a way to crop the image.
pageElements.asImage().replace (imgBlob, true); it is not allowed to pass cropping dimensions as parameters in .replace() to crop a image.
i know this can be achieved using a custom API , passing the image blob and crop area that will call cropping method on another server.
But how it will be possible to work with Google App Script, looking for expert advice.
How about this answer?
Issue:
I think that in the current stage, replace(blobSource, crop) has the limitation. The official document says as follows.
crop Boolean: If true, crops the image to fit the existing image's size. Otherwise, the image is scaled and centered.
I confirmed that when the image is cropped using replace(blobSource, crop), the center of image is left. It seems that this is the current specification. And although there is the "cropProperties" of "UpdateImagePropertiesRequest" in Slides API, unfortunately, in the current stage, this cannot be still used. This has already been reported. Ref
Sample script:
If you use replace(blobSource, crop) under the current specification, how about the following sample script? As the sample situation, 2 images of "image1" and "image2" are prepared in the 1st slide, and "image1" is cropped using "image2".
The flow of this script is as follows.
Flow:
Retrieve 2 images from a slide on Google Slides.
Crop "image1" using "image2". By this, "image2" is replaced with "image1".
Move the cropped image to "image1".
Remove the original "image1".
Script:
function myFunction() {
// 1. Retrieve 2 images from a slide on Google Slides.
var slide = SlidesApp.getActivePresentation().getSlides()[0];
var images = slide.getImages();
var image1 = images[0]; // Red image.
var image2 = images[1]; // Blue image.
// 2. Crop "image1" using "image2". By this, "image2" is replaced with "image1".
var replacedImage = image2.replace(image1.getBlob(), true);
// 3. Move the cropped image to "image1".
replacedImage.setTop(image1.getTop()).setLeft(image1.getLeft());
// 4. Remove the original "image1".
image1.remove();
}
Result:
When the script is run, "image1" is cropped. But it is found that in the current stage, the center of "image1" is left by the crop.
Note:
Slides API and Slides Service are growing now. So I think that this situation might be changed by the future update. But if you want this soon, how about requesting this to the issue tracker as the future request? Ref
References:
replace(blobSource, crop)
CropProperties
Added:
At an additional sample script for using replace(blobSource, crop), I would like to propose the method for using the self image. In this sample script, when the image is sticked out, the image of out of page is removed by cropping. The basic method is the same with above sample script.
Sample script:
function myFunction() {
var s = SlidesApp.getActivePresentation();
var slide = s.getSlides()[0];
var images = slide.getImages();
var image = images[0];
var pageWidth = s.getPageWidth();
var imagePosition = image.getLeft();
var imageWidth = image.getWidth();
var check = imagePosition + imageWidth - pageWidth;
if (check > 0 && check < imageWidth) {
image
.duplicate()
.setWidth(pageWidth - imagePosition)
.asImage()
.replace(image.getBlob(), true);
image.remove();
}
}
Result:
Note:
In this sample script, as a simple sample, I prepared only the right side of the horizontal direction. So when you want to remove the vertical direction, please modify the script for your actual situation.

How can I Copy top half of PDF and insert into new PDF

I have an 8.5" x 11" PDF. I'd like to take the top 1/2 of the page, cut it and insert into page 1 of a new PDF. Then, take the bottom 1/2 of the page and insert it into page 2 of the PDF.
I'm essentially trying to split the PDF page in half... All docs I see relate to splitting the individual pages into separate files. I want to essentially copy part of the page and paste it into another doc.
Any help in providing direction using itextsharp? I have used it before and understand the concepts. But, am having a tough time. I'm sure I'll use the rectangle and use the coordinates.
It seems that you are looking to tile a PDF. You're not telling us which version of iText you plan on using. Since you seem to be new at this, I'm assuming that you're using iText 7. In that case, please consult Chapter 6 of the iText 7 Jump-Start tutorial where we tile a PDF with a single page into a PDF with four pages.
Original PDF:
Tiled PDF:
See TheGoldenGateBridge_Tiles for the code:
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
PdfDocument sourcePdf = new PdfDocument(new PdfReader(src));
PdfPage origPage = sourcePdf.getPage(1);
PdfFormXObject pageCopy = origPage.copyAsFormXObject(pdf);
Rectangle orig = origPage.getPageSize();
//Tile size
Rectangle tileSize = PageSize.A4.rotate();
AffineTransform transformationMatrix = AffineTransform.getScaleInstance(
tileSize.getWidth() / orig.getWidth() * 2f,
tileSize.getHeight() / orig.getHeight() * 2f);
//The first tile
PdfPage page = pdf.addNewPage(PageSize.A4.rotate());
PdfCanvas canvas = new PdfCanvas(page);
canvas.concatMatrix(transformationMatrix);
canvas.addXObject(pageCopy, 0, -orig.getHeight() / 2f);
//The second tile
page = pdf.addNewPage(PageSize.A4.rotate());
canvas = new PdfCanvas(page);
canvas.concatMatrix(transformationMatrix);
canvas.addXObject(pageCopy, -orig.getWidth() / 2f, -orig.getHeight() / 2f);
//The third tile
page = pdf.addNewPage(PageSize.A4.rotate());
canvas = new PdfCanvas(page);
canvas.concatMatrix(transformationMatrix);
canvas.addXObject(pageCopy, 0, 0);
//The fourth tile
page = pdf.addNewPage(PageSize.A4.rotate());
canvas = new PdfCanvas(page);
canvas.concatMatrix(transformationMatrix);
canvas.addXObject(pageCopy, -orig.getWidth() / 2f, 0);
// closing the documents
pdf.close();
sourcePdf.close();
Changing this example into code that tiles a PDF with 1 page into a PDF with 2 pages, is a matter of using some simple Math.
If you're using iText 5, then the question was already answered many times before. See for instance:
Tiling with iText, and adding margins
Tile PDF pages vertically with iTextSharp
How to tile a pdf to multiple pages with a border

How to centrally align an Image in Excel using apache poi

HSSFPatriarch drawing = sheet.createDrawingPatriarch();
HSSFClientAnchor my_anchor = (HSSFClientAnchor) helper.createClientAnchor();
my_anchor.setAnchorType(HSSFClientAnchor.DONT_MOVE_AND_RESIZE);
my_anchor.setCol1(0);
// my_anchor.
my_anchor.setRow1(excelData.getRowNum());
strb.append(" ");
HSSFPicture my_picture = drawing.createPicture(my_anchor, my_picture_id);
/* Call resize method, which resizes the image */
my_picture.resize();
I am passing sheet, helper as parameter to my method.
With this code, still Image Icon can be moved in the excel sheet.
Also I want to set the vertical alignment for the icon in the cell as bottom aligned. Please suggest.
You can align the image using anchor, adjust the values of Dx1, Dy1, Dx2 and Dy2 accordingly. Below is the example:-
ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
anchor.setDx1(0);
anchor.setDy1(0);
anchor.setDx2(0);
anchor.setDy2(0);
Refer to the below URL for complete example:-
https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/ss/examples/AddDimensionedImage.java
You can align the image using anchor, adjust the values of Dx1, Dy1, Dx2 and Dy2, pict.resize() accordingly. Below is the example:
ClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();
Modify below values s per your original image size
anchor.setDx1(0);
anchor.setDy1(0);
anchor.setDx2(90);
anchor.setDy2(90);
// Creates a picture
Picture pict = drawing.createPicture(anchor, pictureIdx);
// Reset the image to the original size
Modify below value s per your original image size
pict.resize(1.75);
Please refer updated below URL for complete example: https://svn.apache.org/repos/asf/poi/trunk/poi-examples/src/main/java/org/apache/poi/examples/ss/AddDimensionedImage.java

Rotate paragraphs or cells some arbitrary number of degrees -- Itext

I have a web site where the users upload photos and create photobooks. Also, they can add text at absolute positions, rotations, and alignments. The text can have new lines.
I've been using the Itext Library to automatize the creation of the Photobooks High Quality Pdfs that are printed latter on.
Adding the user uploaded images to the PDFs was really simple, the problem comes when I try to add the text.
In theory what I would need to do, is to define a paragraph of some defined width and height, set the users text, font, font style, alignment (center, left, right, justify), and finally set the rotation.
For what i've read about Itext, i could create a paragraph set the user properties, and use a ColumnText Object to set the absolute position, width and height. However it's not possibly to set the rotation of anything bigger than single line.
I can't use table cells either, because the rotation method only allow degrees that are multiples of 90.
Is there a way to add a paragraph with some rotation (say 20 degrees) without having to add the text line by line using the ColumnText.showTextAligned() method and all math that involves?
---- Edit: 08-Ago-2013 ----
If it helps anyone, this is the code I used to solve this problem (thanks to Bruno):
//Create the template that will contain the text
PdfContentByte canvas = pdfWriter.getDirectContent();
PdfTemplate textTemplate = canvas.createTemplate(imgWidth, imgHeight); //The width and height of the text to be inserted
ColumnText columnText = new ColumnText(textTemplate);
columnText.setSimpleColumn(0, 0, imgWidth, imgHeight);
columnText.addElement(paragraph);
columnText.go();
//Create de image wraper for the template
Image textImg = Image.getInstance(textTemplate);
//Asign the dimentions of the image, in this case, the text
textImg.setInterpolation(true);
textImg.scaleAbsolute(imgWidth, imgHeight);
textImg.setRotationDegrees((float) -textComp.getRotation()); //Arbitrary number of degress
textImg.setAbsolutePosition(imgXPos, imgYPos);
//Add the text to the pdf
pdfDocument.add(textImg);
Create a PdfTemplate object; just a rectangle.
Draw your ColumnText on this PdfTemplate; don't worry about the rotation, just fill the rectangle with whatever content you want to add to the column.
Wrap the PdfTemplate inside an Image object; this is just for convenience, to avoid the math. This doesn't mean your text will be rasterized.
Now apply a rotation and an absolute position to the Image and add it to your document.
Your problem is now solved ;-)
PS: I'm the author of the iText in Action books.
thanks to both our friends (Bruno & BernalCarlos)
my final code for users that use "RTL" in their projects is here :
// step 1
Document document = new Document();
document.setPageSize(PageSize.A4);
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(destination_file));
CreateBorder event = new CreateBorder();
writer.setPageEvent(event);
// step 3
document.open();
// step 4
int imgWidth=400;
int imgHeight=50;
//Create the template that will contain the text
PdfContentByte canvas = writer.getDirectContent();
PdfTemplate textTemplate = canvas.createTemplate(imgWidth, imgHeight);
//The width and height of the text to be inserted
ColumnText columnText = new ColumnText(textTemplate);
columnText.setSimpleColumn(0, 0, imgWidth, imgHeight);
columnText.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
columnText.addElement(new Paragraph("محاسبه بار غیر متعادل", font_IranSemiBold));
columnText.go();
//Create de image wraper for the template
Image textImg = Image.getInstance(textTemplate);
//Asign the dimentions of the image, in this case, the text
textImg.setInterpolation(true);
textImg.scaleAbsolute(imgWidth, imgHeight);
textImg.setRotationDegrees(90); //Arbitrary number of degress
textImg.setAbsolutePosition(50, 200);
//Add the text to the pdf
document.add(textImg);
// step 5
document.close();

Photoshop Action to fill image to make a certain ratio

I am looking to make a photoshop action (maybe this isn't possible, any other application recommendations would be helpful as well). I want to take a collection of photos and make them a certain aspect ration, ex: 4:3.
So I have an image that is 150px wide by 200px high. What I would like to happen is the image's canvas is made to be 267px wide, with the new area filled with a certain color.
So there are two possibilities I can think of:
1) Photoshop actions could do this, but I would have to pull current height, multiply by 1.333333 and then put that value in the width box of the canvas resize. Is it possible to have calculated values in Photoshop actions?
2) Some other application has this feature built in.
Any help is greatly appreciated.
Wow, I see now (after writing the answer) that this was asked a long time ago. . . oh well. This script does the trick.
This Photoshop script will resize any image's canvas so that it has a 4:5 aspect ratio. You can change the aspect ratio applied by changing arWidth and arHeight. The fill color will be set to the current background color. You could create an action to open a file, apply this script, then close the file to do a batch process.
Shutdown Photoshop.
Copy this javascript into a new file named "Resize Canvas.jsx" in Photoshop's Presets\Scripts folder.
Start Photoshop and in the File - Scripts menu it should appear.
#target photoshop
main ();
function main ()
{
if (app.documents.length < 1)
{
alert ("No document open to resize.");
return;
}
// These can be changed to create images with different aspect ratios.
var arHeight = 4;
var arWidth = 5;
// Apply the resize to Photoshop's active (selected) document.
var doc = app.activeDocument;
// Get the image size in pixels.
var pixelWidth = new UnitValue (doc.width, doc.width.type);
var pixelHeight = new UnitValue (doc.height, doc.height.type);
pixelWidth.convert ('px');
pixelHeight.convert ('px');
// Determine the target aspect ratio and the current aspect ratio of the image.
var targetAr = arWidth / arHeight;
var sourceAr = pixelWidth / pixelHeight;
// Start by setting the current dimensions.
var resizedWidth = pixelWidth;
var resizedHeight = pixelHeight;
// The source image aspect ratio determines which dimension, if any, needs to be changed.
if (sourceAr < targetAr)
resizedWidth = (arWidth * pixelHeight) / arHeight;
else
resizedHeight = (arHeight * pixelWidth) / arWidth;
// Apply the change to the image.
doc.resizeCanvas (resizedWidth, resizedHeight, AnchorPosition.MIDDLECENTER);
}
Mind that the accepted answer from #user268911 may not work for you if the source image has different pixels/inch than 72. Because the UnitValue.convert function works correctly only with 72 px/inch. To be sure the conversion is correct for ever pixel/inch value, set baseUnit property as follows:
...
var pixelWidth = new UnitValue (doc.width, doc.width.type);
pixelWidth.baseUnit = UnitValue (doc.width.baseUnit, "in");
var pixelHeight = new UnitValue (doc.height, doc.height.type);
pixelHeight.baseUnit = UnitValue (doc.height.baseUnit, "in");
...
For more details about the conversion see "Converting pixel and percentage values" section of the Adobe JavaScript Tools Guide.
What languages do you know? ImageMagick has command line tools that can do this, but you'd need to know a scripting language to get the values and calculate the new ones.
For .NET, my company's product, DotImage Photo, is free and can do this (need to know C# or VB.NET)

Resources