PDF轉圖片

 首先用到的是GhostScript,網絡上有一些C#的使用方法,以下面的連接:html

      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/6530046less

      參考以上的方法,能夠在VC++中使用GhostScript的gsdll32.dll(在ghostscript的安裝路徑下能夠找到)把PDF轉爲圖片,但實際使用中會遇到一些問題,某些PDF轉爲圖片後長寬比例出現錯誤,頂部和底部會出現額外的白邊,用GhostScript去顯示這些PDF,顯示效果也同樣會出現一樣的問題。改用imageMagic去打開PDF,顯示效果同樣,頂部和底部也會出現額外的白邊。我猜想兩個軟件使用了相同的算法,或者使用了同一個庫。ide

      後來我改用MuPDF,PDF轉圖片的效果很是好,並且速度比GhostScript更快。函數

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

      英文很差的朋友,能夠看這裏,有人把文章翻譯並提出了本身的看法:http://www.cnblogs.com/pdfpatcher/archive/2012/11/25/2785154.htmlspa

      因爲我是使用C++,對於c開源庫的MuPDF來講,使用起來更直接方便。接下來重點介紹一下MuPDF轉圖片的方法。.net

      得到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

相關文章
相關標籤/搜索