Mirrored (Flipped) Printing A PDF File - pdf

I generating ID Cards of Students of My College in a PDF file using ASP.NET (Framework 3.5) and Crystal Reports But I Want to print the Cards in a Transparent Sheet and Paste it on a Plastic Card of same size for that i need the everything to be printed mirrored.
I tried designing the crystal reports in mirrored form itself but could not find a way to write text in mirrored form. Can anyone suggest a way to do this work all I want is to Flip the contents in PDF File or in Crystal Report.

A couple of Ideas:
1) Render the PDF to an Image (using Ghostscript/ImageMagick or commercial PDF library( (eg Tif) and mirror the image for printing
2) Mirror the PDF Itself, might be possible with iTextSharp
3) Use the reporting tool and try and use some kind of reverse font (coud be quick option)

Any API that lets you import pages and write directly to the PDF content stream will let you do this.
In iText (Java), it'd look something like this:
PdfReader reader = new PdfReader(pdfPath);
Document doc = new Document();
PdfWriter writer = PdfWriter.getInstance( doc, new FileOutputStream(outPath) );
for (int pageNum = 1; pageNum <= reader.getNumberOfPages(); ++pageNum) {
PdfImportedPage page = writer.getImportedPage(reader, pageNum);
PdfContentByte pageContent = writer.getDirectContent();
// flip around vertical axis
pageContent.addTemplate(page, 1f, 0f, 0f, -1f, page.getWidth(), 0f);
doc.newPage();
}
The above code is making the following ass-u-me-ptions:
The default Document() page size matches the size of the current PdfImportedPage.
The source pages aren't rotated.
There are no annotations, optional content groups (layers), and various other bits that aren't just represented in the page contents.
Some workarounds:
// keep the page size consistent
PdfImportedPage page = writer.getImportedPage(reader, pageNum);
doc.newPage(page.getBoundingBox());
PdfContentByte pageContent = writer.getDirectContent();
pageContent.addTemplate(...);
// to compensate for a page's rotation, you need to either rotate the target page
// Easy in PdfStamper, virtually impossible with `Document` / `PdfWriter`.
AffineTransform unRotate = AffineTranform.getRotateInstance(degToRad(360 - pageRotation), pageCenterX, pageCenterY)
AffineTransform flip = new AffineTransform(1f, 0f, 0f, -1f, page.getWidth(), 0f);
AffineTransform finalTrans = flip;
finalTrans.concatenate(unRotate);
pageContent.addTemplate(page, finalTrans);
FAIR WARNING: My 2d matrix-fu isn't all that strong. I'm almost certainly doing something wrong. Debugging these sorts of things is a real PITA. Stuff either "looks right" or is so badly screwed up its off the page entirely (ergo invisible, so you don't know which way it went). I often change the page rectangles by [-1000 -1000 1000 1000] just so I can see where it all went. Fun stuff.
As for copying annotations and such... ouch. PdfCopy does all that for you, via it's addPage() method, but that doesn't let you transform the page content first. Any changes you make to the PdfImportedPage are ignored. You're really stuck with The Hard Way... manually copying all the fiddly bits and changing them to compensate for your flipped page... or messing with the source to addPage() to get the results you want. Both require some in-depth knowledge of PDF.
Given the specifics, you probably don't need to worry about it, but it's worth mentioning in case someone with a different situation comes along with the same goal.

Related

getImportedPage without annotation

I want to use PdfStamper to enlarge every page, and copy some pages.
Enlarge every page:
for (int i = 1; i <= n; i++) {
page = reader.getPageN(i);
media = page.getAsArray(PdfName.CROPBOX);
if (media == null) {
media = page.getAsArray(PdfName.MEDIABOX);
}
crop = new PdfArray();
crop.add(new PdfNumber(0));
crop.add(new PdfNumber(0));
float w = media.getAsNumber(2).floatValue();
crop.add(new PdfNumber(media.getAsNumber(2).floatValue() * 2));
crop.add(new PdfNumber(media.getAsNumber(3).floatValue() * 1));
page.put(PdfName.MEDIABOX, crop);
page.put(PdfName.CROPBOX, crop);
stamper.getUnderContent(i).setLiteral(String.format("\nq 1 0 0 1 %.1f 0 cm\nq\n", w / 2));
stamper.getOverContent(i).setLiteral("\nQ\nQ\n");
}
Insert an empty page, and copy content from page 1.
stamper.insertPage(2, stamper.getReader().getPageSize(1))
PdfContentByte canvas = stamper.getOverContent(2);
PdfImportedPage ip = stamper.getImportedPage(reader, 1);
Image ipage = Image.getInstance(ip);
canvas.addImage(ipage);
But I found PdfImportedPage deletes annotations, and after I enlarge a page the annotations are in the wrong position.
How can I handle these annotations, both when copying a page and when enlarging.
Displaced Annotations
after I enlarge a page the annotations are in the wrong position.
The Cause Of Their Displacement
The cause for this is simple: You (attempt to) enlarge the page to the right and then you prepend a shift to the right for the static page content. But you don't move the annotations. Thus, the annotations remain in their original position while the static page content is moved away.
What Needs To Be Done
If you actually want to move the coordinates of the static content, you also have to move all the other coordinate arguments in the PDF which relate to that content. This means in particular annotations (multiple entries), destinations, and structure tree information.
A complete implementation thereof is beyond the scope of a stack overflow answer.
A Simpler Option
You (attempt to) enlarge the page to the right and then you prepend a shift to the right for the static page content. Why don't you simply enlarge the page half as far both to the left and the right and leave the content at its coordinates? Then you do not need to change any coordinates at all...
Vanished Annotations
PdfImportedPage deletes annotations
The Cause Of Their Vanishment
The getImportedPage implementations of both the basic PdfWriter and the PdfStamper merely copy the static page content, not the annotations or other extra s. The reason is that in these cases the page is imported as a form Xobject which can be drawn in the content of any content stream (of a page, of an annotation, of another Xobject, ...) but which simply cannot have annotations of its own.
What Can Be Done
You can either flatten all annotations in a preparation step (using a PdfStamper and calling setAnnotationFlattening and setFormFlattening) or duplicate the page in a preparation step (using PdfCopy and its getImportedPage).
The former option is keeping document level information but makes the dynamic annotation contents static. The latter option looses document level information but keeps annotations dynamic.

PDFsharp Not Reading in Correct Page Size

I'm trying to develop an application to watermark PDF's. I'm having an issue with saving the PDF document in the correct format.
I've noticed that some documents when pulled in will read the page size as one thing but when I go to save the document part of it will be cut off. For example I have a document saved in landscape at 792x612 pts which correlates to a letter size. However when saved in letter it cuts part of the page off. I noticed that if I save the document in A1 that the entire document will then be present. Here is my code:
Dim gfx As XGraphics = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append)
gfx.RotateTransform(-90)
Dim font As XFont = New XFont("Times New Romans", 6, XFontStyle.Bold)
Dim tf As XTextFormatter = New XTextFormatter(gfx)
Dim rect As XRect = New XRect(-550, 500, 250, 150)
gfx.DrawRectangle(XBrushes.Transparent, rect)
tf.DrawString(Text, font, XBrushes.Red, rect)
page.Size = PdfSharp.PageSize.A1
page.Orientation = PdfSharp.PageOrientation.Landscape
Doc.save(strFileSaveLocation)
Is there any reason why this could be happening? I am reading the page.height and page.width and confirming these to be correct before continuing.
There is a known bug in PDFsharp when it comes to handling pages in landscape format. This bug is present up to PDFsharp 1.50 beta 3b, but should be fixed with the next release.
See discussion in the PDFsharp forum:
http://forum.pdfsharp.net/viewtopic.php?p=9591#p9591
Suggested fix in PdfPage.cs:
internal PdfPage(PdfDictionary dict)
: base(dict)
{
// Set Orientation depending on /Rotate.
//int rotate = Elements.GetInteger(InheritablePageKeys.Rotate);
//if (Math.Abs((rotate / 90)) % 2 == 1)
// _orientation = PageOrientation.Landscape;
}
If you do not want to modify PDFsharp, maybe try the workaround from the first post:
http://forum.pdfsharp.net/viewtopic.php?p=9587#p9587
For others running into the same issue as me, the answer is to simply set the orientation to portrait. This for some reason will trigger the document to save correctly. The answer by PDFsharp Novice will allow you to fix your code to some extent, but if you're like me and need to know the orientation in order to process the page the solution is setting the orientation back to portrait. You may need to reset page width and height also.
Code:
page.Orientation = PdfSharp.PageOrientation.Portrait
page.Width = dblPageWidth
page.Height = dblPageHeight

