PDF转图片

news/2024/11/17 2:28:43/

      前段时间开发一个项目,需要用到PDF转图片,并在MFC开发界面中显示图片。经过google,找到几个可用的方法,分别是GhostScript、imageMagic和MuPDF,由于使用MFC做界面开发,因此需要在VC++中使用。

      首先用到的是GhostScript,网络上有一些C#的使用方法,如下面的链接:

      http://www.codeproject.com/Articles/317700/Convert-a-PDF-into-a-series-of-images-using-Csharp

      http://www.codeproject.com/Articles/32274/How-To-Convert-PDF-to-Image-Using-Ghostscript-API

      http://blog.csdn.net/ljsspace/article/details/6530046

      参考以上的方法,可以在VC++中使用GhostScript的gsdll32.dll(在ghostscript的安装路径下可以找到)把PDF转为图片,但实际使用中会遇到一些问题,某些PDF转为图片后长宽比例出现错误,顶部和底部会出现额外的白边,用GhostScript去显示这些PDF,显示效果也一样会出现同样的问题。改用imageMagic去打开PDF,显示效果一样,顶部和底部也会出现额外的白边。我猜测两个软件使用了相同的算法,或者使用了同一个库。

      后来我改用MuPDF,PDF转图片的效果非常好,而且速度比GhostScript更快。

      同样,在codeproject上有C#的使用方法:http://www.codeproject.com/Articles/498317/Rendering-PDF-Documents-with-Mupdf-and-P-Invoke-in

      英文不好的朋友,可以看这里,有人把文章翻译并提出了自己的见解:http://www.cnblogs.com/pdfpatcher/archive/2012/11/25/2785154.html

      由于我是使用C++,对于c开源库的MuPDF来说,使用起来更直接方便。接下来重点介绍一下MuPDF转图片的方法。

      获得MuPDF开源库,如果去官方下载MuPDF,编译后是一些exe及静态链接库,地址在这里:http://code.google.com/p/mupdf/downloads/list

      很幸运,我们还是能方便能找到动态链接库,有人已经把MuPDF集成到另外一个开源的sumatrapdf中,在下面的地址下载,编译后,在obj-dbg文件夹下可以找到libmupdf.dll、libmupdf.lib、fitz.h。下载地址:http://code.google.com/p/sumatrapdf/downloads/list 

      为了方便大家下载DLL,我贴出CSDN下载地址,不需要积分可下载:http://download.csdn.net/detail/arthurfangmc/4948658

      具体怎么要用哪些函数,及函数的介绍,我就不再重复介绍,上面2篇文章都做了介绍,我直接贴出几个重要的代码。

      我的代码直接从MuPDF源代码中修改而来,写了一个简单的类,变量名基本上没改,成员变量没有改成类似“myValue”或“m_value”,大家随便看看吧。

 

MuPDFConvert.h:

#ifndef MY_MUPDF_CONVERT_PDF_PNG
#define MY_MUPDF_CONVERT_PDF_PNGextern "C" 
{
#include "mupdf/fitz.h"
#include "mupdf/fitz-internal.h"
}class CMuPDFConvert
{
public:CMuPDFConvert(void);~CMuPDFConvert(void);bool Pdf2Png(const wchar_t* pdfFileName/*,const char* imageOutputPath*/,const char* imageName, int &pageNum);private:void drawpage(fz_context *ctx, fz_document *doc, int pagenum);private:static const fz_matrix fz_identity;static fz_colorspace k_device_rgb;fz_colorspace *fz_device_rgb;fz_document *m_doc;fz_stream *m_pStream;fz_context *m_ctx;int uselist;int alphabits;char output[1024];float resolution;float rotation;int res_specified;int width;int height;int fit;fz_colorspace *colorspace;int savealpha;int invert;float gamma_value;char filename[1024];
};#endif

 

MuPDFConvert.cpp:

