0

0

Quartz 2D编程指南(14)

php中文网

php中文网

发布时间:2016-06-07 15:15:36

|

1213人浏览过

|

来源于php中文网

原创

咳咳。。。。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文件。

 Quartz 2D编程指南(14)

你可以通过访问PDF的元数据获得更多有用的信息。图14-1只是一个示例。例如,您可以通过使用图14-1中的代码检查一个PDF是否有缩略图(见图14-2)。

 

清单  14-1  得到PDF的缩略视图

@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@

Quartz为你执行了所有数据流的解密和解密工作。

 

图 14-2  缩略图片

Quartz 2D编程指南(14) 

Quartz提供了很多的功能,您可以使用它来获得PDF的元数据中对应项的指定值。例如,您使用函数CGPDFObjectGetValue传入一个CGPDFObjectRef,和一个PDF对象类型(kCGPDFObjectTypeBooleankCGPDFObjectTypeInteger, 等等),以及一个存储值的存储空间。返回时,此存储空间就被得到的值填充了。

 

还有很多其他的函数可以用来遍历PDF文件的层次结构来访问各个节点和他们的子节点。例如,CGPDFArray函数(CGPDFArrayGetBooleanCGPDFArrayGet DictionaryCGPDFArrayGetInteger,等等)  允许您访问数组的值,以检索特定类型的值。你可以通过阅读阅读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

标志着一个以BMCBDC

 

为操作符编写回调方法

当Quartz调用你的PDF操作符的回调方法时,它通过你的回调方法传递了一个CGPDFScanner对象和一个指向任何必要信息的指针。通常,你的回调方法检索任何与操作符相关联的项。例如,在14-2所展示的清单中对应于MP操作符的回调方法调用了CGPDFScannerPopName函数从堆栈中检索与操作符相关联的字符串。如果清单中的代码成功的从scanner栈中检索出name,就打印出来。

Quartz有各式各样的CGPDFScannerPop函数用于检索objects,Boolean values, names, numbers, strings, arrays, dictionaries, and streams.每个函数都返回一个布尔值表明是否成功检索了该项。

 

清单14-2 MP操作符的回调方法

@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@


创建并设置操作表 

一个CGPDFOperatorTable对象存储了你编写的PDF操作符回调函数。函数CGPDFOperatorTableCreate创建了一个操作符表,如清单14-3所示。当你创建了一个操作符表之后,你要为每个你要加入到表中的回调方法调用函数 CGPDFOperatorTableSetCallback你传入了操作表,指定PDF操作符的字符串,以及一个你编写用来处理指定操作符的回调函数的指针。你可以随意命名这些回调函数。只要确保回调函数的名字和你传入CGPDFOperatorTableSetCallback函数的名字是相同的即可。

 

代码清单14-3为表14-1中列出的每个标记-文本操作符 设置了一个回调方法。你的应用应该为你感兴趣的那些操作符设置回调方法。PDF操作符字符串由Adobe PDF Reference 制定。


清单 14-3 为操作表设置回调方法

@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@



打开PDF文档
 

在你扫描PDF文档之前,你必须打开它。清单14-4 展示了 从代码中提供的URL创建一个CGPDFDocument对象的代码片段。注意此清单只是一个代码段,所以不是所有变量都定义了。此清单中用数字标注的代码行都有详细的解释。

 

清单 14-4 从一个URL打开一个PDF文档


@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@

此处代码做了哪些: 

1. 利用代码中提供的URL创建一个CGPDFDocument对象。

2. 检查以确保CGPDFDocument对象被创建。如果没有,代码退出,因为没有document继续执行没有意义。

3. 检查document是否加密。如果document加密,则代码试图利用空密码打开文档。如果失败,代码要求用户提供密码并试图用此密码解锁文档。

4. 检查document是否解锁,如果没有,代码退出。

5. 检查以确保document至少有一页,否则,代码退出。

 

 

扫描每页的内容流

清单14-5 代码段扫描文档每一页。当此scanner遇到一个注册了回调方法的PDF操作符,Quartz就调用此回调方法。此清单中用数字标注的代码行都有详细的解释。

清单 14-5  扫描文档的每一页

@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@
@@######@@

此处代码解释: 

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
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);
static void
op_MP (CGPDFScannerRef s, void *info)
{
    const char *name;
 
    if (!CGPDFScannerPopName(s, &name))
        return;
 
    printf("MP /%s\n", name);
}
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);
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL(url);// 1
if (myDocument == NULL) {// 2
        error ("can't open `%s'.", filename);
        CFRelease (url);
        return EXIT_FAILURE;
}
CFRelease (url);
if (CGPDFDocumentIsEncrypted (myDocument)) {// 3
    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)) {// 4
        error("can't unlock `%s'.", filename);
        CGPDFDocumentRelease(myDocument);
        return EXIT_FAILURE;
    }
}
 if (CGPDFDocumentGetNumberOfPages(document) == 0) {// 5
        CGPDFDocumentRelease(document);
        return EXIT_FAILURE;
}
int k;
CGPDFPageRef myPage;
CGPDFScannerRef myScanner;
CGPDFContentStreamRef myContentStream;
 
numOfPages = CGPDFDocumentGetNumberOfPages (myDocument);// 1
for (k = 0; k < numOfPages; k++) {
    myPage = CGPDFDocumentGetPage (myDocument, k + 1 );// 2
    myContentStream = CGPDFContentStreamCreateWithPage (myPage);// 3
    myScanner = CGPDFScannerCreate (myContentStream, myTable, NULL);// 4
    CGPDFScannerScan (myScanner);// 5
    CGPDFPageRelease (myPage);// 6
    CGPDFScannerRelease (myScanner);// 7
    CGPDFContentStreamRelease (myContentStream);// 8
 }
 CGPDFOperatorTableRelease(myTable);

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Node.js 教程
Node.js 教程

共57课时 | 9.8万人学习

CSS3 教程
CSS3 教程

共18课时 | 5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号