Increase left margin of an existing pdf using iTextSharp [duplicate]

My web application signs PDF documents. I would like to let users download the original PDF document (not signed) but adding an image and the signers in the left margin of the pdf document.
I've seen this idea in another web application, and I would like to do the same. Of course I would like to do it using itext library.
I have attached two images, the original PDF document (not signed) and the modified PDF document.
First this: it is important to change the document before you digitally sign it. Once digitally signed, these changes will break the signature.
I will break up the question in two parts and I'll skip the part about the actual watermarking as this is already explained here: How to watermark PDFs using text or images?
This question is not a duplicate of that question, because of the extra requirement to add an extra margin to the right.
Take a look at the primes.pdf document. This is the source file we are going to use in the AddExtraMargin example with the following result: primes_extra_margin.pdf. As you can see, a half an inch margin was added to the left of each page.
This is how it's done:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
// properties
PdfContentByte over;
PdfDictionary pageDict;
PdfArray mediabox;
float llx, lly, ury;
// loop over every page
for (int i = 1; i <= n; i++) {
pageDict = reader.getPageN(i);
mediabox = pageDict.getAsArray(PdfName.MEDIABOX);
llx = mediabox.getAsNumber(0).floatValue();
lly = mediabox.getAsNumber(1).floatValue();
ury = mediabox.getAsNumber(3).floatValue();
mediabox.set(0, new PdfNumber(llx - 36));
over = stamper.getOverContent(i);
over.saveState();
over.setColorFill(new GrayColor(0.5f));
over.rectangle(llx - 36, lly, 36, ury - llx);
over.fill();
over.restoreState();
}
stamper.close();
reader.close();
}
The PdfDictionary we get with the getPageN() method is called the page dictionary. It has plenty of information about a specific page in the PDF. We are only looking at one entry: the /MediaBox. This is only a proof of concept. If you want to write a more robust application, you should also look at the /CropBox and the /Rotate entry. Incidentally, I know that these entries don't exist in primes.pdf, so I am omitting them here.
The media box of a page is an array with four values that represent a rectangle defined by the coordinates of its lower-left and upper-right corner (usually, I refer to them as llx, lly, urx and ury).
In my code sample, I change the value of llx by subtracting 36 user units. If you compare the page size of both PDFs, you'll see that we've added half an inch.
We also use these coordinates to draw a rectangle that covers the extra half inch. Now switch to the other watermark examples to find out how to add text or other content to each page.
Update:
if you need to scale down the existing pages, please read Fix the orientation of a PDF in order to scale it

