PDA

View Full Version : iText: Pdfseite als Thumb in anderes Pdf integrieren



Klitzing
26-08-11, 11:38
Hallo,

ich möchte per iText (.Net C#) ein Thumbnail in ein Pdf integrieren. Für normale Bildformate klappt das auch sehr gut per

PdfContentByte cb = Stamper.GetOverContent(page);
Image image =
Image.

GetInstance(picture.FullName);




image.Alignment =
Image.LEFT_ALIGN;
image.ScaleToFit(b, h);
image.SetAbsolutePosition(x, y);
cb.AddImage(image);

Nun liegen mir aber auch "Bilder" als Pdf-Dateien vor.

Es müsste doch irgendwie möglich sein, die 1. Seite dieses Pdfs ganz analog als Thumbnail abzubilden. - Ich weiß nur noch nicht wie. Bitte helft!

Fuerchau
26-08-11, 12:03
Da PDF-Dateien ein PostScript-Format haben, ist das Darstellen der 1. Seite als Bild nicht so einfach möglich.
Es gibt Freeware-Tools, die aus PDF-Dateien Bilder machen können.
Ggf. gibts auch Quell-Beispiele wie man mit Hilfe von GoScript (o.ä.) PDF-Dateien in Bilder umwandeln kann.

Klitzing
26-08-11, 12:21
Was heißt "nicht so leicht"?

Meines Erachtens besteht ein PDF doch aus N Objekten je Seite. Es müsste also doch irgendwie möglich sein, diese aus dem einen Pdf abzugreifen, und in dem anderen Pdf zu platzieren.

Zumindest für 1:1 (mit optionalem Schift) sehe ich da eigentlich keine Hinderungsgründe.

Eine zusätzliche Skalierung im Sinne des ursprünglich Beschriebenen (in einen Rahmen einpassen) wäre natürlich wünschenswert.

Falls das aber in Einzelfällen nicht möglich sein sollte (welche? wie abfangen?), muss ich den Ball halt notgedrungen an die Pdf-Bereitstellung zurückspielen.

Vielleicht geht in diesen Fällen aber immer noch so etwas wie Clipping (also einen wie auch immer gewählten Ausschnitt 1:1 im Rahmen darstellen, den Rest "ausblenden")?

Fuerchau
26-08-11, 13:45
Du kannst dir eine PDF auch mittels Notepad ansehen.
Eine einfache PDF enthält nur Anweisungen zur Seitenaufbereitung, ggf. eingebettete Schriften sowie eben Zeichnungsobjekte (Bilder) im Hexcode.
Natürlich kannst du eine PDF dann einfach lesen und die Anweisungen (analog des PDF-Readers) entsprechend ausführen.

Ich verwende z.B. das Freewaretool PDFill. Dieses kann aus PDF's jede Seite als Bild ausgeben. Ggf. gibts hier auch Batchaufrufe um dieses im Hintergrund machen zu können.

Pikachu
26-08-11, 14:05
Du brauchst ein Programm, das aus zwei PDFs eine PDF macht.

Klitzing
26-08-11, 15:10
Hmmm,

hab da nun selber was gefunden: man kann doch auch (mit iText) mehrere Pdf-Seiten auf eine zusammenfassen. Was ich brauche ist also irgend etwas von der Art:

PdfContentByte cb = Stamper.GetOverContent(page);
PdfReader reader = new PdfReader(picture.FullName);
PdfImportedPage page1 = ????
cb.AddTemplate(page1, scaleX, 0, 0, scaleY, transX, transY);

wobei "picture" eben nun die darzustellende Pdf-Datei ist, page die Datei auf die der Stamper drüber "druckt".

Fehlt also lediglich noch, wie ich aus "picture" oder mittels "reader" zu meiner page1 komme (vorrausgesetzt, dass das gefundene Codesnippet auch wirklich so in C# funzt). - Oder eben irgendwas anderes, was AddTemplate verdauen kann ...

Klitzing
29-08-11, 09:04
Die Idee ist folgende:
Ich baue eine Stamper auf, der bekommt eine initiale Pdf-Datei mit, auf die dann (iterativ) diverse weitere Layer drüber gelegt werden. Das Ergebnis wird letztlich dann geschrieben.

Mit Bildlayern (vgl. erste Mail) und Textlayern klappt das auch wunderbar. Nun brauch ich auch noch ein Abbild eines anderen Pdf.

Nun gibt es ja mit iText die Möglichkeit, mehrere Pdf zusammenzufassen, z.B. vgl. Tutorials in This section (http://www.roseindia.net/java/itext/Combine2page.shtml) . (Okay, das ist java, nicht C#, aber die Idee sollte ja übertragbar sein.)

Entsprechend meinem Ansatz vom Freitag hab ich das jetzt ganz analog so umzusetzen versucht:

PdfContentByte cb = Stamper.GetOverContent(page);

PdfReader reader = new PdfReader(picture.FullName);

Document doc = new Document();
MemoryStream stream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, stream);

PdfImportedPage page1 = writer.GetImportedPage(reader, 1); // get the first page of the PDF

cb.AddTemplate(page1, x, y); // provided it was scaled already accordingly

also einfach einen temporären Stream aufgemacht, um damit einen writer zu definieren, nur um irgendwie an die page1 zu kommen. Diese so abgegriffene page1 soll nun in Form eines Template als weitere Ebene dem Stamper hinzugefügt werden.

Leider geht da aber irgendetwas schief. Ich bekomme folgende Fehlermeldung:

Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
bei iTextSharp.text.pdf.PdfWriter.get_PdfIndirectRefer ence()
bei iTextSharp.text.pdf.PdfTemplate.get_IndirectRefere nce()
bei iTextSharp.text.pdf.PdfWriter.AddDirectTemplateSim ple(PdfTemplate template, PdfName forcedName)
bei iTextSharp.text.pdf.PdfContentByte.AddTemplate(Pdf Template template, Single a, Single b, Single c, Single d, Single e, Single f)
bei iTextSharp.text.pdf.PdfContentByte.AddTemplate(Pdf Template template, Single x, Single y)

Da ich iTextSharp als dll eingebunden habe, kann ich da leider nicht weiter debuggen. Was geht da schief? Und insb., wie lässt sich das reparieren?

Fuerchau
29-08-11, 10:55
Ich denke, da wird dir hier keine Hilfe zu Teil werden können.
Such doch mal in anderen Foren, die sich mit Java und PDF öfter beschäftigen.

Z.B.:
Export PDF pages to a series of images in Java - Stack Overflow (http://stackoverflow.com/questions/550129/export-pdf-pages-to-a-series-of-images-in-java)

max40
29-08-11, 14:23
schau dir mal deinen link an und was du daraus gemacht hast. Das mit dem Stamper sollte falsch sein.

Das PdfContentByte holt man sich auch dem writer, den du willst dein PDF Dokument dem writer hinzufügen!
also so ungefähr müsste es dann aussehen


PdfReader reader = new PdfReader(picture.FullName);

Document doc = new Document();
MemoryStream stream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, stream);

PdfContentByte cb = writer.<code>getDirectContent();</code>


PdfImportedPage page1 = writer.GetImportedPage(reader, 1); // get the first page of the PDF

cb.AddTemplate(page1, x, y); // provided it was scaled already accordingly

Klitzing
29-08-11, 18:10
Und schließlich für diejenigen, die diesen Thread verfolgt haben/verfolgen/oder später mal diesen Thread lesen, hier des Rätsels Lösung:

PdfContentByte cb = Stamper.GetOverContent(page);

PdfReader reader = new PdfReader(picture.FullName);
PdfImportedPage page1 = Stamper.GetImportedPage(reader, 1);
cb.AddTemplate((PdfTemplate)page1, .8f, 0, 0, .8f, x, y); // scaling down to 80%, and translation

D.h., einfach den bereits in der Verarbeitung definierten Stamper benutzen, nicht umständlich erst einen neuen PdfWriter erstellen, nur um irgendwie an page1 zu kommen. Dadurch hat man auch keine Probleme mehr mit .Open() und .Close().