Quartz 2D编程指南(14)
咳咳。。。。PDF文档解析 。。。网上找了好久没找到。。。。。自己翻译了。。水平不行。。。大家将就点随便看看了。这可是哥辛苦一下午翻译的
咳咳。。。。PDF文档解析 。。。网上找了好久没找到。。。。。自己翻译了。。水平不行。。。大家将就点随便看看了。这可是哥辛苦一下午翻译的啊。。累死我了。。
PDF文档解析
Quartz提供了让你检查PDF文档结构和内容流(contentstream)的函数.检查文档结构可以让你读取文档目录的条目和与每个条目相关的内容。通过递归地遍历目录,您可以检查整个文档。
一个PDF的内容流(contentstream)正如其名字所暗示的—一个连续的数据流 例如'BT 12 /F71 Tf (draw thistext) Tj . . . '此处PDF操作符以及他们的描述符都混有实际的PDF内容。检查内容流,你需要按顺序访问它。
本章揭示了如何查看PDF文档的结构和解析一个PDF文件的内容。
检查PDF文档结构
PDF文件可能包含多个页面的图像和文本。您可以使用Quartz访问文档和页面级别的元数据以及PDF页上的对象。本节提供了一个非常简短的介绍,关于您可以访问的元数据。
一个PDF文档对象 (CGPDFDocument)包含了所有的信息,涉及到一个PDF文档,包括它的目录和内容。目录中的条目的递归地描述了PDF文档的内容。你可以访问一个PDF文档的内容通过调用函数CGPDFDocumentGetCatalog。
一个PDF页面对象(CGPDFPage)代表PDF文档中的一页且包含此特定的页面所有信息,包括页面字典和页面内容。您可以获得一个页面字典通过调用该函数CGPDFPageGetDictionary。
图 14-1 展示了描述了两张图片的元数据—组成了图13-2的PDF文件。
你可以通过访问PDF的元数据获得更多有用的信息。图14-1只是一个示例。例如,您可以通过使用图14-1中的代码检查一个PDF是否有缩略图(见图14-2)。
清单 14-1 得到PDF的缩略视图
CGPDFDictionaryRef d; 登入後複製 |
CGPDFStreamRef stream; // represents a sequence of bytes 登入後複製 |
d = CGPDFPageGetDictionary(page); 登入後複製 |
// check for thumbnail data 登入後複製 |
if (CGPDFDictionaryGetStream (d, “Thumb”, &stream)){ 登入後複製 |
// get the data if it exists 登入後複製 |
data = CGPDFStreamCopyData (stream, &format); 登入後複製 |
Quartz为你执行了所有数据流的解密和解密工作。
图 14-2 缩略图片
Quartz提供了很多的功能,您可以使用它来获得PDF的元数据中对应项的指定值。例如,您使用函数CGPDFObjectGetValue,传入一个CGPDFObjectRef,和一个PDF对象类型(kCGPDFObjectTypeBoolean, kCGPDFObjectTypeInteger, 等等),以及一个存储值的存储空间。返回时,此存储空间就被得到的值填充了。
还有很多其他的函数可以用来遍历PDF文件的层次结构来访问各个节点和他们的子节点。例如,CGPDFArray函数(CGPDFArrayGetBoolean, CGPDFArrayGet Dictionary, CGPDFArrayGetInteger,等等) 允许您访问数组的值,以检索特定类型的值。你可以通过阅读阅读PDF规范来找到更多关于如何使用这些函数。
解析PDF内容
你使用CGPDFScanner对象(CGPDFScannerRef数据类型)来解析一个PDF内容流。CGPDFScanner对象调用在流中注册了回调方法的任何操作符的回调方法。
你可以执行以下部分所描述的任务来解析内容流:
1.“为操作符写回调方法”你需要为你要操作的操作符编写回调方法。
2.“创建和设置操作表”。
3.“打开PDF文档”。
4.“扫描每页的内容流”。
当这么做的时候,你应该确保释放了 the scanner, content stream,and operator table。
下面的部分展示如何解析内容流找到标记-内容操作符(marked-content operators)(见表14-1)。标记的内容操作符只代表部分用于PDF内容的PDF操作符。当您编写自己的代码时,你最好寻找适合您的应用程序的PDF操作符。
表 14-1 标注的内容操作符代表一些你可以解析的PDF操作符
Operator |
Description |
MP |
|
DP |
|
BMC |
标志着一个标记内容序列的开始(开始标记内容)和标志一个内容序列结尾的EMC |
BDC |
标志着一个标记内容序列的开始和标志一个内容序列结尾的EMC |
EMC |
标志着一个以BMC或BDC |
为操作符编写回调方法
当Quartz调用你的PDF操作符的回调方法时,它通过你的回调方法传递了一个CGPDFScanner对象和一个指向任何必要信息的指针。通常,你的回调方法检索任何与操作符相关联的项。例如,在14-2所展示的清单中对应于MP操作符的回调方法调用了CGPDFScannerPopName函数从堆栈中检索与操作符相关联的字符串。如果清单中的代码成功的从scanner栈中检索出name,就打印出来。
Quartz有各式各样的CGPDFScannerPop函数用于检索objects,Boolean values, names, numbers, strings, arrays, dictionaries, and streams.每个函数都返回一个布尔值表明是否成功检索了该项。
清单14-2 MP操作符的回调方法
static void 登入後複製 |
op_MP (CGPDFScannerRef s, void *info) 登入後複製 |
{ 登入後複製 |
const char *name; 登入後複製 |
登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
if (!CGPDFScannerPopName(s, &name)) 登入後複製 |
return; 登入後複製 |
登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
printf("MP /%s\n", name); 登入後複製 |
} 登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
创建并设置操作表
一个CGPDFOperatorTable对象存储了你编写的PDF操作符回调函数。函数CGPDFOperatorTableCreate创建了一个操作符表,如清单14-3所示。当你创建了一个操作符表之后,你要为每个你要加入到表中的回调方法调用函数 CGPDFOperatorTableSetCallback。你传入了操作表,指定PDF操作符的字符串,以及一个你编写用来处理指定操作符的回调函数的指针。你可以随意命名这些回调函数。只要确保回调函数的名字和你传入CGPDFOperatorTableSetCallback函数的名字是相同的即可。
代码清单14-3为表14-1中列出的每个标记-文本操作符 设置了一个回调方法。你的应用应该为你感兴趣的那些操作符设置回调方法。PDF操作符字符串由Adobe PDF Reference 制定。
清单 14-3 为操作表设置回调方法
CGPDFOperatorTableRef myTable; 登入後複製 |
登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
myTable = CGPDFOperatorTableCreate(); 登入後複製 |
登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
CGPDFOperatorTableSetCallback (myTable, "MP", &op_MP); 登入後複製 |
CGPDFOperatorTableSetCallback (myTable, "DP", &op_DP); 登入後複製 |
CGPDFOperatorTableSetCallback (myTable, "BMC", &op_BMC); 登入後複製 |
CGPDFOperatorTableSetCallback (myTable, "BDC", &op_BDC); 登入後複製 |
CGPDFOperatorTableSetCallback (myTable, "EMC", &op_EMC); 登入後複製 |
打开PDF文档
在你扫描PDF文档之前,你必须打开它。清单14-4 展示了 从代码中提供的URL创建一个CGPDFDocument对象的代码片段。注意此清单只是一个代码段,所以不是所有变量都定义了。此清单中用数字标注的代码行都有详细的解释。
清单 14-4 从一个URL打开一个PDF文档
CGPDFDocumentRef myDocument; 登入後複製 |
myDocument = CGPDFDocumentCreateWithURL(url);<span>// 1</span> 登入後複製 |
if (myDocument == NULL) {<span>// 2</span> 登入後複製 |
error ("can't open `%s'.", filename); 登入後複製 |
CFRelease (url); 登入後複製 |
return EXIT_FAILURE; 登入後複製 登入後複製 登入後複製 |
} 登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
CFRelease (url); 登入後複製 |
if (CGPDFDocumentIsEncrypted (myDocument)) {<span>// 3</span> 登入後複製 |
if (!CGPDFDocumentUnlockWithPassword (myDocument, "")) { 登入後複製 |
printf ("Enter password: "); 登入後複製 |
fflush (stdout); 登入後複製 |
password = fgets(buffer, sizeof(buffer), stdin); 登入後複製 |
if (password != NULL) { 登入後複製 |
buffer[strlen(buffer) - 1] = '\0'; 登入後複製 |
if (!CGPDFDocumentUnlockWithPassword (myDocument, password)) 登入後複製 |
error("invalid password."); 登入後複製 |
} 登入後複製 |
} 登入後複製 登入後複製 |
} 登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
if (!CGPDFDocumentIsUnlocked (myDocument)) {<span>// 4</span> 登入後複製 |
error("can't unlock `%s'.", filename); 登入後複製 |
CGPDFDocumentRelease(myDocument); 登入後複製 |
return EXIT_FAILURE; 登入後複製 登入後複製 登入後複製 |
} 登入後複製 登入後複製 |
} 登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
if (CGPDFDocumentGetNumberOfPages(document) == 0) {<span>// 5</span> 登入後複製 |
CGPDFDocumentRelease(document); 登入後複製 |
return EXIT_FAILURE; 登入後複製 登入後複製 登入後複製 |
} 登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
此处代码做了哪些:
1. 利用代码中提供的URL创建一个CGPDFDocument对象。
2. 检查以确保CGPDFDocument对象被创建。如果没有,代码退出,因为没有document继续执行没有意义。
3. 检查document是否加密。如果document加密,则代码试图利用空密码打开文档。如果失败,代码要求用户提供密码并试图用此密码解锁文档。
4. 检查document是否解锁,如果没有,代码退出。
5. 检查以确保document至少有一页,否则,代码退出。
扫描每页的内容流
清单14-5 代码段扫描文档每一页。当此scanner遇到一个注册了回调方法的PDF操作符,Quartz就调用此回调方法。此清单中用数字标注的代码行都有详细的解释。
清单 14-5 扫描文档的每一页
int k; 登入後複製 |
CGPDFPageRef myPage; 登入後複製 |
CGPDFScannerRef myScanner; 登入後複製 |
CGPDFContentStreamRef myContentStream; 登入後複製 |
登入後複製 登入後複製 登入後複製 登入後複製 登入後複製 |
numOfPages = CGPDFDocumentGetNumberOfPages (myDocument);<span>// 1</span> 登入後複製 |
for (k = 0; k 登入後複製 |
myPage = CGPDFDocumentGetPage (myDocument, k + 1 );<span>// 2</span> 登入後複製 |
myContentStream = CGPDFContentStreamCreateWithPage (myPage);<span>// 3</span> 登入後複製 |
myScanner = CGPDFScannerCreate (myContentStream, myTable, NULL);<span>// 4</span> 登入後複製 |
CGPDFScannerScan (myScanner);<span>// 5</span> 登入後複製 |
CGPDFPageRelease (myPage);<span>// 6</span> 登入後複製 |
CGPDFScannerRelease (myScanner);<span>// 7</span> 登入後複製 |
CGPDFContentStreamRelease (myContentStream);<span>// 8</span> 登入後複製 |
} 登入後複製 |
CGPDFOperatorTableRelease(myTable); 登入後複製 |
此处代码解释:
1. 得到你先前打开的document的页数。见“Open thePDF Document.”
2. 检索扫描一页。页数以一开始。
3. 为此页创建内容流。
4. 为内容流创建一个scanner。你必须传入先前创建且在回调方法中设置的内容流和操作表。见“Create andSet Up the Operator Table.” 你也可以传入你的回调方法中需要的任何数据。
5. 解析与scanner相关联的内容流。当Quartz每次遇到你在回调方法中提供的操作符时就会调用相应回调方法。
6. 释放 page
7. 释放 scanner
8. 释放 content stream
9. 释放 operator table 在PDF扫描完所有页之后。
原帖地址:http://blog.csdn.net/xiao_se7en/article/details/7620056

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

