macOS 幻灯片转图片研究报告

Posted by CoderLeonidas on March 12, 2020

macOS 幻灯片转图片研究报告

主流程序

  • macOS: Keynote、Powerpoint、OpenOffice for Mac
  • windows: Powerpoint、OpenOffice for Windows

OpenOffice.org 是Apache的一套跨平台的办公室软件套件,能在Windows、Linux、MacOS X (X11)和 Solaris 等操作系统上执行。它与各个主要的办公室软件套件兼容。OpenOffice.org 是自由软件,任何人都可以免费下载、使用及推广它。

文件格式

slides format | Application to open it ——| ——– .key | Keynote .ppt | Powerpoint、Keynote .pptx | Powerpoint、Keynote .pptm | Powerpoint、Keynote .ppsx | Powerpoint、Keynote .ppsm | Powerpoint、Keynote .pps | Powerpoint、Keynote .potx | Powerpoint、Keynote .potm | Powerpoint、Keynote .pot | Powerpoint、Keynote .odp | Powerpoint、Keynote

可见,幻灯片文件格式除了主流的key、ppt、pptx外,还有许多其他不常见的格式。

思路分析

Applescript

Keynote和Powerpoint支持将幻灯片导出成多种格式,包涵PDF、HTML、图片等。可以借助Applescript来进行转换。

幻灯片解析

要转换幻灯片为图片,很重要一点是获取到幻灯片的尺寸页数。 幻灯片文件的本质是一个HTML的压缩包。 猜想可能有原生的库或者通过WebView可以进行幻灯片的解析。

Quicklook

苹果的Quicklook原生就支持对大部分文件的预览,包括.key 、.ppt、 .pptx格式的幻灯片。猜想Quicklook应该会提供能生成预览图片的API。

幻灯片-> PDF-> 图片

幻灯片格式众多,并且都不平台通用的标准文件格式; PDF是一种平台通用的标准文件格式。苹果对PDF的操作开放了PDFKit等框架和接口,能很好地解析PDF并生成图片。因此如果能有方法将幻灯片先转化为PDF,再操作PDF转成图片也是一种网上公认的方式。 但是,其中幻灯片转PDF的操作大部分大部分公司都在后端进行,类似于一些在线转换工具:pptx-to-pdf

因此寻求方案时需要考虑的重点是:

  • 能否直接生成图片
  • 能否生成pdf,然后做二次解析
  • 能否生成html,然后做二次解析

需求

理想的方案应达到以下要求:

  • 良好的图片质量
  • 对其他进程没有依赖
  • 没有过多的要求用户授权
  • 不静默下载其他库或app
  • 尽可能不产生中间文件
  • 良好的转换效率

研究过的方案

1. Cocoa原生解析库

目前Cocoa没有针对幻灯片的原生解析库。

2. QuickLook

QuickLook对于带有图片和文本的复杂文档的预览,底层是将其转化为一个HTML,来进行动态预览。同时在QuickLook插件开发的API中,提供了在当前预览上下文中绘制PDF的API:

1
2
3
4
5
QL_EXPORT CGContextRef QLPreviewRequestCreatePDFContext(QLPreviewRequestRef preview,
                                                        const CGRect * mediaBox,
                                                        CFDictionaryRef auxiliaryInfo,
                                                        CFDictionaryRef properties);

这个API会创建换一个PDF的上下文,并将预览结果绘制其中,非常适合多页文档的预览。

但是这个API的使用场景是在下面的回调函数中进行调用:

1
2
3
4
5
6
7
8
OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
{
			CGRect rect = CGRectMake(0, 0, width, height);
			CGContextRef c;
			c = QLPreviewRequestCreatePDFContext(preview, &rect, NULL, NULL)
return noErr;
}

