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
在 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需要导出的函数。
遇到错误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。
以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);
然后重新编译即可。