编译第三方开源库mupdf,实现pdf转png

  • step1: 下载SumatraPDF工程:

https://github.com/Bitterbell/Pdf-Reader
 muPdf 库是一个开源的 pdf 读取器,但是在 github 上下载的源码编译得到 muPdf.dll 比较困难。所以我们下载 SumatraPDF 这个工程,它只能用 vs2017 打开。
【注1】Pdf-Reader-master.zip 这个解压后就是 SumatraPDF。
【注2】下面的连接有 vs2008、vs2010 等的 sln 文件。
https://github.com/kzmkv/SumatraPDF

  • step2: 修改  libmupdf.def 文件,正确导出我们需要的接口。

在  libmupdf.def  文件里面加上如下的内容:

fz_register_document_handlers
fz_open_document
fz_close_document
fz_count_pages
fz_load_page
fz_bound_page
fz_run_page
fz_free_page

这些是使用example.c需要导出的函数。

  • step3: 编译 pdf-reader-master 得到动态库。

遇到错误1:
 error C2220: 警告被视为错误 - 没有生成“object”文件
解决:
属性-C/C++-将警告视为错误-是 修改为否

遇到的错误2:
LINK : error LNK1218: 警告被视为错误;未生成输出文件
解决:
属性-库管理器-将Lib警告视为错误-是 修改为否

遇到错误3:
libmupdf.def : error LNK2001: 无法解析的外部符号 fz_register_document_handlers
解决步骤:
(1)属性-链接器-输入-模块定义文件libmupdf.def
(2)找到该函数的定义文件document-all.c,将此文件添加到项目libmupdf
(3)报错:
document-all.c(1): fatal error C1083: 无法打开包括文件: “mupdf/fitz.h”: No such file or directory
遇到头文件找不到,属性-C/C++-附加包含目录中添加头文件路径
(4)报错:
1>document-all.obj : error LNK2001: 无法解析的外部符号 cbz_document_handler
1>document-all.obj : error LNK2001: 无法解析的外部符号 tiff_document_handler
1>document-all.obj : error LNK2001: 无法解析的外部符号 img_document_handler
分别找到这三个函数的实现文件mucbz.c,mutiff.c,muimage.c,然后添加到项目libmupdf。

  • setp4:使用编译得到的动态库。

以release64为例说明:
(1)新建空项目,将mupdf\include,mupdf\docs\example.c,Pdf-Reader-master\rel64\libmupdf.lib,Pdf-Reader-master\rel64\libmupdf.dll
拷贝到项目中。
(2)添加源文件example.c,重命名为example.cpp,修改两处
第一处:
extern "C"
{
    // Include the MuPDF header file.
    #include
}
第二处:
render(char *filename, int pagenumber, int zoom, int rotation)函数前加入
#ifdef __cplusplus    
extern "C" {
#endif

函数后加入

#ifdef __cplusplus
}
#endif

修改之后的example.cpp:

// Rendering a page of a PDF document to a PNG image in less than 100 lines.

// Compile a debug build of mupdf, then compile and run this example:
//
// gcc -g -o build/debug/example -Iinclude docs/example.c \
//	build/debug/libmupdf.a \
//	build/debug/libfreetype.a build/debug/libjbig2dec.a \
//	build/debug/libjpeg.a build/debug/libopenjpeg.a \
//	build/debug/libmujs.a \
//	build/debug/libz.a -lm
//
// build/debug/example /path/to/document.pdf 1 200 25

extern "C"
{
	// Include the MuPDF header file.
	#include 
}

