码迷,mamicode.com
首页 > 其他好文 > 详细

PDF转图片

时间:2015-11-05 17:01:02      阅读:1556      评论:0      收藏:0      [点我收藏+]

标签:

 首先用到的是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_PNG

extern "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 _DEBUG
  fprintf(stderr, "mupdf cannot initialise context\n");
#endif
  return 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 _DEBUG
   fprintf(stderr, "mupdf cannot open pdf\n");
#endif
   return false;
  }
  if (fz_needs_password(m_doc))
  { 
#if _DEBUG
   fprintf(stderr, "mupdf cannot authenticate password\n");
   fz_throw(m_ctx, "mupdf cannot authenticate password: %s", filename);
#endif
   return 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-->PNG
   drawpage(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;
    else
     scaley = 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);
   else
    fz_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);
   else
    fz_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图片下载代码,辛苦劳动,大家给点分吧,如果你没分,又需要下载,给我消息,我发给你。

http://download.csdn.net/detail/arthurfangmc/4948833


PDF转图片

标签:

原文地址:http://my.oschina.net/u/1426828/blog/526527

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!