iTextSharp rotated PDF page reverts orientation when file is rasterized at print house

Using iTextSharp I am creating a PDF composed of a collection of existing PDFs, some of the included PDFs are landscape orientation and need to be rotated. So, I do the following:
private static void AdjustRotationIfNeeded(PdfImportedPage pdfImportedPage, PdfReader reader, int documentPage)
{
float width = pdfImportedPage.Width;
float height = pdfImportedPage.Height;
if (pdfImportedPage.Rotation != 0)
{
PdfDictionary pageDict = reader.GetPageN(documentPage);
pageDict.Put(PdfName.ROTATE, new PdfNumber(0));
}
if (width > height)
{
PdfDictionary pageDict = reader.GetPageN(documentPage);
pageDict.Put(PdfName.ROTATE, new PdfNumber(270));
}
}
This works great. The included PDFs rotated to portrait orientation if needed. The PDF prints correctly on my local printer.
This file is sent to a fulfillment house, and unfortunately, the landscape included files do not print properly when going through their printer and rasterization process. They use Kodak (Creo) NexRip 11.01 or Kodak (Creo) Prinergy 6.1. machines. The fulfillment house's suggestion is to: "generate a new PDF file after we rotate pages or make any changes to a PDF. It is as easy as exporting out to a PostScript and distilling back to a PDF."
I know iTextSharp doesn't support PostScript. Is there another way iTextSharp can rotate included PDFs to hold the orientation when rasterized?
First let me assure you that changing the rotation in the page dictionary is the correct procedure to achieve what you want. As far as I can see your code, there's nothing wrong with it. You are doing the right thing.
Unfortunately, you are faced with a third party product over which you have no control that is not doing the right thing. How to solve this?
I have written an example called IncorrectExample. I have named it that way because I don't want it to be used in a context that is different from yours. You can safely ignore all the warnings I added: they are not meant for you. This example is very specific to your problem.
Please try the following code:
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
// Creating a reader
PdfReader reader = new PdfReader(src);
// step 1
Rectangle pagesize = getPageSize(reader, 1);
Document document = new Document(pagesize);
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
PdfContentByte cb = writer.getDirectContent();
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
pagesize = getPageSize(reader, i);
document.setPageSize(pagesize);
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
if (isPortrait(reader, i)) {
cb.addTemplate(page, 0, 0);
}
else {
cb.addTemplate(page, 0, 1, -1, 0, pagesize.getWidth(), 0);
}
}
// step 4
document.close();
reader.close();
}
public Rectangle getPageSize(PdfReader reader, int pagenumber) {
Rectangle pagesize = reader.getPageSizeWithRotation(pagenumber);
return new Rectangle(
Math.min(pagesize.getWidth(), pagesize.getHeight()),
Math.max(pagesize.getWidth(), pagesize.getHeight()));
}
public boolean isPortrait(PdfReader reader, int pagenumber) {
Rectangle pagesize = reader.getPageSize(pagenumber);
return pagesize.getHeight() > pagesize.getWidth();
}
I have taken the pages.pdf file as an example. This file is special in the sense that it has two pages in landscape that are created in a different way:
one page is a page of which the width is smaller than the height (sounds like it's a page in portrait), but as there's a /Rotate value of 90 added to the page dictionary, it is shown in landscape.
the other page isn't rotated, but it has a height that is smaller than the width.
In my example, I am using the classes Document and PdfWriter to create a copy of the original document. This is wrong in general because it throws away all interaction. I should use PdfStamper or PdfCopy instead, but it is right in your specific case because you don't need the interactivity: the final purpose of the PDF is to be printed.
With Document, I create new pages using a new Rectangle that uses the lowest value of the dimensions of the existing page as the width and the highest value as the height. This way, the page will always be in portrait. Note that I use the method getPageSizeWithRotation() to make sure I get the correct width and height, taking into account any possible rotation.
I then add a PdfImportedPage to the direct content of the writer. I use the isPortrait() method to find out if I need to rotate the page or not. Observe that the isPortrait() method looks at the page size without taking into account the rotation. If we did take into account the rotation, we'd rotate pages that don't need rotating.
The resulting PDF can be found here: pages_changed.pdf
As you can see, some information got lost: there was an annotation on the final page: it's gone. There were specific viewer preferences defined for the original document: they're gone. But that shouldn't matter in your specific case, because all that matters for you is that the pages are printed correctly.

Page by page conversion of PDF into TIFF with proper compression

Problem
There are PDF documents with different type of objects inside. There are simple texts. There can be scanned images that are B&W, and also other images, that are true color. The resolution can be quite high for both (~1789X2711).
I need to convert the PDF into a set of single page TIFF files. There are quite good tools for that. For example Irfanview, ImageMagick. The problem is that I have to define a single compression type for all the pages.
Using JPG for all pages would result in loosing details for B&W images and they would be huge compared to lossless fax compression.
Using lossless fax for all would wanish colors and details of true color images.
Idea
It would be nice to examine the PDF page by page. I could check the content of the page. What kind of images are there inside, and which compression is recommanded for the particular page. I think this can be done with IText, but I don't know exactly, how it should be done. A second thing is that I want to do this analysis without fully reading the PDF file. Is it possible?
Maybe the fastest solution would be to create a list of pages for each compression type with IText analysis, and then to call Irfanview to process the choosen pages with the proper compression.
Any ideas and recommendations are welcome.
UPDATE:
I have now an answer. It does not cover all requirements, and its not freeware. Any opensource ideas? Maybe Java based solutions?
This can be done with DotImage DotPdf from Atalasoft (cue the obligatory "I work there and work on these products"). Here is how I would do this task in C#:
PdfImageSource source = new PdfImageSource(pdfStream);
while (source.HasMoreImages()) {
AtalaImage image = source.AcquireNext();
string fileName = GetNextTiffName();
using (FileStream outStm = new FileStream(fileName, FileMode.Create)) {
TiffEncoder encoder = new TiffEncoder();
encoder.Compression = SelectCompression(image.PixelFormat);
image.Save(outStm, encoder, null);
}
source.Release(image);
}
private TiffCompression SelectCompression(PixelFormat pf)
{
switch (pf) {
// 1 bit? use CCITT G4
case PixelFormat.Pixel1bbIndexed: return TiffCompression.Group4FaxEncoding;
// 24 bit? use JPEG
case PixelFormat.Pixel24bppBgr: return TiffCompression.JpegCompression;
// all else, Lzw
default: return TiffCompression.Lzw;
}
}
You can make SelectCompression do pretty much whatever you want. If you select an invalid compression for that pixel format, the encoder will use an appropriate lossless one in its place (for example, if you select CCITT for 24bit color, the encoder will instead use Lzw).
Our PDF decoder knows when a PDF page is just gray and returns a gray image. It does NOT do anything to get you to 1 bit (this is so antialiased text looks good), however you could threshold the gray image and look at the overall differences between it and the gray image to determine if it could go to 1 bit).
Here's how you could do a set of pages:
public void ExtractNPages(Stream pdfStream, params int[] pageIndexes)
{
PdfImageSource source = new PdfImageSource(pdfStream);
for (int i in pageIndexes) {
AtalaImage image = source[i]; // implied Acquire
string fileName = GetNextTiffName();
using (FileStream outStm = new FileStream(fileName, FileMode.Create)) {
TiffEncoder = new TiffEncoder();
encoder.Compression = SelectCompression(image.PixelFormat);
image.Save(outStm, encoder, null);
}
source.Release(image);
}
}
so now you can just do ExtractNPages(stm, 0, 2, 4, 6);