目錄:
1、PDF格式分析
1.1 header
1.2 Obj
1.3 cross reference table
1.4 trailer
1.5 文件尾
1.6 Obj對象
2、VC生成PDF
2.1 前期準備
2.2 源碼及效果
3、參考資料
正文:
1、PDF文件分析
PDF文件主要包含以下幾種結構:
1.1 header
PDF文件的第一行,格式如下:
%PDF-1.1 //表示當前文件的版本爲1.1(目前最高版本是1.7)
1.2 Obj (文件體)
PDF中用到的對象,包括文本/圖象/音樂/視頻/字體/超連接/加密信息等,格式如下:
例:
代碼:
//1標示這個obj的序號,便於在xref中查找,0是用來標示不同的obj現在都是0,obj是關鍵字
<< // 從這裏開始各行就是obj的屬性了 以“/關鍵字 值”的形式來出現
/Type /Catalog //obj的類型是目錄catalog
/Outlines 2 0 R //第二個obj是outlines
/Pages 3 0 R //第三個obj是Pages
/OpenAction 7 0 R // OpenAction 在第7個obj
>>
endobj //一個obj結束
1.3 cross reference table
代碼:
0 5
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
xref
是obj的索引表,用來索引各個obj在文檔中的起始位置,它的形式如下圖,其中0,211分別代表這個xref的obj的起始和終止序號。下面的各行就
代表各個obj在這個文檔的起始位置,其中第一串字符(10個)代表起始位置,中間的五個字符也是爲了區分用的,只有當這個對象被刪除的時候纔有用,表示
這個對象被刪除後又被重新生成後的對象號,現在基本上全爲0。 後面的字母有兩種:f代表刪除的,n代表要使用的。
1.4 trailer
代碼:
<<
/Size 8
/Root 1 0 R
>>
後面的trailer是對整個xref的摘要,說明裏面有多少個OBJ,讀的時候從哪個OBJ開始解析,信息節點等,其中:
/size :這個pdf中總共使用了多少個對象
/root :這個pdf文件的catalog對象的對象號,這是pdf中最頂層的對象,即PDF是組織對象號,此例中位 1 0 R
1.5 文件尾
代碼:
553
%%EOF
因爲一個文檔中可以有多個xref,所以這裏要指明要從哪個xref開始進行解析這個文件。
/startxref: 後面的數字表示cross reference table的開始位置,裏面的數字是10進制。
/%%EOF :文件結束符.
1.6 OBJ對象
Pdf的OBJ中的對象有如下幾種,現介紹如下:
(1)文件描述對象,用來描述這個文件的標題,作者,時間等
(2)組對象,也就是文檔內容的起始結點。Type 爲Catalog
(3)頁集合,裏面聚合了大量的頁對象。 Type 爲pages
(4)頁對象,裏面指明瞭當前頁裏面用到的字體,內容,活動對象,圖片等。Type 爲page
(5)活動對象,有鏈接,文字,聲音,電影等,Type 爲Annots
(6)圖片對象, Type 爲 XObject
(7)字體對象,Type 爲 Font 。PDF可以內置字體,所以即使目標機器上沒有,只要它內置了,也可以正常地顯示,不受影響。
(8)
流對象。所有的二進制內容都是存在這個對象裏面,文件流的常見的壓縮方式是:圖片的一些壓縮算
法,FlateDecode,ASCIIHexDecode,ASCII85Decode等等,FlateDecode事實上就是ZIP的壓縮算法。流對
象的長度是關連到一個長度對象上的/Length 188 0 R這種形式。188就是存這個長度的OBJ的順序號。
(9)數字對象。例如:
188 0 obj
2538
endobj
裏面只有一個數字,經常用來表示長度。
2、VC生成PDF
PDFLib是用於創建PDF文檔的開發庫,提供了簡單易用的API,隱藏了創建PDF的複雜細節且不需要第3方軟件的支持。已VC編輯一個控制應用臺程序爲例來生成一個PDF。
2.1 前期準備
先到PDFLib官網下載庫文件,最新版爲pdflib8,但是生成的pdf有一個官網的網址,5.0版本以下沒有,鏈接地址:http://www.pdflib.com/download/pdflib-family/pdflib-8
建立工程後,將下載庫中pdflib.h,pdflib.dll,pdflib.lib拷貝到工程目錄。
2.2 源碼
參照官網提供的一些sample,改編了一個,源代碼如下:
代碼:
#include "pdflib.h"
#pragma comment(lib,"pdflib.lib")
int main()
{
PDF *p;
/* create a new PDFlib object */
if ((p = PDF_new()) == (PDF *) 0)
{
printf("Couldn't create PDFlib object (out of memory)!/n");
return(2);
}
PDF_TRY(p)
{
/* This means we must check return values of load_font() etc. */
PDF_set_parameter(p, "errorpolicy", "return");
if (PDF_begin_document(p, "pediy.pdf", 0, "") == -1)
{
printf("Error: %s/n", PDF_get_errmsg(p));
return(2);
}
// /* This line is required to avoid problems on Japanese systems */
// PDF_set_parameter(p, "hypertextencoding", "host");
PDF_set_info(p, "Creator", "pediy.c");
PDF_set_info(p, "Author", "youstar");
PDF_set_info(p, "Title", "Hello, pediy (C)!");
PDF_begin_page_ext(p, a4_width, a4_height, "");
/* Change "host" encoding to "winansi" or whatever you need! */
font = PDF_load_font(p, "Helvetica-Bold", 0, "host", "");
if (font == -1)
{
printf("Error: %s/n", PDF_get_errmsg(p));
PDF_delete(p);
return(2);
}
PDF_setfont(p, font, 24);
PDF_set_text_pos(p, 50, 700);
PDF_show(p, "pediy");
PDF_continue_text(p, "2010 better!");
PDF_end_page_ext(p, "");
PDF_end_document(p, "");
}
PDF_CATCH(p) {
printf("PDFlib exception occurred in hello sample:/n");
printf("[%d] %s: %s/n",
PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p));
PDF_delete(p);
return(2);
}