文件格式之PDF

目錄:
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  0  obj  
//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
代碼:

xref  
  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
代碼:

trailer  
  <<  
  /Size   8  
  /Root   1   0   R  
  >>  


後面的trailer是對整個xref的摘要,說明裏面有多少個OBJ,讀的時候從哪個OBJ開始解析,信息節點等,其中:
/size   :這個pdf中總共使用了多少個對象  
/root   :這個pdf文件的catalog對象的對象號,這是pdf中最頂層的對象,即PDF是組織對象號,此例中位 1 0 R
1.5 文件尾
代碼:

startxref  
  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 "stdafx.h"
#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);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章