#ifdef __cplusplus    
extern "C" {
#endif

void
render(char *filename, int pagenumber, int zoom, int rotation)
{
	// Create a context to hold the exception stack and various caches.

	fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);

	// Register the default file types.

	fz_register_document_handlers(ctx);

	// Open the PDF, XPS or CBZ document.

	fz_document *doc = fz_open_document(ctx, filename);

	// Retrieve the number of pages (not used in this example).

	int pagecount = fz_count_pages(doc);

	// Load the page we want. Page numbering starts from zero.

	fz_page *page = fz_load_page(doc, pagenumber - 1);

	// Calculate a transform to use when rendering. This transform
	// contains the scale and rotation. Convert zoom percentage to a
	// scaling factor. Without scaling the resolution is 72 dpi.

	fz_matrix transform;
	fz_rotate(&transform, rotation);
	fz_pre_scale(&transform, zoom / 100.0f, zoom / 100.0f);

	// Take the page bounds and transform them by the same matrix that
	// we will use to render the page.

	fz_rect bounds;
	fz_bound_page(doc, page, &bounds);
	fz_transform_rect(&bounds, &transform);

	// Create a blank pixmap to hold the result of rendering. The
	// pixmap bounds used here are the same as the transformed page
	// bounds, so it will contain the entire page. The page coordinate
	// space has the origin at the top left corner and the x axis
	// extends to the right and the y axis extends down.

	fz_irect bbox;
	fz_round_rect(&bbox, &bounds);
	fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
	fz_clear_pixmap_with_value(ctx, pix, 0xff);

	// A page consists of a series of objects (text, line art, images,
	// gradients). These objects are passed to a device when the
	// interpreter runs the page. There are several devices, used for
	// different purposes:
	//
	//	draw device -- renders objects to a target pixmap.
	//
	//	text device -- extracts the text in reading order with styling
	//	information. This text can be used to provide text search.
	//
	//	list device -- records the graphic objects in a list that can
	//	be played back through another device. This is useful if you
	//	need to run the same page through multiple devices, without
	//	the overhead of parsing the page each time.

	// Create a draw device with the pixmap as its target.
	// Run the page with the transform.

	fz_device *dev = fz_new_draw_device(ctx, pix);
	fz_run_page(doc, page, dev, &transform, NULL);
	fz_free_device(dev);

	// Save the pixmap to a file.

	fz_write_png(ctx, pix, "out.png", 0);

	// Clean up.

	fz_drop_pixmap(ctx, pix);
	fz_free_page(doc, page);
	fz_close_document(doc);
	fz_free_context(ctx);
}

#ifdef __cplusplus
}
#endif

int main(int argc, char **argv)
{
	//char *filename = argc >= 2 ? argv[1] : "";
	//int pagenumber = argc > 2 ? atoi(argv[2]) : 1;
	//int zoom = argc > 3 ? atoi(argv[3]) : 100;
	//int rotation = argc > 4 ? atoi(argv[4]) : 0;

	char *filename = "1.pdf";
	int pagenumber = 1;
	int zoom = 100;
	int rotation = 0;

	render(filename, pagenumber, zoom, rotation);

	getchar();
	return 0;
}

(3)在release64属性管理器下添加新属性表VS2017MupdfRelease64.props
VC++目录-包含目录添加.\include
链接器-常规-附加库目录.\lib\rel64 (注意这两个文件夹是需要自己新建,将Pdf-Reader-master\rel64\libmupdf.lib放入这个目录下)
链接器-输入-附加依赖项libmupdf.lib

编译报错:
无法将参数 2 从“const char [71]”转换为“char *”
解决:
C/C++-命令行-其他选项 添加 /Zc:strictStrings- 

编译成功。

(4)将Pdf-Reader-master\rel64\libmupdf.dll移动到exe所在文件夹,即可正常运行
命令行参数配置参考文件中的提示即可。我是修改为指定参数,不从命令行参数中获取。


参考博客:

https://blog.csdn.net/jiangdewei2012/article/details/80748650

 

  • 其他

程序运行时会在控制台打印:- font.c:63: not building glyph bbox table for font '瀹嬩綋' with 28762 glyphs
warning: ... repeated 2 times ...

因为项目要求不能在控制台打印无关信息,所以打算编译把这个打印去掉。

找到font.c,注释掉Line62,63

		//if (use_glyph_bbox)
		//	fz_warn(ctx, "not building glyph bbox table for font '%s' with %d glyphs", font->name, glyph_count);

然后重新编译即可。

你可能感兴趣的:(工具)