参数中的preview、需要从外部传入,无法自己手工设置,也就是说这个API只能在GeneratePreviewForURL 回调函数中调用。因此只用QuickLook无法完成转换功能。(详见Seamlessly converting any type of document to PDF?

3 WebView

iOS的UIWebView能很好的解析并加载出幻灯片,并在代理方法中- (void)webViewDidFinishLoad:(UIWebView *)_webView中获取到HTML内容,并解析出尺寸和页数。

不幸的是,macOS的WebView和WKWebView却不行。macOS的WebView和WKWebView可以正常加载HTML、png、pdf等常规类型的文件,但是不能加载出ppt、pptx和key文件。(详见:WKWebview not rendering .doc file but renders pdf/png/jpeg?)

4. Applescript

苹果的app和微软Office的app都对Applescript有很好的支持。使用简单的脚本语言就能导出成图片,并且图片质量很好。

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
property exportFormat : "PNG" -- "TIFF" "JPEG" "PNG"
property includeSkippedSlides : false
property compressionFactor : 1.0

-- THE DESTINATION FOLDER 
-- (see the "path" to command in the Standard Additions dictionary for other locations, such as documents folder, movies folder, desktop folder)
set the defaultDestinationFolder to (path to pictures folder)

tell application "Keynote"
	activate
	try
		if playing is true then tell the front document to stop
		
		if not (exists document 1) then error number -128
		
		-- DERIVE NAME FOR NEW FOLDER FROM NAME OF THE FRONT DOCUMENT
		set documentName to the name of the front document
		if documentName ends with ".key" then ¬
			set documentName to text 1 thru -5 of documentName
		
		-- CREATE AN EXPORT DESTINATION FOLDER
		-- IMPORTANT: IT’S ADVISED TO ALWAYS CREATE A NEW DESTINATION FOLDER, AS THE CONTENTS OF ANY TARGETED FOLDER WILL BE OVERWRITTEN
		tell application "Finder"
			set newFolderName to documentName
			set incrementIndex to 1
			repeat until not (exists folder newFolderName of defaultDestinationFolder)
				set newFolderName to documentName & "-" & (incrementIndex as string)
				set incrementIndex to incrementIndex + 1
			end repeat
			set the targetFolder to ¬
				make new folder at defaultDestinationFolder with properties ¬
					{name:newFolderName}
			set the targetFolderHFSPath to targetFolder as string
		end tell
		
		-- EXPORT THE DOCUMENT
		if exportFormat is "PNG" then
			-- EXPORT THE FRONT DOCUMENT TO PNG IMAGES
			export front document as slide images to file targetFolderHFSPath with properties ¬
				{image format:PNG, skipped slides:includeSkippedSlides}
		else if exportFormat is "JPEG" then
			-- EXPORT THE FRONT DOCUMENT TO JPEG IMAGES
			export front document as slide images to file targetFolderHFSPath with properties ¬
				{image format:JPEG, skipped slides:includeSkippedSlides ¬
					, compression factor:compressionFactor}
		else if exportFormat is "TIFF" then
			-- EXPORT THE FRONT DOCUMENT TO TIFF IMAGES
			export front document as slide images to file targetFolderHFSPath with properties ¬
				{image format:TIFF, skipped slides:includeSkippedSlides ¬
					, compression factor:compressionFactor}
		end if
	on error errorMessage number errorNumber
		display alert "EXPORT PROBLEM" message errorMessage
		error number -128
	end try
	
	close documentName
end tell

-- OPEN THE DESTINATION FOLDER
tell application "Finder"
	activate
	open the targetFolder
end tell

不幸的是,Applescript的执行会要求用户已安装Keynote或者PowerPoint。并且启动Keynote或者PowerPoint来完成导出成图片的操作。并且启动程序时,程序会打开文档,此时文档窗口一定会出现在用户眼前。即使可以在Applescript代码中设置将窗口隐藏或者改变窗口位置到屏幕外,但是只要执行到openexport 的操作时,窗口又会出现在用户面前,无法实现用户无感的图片转换。

5 Automater

Automater有GUI也有编程接口。早期Automater的Library中,支持很多的app和action,其中就包涵了文件export、save as的action。并且从网上资料得知,Automater可以实现让程序窗口不显示。然而,当前版本的Automater功能已经大大阉割,不仅支持的程序更少了,现在只支持苹果自带的app,并且支持的action也更少了,已经无法找到export和save as 的action。

如图,Automater的Library中只能找到苹果的Keynote(Powerpoint无法在Automater中操作了)。并且支持的action非常有限。

而早期的Automator是支持export的(详见Keynote & Automator: The “Export Presentation” Action

6. qlmange + webview

苹果自带一个qlmange 命令,它是苹果QuickLook体系的一部分。这个命令有个参数-o,可以将预览生成的文件输出到其他地方。实验发现,对于幻灯片生成的预览文件,最终是一个名为Preview.html的文件及其所包含的附件图片,如图:

而获得了html文件,就能走正常的webview解析的流程了。

但是本方案有几个问题:

  • 生成了中间文件
  • QuickLook对ppt和pptx的部分元素解析效果不好,比如页码等。最终生成的html展示出来会有元素的丢失。
  • macOS的webview本身没有scrollview的操作接口,需要自己去精确的计算webview的滚动,以生成尺寸正确的图片。

7. unoconv命令

是一个命令,意思是Universal Office Converter , 可将LibreOffice支持的任何文档格式转换为LibreOffice可以导出的任何文档格式。其中就包涵了幻灯片到图片的转换,非常强大。可惜的是,这个命令需要安装,并且要求用户安装LibreOffice 或者 OpenOffice。 详见unoconv

8. CUPS虚拟打印机

这种方案是在本机安装一个CUPS-PDF虚拟打印机。安装完后能在Keynote或PowerPoint中通过脚本的方式选择虚拟打印机,最终将幻灯片通过虚拟打印机生成一个PDF。但这种方式必须安装CUPS GhostScript ,且虚拟打印机在安装过程中会涉及到各种权限问题(获取超级用户权限)。

详见Printing with CUPS

9. 开源库

网上有众多优秀的C++开源库,可以将Office转换成PDF,比如PDFTron。但是这种方式就引入了外部的三方框架,维护麻烦,且会大大增加程序包体积。

详见Convert Office documents (Excel word PowerPoint) to PDF using C++

当前可行方案

经过多方讨论,认为涉及到以下几点的方案绝对不可行:

  • 需要下载其他app或库
  • 需要超级用户权限
  • 导致程序包体积过多的增大

因此方案中的Applescript和qlmange+webview 这2个方案,是当前勉为其难可以实现功能的方案。

综合考虑用户Keynote或者PowerPoint的安装情况、生成图片质量等,现有的综合方案是:

  • 1 用户是否安装keynote,若是则使用针对keynote的Applescript;若否,则2
  • 2 用户是否安装PowerPoint,若是则使用针对PowerPoint的Applescript;若否,则3
  • 3 使用qlmange+webview,纯OC代码实现转换

同时,这种方案注意点如下:

  1. 尽量做到无感转换
  2. 生成的中间文件需要在合适的地方保存,并在合适的时机删除
  3. webview的滚动需要精确计算以确保图片和幻灯片的尺寸是一致的

参考文章

Seamlessly converting any type of document to PDF?

PPTX to JPG

Cocoa API to extract data from a Microsoft PowerPoint presentation

Creating the Previews of MS Office Files like word excel and PPT in cocoa

How to get a Quick Look preview as an NSImage

QuickLook Previews for Microsoft Office Files

Convert PDF pages to images with COCOA

关于PPT转图片的问题需要注意的问题

Convert-ppt-to-pdf

How to Generate PDF using HTML Templates and UIPrintPageRenderer in iOS

Displaying PowerPoint Slides in Objective-C

IOS library to convert powerpoint presentations into images

convert powerpoint and keynote file to set of images

Print to PDF with AppleScript and Microsoft Word

Programming a Filter/Backend to ‘Print to PDF’ with CUPS from any Mac OS X application

Quick Look Programming Guide

WKWebview not rendering .doc file but renders pdf/png/jpeg?

WKWebView: Unable to render MS Word documents

常见 MIME 类型列表

Install unoconv on Mac OSX

Convert Office documents (Excel word PowerPoint) to PDF using C++