#include "StdAfx.h"
#include "MuPDFConvert.h"void fz_free_colorspace_imp(fz_context *ctx, fz_storable *cs_)
{fz_colorspace *cs = (fz_colorspace *)cs_;if (cs->free_data && cs->data)cs->free_data(ctx, cs);fz_free(ctx, cs);
}static void rgb_to_rgb(fz_context *ctx, fz_colorspace *cs, float *rgb, float *xyz)
{xyz[0] = rgb[0];xyz[1] = rgb[1];xyz[2] = rgb[2];
}const fz_matrix CMuPDFConvert::fz_identity = { 1, 0, 0, 1, 0, 0 };
fz_colorspace CMuPDFConvert::k_device_rgb = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb };CMuPDFConvert::CMuPDFConvert(void)
{fz_device_rgb = &k_device_rgb;uselist = 1;alphabits = 8;//output = NULL;resolution = 72;rotation = 0;res_specified = 0;width = 0;height = 0;fit = 0;colorspace = NULL;savealpha = 0;invert = 0;gamma_value = 1;m_doc = NULL;m_ctx = NULL;
}CMuPDFConvert::~CMuPDFConvert(void)
{if (m_pStream){fz_close(m_pStream);m_pStream = NULL;}if (m_doc){fz_close_document(m_doc);m_doc = NULL;}if (m_ctx){fz_free_context(m_ctx);m_ctx = NULL;}}bool CMuPDFConvert::Pdf2Png(const wchar_t* wcharPdfFile/*,const char* imageOutputPath*/,const char* imageName, int &pageNum)
{char tempPath[1024];//strcpy_s(tempPath, imageOutputPath);//strcat_s(tempPath, imageName);strcpy_s(tempPath, imageName);strcat_s(tempPath, "%d.png");strcpy_s(output, (strlen(tempPath)+1)*sizeof(char), tempPath);m_ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);if (!m_ctx){
#if _DEBUGfprintf(stderr, "mupdf cannot initialise context\n");
#endifreturn false;}fz_try(m_ctx){fz_set_aa_level(m_ctx, alphabits);colorspace = fz_device_rgb;m_pStream = fz_open_file_w(m_ctx, wcharPdfFile);if (m_pStream){m_doc = fz_open_document_with_stream(m_ctx, ".pdf", m_pStream);}if (!m_doc){
#if _DEBUGfprintf(stderr, "mupdf cannot open pdf\n");
#endifreturn false;}if (fz_needs_password(m_doc)){	
#if _DEBUGfprintf(stderr, "mupdf cannot authenticate password\n");fz_throw(m_ctx, "mupdf cannot authenticate password: %s", filename);
#endifreturn false;}int pn = fz_count_pages(m_doc);pageNum = pn;for (int i=0; i<pn; ++i){fz_page *page = fz_load_page(m_doc, i);fz_rect bound = fz_bound_page(m_doc, page);//PDF-->PNGdrawpage(m_ctx, m_doc, i+1);fz_free_page(m_doc, page);page = NULL;}	}fz_catch(m_ctx){return false;}if (m_pStream){fz_close(m_pStream);m_pStream = NULL;}if (m_doc){fz_close_document(m_doc);m_doc = NULL;}if (m_ctx){fz_free_context(m_ctx);m_ctx = NULL;}return true;
}void CMuPDFConvert::drawpage(fz_context *ctx, fz_document *doc, int pagenum)
{fz_page *page;fz_display_list *list = NULL;fz_device *dev = NULL;int start;fz_var(list);fz_var(dev);fz_try(ctx){page = fz_load_page(doc, pagenum - 1);}fz_catch(ctx){fz_throw(ctx, "cannot load page %d in file '%s'", pagenum, filename);}if (uselist){fz_try(ctx){list = fz_new_display_list(ctx);dev = fz_new_list_device(ctx, list);fz_run_page(doc, page, dev, fz_identity, NULL);}fz_catch(ctx){fz_free_device(dev);fz_free_display_list(ctx, list);fz_free_page(doc, page);fz_throw(ctx, "cannot draw page %d in file '%s'", pagenum, filename);}fz_free_device(dev);dev = NULL;}if (output){float zoom;fz_matrix ctm;fz_rect bounds, bounds2;fz_bbox bbox;fz_pixmap *pix = NULL;int w, h;fz_var(pix);bounds = fz_bound_page(doc, page);zoom = resolution / 72;ctm = fz_scale(zoom, zoom);ctm = fz_concat(ctm, fz_rotate(rotation));bounds2 = fz_transform_rect(ctm, bounds);bbox = fz_round_rect(bounds2);/* Make local copies of our width/height */w = width;h = height;/* If a resolution is specified, check to see whether w/h are* exceeded; if not, unset them. */if (res_specified){int t;t = bbox.x1 - bbox.x0;if (w && t <= w)w = 0;t = bbox.y1 - bbox.y0;if (h && t <= h)h = 0;}/* Now w or h will be 0 unless then need to be enforced. */if (w || h){float scalex = w/(bounds2.x1-bounds2.x0);float scaley = h/(bounds2.y1-bounds2.y0);if (fit){if (w == 0)scalex = 1.0f;if (h == 0)scaley = 1.0f;}else{if (w == 0)scalex = scaley;if (h == 0)scaley = scalex;}if (!fit){if (scalex > scaley)scalex = scaley;elsescaley = scalex;}ctm = fz_concat(ctm, fz_scale(scalex, scaley));bounds2 = fz_transform_rect(ctm, bounds);}bbox = fz_round_rect(bounds2);/* TODO: banded rendering and multi-page ppm */fz_try(ctx){pix = fz_new_pixmap_with_bbox(ctx, colorspace, bbox);if (savealpha)fz_clear_pixmap(ctx, pix);elsefz_clear_pixmap_with_value(ctx, pix, 255);dev = fz_new_draw_device(ctx, pix);if (list)fz_run_display_list(list, dev, ctm, bbox, NULL);elsefz_run_page(doc, page, dev, ctm, NULL);fz_free_device(dev);dev = NULL;if (invert)fz_invert_pixmap(ctx, pix);if (gamma_value != 1)fz_gamma_pixmap(ctx, pix, gamma_value);if (savealpha)fz_unmultiply_pixmap(ctx, pix);if (output){char buf[512];sprintf(buf, output, pagenum);if (strstr(output, ".png")){fz_write_png(ctx, pix, buf, savealpha);}}fz_drop_pixmap(ctx, pix);}fz_catch(ctx){fz_free_device(dev);fz_drop_pixmap(ctx, pix);fz_free_display_list(ctx, list);fz_free_page(doc, page);fz_rethrow(ctx);}}if (list)fz_free_display_list(ctx, list);fz_free_page(doc, page);fz_flush_warnings(ctx);
}

 