使用正規表示式從PHP數組中移除重複值的方法:使用正規表示式/(.*)(.+)/i匹配並取代重複項。遍歷數組元素,使用preg_match檢查匹配情況。如果匹配,請跳過值;否則,將其添加到無重複值的新數組中。

1.使用線上轉換工具,如Smallpdf、Adobe Acrobat或Zamzar。 2、這些工具通常提供簡單易用的介面,讓使用者上傳 PDF 檔案並選擇將其轉換為 Word 格式。 3.轉換完成後,使用者可以下載 Word 文件並進行進一步編輯。 4.使用專業的PDF轉換軟體,如Adobe Acrobat Pro或Wondershare PDFelement。

C語言是初學者學習程式設計的理想選擇,其優點包括效率、多功能性和可移植性。學習C語言需要:安裝C編譯器(如MinGW或Cygwin)了解變數、資料型別、條件語句和迴圈語句編寫包含主函數和printf()函數的第一個程式透過實戰案例(如計算平均數)練習C語言知識

1、程式設計可用於開發各種軟體和應用程序,包括網站、手機應用程式、遊戲和數據分析工具等。它的應用領域非常廣泛,幾乎涵蓋了所有行業,包括科學研究、醫療保健、金融、教育、娛樂等。 2.學習程式設計可以幫助我們提升問題解決能力和邏輯思考能力。在程式設計過程中,我們需要分析和理解問題,找出解決方案,並將其轉換為程式碼。這種思維方式能夠培養我們的分析和抽象能力,提升我們解決實際問題的能力。

C++程式設計謎題涵蓋斐波那契數列、階乘、漢明距離、陣列最大值和最小值等演算法和資料結構概念,透過解決這些謎題,可以鞏固C++知識,提升演算法理解和程式設計技巧。

Python透過其易學性和強大功能,是初學者的理想程式設計入門語言。其基礎包括:變數:用於儲存資料(數字、字串、列表等)。資料型態:定義變數中資料的型態(整數、浮點數等)。運算符:用於數學運算和比較。控制流程:控製程式碼執行流程(條件語句、迴圈)。

Python程式設計入門安裝Python:從官方網站下載並安裝。 HelloWorld!:使用print("HelloWorld!")列印第一行程式碼。實戰案例:計算圓面積:使用π(3.14159)和半徑計算圓面積。變數和資料類型:使用變數儲存數據,Python中的資料類型包括整數、浮點數、字串和布林值。表達式與賦值:使用運算子將變數、常數和函數連接起來,並使用賦值運算子(=)將值賦給變數。控制流程:if-else語句:根據條件執行不同的程式碼區塊,確定奇
