用C#制作PDF文件全攻略

發布時間:2009年06月04日      浏覽次數:1822 次
PDF文件是目前比較流行的電子文檔格式,在辦公自動化(OA)等軟件的開(kāi)發中(zhōng),經常要用到該格式,但介紹如何制作PDF格式文件的資(zī)料非常少,在網上搜來搜去(qù),都轉貼的是同一(yī)段“暴力”破解的方法,代碼片斷如下(xià):
StreamWriter pPDF=new StreamWriter(filePath);
ArrayList xRefs=new ArrayList();
float yPos =0f;
long streamStart=0;
long streamEnd=0;
long streamLen =0;
string strPDFMessage=null;
//PDF文檔頭信息
strPDFMessage="%PDF-1.1\n";
ConvertToByteAndAddtoStream(strPDFMessage);

xRefs.Add(mPDF.Length);
strPDFMessage="1 0 obj\n";
ConvertToByteAndAddtoStream(strPDFMessage);
strPDFMessage="<< /Length 2 0 R >>\n";
ConvertToByteAndAddtoStream(strPDFMessage);
strPDFMessage="stream\n";
ConvertToByteAndAddtoStream(strPDFMessage);
……
看了上面的制作辦法,我(wǒ)(wǒ)眼鏡都摔壞了三幅,如果用上面這樣原始的辦法能制作出滿意的PDF文件,那一(yī)定是天才所爲。後來,我(wǒ)(wǒ)從一(yī)個網站(網址:http://itextsharp.sourceforge.net/index.html)中(zhōng)看到了專門制作PDF文件的控件的介紹,暗喜之餘,立馬下(xià)載試驗,果然非常輕松地制作出了想要的PDF文件,因爲網站爲英文,内容又(yòu)多,讀起來非常費(fèi)力,在解決了自己的問題後,看到許多網友還在爲PDF文件制作而郁悶,遂決定将該内容翻譯爲中(zhōng)文,由于本人英語水平一(yī)般,許多地方又(yòu)晦澀難懂,故翻譯質量不是很滿意,敬請斧正,但大(dà)部分(fēn)能看懂。本文的目的一(yī)是解決部分(fēn)網友的燃眉之急,二是抛磚引玉,如果哪位仁兄願意将該網站中(zhōng)的内容準确翻譯出來,則是天下(xià)之大(dà)幸。
要用本文的方法生(shēng)成PDF文件,需要兩個控件:itextsharp.dll和ICSharpCode.SharpZipLib.dll,由于示例代碼實在太多,我(wǒ)(wǒ)将代碼全部整理出來,放(fàng)在另外(wài)一(yī)個文件“示例代碼.doc”中(zhōng),所有這些資(zī)源,我(wǒ)(wǒ)均放(fàng)在了本人的ftp站點(ftp://202.107.251.26/)上的“苟安廷”文件夾中(zhōng),文件名爲“Pdf文件制作.rar”(壓縮包中(zhōng)另外(wài)兩個rar壓縮文件爲兩個控件的源代碼,供大(dà)家學習研究使用),你可以到這裏下(xià)載相應的資(zī)源,或者直接到原網站下(xià)載。
爲便于調試和叙述,所有例子均爲DOS控制台程序,windows程序使用方法完全一(yī)樣,按照下(xià)面的步驟創建一(yī)個可調試的項目:
1、 打開(kāi)VS2003;
2、 單擊菜單“文件”→“新建”→“項目”,在項目類型中(zhōng)選擇“Visual C#項目”,在模闆中(zhōng)選擇“控制台應用程序”,輸入文件名稱如“MakePdf”,指定好存放(fàng)路徑,然後點确定按鈕;
3、 在“解決方案資(zī)源管理器”中(zhōng)右鍵單擊“引用”,從彈出的菜單中(zhōng)選擇“添加引用”,在“.NET”選項夾中(zhōng)選擇“浏覽”,添加前面提到的兩個應用,如下(xià)圖:

4、 在代碼窗口頂部添加兩個引用:
using iTextSharp.text;
using iTextSharp.text.pdf;
至此,準備工(gōng)作完畢。

第一(yī)部分(fēn) iText的簡單應用
第一(yī)章 創建一(yī)個Document
利用iText五步創建一(yī)個PDF文件:helloword。
第一(yī)步,創建一(yī)個 iTextSharp.text.Document對象的實例:
Document document = new Document();
第二步,爲該Document創建一(yī)個Writer實例:
PdfWriter.getInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));
第三步,打開(kāi)當前Document
document.Open();
第四步,爲當前Document添加内容:
document.Add(new Paragraph("Hello World"));
第五步,關閉Document
document.Close();
完整的代碼見示例代碼0101。
在例中(zhōng),不難看出,制作一(yī)個PDF文件是非常簡單的。
注:如果你将例中(zhōng)“document.Add(new Paragraph("Hello World"));”中(zhōng)的字符串“Hello Word”換成中(zhōng)文,如“這是我(wǒ)(wǒ)的第一(yī)個PDF文件”,産生(shēng)的結果一(yī)定讓你大(dà)失所望,因爲生(shēng)成的PDF文件中(zhōng)并沒有将中(zhōng)文顯示出來,不要擔心,在第9章中(zhōng)要專門講解字體(tǐ)問題,中(zhōng)文顯示也就迎刃而解了,如果不能正确顯示中(zhōng)文,也就沒有必要翻譯本文了。
下(xià)面對這幾步做詳細介紹。
第一(yī)步 創建一(yī)個Document實例:
iTextSharp.text.Document-object共有三個構造函數:
public Document();
public Document(Rectangle pageSize);
public Document(Rectangle pageSize,
int marginLeft,
int marginRight,
int marginTop,
int marginBottom);
第一(yī)個構造函數以A4頁面作爲參數調用第二個構造函數,第二個構造函數以每邊36磅頁邊距爲參數調用第三個構造函數
u 頁面尺寸:
你可以通過指定的顔色和大(dà)小(xiǎo)創建你自己的頁面,示例代碼0102創建一(yī)個細長的淺黃色背景的頁面:
Rectangle pageSize = new Rectangle(144, 720);
pageSize.BackgroundColor = new Color(0xFF, 0xFF, 0xDE);
Document document = new Document(pageSize);
通常,你不必創建這樣的頁面,而可以從下(xià)面頁面尺寸中(zhōng)選擇:
A0-A10, LEGAL, LETTER, HALFLETTER, _11x17, LEDGER, NOTE, B0-B5, ARCH_A-ARCH_E, FLSA 和 FLSE
大(dà)多數情況下(xià)使用縱向頁面,如果希望使用橫向頁面,你隻須使用rotate()函數:
Document document = new Document(PageSize.A4.rotate());
詳細代碼見示例代碼0103。
u 頁邊距:
當創建一(yī)個文件時,你還可以定義上、下(xià)、左、右頁邊距:
Document document = new Document(PageSize.A5, 36, 72, 108, 180);
在示例代碼0104中(zhōng)你可以看到該文檔有一(yī)個0.5英寸的左邊距和1英寸的右邊距,上邊距爲1.5英寸,下(xià)邊距爲2.5英寸。
說明:
當創建一(yī)個矩形或設置邊距時,你可能希望知(zhī)道該用什麽度量單位:厘米、英寸或象素,事實上,默認的度量系統以排版單位磅爲基礎得出其他單位的近似值,如1英寸=72磅,如果你想在A4頁面的PDF中(zhōng)創建一(yī)個矩形,你需要計算以下(xià)數據:
21 厘米 / 2.54 = 8.2677 英寸
8.2677英寸* 72 = 595 磅
29.7 厘米 / 2.54 = 11.6929 英寸
11.6929英寸* 72 = 842 磅
默認邊距爲36磅即半英寸。
如果你修改了頁面尺寸,僅僅影響到下(xià)一(yī)頁,如果你修改了頁邊距,則影響到全部,故慎用。
關于頁面的初始值,請參考第三步。
第二步 創建Writer實例
一(yī)旦創建了document,我(wǒ)(wǒ)們可以創建該文檔的多個Writer的實例,所有這些Writer實例均繼承自抽象類“iTextSharp.text.DocWriter”。
同時還有另外(wài)一(yī)種情況,你可以用iTextSharp.text.pdf.PdfWriter産生(shēng)文檔PDF文件,如果你想創建一(yī)個TeX文檔,你可以使用iTextSharp.text.TeX.TeXWriter包。
Writer類的構造函數是私有的,你隻能通過下(xià)面的方法創建一(yī)個實例:
public static xxxWriter getInstance(Document document, Stream os);(xxx 是 Pdf 或 Xml)
你可以通過下(xià)面的方法創建一(yī)個實例:
PdfWriter writer = PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));
但是你幾乎永遠不會用到Writer實例(除非你想創建高級PDF或者希望用一(yī)些非常特殊的函數,如ViewerPreferences 或 Encryption)。所以通過下(xià)面的辦法得到實例已經足夠了: PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));
在第一(yī)步中(zhōng)創建一(yī)個文檔時,第一(yī)個參數意義不大(dà),第二個參數可以是任何一(yī)種流,到目前爲止我(wǒ)(wǒ)們一(yī)直使用System.IO.FileStream将Document寫入文件中(zhōng),示例代碼0105用到了System.IO.MemoryStream(這不是一(yī)個獨立的例子,你必須在Servlet Engine中(zhōng)測試這些代碼。
第三步 打開(kāi)Document
u 摘要
在你寫入任何實際數據之前,你可能希望通過以下(xià)幾種方法寫入一(yī)些關于本文檔的摘要:
public boolean addTitle(String title)
public boolean addSubject(String subject)
public boolean addKeywords(String keywords)
public boolean addAuthor(String author)
public boolean addCreator(String creator)
public boolean addProducer()
public boolean addCreationDate()
public boolean addHeader(String name, String content)
你可以選擇自己的标題、主題、關鍵字、作者、創建程序,但以下(xià)産品信息将始終被添加:iTextSharp (或者iTextSharp的引用)和創建時間(實際上這兩種方法是自動調用的)。
你還可以将自定義的名稱添加爲“報頭信息”,但是這對于PdfWriter沒有任何作用,如果看看實例代碼0101産生(shēng)的pdf文件的“文檔屬性”,我(wǒ)(wǒ)們可以看到僅僅有PDF創建程序和産品日期,而示例代碼0106的“文檔屬性”框中(zhōng)有更多的信息。

打開(kāi)document前要做的事:
你隻能在Open方法調用之前添加摘要,這是iText開(kāi)發工(gōng)具提供的一(yī)個選擇。
在HTML中(zhōng),報頭信息被放(fàng)在文檔前面報頭标識中(zhōng)間,調用Open方法将導緻報頭信息寫入流,因而在Document被打開(kāi)後無法更改這些數據。
PDF報頭信息不包括摘要,看起來有類似于:
%PDF-1.2
該行顯示生(shēng)成的文檔是一(yī)個版本爲1.2的PDF格式的文件,在PDF中(zhōng),摘要保存在PdfInfo對象中(zhōng),當文檔關閉時已經寫入PdfWriter中(zhōng)了,因此,沒有關于爲什麽不能修改庫來滿足任何時候添加或更改摘要的技術原因
u 頁面初始化
Open方法在不同的Witer中(zhōng)同時會産生(shēng)初始化事件,舉例來說,如果你需要一(yī)個水印或者頁眉頁角對象出現在文檔第一(yī)頁的開(kāi)始處,你需要在打開(kāi)文檔前添加這些,同樣的用于設置該文檔其他頁水印、頁眉、頁角、頁數和尺寸。
當調用下(xià)列方法:
public bool setPageSize(Rectangle pageSize)
public bool Add(Watermark watermark)
public void removeWatermark()
setting Header property
public void resetHeader()
setting Footer property
public void resetFooter()
public void resetPageCount()
setting PageCount property
産生(shēng)的結果隻能在下(xià)一(yī)個新頁中(zhōng)看到(當在本頁調用初始化方法時),代碼見示例代碼0107,你必須要準備一(yī)張名爲watermark.jpg的圖片,如下(xià)圖:

u 閱讀器參數:
你可以通過下(xià)面的辦法爲PDF文件指定一(yī)些閱讀器 (如Adobe Reader) 參數:
public void setViewerPreferences(int preferences)
在示例代碼0108中(zhōng),指定了下(xià)面一(yī)些參數:
writerA.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft);
writerB.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar);
writerC.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft | PdfWriter.PageModeFullScreen | PdfWriter.NonFullScreenPageModeUseThumbs);
正如你所看到的,參數可以使用以下(xià)一(yī)些常量:
l 文件被打開(kāi)時,頁面布局用到下(xià)面的其中(zhōng)一(yī)個 :
PdfWriter.PageLayoutSinglePage – 同時隻顯示一(yī)個頁面
PdfWriter.PageLayoutOneColumn –單列顯示
PdfWriter.PageLayoutTwoColumnLeft –雙列顯示,奇數頁在左
PdfWriter.PageLayoutTwoColumnRight -雙列顯示,奇數頁在右
l 文件打開(kāi)時,頁面模式用到下(xià)面其中(zhōng)之一(yī):
PdfWriter.PageModeUseNone – 既不顯示大(dà)鋼也不顯示縮略圖
PdfWriter.PageModeUseOutlines – 顯示大(dà)綱
PdfWriter.PageModeUseThumbs – 顯示縮略圖
PdfWriter.PageModeFullScreen – 全屏模式,沒有菜單、windows控件或者其他任何windows可見控件
l PdfWriter.HideToolbar – 當文檔激活時,是否隐藏閱讀程序(如Adobe Reader)的工(gōng)具條
l PdfWriter.HideMenubar -當文檔激活時,是否隐藏閱讀程序的菜單.
l PdfWriter.HideWindowUI -當文檔激活時,是否隐藏閱讀程序的界面元素,如滾動條、導航條等,而僅僅保留文檔顯示
l PdfWriter.FitWindow – 是否調整文檔窗口尺寸以适合顯示第一(yī)頁。
l PdfWriter.CenterWindow – 是否将文檔窗口放(fàng)到屏幕中(zhōng)央
l 在全屏模式下(xià),指定如何顯示界面元素(選擇一(yī)個)
PdfWriter.NonFullScreenPageModeUseNone -既不顯示大(dà)鋼也不顯示縮略圖
PdfWriter.NonFullScreenPageModeUseOutlines – 顯示大(dà)鋼
PdfWriter.NonFullScreenPageModeUseThumbs – 顯示縮略圖
說明:你隻能在類PdfWriter中(zhōng)調用這些方法。
u 加密
打開(kāi)文檔之前還要做的一(yī)件事情就是加密(如果你希望該文檔加密),要達到這個目的,你可以使用下(xià)面的方法:
public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions);
strength 是下(xià)面兩個常量之一(yī):
PdfWriter.STRENGTH40BITS: 40 位
PdfWriter.STRENGTH128BITS: 128位 (Acrobat Reader 5.0及以上版本支持)
UserPassword和ownerPassword 可以爲空或零長度, 這種情況下(xià), ownerPassword 将被随機的字符串代替
Permissions 爲下(xià)列常量之一(yī):
PdfWriter.AllowPrinting
PdfWriter.AllowModifyContents
PdfWriter.AllowCopy
PdfWriter.AllowModifyAnnotations
PdfWriter.AllowFillIn
PdfWriter.AllowScreenReaders
PdfWriter.AllowAssembly
PdfWriter.AllowDegradedPrinting
該功能參見示例代碼0109和示例代碼0110。
writer.setEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.AllowCopy);
示例代碼0109産生(shēng)的文件能夠被打開(kāi)而無須密碼,但用戶不能打印、修改本文檔。
writer.setEncryption(PdfWriter.STRENGTH128BITS, "userpass", "ownerpass", PdfWriter.AllowCopy | PdfWriter.AllowPrinting);
打你試圖打開(kāi)示例代碼0110産生(shēng)的文件時,将要求輸入密碼('userpass'),因爲添加了AllowPrinting參數,你可以打印該文檔而不會發生(shēng)任何問題。
第四步 添加内容
在解釋第一(yī)步到第三步的不同示例中(zhōng),你可能已經遇到了一(yī)些對象如Phrase, Paragraph等 在接下(xià)來的幾章中(zhōng),所有這些問題都将得到詳細解釋。
有時你可能想一(yī)個writer故意忽略document産生(shēng)的行爲,如示例代碼0111:
當我(wǒ)(wǒ)們創建了兩個writer: writerA 和 writerB:
PdfWriter writerA = PdfWriter.getInstance(document, new FileStream("Chap0111a.pdf", FileMode.Create));
PdfWriter writerB = PdfWriter.getInstance(document, new FileStream("Chap0111b.pdf", FileMode.Create));
我(wǒ)(wǒ)們可以創建兩個有細微差别的文檔:
writerA.Pause();
document.add(new Paragraph("This paragraph will only be added to Chap0111b.pdf, not to Chap0111a.pdf"));
writerA.resume();
你可以比較文件: Chap0111a.pdf和Chap0111b.pdf的區别
第五步,關閉 document
關閉 document 非常重要, 因爲它将關閉正在運行的Writer并将内容寫入文件,該方法在最後被調用,你應該總是要關閉文檔。
高級話(huà)題:閱讀PDF文件
該部分(fēn)内容介紹了iText隻能産生(shēng)PDF格式的文件而不能解析PDF格式文件,不再翻譯。
第二章 塊、短句和段落