使用方法:

 

#include "stdafx.h"
#include "MuPDFConvert.h"int _tmain(int argc, _TCHAR* argv[])
{CMuPDFConvert pdfConvert;int nNum = 0;pdfConvert.Pdf2Png(L"test.pdf", "test", nNum);return 0;
}


      这里生成的图片是PNG格式,如果你需要其他格式的图片,可以再选择其它库,如果编译器版本支持CImage,可以使用CImage来转其它图片格式,

 

 

 

另外,在MFC中可以直接使用CImage来显示PNG及其它格式图片,使用方法非常简单。

 

定义一个变量

CImage m_img;

导入图片

 
if(!m_img.IsNull()) 
{	m_img.Destroy();
}
m_img.Load(strImagePath); 

在OnPaint()函数中:

if(!m_img.IsNull()) 
{ CPaintDC dc(GetDlgItem(IDC_CHILD_PIC));        dc.SetStretchBltMode(HALFTONE);m_img.Draw(dc.m_hDC, 0, 0, m_nFitWidth, m_nFitHeight, 0, 0, m_nRegionWidth, m_nRegionHeight);//透明显示PNG图片//m_img.TransparentBlt(dc.m_hDC, 0, 0, m_nFitWidth, m_nFitHeight, //						0, 0, m_nRegionWidth, m_nRegionHeight, RGB(255,255,255));
}

 

      使用过程中,PDF转图片还是需要花费一定的时间,如果你需要实时显示图片,而PDF页数又非常多,最好另开一个线程来做PDF转图片的工作。ghostScript和MuPDF我都在项目中使用过,PDF页数很多或者图片分辨率很大的时候,MuPDF的速度优势还是十分明显的。

 