塊(Chunk)是能被添加到文檔的文本的最小(xiǎo)單位,塊可以用于構建其他基礎元素如短句、段落、錨點等,塊是一(yī)個有确定字體(tǐ)的字符串,要添加塊到文檔中(zhōng)時,其他所有布局變量均要被定義。下(xià)面一(yī)行中(zhōng),我(wǒ)(wǒ)們創建了一(yī)個内容爲“hello World”、紅色、斜體(tǐ)、COURIER字體(tǐ)、尺寸20的一(yī)個塊:
Chunk chunk = new Chunk("Hello world", FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0, 0)));
u 典型字體(tǐ)1:
在本指南(nán)中(zhōng),除了第九章外(wài)(你可以在這裏學會使用其他字體(tǐ)),我(wǒ)(wǒ)們将始終使用典型字體(tǐ)1,這些是不同的典型字體(tǐ)1:
· Courier (該字體(tǐ)定寬)
· Helvetica
· Times Roman
· Symbol
· ZapfDingbats

u 下(xià)劃線/删除線
如果你希望一(yī)些塊有下(xià)劃線或删除線,你可以通過改變字體(tǐ)風格簡單做到:
Chunk chunk1 = new Chunk("This text is underlined", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.UNDERLINE));
Chunk chunk2 = new Chunk("This font is of type ITALIC | STRIKETHRU", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.ITALIC | Font.STRIKETHRU));
u 上标/下(xià)标
在塊中(zhōng)有幾個方法可以調用,其中(zhōng)大(dà)部分(fēn)将在接下(xià)來的章節中(zhōng)介紹,本章中(zhōng)隻介紹一(yī)個方法 setTextRise(float f). 你可以使用該方法在上标或下(xià)标中(zhōng)寫塊。
u 塊的背景
如果你想改變塊的背景,你可以使用方法setBackground(Color color). 這将在塊文本的下(xià)面添加一(yī)個彩色矩形:
ck.setBackground(new Color(0xFF, 0xFF, 0x00));
在示例代碼0101中(zhōng),你可以概覽典型字體(tǐ)1和一(yī)個使用setTextRise, setBackground等方法的的例子。
短句
短句(Phrases)是一(yī)系列以特定間距(兩行之間的距離(lí))作爲參數的塊,一(yī)個短句有一(yī)個主字體(tǐ),但短句中(zhōng)的一(yī)些塊具有不同于主字體(tǐ)的字體(tǐ),你有更多的選擇去(qù)創建短句,一(yī)些具體(tǐ)使用參見代碼0202。

u 古希臘語
因爲古希臘語經常使用,在類Phrase的構造函數中(zhōng)有一(yī)個特征:将一(yī)個字符串作爲參數(如果你想避免這種情況,你隻能使用塊工(gōng)作而不能使用字符串),正如你在示例代碼0203中(zhōng)看到的,這個特征自動地将913至937(除903)和945至969(古希臘的ASCII值)範圍内的所有字體(tǐ)改爲希臘符号。
u 非主要性
與其說這是一(yī)個特征,不如說是一(yī)個缺陷,但無論如何,這使創建一(yī)個非主要性的短句或段落成爲可能,這将産生(shēng)一(yī)個由下(xià)向上書(shū)寫的臨時作用(參見示例代碼0204)。如果你想在一(yī)頁中(zhōng)将一(yī)些位置移動到上面時可能有用。
說明,當你穿越上邊屆時無法檢查,也沒有辦法讓你回到前一(yī)頁。
段落
段落是一(yī)系列塊和(或)短句。同短句一(yī)樣,段落有确定的間距。用戶還可以指定縮排;在邊和(或)右邊保留一(yī)定空白(bái),段落可以左對齊、右對齊和居中(zhōng)對齊。添加到文檔中(zhōng)的每一(yī)個段落将自動另起一(yī)行。有幾種辦法建立一(yī)個段落,如:
Paragraph p1 = new Paragraph(new Chunk("This is my first paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12)));
Paragraph p2 = new Paragraph(new Phrase("This is my second paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12)));
Paragraph p3 = new Paragraph("This is my third paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12));
所有有些對象将被添加到段落中(zhōng):
p1.add("you can add strings, "); p1.add(new Chunk("you can add chunks ")); p1.add(new Phrase("or you can add phrases."));
說明:一(yī)個段落有一(yī)個且僅有一(yī)個間距,如果你添加了一(yī)個不同字體(tǐ)的短句或塊,原來的間距仍然有效,你可以通過SetLeading來改變間距,但是段落中(zhōng)所有内容将使用新的中(zhōng)的間距。見示例代碼0205。
u 保持段落的整體(tǐ)性
在示例代碼0206中(zhōng),我(wǒ)(wǒ)們使用了setKeepTogether(true)方法來試圖将一(yī)個段落放(fàng)在同一(yī)頁中(zhōng),該方法并不是始終有效,舉個例子,第一(yī)段不能剛好在一(yī)頁中(zhōng),于是被分(fēn)成了兩部分(fēn)。第二段被放(fàng)置在第二頁,但第三段順沿到了第三頁上。
字體(tǐ)的延續
你應該掌握字體(tǐ)延續的一(yī)些規則,這些規則的應用見示例代碼0207,當我(wǒ)(wǒ)們将一(yī)些内容用指定的字體(tǐ)(非默認字體(tǐ))創建一(yī)個短句或者段落後再添加更多内容時,初始對象的字體(tǐ)風格将被延續,請看“Hello 1!”和“Hello 2”:
Phrase myPhrase = new Phrase("Hello 2! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD));
myPhrase.Add(new Phrase("some other font ", new Font(Font.HELVETICA, 8, Font.ITALIC)));
myPhrase.Add(new Phrase("This is the end of the sentence.\n", new Font(Font.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myPhrase);
我(wǒ)(wǒ)們由Times New Roman 粗體(tǐ)字開(kāi)始,添加一(yī)些文本使用Helvetica字體(tǐ)而不指定風格,我(wǒ)(wǒ)們發現文本被改變成了粗體(tǐ),當我(wǒ)(wǒ)們再加一(yī)些文本使用Times New Roman字體(tǐ)和斜體(tǐ)風格,結果變成了粗斜體(tǐ)。
如果我(wǒ)(wǒ)們使用FontFactory來創建字體(tǐ),字體(tǐ)風格不會被延續,因爲FontFactory使用了另外(wài)的技術構建一(yī)個字體(tǐ):
myPhrase = new Phrase("Hello 1bis! ", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 8, Font.BOLD));
myPhrase.Add(new Phrase("some other font ", FontFactory.getFont(FontFactory.HELVETICA, 8, Font.ITALIC)));
myPhrase.Add(new Phrase("This is the end of the sentence.\n", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myPhrase);
在上面的代碼中(zhōng),使用Helvetica字體(tǐ)的文本風字體(tǐ)沒有指定(既不是粗體(tǐ)也不是斜體(tǐ))。采用Times New Roman的額外(wài)文本僅僅顯示爲斜體(tǐ)。
你也看到我(wǒ)(wǒ)們添加了一(yī)個段落,添加該段落就如同一(yī)個短句。
Paragraph myParagraph = new Paragraph("Hello 1! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD));
myParagraph.Add(new Paragraph("This is the end of the sentence.",FontFactory.getFont(new Font.TIMES_NEW_ROMAN, 8)));
document.Add(myParagraph);
你可以不這樣做,但将失去(qù)字體(tǐ)風格的延續,首先不用任何字體(tǐ)創建段落(例中(zhōng)我(wǒ)(wǒ)們僅僅給字體(tǐ)出間距爲1.5倍),然後添加内容的不同部分(fēn)。

myParagraph = new Paragraph(12);
myParagraph.Add(new Paragraph("Hello 3! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD)));
myParagraph.Add(new Paragraph("This is the end of the sentence.", new Font(Font.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myParagraph);
如果你使用了Phrase對象,你同樣會失去(qù)字體(tǐ)風格的延續:
myPhrase = new Phrase(12);
myPhrase.Add(new Phrase("Hello 4! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD)));
myPhrase.Add(new Phrase("This is the end of the sentence.", newFont(Font.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myPhrase);
u 更改分(fēn)割符
通常,當文本不能放(fàng)在一(yī)行時,文本将被分(fēn)割成不同的部分(fēn),iText首先會查找分(fēn)割符,如果沒有找到,文本将在行尾被截斷。有一(yī)些預定的分(fēn)割符如“ ”空格和“-”連字符,但是你可以使用setSplitCharacter方法來覆蓋這些默認值。在示例代碼0208中(zhōng),你可以看到當到達行尾時一(yī)個塊是如何被分(fēn)割的。然後分(fēn)隔符被改成點“.”,該行在該字符處被分(fēn)割。
第三章 錨點、列表和注釋
錨點
我(wǒ)(wǒ)們都知(zhī)道HTML中(zhōng)的超文本鏈接,當我(wǒ)(wǒ)們點擊某些語句,你能夠跳轉到網上的其他頁。在PDF中(zhōng)也可以實現這種功能。事實上,在第十一(yī)章整個章節中(zhōng)有關于PDF鏈接的介紹,但這是iText的更高級的應用,本章中(zhōng)我(wǒ)(wǒ)們處理簡單的iText。
如果你想在文檔中(zhōng)添加一(yī)個外(wài)部鏈接(例如使用URL鏈接到WEB上的其他文檔),你可以簡單地使用Anchor對象,它派生(shēng)于Phrase對象,使用方法相同。隻有兩種額外(wài)方法定義兩種額外(wài)變量:setName和 setReference。
外(wài)部鏈接示例:
Anchor anchor = new Anchor("website", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.UNDERLINE, new Color(0, 0, 255)));
anchor.Reference = "http://itextsharp.sourceforge.net";
anchor.Name = "website";
如果你想添加内部鏈接,你需要選擇該鏈接不同的名稱,就象你相位在HTML中(zhōng)利用名稱作爲錨點一(yī)樣。爲達到該目的,你需要添加一(yī)個“#”。
内部鏈接示例:
Anchor anchor1 = new Anchor("This is an internal link");
anchor1.Name = "link1";
Anchor anchor2 = new Anchor("Click here to jump to the internal link");
anchor.Reference = "#link1";
這兩個鏈接的例子請見示例代碼0301。
列表
通過類List 和ListItem,你可以添加列表到PDF文件中(zhōng),對于列表你還可以選擇是否排序。
排序列表示例:
List list = new List(true, 20);
list.Add(new ListItem("First line"));
list.Add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));
list.Add(new ListItem("Third line"));
結果如下(xià):
First line
The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
Third line
不排序示例如下(xià):
List overview = new List(false, 10);
overview.Add(new ListItem("This is an item"));
overview.Add("This is another item");
結果如下(xià):
This is an item
This is another item
你可以通過setListSymbol方法更改列表符号:
// 用字符串作爲列表符号
list1.ListSymbol = "*";
// 用Chunk 作爲列表符号(包含“•”字符)
list2.ListSymbol = new Chunk("\u2022", FontFactory.getFont(FontFactory.HELVETICA, 20));
//用圖片作爲列表符号
list3.ListSymbol = new Chunk(Image.getInstance("myBullet.gif"), 0, 0);
還可以使用setIndentationLeft和setIndentationRight方法設置縮排,列表符号的縮排在構造函數中(zhōng)設置。更多的例子請參見示例代碼0302。
注釋
iText支持不同風格的注釋。
u 文本注釋:
你可以添加一(yī)小(xiǎo)段文本到你的文檔中(zhōng),但它并非文檔内容的一(yī)部分(fēn),注釋有标題和内容:
Annotation a = new Annotation(
"authors",
"Maybe it's because I wanted to be an author myself that I wrote iText.");
u 外(wài)部鏈接注釋:
你需要指定一(yī)個可點擊的矩形和一(yī)個字符串(URL描述)或URL對象:
Annotation annot = new Annotation(100f, 700f, 200f, 800f, new URL("http://www.lowagie.com"));
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "http://www.lowagie.com");
u 外(wài)部PDF文件鏈接注釋:
你需要指定一(yī)個可點擊的矩形和一(yī)個字符串(文件名稱)和目的文件或頁碼。
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", "mark");
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", 2);
u 指定行爲鏈接注釋
你需要指定一(yī)個可點擊的矩形和一(yī)個指定的行爲:
Annotation annot = new Annotation(100f, 700f, 200f, 800f, PdfAction.FIRSTPAGE);
u 應用程序鏈接注釋:
你需要指定一(yī)個可點擊的矩形和一(yī)個應用程序:
Annotation annot = new Annotation(300f, 700f, 400f, 800f, "C://winnt/notepad.exe", null, null, null);
我(wǒ)(wǒ)們無須在頁面上指定一(yī)個位置,iText會内部處理。你能夠看到iText添加文本注釋在頁面上當前位置下(xià)面,第一(yī)個在段後第一(yī)行下(xià)面,第二個在短句結束處的下(xià)面。
所有其他注釋需要指定想匹配的矩形區域,在示例代碼0304中(zhōng),我(wǒ)(wǒ)們畫了一(yī)些正方形(使用的函數将在第十章中(zhōng)介紹),爲每個正方形添加了一(yī)些鏈接注釋。
第四章 頁眉頁腳、章節、區域和繪圖對象
使用在第三至第五章中(zhōng)描述的大(dà)量簡單iText對象可以避免更多的高級話(huà)題(第九至十二章),緊記這些簡單對象限制的功能,大(dà)量複雜(zá)的功能在第三部分(fēn)。
頁眉頁腳
HeaderFooter對象可以于爲文檔每頁添加頁眉和頁腳。這樣一(yī)個頁眉或頁腳包含一(yī)個标準的短句(如果需要)和當前頁碼,如果你需要更多複雜(zá)的頁眉和頁腳(使用表格或者第幾頁共幾頁),請閱讀第十二章。
在示例代碼0401中(zhōng),你可以看到我(wǒ)(wǒ)們首先添加了一(yī)個包含頁碼沒有任何邊框的頁腳。
HeaderFooter footer = new HeaderFooter(new Phrase("This is page: "), true);
footer.Border = Rectangle.NO_BORDER;
document.Footer = footer
我(wǒ)(wǒ)們還可以使用下(xià)面的構造函數:
HeaderFooter footer = new HeaderFooter(new Phrase("This is page "), new Phrase("."));
構造函數知(zhī)道你希望添加一(yī)個頁碼和将其放(fàng)置在兩個短句間,如果你隻是設置一(yī)個HeaderFooter而不改變邊框,頁眉或頁腳的文本上下(xià)各有一(yī)條直線。
HeaderFooter header = new HeaderFooter(new Phrase("This is a header without a page number"), false);
document.Header = header;
章節和區域
在第十一(yī)章中(zhōng)将描述如何構建一(yī)個樹(shù)的外(wài)觀,如果你隻需要一(yī)個簡單的章節和(子)區域,你可以用Chapter對象和Section對象自動構建一(yī)個樹(shù):
Paragraph cTitle = new Paragraph("This is chapter 1", chapterFont);
Chapter chapter = new Chapter(cTitle, 1);
Paragraph sTitle = new Paragraph("This is section 1 in chapter 1", sectionFont);
Section section = chapter.addSection(sTitle, 1);
在示例代碼0402中(zhōng),我(wǒ)(wǒ)們添加了一(yī)系列的章節和子區域,你可以看到完整的樹(shù)形,樹(shù)形結構默認打開(kāi),如果你希望部分(fēn)節點關閉,你必須使用用BookmarkOpen屬性其值爲false,詳見示例代碼0403。
圖形
如果你想添加圖形,如直線、圓、幾何窗體(tǐ),你應該閱讀讀十章,但如果你隻需要一(yī)些有限的功能,你可以使用Graphic對象
Graphic grx = new Graphic();
//添加一(yī)個矩形
grx.rectangle(100, 700, 100, 100);
// 添加一(yī)條斜線
grx.moveTo(100, 700);
grx.lineTo(200, 800);
// 将圖形顯示出來
grx.stroke();
document.Add(grx);
完整的代碼請見示例代碼0404,如果想看到全部的方法,請參見PdfContentByte對象API。
當你想給頁面加一(yī)個邊框或者在文本當前位置畫一(yī)條水平線時,圖形對象非常有用。下(xià)面的方法用指定的寬度、間距(如果需要)和顔色畫一(yī)個邊框。
public void setBorder(float linewidth, float extraSpace);
public void setBorder(float linewidth, float extraSpace, Color color);
下(xià)面的方法用指定的寬度(如果需要)和顔色畫一(yī)條水平線,線的長度是指定兩邊緣間可用面積的的百分(fēn)比。
public void setHorizontalLine(float linewidth, float percentage)
public void setHorizontalLine(float linewidth, float percentage, Color color)
示例代碼5中(zhōng),有一(yī)個離(lí)邊界5磅,線寬3磅的邊框,還有兩條水平線,一(yī)條爲黑色,5磅寬,可用空間的100%,另外(wài)一(yī)條爲紅色,線寬3磅,可用空間的80%。
第五章 表格
重點:如果你僅僅生(shēng)成PDF文件(沒有XML、HTML、RTF……),使用類pdfPTable代替類Table更好。
一(yī)些簡單的表格
一(yī)個表格是包含單元格排列成矩陣的矩形區域。表格的距陣并不要求是m×n的,它可以有空洞或者單元格比單個的要大(dà)。
創建一(yī)個表格最通用的辦法是預先知(zhī)道有幾行幾列:
public Table(int columns, int rows);
在示例代碼0501中(zhōng),我(wǒ)(wǒ)們構建了一(yī)個簡單的表:
Table aTable = new Table(2,2);
aTable.addCell("0.0");
aTable.addCell("0.1");
aTable.addCell("1.0");
aTable.addCell("1.1");
該表格有兩行兩列,單元格被自動添加,從第一(yī)行第一(yī)列開(kāi)始,然後是第二列,當一(yī)行滿後,下(xià)一(yī)單元格自動添加到下(xià)一(yī)行的第一(yī)列中(zhōng)。
也可以将單元格添加到表中(zhōng)指定的位置,如示例代碼0502,别了要添加System.Drawing.dll引用,以獲得Point對象,我(wǒ)(wǒ)們創建了一(yī)個4行4列的表格然後添加一(yī)些單元格到随機的位置上:
Table aTable = new Table(4,4);
aTable.AutoFillEmptyCells = true;
aTable.addCell("2.2", new Point(2,2));
aTable.addCell("3.3", new Point(3,3));
aTable.addCell("2.1", new Point(2,1));
aTable.addCell("1.3", new Point(1,3));
你可以看到我(wǒ)(wǒ)們将AutoFillEmptyCells屬性設置爲true,這将自動、默認的單元格布局填充空的單元格,如果我(wǒ)(wǒ)們忘記了這樣做(就象本例中(zhōng)第二個表格),将沒有額外(wài)的單元格添加,不包含任何單格的行也将被忽略,在本例中(zhōng),第一(yī)行将不顯示,因爲該行是空行。
經常用數據庫查詢結果來填充表格,大(dà)多數情況下(xià),你預先并不知(zhī)道到底需要多少行,這就是爲什麽還有第二個構造函數的原因:
public Table(int columns);
iText根據需要自動添加行,在示例代碼0503中(zhōng),初始化了4行4列,當我(wǒ)(wǒ)們添加第6行和第7行的單元格時,iText自動增加行數到7。
增加列數也是可能的,但是有點麻煩,它不能自動生(shēng)成,你必須使用addColumns方法并設置列寬,詳見示例代碼0504。
一(yī)些表格參數
前面例子中(zhōng)的表格并不美觀,我(wǒ)(wǒ)們可以設置大(dà)量的參數來改變表格外(wài)觀。類Table和類Cell派生(shēng)于類Rectangle,我(wǒ)(wǒ)們可以用大(dà)量典型的Rectangle方法,讓我(wǒ)(wǒ)們來看看示例代碼0505。
Table table = new Table(3);
table.BorderWidth = 1;
table.BorderColor = new Color(0, 0, 255);
table.Cellpadding = 5;
5. table.Cellspacing = 5;
Cell cell = new Cell("header");
cell.Header = true;
cell.Colspan = 3;
table.addCell(cell);
10. cell = new Cell("example cell with colspan 1 and rowspan 2");
cell.Rowspan = 2;
cell.BorderColor = new Color(255, 0, 0);
table.addCell(cell);
table.addCell("1.1");
15. table.addCell("2.1");
table.addCell("1.2");
table.addCell("2.2");
table.addCell("cell test1");
cell = new Cell("big cell");
20. cell.Rowspan = 2;
cell.Colspan = 2;
cell.BackgroundColor = new Color(0xC0, 0xC0, 0xC0);
table.addCell(cell);
table.addCell("cell test2");
25. document.Add(table);

u 單元格間距和填距
在第4行中(zhōng),我(wǒ)(wǒ)們設置了表格的填距,就是單元格邊界和内容間一(yī)定數量的空間,在前面的示例中(zhōng),我(wǒ)(wǒ)們看到文本緊貼邊界,通過使用用特定的填距,就可以避免。
在第5行中(zhōng),我(wǒ)(wǒ)們設置了表格的間距,就是單元格和表格邊界間的一(yī)定數量的空間,不同的單元格間使用了半數空間,具體(tǐ)代碼見示例代碼0506。
u 對齊方式
在示例代碼0506中(zhōng),我(wǒ)(wǒ)們也改變了單元格“big cell”的對齊方式:
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.VerticalAlignment = Element.ALIGN_MIDDLE;
注:不能總是相信垂直對齊方式。
u 邊框
如果我(wǒ)(wǒ)們象在第14行中(zhōng)那樣添加了一(yī)個單元格,将使用默認的單元格布局(默認的布局可以SetDefalut方法改變),如果我(wǒ)(wǒ)們使用了Cell對象,我(wǒ)(wǒ)們可以控制每一(yī)個單元格的布局。
在第2和第三中(zhōng),我(wǒ)(wǒ)們設置整個表格的邊框寬度和邊框顔色,我(wǒ)(wǒ)們在單元格上可以使用的方法,在12行中(zhōng),每個單元格用“box”作爲邊界繪制(就象在HTML中(zhōng)),但是示例代碼0507顯示,我(wǒ)(wǒ)們在PDF中(zhōng)有大(dà)量更多可能。
u 顔色
在第22行中(zhōng),你也能定義單元格的背景色,在示例代碼0507中(zhōng),我(wǒ)(wǒ)們不使用顔色隻是用一(yī)定灰度填充。
u 行跨和列跨
最後,你也能設置單元格的行跨(11/20行)和列跨(8/21列)。通過這種方法可以将幾個單元格合并成一(yī)個大(dà)的單元格。
u 備注
第7行在PDF中(zhōng)沒有意義,用于生(shēng)成HTML,在HTML中(zhōng)并不是總能産生(shēng)同樣的布局,PDF表格有點象:

header

example cell with colspan 1 and rowspan 2
1.1
2.1

1.2
2.2

cell test1
big cell

cell test2











u 表格分(fēn)割
如果一(yī)個表格不能放(fàng)在一(yī)頁中(zhōng),将自動被分(fēn)割,示例代碼0508顯示了當一(yī)個表格到達頁邊時發生(shēng)的情況,這将在下(xià)一(yī)節中(zhōng)解釋。
大(dà)表格
跨越幾頁的表格将自動被分(fēn)割成不同的部分(fēn)。示例代碼0509顯示了一(yī)個跨越多頁的報表。該報表有一(yī)個表頭,如果你希望這個表頭在每頁都出現,你可以用endHeaders()方法标記表頭區域的結束點,見示例代碼0510。
爲做這樣的報表,建議設置單元格間距爲0和僅使用指定的填距。
你可能已經注意到了,當一(yī)個表格被分(fēn)割時,一(yī)些邊界好象丢失了。這是因爲單元格在前一(yī)頁被完整地繪制了而不會傳遞給下(xià)一(yī)頁。
u 強行将一(yī)個表格或單元格布置到一(yī)頁上
有有些情況下(xià),你可能希望避免單元格或者整個表被拆分(fēn)成兩個部分(fēn),示例代碼0511差不多和示例代碼0508完全一(yī)樣,但我(wǒ)(wǒ)們設置了參數TableHasToFit爲true,看看示例代碼0508和示例代碼0511結果區别。在示例代碼0512中(zhōng)我(wǒ)(wǒ)們修改了示例代碼0510的CellsHaveToFit屬性爲true,比較兩個示例産生(shēng)結果的區别。
内存管理
當我(wǒ)(wǒ)們添加一(yī)個對象到文檔時,該對象一(yī)有可能就寫入了輸出流,但當創建一(yī)個表格時,該Table對象一(yī)直保存着,對于真正的大(dà)表格,這将成爲一(yī)個問題。
同樣,當你正寫一(yī)個HttpServletResponse對象到輸出流時,浏覽器也可能超時。這就是爲什麽你自己用fitsPage()方法控制表分(fēn)割是有用的,示例代碼0513告訴你如何做。
嵌套表格
有兩種方法嵌套表格,第一(yī)種是利用insertTable方法明确地将一(yī)個表格插入到另外(wài)一(yī)個表格,示例代碼0514顯示了通過插入到其他表格的辦法創建的5個表格。正如你看到的在前面兩個表中(zhōng),所有空的單元格自動得到分(fēn)割,因爲改變了原來的表格。如果一(yī)個單元格不空,列跨度和(或)行跨度将自動調整到新的位置,頁面上第三個表格顯示所有原表中(zhōng)列的相關寬度都得到了保護,第四個表格顯示我(wǒ)(wǒ)們可以在插入了表格後添加其他單元格:該單元格自由地添加到下(xià)一(yī)個單元格中(zhōng)。最後是一(yī)個深度嵌套的表格。
當你使用insertTable方法時,插入表的寬度百分(fēn)比不會被考慮,如果你希望插入表僅占單元格的80%(這是默認的寬度百分(fēn)比),你不得不在單元格中(zhōng)繞排,見示例代碼0515,這也是讓一(yī)個表結合其他數據存放(fàng)在同一(yī)個單元格中(zhōng)的唯一(yī)辦法,見示例代碼0516。
備注:你隻能将一(yī)個表格插入到列跨度和行跨度均爲1的單元格中(zhōng)。
表格偏移
當一(yī)個表格被添加到文檔之前,以當前間距爲準的新行将被添加(如前一(yī)個插入對象的間距)。有時因爲前一(yī)個插入對象和當前表格間的間距過大(dà)或過小(xiǎo)你并不希望這樣做,如果你想改變這個空間,你不得不設置表格偏移,如示例代碼0517。
表格的絕對位置
iTextSharp.text.Table是一(yī)個通過标準方法創建表格的相當簡單的類,但有時你希望表格有一(yī)些特殊的行爲,這種情況下(xià)你将使用更複雜(zá)的類com.lowagie.text.pdf.PdfPTable,示例代碼0518是一(yī)個非常簡單的例子,在第十章和十二章中(zhōng)将有一(yī)些更複雜(zá)的例子。
第六章 圖片
Image對象
如果你學習過API,你可能已經注意到可以通過幾種構造函數來創建圖片,本手冊中(zhōng),我(wǒ)(wǒ)們将僅僅告訴你最簡單的解決方案,如訪問通過文件名或URL确定的圖片生(shēng)成的Image對象。
public static Image getInstance(Uri url)
public static Image getInstance(string filename)
Image是一(yī)個抽象類,故得到實例的方法将判斷給出的圖片的類别(GIF、Jpeg、PNG……)并返回對象的類别Gif、Jpeg、Png……,一(yī)些圖片會被忽略,如果你想知(zhī)道哪些圖片會被忽略,請查閱FAQ(http://www.lowagie.com/iText/faq.html#images)。
u 通過URL得到圖片實例
這是添加一(yī)個圖片最簡單的辦法,見示例代碼0601,我(wǒ)(wǒ)們添加了一(yī)個WMF、一(yī)個Gif、一(yī)個Jpeg和一(yī)個PNG圖片到文檔中(zhōng),使用4個URL得到:
Image wmf = Image.getInstance(new URL("/examples/harbour.wmf"));
Image gif = Image.getInstance(new URL("/examples/vonnegut.gif"));
Image jpeg = Image.getInstance(new URL("/examples/myKids.jpg"));
Image png = Image.getInstance(new URL("/examples/hitchcock.png"));
備注:許多PDF庫在插入一(yī)個圖片前都将其解壓縮并轉換成位圖格式,下(xià)面是幾個我(wǒ)(wǒ)爲什麽不這樣做的原因:
這将導緻PDF文件增大(dà),這樣産生(shēng)的PDF文件尺寸是不同圖片文件尺寸總和的數十倍。
面臨一(yī)個法律問題:LZW算法受專利保護,所以不允許使用這種算法來解壓縮GIF等文件。
u 通過文件名得到圖片實例
通過簡單地改變圖片引用路徑将示例代碼0601改成示例代碼0602:
Image gif = Image.getInstance("vonnegut.gif");
Image jpeg = Image.getInstance("myKids.jpg");
Image png = Image.getInstance("hitchcock.png");
同示例代碼0601的區别隻是該圖象從本地獲取而已,另外(wài)一(yī)個例子見示例代碼0603。
圖片的位置
u 對齊方式
通過下(xià)面方法設置圖片的對齊方式:
Alignment = Image.RIGHT
Alignment = Image.MIDDLE
Alignment = Image.LEFT
參見示例代碼0604。
我(wǒ)(wǒ)們将Vonnegut的圖片放(fàng)在右邊,小(xiǎo)孩的圖片放(fàng)在中(zhōng)間,hitchcock的圖片放(fàng)在左邊。
u 圖片和文本
另外(wài),你還可以指定文本相對圖片的環繞方式:
Alignment = Image.RIGHT | Image.TEXTWRAP
Alignment = Image.MIDDLE
Alignment = Image.LEFT | Image.UNDERLYING
見示例代碼0506,文字在Vonnegut圖片的左側,并不在我(wǒ)(wǒ)小(xiǎo)孩的圖處環繞,且排在Hitchcock圖片的上面。
說明:該功能尚有一(yī)些BUG。
u 絕對位置
當制作PDF文件時,你可能用到該方法:
public void setAbsolutePosition(int absoluteX, int absoluteY)
将一(yī)個圖片放(fàng)要頁面上一(yī)個絕對位置的代碼見示例代碼0606,我(wǒ)(wǒ)們在不同的坐标處添加了兩幅圖片,這裏使用給定的坐标将圖片放(fàng)在了左下(xià)角,通過将圖片的寬度和高度作爲X和Y坐标将設置第一(yī)個圖片,坐标的2倍設置第二個圖片。
縮放(fàng)和旋轉圖片
u 縮放(fàng)
有幾種辦法可以縮放(fàng)圖片:
public void scaleAbsolute(int newWidth, int newHeight)
public void scalePercent(int percent)
public void scalePercent(int percentX, int percentY)
public void scaleToFit(int fitWidth, int fitHeight)
小(xiǎo)孩的圖片大(dà)小(xiǎo)爲194×202象素,如果你想讓圖片小(xiǎo)一(yī)些,你可以通過scaleAbsolute(97, 101)進行縮放(fàng),使用scalePercent(50)也能到達同樣的效果。
還可以通過scaleAbsolute(194, 101)來減小(xiǎo),所以這些例子都放(fàng)在了示例代碼0607中(zhōng)。
u 對分(fēn)辨率的影響
如果一(yī)個圖片不經任何縮放(fàng),其分(fēn)辨率(resolution)爲72,如果該圖片縮放(fàng)比例爲50%,則分(fēn)辨率爲144,如果有更低的縮放(fàng)比,則分(fēn)辨率将更大(dà),因爲象素相同但尺寸變得更小(xiǎo)了。使用72/300=24%的比例放(fàng)置一(yī)個300dpi的圖片,例:你用300dpi掃描了一(yī)個5×5英寸的圖片,圖片結果爲1500×1500象素(5×300),當你用24%(72/300=0.24)的比例将該圖片放(fàng)置到PDF文件中(zhōng)時,PDF中(zhōng)的圖片将爲5×5英寸1500X1500象素300dpi,該圖片将始終爲1500X1500象素而不管尺寸如何。
u 旋轉
可以通過下(xià)面的方法旋轉圖片
public void setRotation(double r)
詳見示例代碼0608。
原始圖片數據
到目前爲止,所有例子中(zhōng)使用的圖片均來自地本地磁盤或者某個網站,但也可能使用包含圖片信息的數組來得到圖片的實例:
public static Image getInstance(byte[] img)
該方法同前面方法的效果相同,返回一(yī)個新的Gif,Jpeg或者Png類别的Image對象。
在示例代碼0609中(zhōng),我(wǒ)(wǒ)們添加一(yī)個從一(yī)個Jpeg文件中(zhōng)讀入到字節數組中(zhōng)的圖片,很明顯,使用其他getInstance方法得到實例更優越,但這僅僅是一(yī)個例子,該getInstance方法在動态創建那些根本不存在的圖片時非常有用。
該例子也演示了如何創建和使用一(yī)個原始圖片。
public static Image getInstance(int width, int height, int components, int bpc, byte data[])
本例中(zhōng)創建了一(yī)個100×100象素的圖片,因爲每個象素用RGB描述,所以圖片大(dà)小(xiǎo)爲100×100×3字節。
System.Drawing.Bitmap
示例代碼0610是一(yī)個比較高級的話(huà)題,理由如下(xià):
首次使用到了System.Drawing.Bitmap類。該類在.net框架中(zhōng),可以使用更多類型的圖片,如TIFF、GIF,而這些圖片在iText中(zhōng)均不支持,你可以檢查一(yī)下(xià).net框架看看你需要的圖片格式是否得到支持。
前面的例子中(zhōng),還有一(yī)些事情要注意:當添加一(yī)個圖片時不會出現什麽問題,文字始終浮于圖片上面,本例中(zhōng),我(wǒ)(wǒ)們希望圖片浮在文字上面。這也是爲什麽我(wǒ)(wǒ)們将使用iTextSharp.text.pdf.PdfContentByte類的原因(見第十章)。
你将發現使用的圖片爲透明的gif格式,你可以到http://itextsharp.sourceforge.net/examples/h.gif下(xià)載得到。
TIFF和CCITT
示例代碼0611也是一(yī)個比較高級的話(huà)題,例中(zhōng)轉換一(yī)個TIFF文件到PDF文件。
u 圖片遮罩
示例代碼0613在,我(wǒ)(wǒ)們創建了一(yī)個用作遮罩的圖片
免責聲明:本站相關技術文章信息部分(fēn)來自網絡,目的主要是傳播更多信息,如果您認爲本站的某些信息侵犯了您的版權,請與我(wǒ)(wǒ)們聯系,我(wǒ)(wǒ)們會即時妥善的處理,謝謝合作!