附PDF转PNG图片下载代码

https://download.csdn.net/download/ArthurFangmc/12718742

 


http://www.ppmy.cn/news/440080.html

相关文章

如何编辑修改PDF文件的内容?

PDF是我们在生活和工作中经常接触到的格式文件&#xff0c;但需要编辑内容时&#xff0c;很多人却无从下手&#xff0c;下面来具体说说如何编辑修改PDF文件。 首先&#xff0c;我们要知道PDF文件分两种格式&#xff0c;一种是扫描或者照片转成的PDF&#xff0c;它本质就是一张…

如何用PDF编辑器编辑、修改PDF文本和图片?

作为编辑PDF必不可少的软件&#xff0c;PDF编辑器随着PDF应用越来越广泛&#xff0c;被人们逐渐熟悉。使用PDF编辑器修改文字内容属于PDF编辑的一项功能&#xff0c;通常来说需要分两种情况对待&#xff0c;一种是PDF中的文字是文本&#xff0c;另一种是PDF中的文字是图片。金闪…

怎么使用PDF编辑器在PDF中插入图片?PDF插入图片的教程

怎么使用PDF编辑器在PDF中插入图片&#xff1f;可能很多人对PDF还停留在只能阅读的认知上&#xff0c;但是随着PDF使用范围的越来越广泛&#xff0c;人们对PDF功能的需求越来越高&#xff0c;PDF工具的功能也越来越多样化&#xff0c;不仅可以在阅读PDF文件的时候可以像在阅读纸…

Acrobat Pro DC 教程:如何编辑 PDF 文件中的文本和图片?

欢迎观看 Acrobat Pro DC 教程&#xff0c;小编带大家学习 Acrobat Pro DC 的基本工具和使用技巧&#xff0c;了解如何使用 Acrobat Pro DC 轻松快捷地编辑PDF 文档中的文本和图片。 打开 Acrobat Pro DC&#xff0c;在「工具」面板中选择「编辑PDF」工具。 点击「选择文件」按…

Web安全信息收集之CMS指纹识别

1、CMS指纹识别 CMS(内容管理系统),又称整站系统或文章系统网站内容管理。用户只需要下载对应的CMS软 件包,部署搭建,就可以直接利用CMS,简单方便。但是各种CMS都具有其独特的结构命名规则和定 的文件内容,因此可以利用这些内容来获取CMS站点的具体软件CMS与版本 常见CMs: …

定风量与变风量空调系统区别

最小新风量 空调系统分类 定风量与变风量 定风量空调系统与变风量空调系统有什么区别 1、定风量空调系统描述 定风量空调系统的特点是改变送风量来满足室内冷&#xff08;热&#xff09;负荷的变化。系统向室内送入冷&#xff08;热&#xff09;风&#xff0c;送入室内的冷&am…

k8s 部署zookeeper-kafka,nfs作为存储

目录 备注&#xff1a;nfs存储参考链接 一、zk镜像拉取并制作为自己镜像 二、编辑zookeeper.yaml文件 三、安装zk并检查状态 四、验证zookeeper集群可用性 五、制作对应版本的kafka镜像 六、编辑kafka.yaml文件 七、创建kafka并查看状态 八、zk与kafka连通性查看 九…

PHP+SQL考勤系统安全性实现(源代码+论文+答辩PPT+指导书)

第一章 概 述 1.1 PHP的概念 PHP: Hypertext Preprocessor (超文本预处理器) 的缩写,它是一种服务器端的 HTML 脚本/编程语言,是一种简单的、面向对象的、解释型的、健壮的、安全的、性能非常之高的、独立于架构的、可移植的、动态的脚本语言 PHP是一种功能强大的脚本语言…